Modified the LocateMacOSXFilesUsingDebugSymbols(...) function to locate

an executable file if it is right next to a dSYM file that is found using
DebugSymbols. The code also looks into a bundle if the dSYM file is right
next to a bundle.

Modified the MacOSX kernel dynamic loader plug-in to correctly set the load
address for kext sections. This is a tad tricky because of how LLDB chooses
to treat mach-o segments with no name. Also modified the loader to properly
handle the older version 1 kext summary info.

Fixed a crasher in the Mach-o object file parser when it is trying to set
the section size correctly for dSYM sections.

Added packet dumpers to the CommunicationKDP class. We now also properly 
detect address byte sizes based on the cpu type and subtype that is provided.
Added a read memory and read register support to CommunicationKDP. Added a
ThreadKDP class that now uses subclasses of the RegisterContextDarwin_XXX for
arm, i386 and x86_64. 

Fixed some register numbering issues in the RegisterContextDarwin_arm class
and added ARM GDB numbers to the ARM_GCC_Registers.h file.

Change the RegisterContextMach_XXX classes over to subclassing their
RegisterContextDarwin_XXX counterparts so we can share the mach register 
contexts between the user and kernel plug-ins.

llvm-svn: 135466
This commit is contained in:
Greg Clayton 2011-07-19 03:57:15 +00:00
parent e4e9a590d2
commit a63d08c9ff
32 changed files with 5827 additions and 3961 deletions

View File

@ -12,18 +12,19 @@
260E07C8136FAB9200CF21D3 /* OptionGroupFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260E07C7136FAB9200CF21D3 /* OptionGroupFile.cpp */; };
261744781168585B005ADD65 /* SBType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 261744771168585B005ADD65 /* SBType.cpp */; };
2617447A11685869005ADD65 /* SBType.h in Headers */ = {isa = PBXBuildFile; fileRef = 2617447911685869005ADD65 /* SBType.h */; settings = {ATTRIBUTES = (Public, ); }; };
2628A4D513D4977900F5487A /* ThreadKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2628A4D313D4977900F5487A /* ThreadKDP.cpp */; };
262CFC7711A4510000946C6C /* debugserver in Resources */ = {isa = PBXBuildFile; fileRef = 26CE05A0115C31E50022F371 /* debugserver */; };
26368A3C126B697600E8659F /* darwin-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26368A3B126B697600E8659F /* darwin-debug.cpp */; };
26368AF7126B960500E8659F /* darwin-debug in Resources */ = {isa = PBXBuildFile; fileRef = 26579F68126A25920007C5CB /* darwin-debug */; };
263E949F13661AEA00E7D1CE /* UnwindAssembly-x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */; };
2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */; };
2642FBAF13D003B400ED6808 /* CommunicationKDP.h in Headers */ = {isa = PBXBuildFile; fileRef = 2642FBA913D003B400ED6808 /* CommunicationKDP.h */; };
2642FBB013D003B400ED6808 /* ProcessKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */; };
2642FBB113D003B400ED6808 /* ProcessKDP.h in Headers */ = {isa = PBXBuildFile; fileRef = 2642FBAB13D003B400ED6808 /* ProcessKDP.h */; };
2642FBB213D003B400ED6808 /* ProcessKDPLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */; };
2642FBB313D003B400ED6808 /* ProcessKDPLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 2642FBAD13D003B400ED6808 /* ProcessKDPLog.h */; };
264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */; };
264D8D5013661BD7003A368F /* UnwindAssembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */; };
265205A813D3E3F700132FE2 /* RegisterContextKDP_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A213D3E3F700132FE2 /* RegisterContextKDP_arm.cpp */; };
265205AA13D3E3F700132FE2 /* RegisterContextKDP_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A413D3E3F700132FE2 /* RegisterContextKDP_i386.cpp */; };
265205AC13D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A613D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp */; };
265ABF6310F42EE900531910 /* DebugSymbols.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 265ABF6210F42EE900531910 /* DebugSymbols.framework */; };
26651A18133BF9E0005B64B7 /* Opcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26651A17133BF9DF005B64B7 /* Opcode.cpp */; };
266603CA1345B5A8004DA8B6 /* ConnectionSharedMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266603C91345B5A8004DA8B6 /* ConnectionSharedMemory.cpp */; };
@ -73,6 +74,7 @@
2671A0D013482601003A87BB /* ConnectionMachPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */; };
26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */; };
26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */; };
2676045A13D49D2300AB1B6A /* ProcessControl-mig.defs in Sources */ = {isa = PBXBuildFile; fileRef = 260C89A110F57C5600BB2B04 /* ProcessControl-mig.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; };
267C012B136880DF006E963E /* OptionGroupValueObjectDisplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */; };
267C01371368C49C006E963E /* OptionGroupOutputFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BCFC531368B3E4006DC050 /* OptionGroupOutputFile.cpp */; };
2686536C1370ACB200D186A3 /* OptionGroupBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2686536B1370ACB200D186A3 /* OptionGroupBoolean.cpp */; };
@ -342,6 +344,9 @@
268F9D55123AA16600B91E9B /* SBSymbolContextList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268F9D54123AA16600B91E9B /* SBSymbolContextList.cpp */; };
2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2690B3701381D5C300ECFBAE /* Memory.cpp */; };
2692BA15136610C100F9E14D /* UnwindAssemblyInstEmulation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2692BA13136610C100F9E14D /* UnwindAssemblyInstEmulation.cpp */; };
26957D9813D381C900670048 /* RegisterContextDarwin_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9213D381C900670048 /* RegisterContextDarwin_arm.cpp */; };
26957D9A13D381C900670048 /* RegisterContextDarwin_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9413D381C900670048 /* RegisterContextDarwin_i386.cpp */; };
26957D9C13D381C900670048 /* RegisterContextDarwin_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9613D381C900670048 /* RegisterContextDarwin_x86_64.cpp */; };
2697A54D133A6305004E4240 /* PlatformDarwin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2697A54B133A6305004E4240 /* PlatformDarwin.cpp */; };
26A69C5F137A17A500262477 /* RegisterValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C6886E137880C400407EDF /* RegisterValue.cpp */; };
26A7A035135E6E4200FB369E /* NamedOptionValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A7A034135E6E4200FB369E /* NamedOptionValue.cpp */; };
@ -425,7 +430,6 @@
9A3576AA116E9AC700E8ED2F /* SBHostOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */; };
9A4F35101368A51A00823F52 /* StreamAsynchronousIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */; };
9A9E1EFF1398086D005AC039 /* InputReaderStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9E1EFE1398086D005AC039 /* InputReaderStack.cpp */; };
9A9E1F0113980943005AC039 /* InputReaderStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9E1F0013980943005AC039 /* InputReaderStack.h */; };
9AA69DA61188F52100D753A0 /* PseudoTerminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */; };
9AA69DAF118A023300D753A0 /* SBInputReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AA69DAE118A023300D753A0 /* SBInputReader.h */; settings = {ATTRIBUTES = (Public, ); }; };
9AA69DB1118A024600D753A0 /* SBInputReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AA69DB0118A024600D753A0 /* SBInputReader.cpp */; };
@ -639,6 +643,8 @@
26217930133BC8640083B112 /* lldb-private-types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-types.h"; path = "include/lldb/lldb-private-types.h"; sourceTree = "<group>"; };
26217932133BCB850083B112 /* lldb-private-enumerations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-enumerations.h"; path = "include/lldb/lldb-private-enumerations.h"; sourceTree = "<group>"; };
2623096E13D0EFFB006381D9 /* StreamBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StreamBuffer.h; path = include/lldb/Core/StreamBuffer.h; sourceTree = "<group>"; };
2628A4D313D4977900F5487A /* ThreadKDP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadKDP.cpp; sourceTree = "<group>"; };
2628A4D413D4977900F5487A /* ThreadKDP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadKDP.h; sourceTree = "<group>"; };
263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
26368A3B126B697600E8659F /* darwin-debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "darwin-debug.cpp"; path = "tools/darwin-debug/darwin-debug.cpp"; sourceTree = "<group>"; };
@ -664,6 +670,12 @@
264AD83911095BBD00E0B039 /* CommandObjectLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectLog.h; path = source/Commands/CommandObjectLog.h; sourceTree = "<group>"; };
264D8D4E13661BCC003A368F /* UnwindAssembly.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UnwindAssembly.h; path = include/lldb/Target/UnwindAssembly.h; sourceTree = "<group>"; };
264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindAssembly.cpp; path = source/Target/UnwindAssembly.cpp; sourceTree = "<group>"; };
265205A213D3E3F700132FE2 /* RegisterContextKDP_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextKDP_arm.cpp; sourceTree = "<group>"; };
265205A313D3E3F700132FE2 /* RegisterContextKDP_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextKDP_arm.h; sourceTree = "<group>"; };
265205A413D3E3F700132FE2 /* RegisterContextKDP_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextKDP_i386.cpp; sourceTree = "<group>"; };
265205A513D3E3F700132FE2 /* RegisterContextKDP_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextKDP_i386.h; sourceTree = "<group>"; };
265205A613D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextKDP_x86_64.cpp; sourceTree = "<group>"; };
265205A713D3E3F700132FE2 /* RegisterContextKDP_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextKDP_x86_64.h; sourceTree = "<group>"; };
26579F68126A25920007C5CB /* darwin-debug */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "darwin-debug"; sourceTree = BUILT_PRODUCTS_DIR; };
265ABF6210F42EE900531910 /* DebugSymbols.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DebugSymbols.framework; path = /System/Library/PrivateFrameworks/DebugSymbols.framework; sourceTree = "<absolute>"; };
265E9BE1115C2BAA00D0DCCB /* debugserver.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = debugserver.xcodeproj; path = tools/debugserver/debugserver.xcodeproj; sourceTree = "<group>"; };
@ -729,6 +741,12 @@
2692BA14136610C100F9E14D /* UnwindAssemblyInstEmulation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnwindAssemblyInstEmulation.h; sourceTree = "<group>"; };
269416AD119A024800FF2715 /* CommandObjectTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectTarget.cpp; path = source/Commands/CommandObjectTarget.cpp; sourceTree = "<group>"; };
269416AE119A024800FF2715 /* CommandObjectTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectTarget.h; path = source/Commands/CommandObjectTarget.h; sourceTree = "<group>"; };
26957D9213D381C900670048 /* RegisterContextDarwin_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDarwin_arm.cpp; path = Utility/RegisterContextDarwin_arm.cpp; sourceTree = "<group>"; };
26957D9313D381C900670048 /* RegisterContextDarwin_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDarwin_arm.h; path = Utility/RegisterContextDarwin_arm.h; sourceTree = "<group>"; };
26957D9413D381C900670048 /* RegisterContextDarwin_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDarwin_i386.cpp; path = Utility/RegisterContextDarwin_i386.cpp; sourceTree = "<group>"; };
26957D9513D381C900670048 /* RegisterContextDarwin_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDarwin_i386.h; path = Utility/RegisterContextDarwin_i386.h; sourceTree = "<group>"; };
26957D9613D381C900670048 /* RegisterContextDarwin_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDarwin_x86_64.cpp; path = Utility/RegisterContextDarwin_x86_64.cpp; sourceTree = "<group>"; };
26957D9713D381C900670048 /* RegisterContextDarwin_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDarwin_x86_64.h; path = Utility/RegisterContextDarwin_x86_64.h; sourceTree = "<group>"; };
2697A54B133A6305004E4240 /* PlatformDarwin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformDarwin.cpp; sourceTree = "<group>"; };
2697A54C133A6305004E4240 /* PlatformDarwin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformDarwin.h; sourceTree = "<group>"; };
269FF07D12494F7D00225026 /* FuncUnwinders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FuncUnwinders.h; path = include/lldb/Symbol/FuncUnwinders.h; sourceTree = "<group>"; };
@ -1746,6 +1764,14 @@
2642FBAB13D003B400ED6808 /* ProcessKDP.h */,
2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */,
2642FBAD13D003B400ED6808 /* ProcessKDPLog.h */,
265205A213D3E3F700132FE2 /* RegisterContextKDP_arm.cpp */,
265205A313D3E3F700132FE2 /* RegisterContextKDP_arm.h */,
265205A413D3E3F700132FE2 /* RegisterContextKDP_i386.cpp */,
265205A513D3E3F700132FE2 /* RegisterContextKDP_i386.h */,
265205A613D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp */,
265205A713D3E3F700132FE2 /* RegisterContextKDP_x86_64.h */,
2628A4D313D4977900F5487A /* ThreadKDP.cpp */,
2628A4D413D4977900F5487A /* ThreadKDP.h */,
);
path = "MacOSX-Kernel";
sourceTree = "<group>";
@ -1888,6 +1914,12 @@
B28058A2139988C6002D96D0 /* InferiorCallPOSIX.h */,
AF68D32F1255A110002FF25B /* UnwindLLDB.cpp */,
AF68D3301255A110002FF25B /* UnwindLLDB.h */,
26957D9213D381C900670048 /* RegisterContextDarwin_arm.cpp */,
26957D9313D381C900670048 /* RegisterContextDarwin_arm.h */,
26957D9413D381C900670048 /* RegisterContextDarwin_i386.cpp */,
26957D9513D381C900670048 /* RegisterContextDarwin_i386.h */,
26957D9613D381C900670048 /* RegisterContextDarwin_x86_64.cpp */,
26957D9713D381C900670048 /* RegisterContextDarwin_x86_64.h */,
AF68D2541255416E002FF25B /* RegisterContextLLDB.cpp */,
AF68D2551255416E002FF25B /* RegisterContextLLDB.h */,
26E3EEF811A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.h */,
@ -2713,10 +2745,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
9A9E1F0113980943005AC039 /* InputReaderStack.h in Headers */,
2642FBAF13D003B400ED6808 /* CommunicationKDP.h in Headers */,
2642FBB113D003B400ED6808 /* ProcessKDP.h in Headers */,
2642FBB313D003B400ED6808 /* ProcessKDPLog.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3313,6 +3341,14 @@
2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */,
2642FBB013D003B400ED6808 /* ProcessKDP.cpp in Sources */,
2642FBB213D003B400ED6808 /* ProcessKDPLog.cpp in Sources */,
26957D9813D381C900670048 /* RegisterContextDarwin_arm.cpp in Sources */,
26957D9A13D381C900670048 /* RegisterContextDarwin_i386.cpp in Sources */,
26957D9C13D381C900670048 /* RegisterContextDarwin_x86_64.cpp in Sources */,
265205A813D3E3F700132FE2 /* RegisterContextKDP_arm.cpp in Sources */,
265205AA13D3E3F700132FE2 /* RegisterContextKDP_i386.cpp in Sources */,
265205AC13D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp in Sources */,
2628A4D513D4977900F5487A /* ThreadKDP.cpp in Sources */,
2676045A13D49D2300AB1B6A /* ProcessControl-mig.defs in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -746,7 +746,9 @@ ModuleList::GetSharedModule
// Fixup the incoming path in case the path points to a valid file, yet
// the arch or UUID (if one was passed in) don't match.
FileSpec file_spec = Symbols::LocateExecutableObjectFile (&in_file_spec, arch.IsValid() ? &arch : NULL, uuid_ptr);
FileSpec file_spec = Symbols::LocateExecutableObjectFile (in_file_spec ? &in_file_spec : NULL,
arch.IsValid() ? &arch : NULL,
uuid_ptr);
// Don't look for the file if it appears to be the same one we already
// checked for above...

View File

@ -29,6 +29,9 @@
#include "Host/macosx/cfcpp/CFCString.h"
#include "mach/machine.h"
#include "CFCBundle.h"
using namespace lldb;
using namespace lldb_private;
using namespace llvm::MachO;
@ -291,7 +294,7 @@ LocateMacOSXFilesUsingDebugSymbols
const UInt8 *module_uuid = (const UInt8 *)uuid->GetBytes();
if (module_uuid != NULL)
{
CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes ( NULL,
CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes (NULL,
module_uuid[0],
module_uuid[1],
module_uuid[2],
@ -366,6 +369,57 @@ LocateMacOSXFilesUsingDebugSymbols
}
}
}
else
{
// No dictionary, check near the dSYM bundle for an executable that matches...
if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
{
char *dsym_extension_pos = ::strstr (path, ".dSYM");
if (dsym_extension_pos)
{
*dsym_extension_pos = '\0';
FileSpec file_spec (path, true);
switch (file_spec.GetFileType())
{
case FileSpec::eFileTypeDirectory: // Bundle directory?
{
CFCBundle bundle (path);
CFCReleaser<CFURLRef> bundle_exe_url (bundle.CopyExecutableURL ());
if (bundle_exe_url.get())
{
if (::CFURLGetFileSystemRepresentation (bundle_exe_url.get(), true, (UInt8*)path, sizeof(path)-1))
{
FileSpec bundle_exe_file_spec (path, true);
if (FileAtPathContainsArchAndUUID (bundle_exe_file_spec, arch, uuid))
{
++items_found;
*out_exec_fspec = bundle_exe_file_spec;
}
}
}
}
break;
case FileSpec::eFileTypePipe: // Forget pipes
case FileSpec::eFileTypeSocket: // We can't process socket files
case FileSpec::eFileTypeInvalid: // File doesn't exist...
break;
case FileSpec::eFileTypeUnknown:
case FileSpec::eFileTypeRegular:
case FileSpec::eFileTypeSymbolicLink:
case FileSpec::eFileTypeOther:
if (FileAtPathContainsArchAndUUID (file_spec, arch, uuid))
{
++items_found;
*out_exec_fspec = file_spec;
}
break;
}
}
}
}
}
}
}

View File

@ -241,8 +241,8 @@ DynamicLoaderMacOSXKernel::FindTargetModule (OSKextLoadedKextSummary &image_info
if (image_info_uuid_is_valid)
{
image_info.module_sp = m_process->GetTarget().GetSharedModule (FileSpec(),
arch,
&image_info.uuid);
arch,
&image_info.uuid);
if (did_create_ptr)
*did_create_ptr = image_info.module_sp;
}
@ -306,26 +306,48 @@ DynamicLoaderMacOSXKernel::UpdateImageLoadAddress (OSKextLoadedKextSummary& info
uint32_t num_segments = info.segments.size();
for (uint32_t i=0; i<num_segments; ++i)
{
SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
const addr_t new_section_load_addr = info.segments[i].vmaddr;
if (section_sp)
if (section_list->FindSectionByName(info.segments[i].name))
{
const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
old_section_load_addr != new_section_load_addr)
SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
if (section_sp)
{
if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
changed = true;
const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
old_section_load_addr != new_section_load_addr)
{
if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
changed = true;
}
}
else
{
fprintf (stderr,
"warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
info.segments[i].name.AsCString("<invalid>"),
(uint64_t)new_section_load_addr,
image_object_file->GetFileSpec().GetDirectory().AsCString(),
image_object_file->GetFileSpec().GetFilename().AsCString());
}
}
else
{
fprintf (stderr,
"warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
info.segments[i].name.AsCString("<invalid>"),
(uint64_t)new_section_load_addr,
image_object_file->GetFileSpec().GetDirectory().AsCString(),
image_object_file->GetFileSpec().GetFilename().AsCString());
// The segment name is empty which means this is a .o file.
// Object files in LLDB end up getting reorganized so that
// the segment name that is in the section is promoted into
// an actual segment, so we just need to go through all sections
// and slide them by a single amount.
uint32_t num_sections = section_list->GetSize();
for (uint32_t i=0; i<num_sections; ++i)
{
Section* section = section_list->GetSectionAtIndex (i).get();
if (section)
{
if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress() + new_section_load_addr))
changed = true;
}
}
}
}
}
@ -442,10 +464,17 @@ DynamicLoaderMacOSXKernel::ReadKextSummaryHeader ()
if (bytes_read == count)
{
uint32_t offset = 0;
m_kext_summary_header.version = data.GetU32(&offset);
m_kext_summary_header.entry_size = data.GetU32(&offset);
m_kext_summary_header.entry_count = data.GetU32(&offset);
m_kext_summary_header.reserved = data.GetU32(&offset);
m_kext_summary_header.version = data.GetU32(&offset);
if (m_kext_summary_header.version >= 2)
{
m_kext_summary_header.entry_size = data.GetU32(&offset);
}
else
{
// Versions less than 2 didn't have an entry size, it was hard coded
m_kext_summary_header.entry_size = KERNEL_MODULE_ENTRY_SIZE_VERSION_1;
}
m_kext_summary_header.entry_count = data.GetU32(&offset);
return true;
}
}
@ -472,14 +501,14 @@ DynamicLoaderMacOSXKernel::ParseKextSummaries (const Address &kext_summary_addr,
for (uint32_t i = 0; i < count; i++)
{
if (!kext_summaries[i].UUIDValid())
DataExtractor data; // Load command data
if (ReadMachHeader (kext_summaries[i], &data))
{
DataExtractor data; // Load command data
if (!ReadMachHeader (kext_summaries[i], &data))
continue;
ParseLoadCommands (data, kext_summaries[i]);
}
if (log)
kext_summaries[i].PutToLog (log.get());
}
bool return_value = AddModulesUsingImageInfos (kext_summaries);
return return_value;
@ -560,11 +589,14 @@ DynamicLoaderMacOSXKernel::ReadKextSummaries (const Address &kext_summary_addr,
error);
if (bytes_read == count)
{
uint32_t offset = 0;
DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size);
uint32_t i=0;
for (; i < image_infos.size() && extractor.ValidOffsetForDataOfSize(offset, m_kext_summary_header.entry_size); ++i)
for (uint32_t kext_summary_offset = 0;
i < image_infos.size() && extractor.ValidOffsetForDataOfSize(kext_summary_offset, m_kext_summary_header.entry_size);
++i, kext_summary_offset += m_kext_summary_header.entry_size)
{
uint32_t offset = kext_summary_offset;
const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
if (name_data == NULL)
break;
@ -577,7 +609,14 @@ DynamicLoaderMacOSXKernel::ReadKextSummaries (const Address &kext_summary_addr,
image_infos[i].version = extractor.GetU64(&offset);
image_infos[i].load_tag = extractor.GetU32(&offset);
image_infos[i].flags = extractor.GetU32(&offset);
image_infos[i].reference_list = extractor.GetU64(&offset);
if ((offset - kext_summary_offset) < m_kext_summary_header.entry_size)
{
image_infos[i].reference_list = extractor.GetU64(&offset);
}
else
{
image_infos[i].reference_list = 0;
}
}
if (i < image_infos.size())
image_infos.resize(i);
@ -601,7 +640,7 @@ DynamicLoaderMacOSXKernel::ReadAllKextSummaries ()
if (m_kext_summary_header.entry_count > 0 && m_kext_summary_header_addr.IsValid())
{
Address summary_addr (m_kext_summary_header_addr);
summary_addr.Slide(16);
summary_addr.Slide(m_kext_summary_header.GetSize());
if (!ParseKextSummaries (summary_addr, m_kext_summary_header.entry_count))
{
m_kext_summaries.clear();
@ -835,7 +874,7 @@ DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
{
if (u)
{
log->Printf("\t uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name='%s' (UNLOADED)",
log->Printf("\tuuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\" (UNLOADED)",
u[ 0], u[ 1], u[ 2], u[ 3],
u[ 4], u[ 5], u[ 6], u[ 7],
u[ 8], u[ 9], u[10], u[11],
@ -843,23 +882,23 @@ DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
name);
}
else
log->Printf("\t name='%s' (UNLOADED)", name);
log->Printf("\tname=\"%s\" (UNLOADED)", name);
}
else
{
if (u)
{
log->Printf("\taddress=0x%16.16llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name='%s'",
address,
u[ 0], u[ 1], u[ 2], u[ 3],
u[ 4], u[ 5], u[ 6], u[ 7],
u[ 8], u[ 9], u[10], u[11],
u[12], u[13], u[14], u[15],
log->Printf("\taddr=0x%16.16llx size=0x%16.16llx version=0x%16.16llx load-tag=0x%8.8x flags=0x%8.8x ref-list=0x%16.16llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\"",
address, size, version, load_tag, flags, reference_list,
u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7],
u[ 8], u[ 9], u[10], u[11], u[12], u[13], u[14], u[15],
name);
}
else
{
log->Printf("\taddress=0x%16.16llx path='%s/%s'", address, name);
log->Printf("\t[0x%16.16llx - 0x%16.16llx) version=0x%16.16llx load-tag=0x%8.8x flags=0x%8.8x ref-list=0x%16.16llx name=\"%s\"",
address, address+size, version, load_tag, flags, reference_list,
name);
}
for (uint32_t i=0; i<segments.size(); ++i)
segments[i].PutToLog(log, 0);
@ -877,12 +916,11 @@ DynamicLoaderMacOSXKernel::PutToLog(Log *log) const
return;
Mutex::Locker locker(m_mutex);
log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u, reserved=%u }",
log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u }",
m_kext_summary_header_addr.GetFileAddress(),
m_kext_summary_header.version,
m_kext_summary_header.entry_size,
m_kext_summary_header.entry_count,
m_kext_summary_header.reserved);
m_kext_summary_header.entry_count);
size_t i;
const size_t count = m_kext_summaries.size();

View File

@ -192,7 +192,15 @@ protected:
};
enum { KERNEL_MODULE_MAX_NAME = 64u };
enum
{
KERNEL_MODULE_MAX_NAME = 64u,
// Versions less than 2 didn't have an entry size,
// they had a 64 bit name, 16 byte UUID, 8 byte addr,
// 8 byte size, 8 byte version, 4 byte load tag, and
// 4 byte flags
KERNEL_MODULE_ENTRY_SIZE_VERSION_1 = 64u + 16u + 8u + 8u + 8u + 4u + 4u
};
struct OSKextLoadedKextSummary
{
@ -327,25 +335,35 @@ protected:
uint32_t version;
uint32_t entry_size;
uint32_t entry_count;
uint32_t reserved; /* explicit alignment for gdb */
lldb::addr_t image_infos_addr;
OSKextLoadedKextSummaryHeader() :
version (0),
entry_size (0),
entry_count (0),
reserved (0),
image_infos_addr (LLDB_INVALID_ADDRESS)
{
}
uint32_t
GetSize()
{
switch (version)
{
case 0: return 0; // Can't know the size without a valid version
case 1: return 8; // Version 1 only had a version + entry_count
default: break;
}
// Version 2 and above has version, entry_size, entry_count, and reserved
return 16;
}
void
Clear()
{
version = 0;
entry_size = 0;
entry_count = 0;
reserved = 0;
image_infos_addr = LLDB_INVALID_ADDRESS;
}

View File

@ -604,7 +604,7 @@ ObjectFileMachO::ParseSections ()
segment_name.Clear();
}
}
if (m_header.filetype == HeaderFileTypeDSYM)
if (segment_sp && m_header.filetype == HeaderFileTypeDSYM)
{
if (first_segment_sectID <= sectID)
{

View File

@ -161,14 +161,14 @@ PlatformMacOSX::GetSharedModule (const FileSpec &platform_file,
if (!module_sp)
{
// Fall back to the local platform and find the file locally
error = Platform::GetSharedModule(platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
old_module_sp_ptr,
did_create_ptr);
error = Platform::GetSharedModule (platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
old_module_sp_ptr,
did_create_ptr);
}
if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);

View File

@ -15,10 +15,13 @@
#include <string.h>
// C++ Includes
#include "llvm/Support/MachO.h"
// Other libraries and framework includes
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/TimeValue.h"
@ -37,6 +40,7 @@ using namespace lldb_private;
//----------------------------------------------------------------------
CommunicationKDP::CommunicationKDP (const char *comm_name) :
Communication(comm_name),
m_addr_byte_size (4),
m_byte_order (eByteOrderLittle),
m_packet_timeout (1),
m_sequence_mutex (Mutex::eMutexTypeRecursive),
@ -129,13 +133,9 @@ CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packe
LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
if (log)
{
PacketStreamType log_strm;
DataExtractor::DumpHexBytes (&log_strm, packet_data, packet_size, UINT32_MAX, LLDB_INVALID_ADDRESS);
log->Printf("send kdp-packet: %.*s",
(uint32_t)log_strm.GetSize(),
log_strm.GetData());
PacketStreamType log_strm;
DumpPacket (log_strm, packet_data, packet_size);
log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
}
ConnectionStatus status = eConnectionStatusSuccess;
@ -298,18 +298,9 @@ CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtrac
if (log)
{
PacketStreamType log_strm;
packet.Dump (&log_strm, // Stream to dump to
0, // Offset into "packet"
eFormatBytes, // Dump as hex bytes
1, // Size of each item is 1 for single bytes
length, // Number of bytes
UINT32_MAX, // Num bytes per line
LLDB_INVALID_ADDRESS, // Base address
0, 0); // Bitfield info set to not do anything bitfield related
DumpPacket (log_strm, packet);
log->Printf("recv kdp-packet: %.*s",
(uint32_t)log_strm.GetSize(),
log_strm.GetData());
log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
}
return true;
}
@ -336,7 +327,7 @@ CommunicationKDP::SendRequestConnect (uint16_t reply_port,
uint16_t exc_port,
const char *greeting)
{
PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
if (greeting == NULL)
greeting = "";
@ -369,7 +360,7 @@ CommunicationKDP::ClearKDPSettings ()
bool
CommunicationKDP::SendRequestReattach (uint16_t reply_port)
{
PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = eCommandTypeReattach;
// Length is 8 bytes for the header plus 2 bytes for the reply UDP port
const uint32_t command_length = 8 + 2;
@ -410,7 +401,7 @@ CommunicationKDP::GetFeatureFlags ()
bool
CommunicationKDP::SendRequestVersion ()
{
PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = eCommandTypeVersion;
const uint32_t command_length = 8;
const uint32_t request_sequence_id = m_request_sequence_id;
@ -454,7 +445,7 @@ CommunicationKDP::GetCPUSubtype ()
bool
CommunicationKDP::SendRequestHostInfo ()
{
PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = eCommandTypeHostInfo;
const uint32_t command_length = 8;
const uint32_t request_sequence_id = m_request_sequence_id;
@ -464,9 +455,17 @@ CommunicationKDP::SendRequestHostInfo ()
{
// Reset the sequence ID to zero for reattach
uint32_t offset = 8;
m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset);
m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset);
m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset);
m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset);
m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset);
m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset);
ArchSpec kernel_arch;
kernel_arch.SetArchitecture (eArchTypeMachO,
m_kdp_hostinfo_cpu_type,
m_kdp_hostinfo_cpu_subtype);
m_addr_byte_size = kernel_arch.GetAddressByteSize();
m_byte_order = kernel_arch.GetByteOrder();
return true;
}
return false;
@ -475,7 +474,7 @@ CommunicationKDP::SendRequestHostInfo ()
bool
CommunicationKDP::SendRequestDisconnect ()
{
PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = eCommandTypeDisconnect;
const uint32_t command_length = 8;
const uint32_t request_sequence_id = m_request_sequence_id;
@ -489,3 +488,331 @@ CommunicationKDP::SendRequestDisconnect ()
return true;
}
uint32_t
CommunicationKDP::SendRequestReadMemory (lldb::addr_t addr,
void *dst,
uint32_t dst_len,
Error &error)
{
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
bool use_64 = (GetVersion() >= 11);
uint32_t command_addr_byte_size = use_64 ? 8 : 4;
const CommandType command = use_64 ? eCommandTypeReadMemory64 : eCommandTypeReadMemory;
// Size is header + address size + uint32_t length
const uint32_t command_length = 8 + command_addr_byte_size + 4;
const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
request_packet.PutMaxHex64 (addr, command_addr_byte_size);
request_packet.PutHex32 (dst_len);
DataExtractor reply_packet;
if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
{
// Reset the sequence ID to zero for reattach
uint32_t offset = 8;
uint32_t kdp_error = reply_packet.GetU32 (&offset);
uint32_t src_len = reply_packet.GetByteSize() - 12;
if (src_len > 0)
{
const void *src = reply_packet.GetData(&offset, src_len);
if (src)
{
::memcpy (dst, src, src_len);
error.Clear();
return src_len;
}
}
if (kdp_error)
error.SetErrorStringWithFormat ("kdp read memory failed (error %u)", kdp_error);
else
error.SetErrorString ("kdp read memory failed");
}
return 0;
}
const char *
CommunicationKDP::GetCommandAsCString (uint8_t command)
{
switch (command)
{
case eCommandTypeConnect: return "KDP_CONNECT";
case eCommandTypeDisconnect: return "KDP_DISCONNECT";
case eCommandTypeHostInfo: return "KDP_HOSTINFO";
case eCommandTypeVersion: return "KDP_VERSION";
case eCommandTypeMaxBytes: return "KDP_MAXBYTES";
case eCommandTypeReadMemory: return "KDP_READMEM";
case eCommandTypeWriteMemory: return "KDP_WRITEMEM";
case eCommandTypeReadRegisters: return "KDP_READREGS";
case eCommandTypeWriteRegisters: return "KDP_WRITEREGS";
case eCommandTypeLoad: return "KDP_LOAD";
case eCommandTypeImagePath: return "KDP_IMAGEPATH";
case eCommandTypeSuspend: return "KDP_SUSPEND";
case eCommandTypeResume: return "KDP_RESUMECPUS";
case eCommandTypeException: return "KDP_EXCEPTION";
case eCommandTypeTermination: return "KDP_TERMINATION";
case eCommandTypeBreakpointSet: return "KDP_BREAKPOINT_SET";
case eCommandTypeBreakpointRemove: return "KDP_BREAKPOINT_REMOVE";
case eCommandTypeRegions: return "KDP_REGIONS";
case eCommandTypeReattach: return "KDP_REATTACH";
case eCommandTypeHostReboot: return "KDP_HOSTREBOOT";
case eCommandTypeReadMemory64: return "KDP_READMEM64";
case eCommandTypeWriteMemory64: return "KDP_WRITEMEM64";
case eCommandTypeBreakpointSet64: return "KDP_BREAKPOINT64_SET";
case eCommandTypeBreakpointRemove64: return "KDP_BREAKPOINT64_REMOVE";
case eCommandTypeKernelVersion: return "KDP_KERNELVERSION";
}
return NULL;
}
void
CommunicationKDP::DumpPacket (Stream &s, const void *data, uint32_t data_len)
{
DataExtractor extractor (data, data_len, m_byte_order, m_addr_byte_size);
DumpPacket (s, extractor);
}
void
CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
{
const char *error_desc = NULL;
if (packet.GetByteSize() < 8)
{
error_desc = "error: invalid packet (too short): ";
}
else
{
uint32_t offset = 0;
const uint8_t first_packet_byte = packet.GetU8 (&offset);
const uint8_t sequence_id = packet.GetU8 (&offset);
const uint16_t length = packet.GetU16 (&offset);
const uint32_t key = packet.GetU32 (&offset);
const CommandType command = ExtractCommand (first_packet_byte);
const char *command_name = GetCommandAsCString (command);
if (command_name)
{
const bool is_reply = ExtractIsReply(first_packet_byte);
s.Printf ("%s {%u:%u} <0x%4.4x> %s",
is_reply ? "<--" : "-->",
key,
sequence_id,
length,
command_name);
if (is_reply)
{
// Dump request reply packets
switch (command)
{
case eCommandTypeConnect:
{
const uint32_t error = packet.GetU32 (&offset);
s.Printf(" (error=0x%8.8x)", error);
}
break;
case eCommandTypeDisconnect:
case eCommandTypeReattach:
case eCommandTypeHostReboot:
// No return value for the reply, just the header to ack
break;
case eCommandTypeHostInfo:
{
const uint32_t cpu_mask = packet.GetU32 (&offset);
const uint32_t cpu_type = packet.GetU32 (&offset);
const uint32_t cpu_subtype = packet.GetU32 (&offset);
s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype);
}
break;
case eCommandTypeVersion:
{
const uint32_t version = packet.GetU32 (&offset);
const uint32_t feature = packet.GetU32 (&offset);
s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature);
}
break;
case eCommandTypeRegions:
{
const uint32_t region_count = packet.GetU32 (&offset);
s.Printf(" (count = %u", region_count);
for (uint32_t i=0; i<region_count; ++i)
{
const addr_t region_addr = packet.GetPointer (&offset);
const uint32_t region_size = packet.GetU32 (&offset);
const uint32_t region_prot = packet.GetU32 (&offset);
s.Printf("\n\tregion[%i] = { range = [0x%16.16llx - 0x%16.16llx), size = 0x%8.8x, prot = %s }", region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot));
}
}
break;
case eCommandTypeReadMemory:
case eCommandTypeReadMemory64:
case eCommandTypeReadRegisters:
{
const uint32_t error = packet.GetU32 (&offset);
const uint32_t count = packet.GetByteSize() - 12;
s.Printf(" (error = 0x%8.8x <0x%x>:\n", error, count);
if (count > 0)
DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, count), count, 32, LLDB_INVALID_ADDRESS);
}
break;
case eCommandTypeMaxBytes:
case eCommandTypeWriteMemory:
case eCommandTypeWriteRegisters:
case eCommandTypeLoad:
case eCommandTypeImagePath:
case eCommandTypeSuspend:
case eCommandTypeResume:
case eCommandTypeException:
case eCommandTypeTermination:
case eCommandTypeBreakpointSet:
case eCommandTypeBreakpointRemove:
case eCommandTypeWriteMemory64:
case eCommandTypeBreakpointSet64:
case eCommandTypeBreakpointRemove64:
case eCommandTypeKernelVersion:
break;
}
}
else
{
// Dump request packets
switch (command)
{
case eCommandTypeConnect:
{
const uint16_t reply_port = packet.GetU16 (&offset);
const uint16_t exc_port = packet.GetU16 (&offset);
s.Printf(" (reply_port=%u, exc_port=%u, greeting=\"%s\")", reply_port, exc_port, packet.GetCStr(&offset));
}
break;
case eCommandTypeDisconnect:
case eCommandTypeHostReboot:
case eCommandTypeHostInfo:
case eCommandTypeVersion:
case eCommandTypeRegions:
// No args, just the header in the request...
break;
case eCommandTypeReadMemory:
{
const uint32_t addr = packet.GetU32 (&offset);
const uint32_t size = packet.GetU32 (&offset);
s.Printf(" (addr = 0x%8.8x, size=%u)", addr, size);
}
break;
case eCommandTypeReadMemory64:
{
const uint64_t addr = packet.GetU64 (&offset);
const uint32_t size = packet.GetU32 (&offset);
s.Printf(" (addr = 0x%16.16llx, size=%u)", addr, size);
}
break;
case eCommandTypeReadRegisters:
{
const uint32_t cpu = packet.GetU32 (&offset);
const uint32_t flavor = packet.GetU32 (&offset);
s.Printf(" (cpu = %u, flavor=%u)", cpu, flavor);
}
break;
case eCommandTypeMaxBytes:
case eCommandTypeWriteMemory:
case eCommandTypeWriteRegisters:
case eCommandTypeLoad:
case eCommandTypeImagePath:
case eCommandTypeSuspend:
case eCommandTypeResume:
case eCommandTypeException:
case eCommandTypeTermination:
case eCommandTypeBreakpointSet:
case eCommandTypeBreakpointRemove:
break;
case eCommandTypeReattach:
{
const uint16_t reply_port = packet.GetU16 (&offset);
s.Printf(" (reply_port=%u)", reply_port);
}
break;
case eCommandTypeWriteMemory64:
case eCommandTypeBreakpointSet64:
case eCommandTypeBreakpointRemove64:
case eCommandTypeKernelVersion:
break;
}
}
}
else
{
error_desc = "error: invalid packet command: ";
}
}
if (error_desc)
{
s.PutCString (error_desc);
packet.Dump (&s, // Stream to dump to
0, // Offset into "packet"
eFormatBytes, // Dump as hex bytes
1, // Size of each item is 1 for single bytes
packet.GetByteSize(), // Number of bytes
UINT32_MAX, // Num bytes per line
LLDB_INVALID_ADDRESS, // Base address
0, 0); // Bitfield info set to not do anything bitfield related
}
}
uint32_t
CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
uint32_t flavor,
void *dst,
uint32_t dst_len,
Error &error)
{
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = eCommandTypeReadRegisters;
// Size is header + 4 byte cpu and 4 byte flavor
const uint32_t command_length = 8 + 4 + 4;
const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
request_packet.PutHex32 (cpu);
request_packet.PutHex32 (flavor);
DataExtractor reply_packet;
if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
{
// Reset the sequence ID to zero for reattach
uint32_t offset = 8;
uint32_t kdp_error = reply_packet.GetU32 (&offset);
uint32_t src_len = reply_packet.GetByteSize() - 12;
if (src_len > 0)
{
const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len);
const void *src = reply_packet.GetData(&offset, bytes_to_copy);
if (src)
{
::memcpy (dst, src, bytes_to_copy);
error.Clear();
// Return the number of bytes we could have returned regardless if
// we copied them or not, just so we know when things don't match up
return src_len;
}
}
if (kdp_error)
error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
else
error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
}
return 0;
}

View File

@ -140,6 +140,9 @@ public:
lldb_private::ProcessLaunchInfo &launch_info);
//------------------------------------------------------------------
// Public Request Packets
//------------------------------------------------------------------
bool
SendRequestConnect (uint16_t reply_port,
uint16_t exc_port,
@ -151,6 +154,24 @@ public:
bool
SendRequestDisconnect ();
uint32_t
SendRequestReadMemory (lldb::addr_t addr,
void *buf,
uint32_t size,
lldb_private::Error &error);
uint32_t
SendRequestReadRegisters (uint32_t cpu,
uint32_t flavor,
void *dst,
uint32_t dst_size,
lldb_private::Error &error);
// size_t
// SendRequestWriteMemory (lldb::addr_t addr,
// const void *buf,
// size_t size,
// lldb_private::Error &error);
uint32_t
GetVersion ();
@ -184,9 +205,25 @@ protected:
PacketStreamType &request_packet,
uint16_t request_length);
//------------------------------------------------------------------
// Protected Request Packets (use public accessors which will cache
// results.
//------------------------------------------------------------------
bool
SendRequestVersion ();
bool
SendRequestHostInfo ();
void
DumpPacket (lldb_private::Stream &s,
const void *data,
uint32_t data_len);
void
DumpPacket (lldb_private::Stream &s,
const lldb_private::DataExtractor& extractor);
bool
VersionIsValid() const
@ -201,7 +238,21 @@ protected:
}
bool
SendRequestHostInfo ();
ExtractIsReply (uint8_t first_packet_byte) const
{
// TODO: handle big endian...
return (first_packet_byte & ePacketTypeMask) != 0;
}
CommandType
ExtractCommand (uint8_t first_packet_byte) const
{
// TODO: handle big endian...
return (CommandType)(first_packet_byte & eCommandTypeMask);
}
static const char *
GetCommandAsCString (uint8_t command);
void
ClearKDPSettings ();
@ -214,6 +265,7 @@ protected:
//------------------------------------------------------------------
// Classes that inherit from CommunicationKDP can see and modify these
//------------------------------------------------------------------
uint32_t m_addr_byte_size;
lldb::ByteOrder m_byte_order;
uint32_t m_packet_timeout;
lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time

View File

@ -18,11 +18,12 @@
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
// Project includes
#include "ProcessKDP.h"
#include "ProcessKDPLog.h"
//#include "ThreadKDP.h"
#include "ThreadKDP.h"
#include "StopInfoMachException.h"
using namespace lldb;
@ -182,7 +183,10 @@ ProcessKDP::DoConnectRemote (const char *remote_url)
ArchSpec kernel_arch;
kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
m_target.SetArchitecture(kernel_arch);
// TODO: thread registers based off of architecture...
SetID (1);
UpdateThreadListIfNeeded ();
SetPrivateState (eStateStopped);
}
}
else
@ -295,34 +299,24 @@ ProcessKDP::UpdateThreadListIfNeeded ()
log->Printf ("ProcessKDP::%s (pid = %i)", __FUNCTION__, GetID());
Mutex::Locker locker (m_thread_list.GetMutex ());
// TODO: get the thread list here!
const uint32_t stop_id = GetStopID();
if (m_thread_list.GetSize(false) == 0 || stop_id != m_thread_list.GetStopID())
if (m_thread_list.GetSize(false) == 0)
{
// Update the thread list's stop id immediately so we don't recurse into this function.
// ThreadList curr_thread_list (this);
// curr_thread_list.SetStopID(stop_id);
//
// std::vector<lldb::tid_t> thread_ids;
// bool sequence_mutex_unavailable = false;
// const size_t num_thread_ids = m_comm.GetCurrentThreadIDs (thread_ids, sequence_mutex_unavailable);
// if (num_thread_ids > 0)
// {
// for (size_t i=0; i<num_thread_ids; ++i)
// {
// tid_t tid = thread_ids[i];
// ThreadSP thread_sp (GetThreadList().FindThreadByID (tid, false));
// if (!thread_sp)
// thread_sp.reset (new ThreadGDBRemote (*this, tid));
// curr_thread_list.AddThread(thread_sp);
// }
// }
//
// if (sequence_mutex_unavailable == false)
// {
// m_thread_list = curr_thread_list;
// SetThreadStopInfo (m_last_stop_packet);
// }
// We currently are making only one thread per core and we
// actually don't know about actual threads. Eventually we
// want to get the thread list from memory and note which
// threads are on CPU as those are the only ones that we
// will be able to resume.
ThreadList curr_thread_list (this);
curr_thread_list.SetStopID(stop_id);
const uint32_t cpu_mask = m_comm.GetCPUMask();
for (uint32_t cpu_mask_bit = 1; cpu_mask_bit & cpu_mask; cpu_mask_bit <<= 1)
{
// The thread ID is currently the CPU mask bit
ThreadSP thread_sp (new ThreadKDP (*this, cpu_mask_bit));
curr_thread_list.AddThread(thread_sp);
}
m_thread_list = curr_thread_list;
}
return GetThreadList().GetSize(false);
}
@ -549,7 +543,9 @@ ProcessKDP::IsAlive ()
size_t
ProcessKDP::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
error.SetErrorString ("ProcessKDP::DoReadMemory not implemented");
if (m_comm.IsConnected())
return m_comm.SendRequestReadMemory (addr, buf, size, error);
error.SetErrorString ("not connected");
return 0;
}

View File

@ -183,6 +183,12 @@ public:
virtual lldb_private::Error
DisableWatchpoint (lldb_private::WatchpointLocation *wp_loc);
CommunicationKDP &
GetCommunication()
{
return m_comm;
}
protected:
friend class ThreadKDP;
friend class CommunicationKDP;
@ -229,12 +235,6 @@ protected:
uint32_t
UpdateThreadListIfNeeded ();
CommunicationKDP &
GetCommunication()
{
return m_comm;
}
enum
{
eBroadcastBitAsyncContinue = (1 << 0),

View File

@ -0,0 +1,90 @@
//===-- RegisterContextKDP_arm.cpp ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "RegisterContextKDP_arm.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "ProcessKDP.h"
#include "ThreadKDP.h"
using namespace lldb;
using namespace lldb_private;
RegisterContextKDP_arm::RegisterContextKDP_arm(ThreadKDP &thread, uint32_t concrete_frame_idx) :
RegisterContextDarwin_arm (thread, concrete_frame_idx),
m_kdp_thread (thread)
{
}
RegisterContextKDP_arm::~RegisterContextKDP_arm()
{
}
int
RegisterContextKDP_arm::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
{
Error error;
if (m_kdp_thread.GetKDPProcess().GetCommunication().SendRequestReadRegisters (tid,
GPRRegSet,
&gpr, sizeof(gpr),
error))
{
if (error.Success())
return 0;
}
return -1;
}
int
RegisterContextKDP_arm::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
return -1;
}
int
RegisterContextKDP_arm::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
return -1;
}
int
RegisterContextKDP_arm::DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg)
{
return -1;
}
int
RegisterContextKDP_arm::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return -1;
}
int
RegisterContextKDP_arm::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return -1;
}
int
RegisterContextKDP_arm::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
return -1;
}
int
RegisterContextKDP_arm::DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg)
{
return -1;
}

View File

@ -0,0 +1,61 @@
//===-- RegisterContextKDP_arm.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextKDP_arm_h_
#define liblldb_RegisterContextKDP_arm_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
class ThreadKDP;
class RegisterContextKDP_arm : public RegisterContextDarwin_arm
{
public:
RegisterContextKDP_arm (ThreadKDP &thread,
uint32_t concrete_frame_idx);
virtual
~RegisterContextKDP_arm();
protected:
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
int
DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg);
int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
int
DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg);
ThreadKDP &m_kdp_thread;
};
#endif // liblldb_RegisterContextKDP_arm_h_

View File

@ -0,0 +1,71 @@
//===-- RegisterContextKDP_i386.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
#include <mach/thread_act.h>
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "RegisterContextKDP_i386.h"
using namespace lldb;
using namespace lldb_private;
RegisterContextKDP_i386::RegisterContextKDP_i386(Thread &thread, uint32_t concrete_frame_idx) :
RegisterContextDarwin_i386 (thread, concrete_frame_idx)
{
}
RegisterContextKDP_i386::~RegisterContextKDP_i386()
{
}
int
RegisterContextKDP_i386::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
{
mach_msg_type_number_t count = GPRWordCount;
return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count);
}
int
RegisterContextKDP_i386::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
mach_msg_type_number_t count = FPUWordCount;
return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count);
}
int
RegisterContextKDP_i386::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
mach_msg_type_number_t count = EXCWordCount;
return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count);
}
int
RegisterContextKDP_i386::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount);
}
int
RegisterContextKDP_i386::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount);
}
int
RegisterContextKDP_i386::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount);
}

View File

@ -0,0 +1,49 @@
//===-- RegisterContextKDP_i386.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextKDP_i386_h_
#define liblldb_RegisterContextKDP_i386_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
class RegisterContextKDP_i386 : public RegisterContextDarwin_i386
{
public:
RegisterContextKDP_i386 (lldb_private::Thread &thread,
uint32_t concrete_frame_idx);
virtual
~RegisterContextKDP_i386();
protected:
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
};
#endif // liblldb_RegisterContextKDP_i386_h_

View File

@ -0,0 +1,66 @@
//===-- RegisterContextKDP_x86_64.cpp ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
#include <mach/thread_act.h>
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "RegisterContextKDP_x86_64.h"
using namespace lldb;
using namespace lldb_private;
RegisterContextKDP_x86_64::RegisterContextKDP_x86_64(Thread &thread, uint32_t concrete_frame_idx) :
RegisterContextDarwin_x86_64 (thread, concrete_frame_idx)
{
}
RegisterContextKDP_x86_64::~RegisterContextKDP_x86_64()
{
}
int
RegisterContextKDP_x86_64::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
{
return -1;
}
int
RegisterContextKDP_x86_64::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
return -1;
}
int
RegisterContextKDP_x86_64::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
return -1;
}
int
RegisterContextKDP_x86_64::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return -1;
}
int
RegisterContextKDP_x86_64::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return -1;
}
int
RegisterContextKDP_x86_64::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
return -1;
}

View File

@ -0,0 +1,50 @@
//===-- RegisterContextKDP_x86_64.h -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextKDP_x86_64_h_
#define liblldb_RegisterContextKDP_x86_64_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
class RegisterContextKDP_x86_64 : public RegisterContextDarwin_x86_64
{
public:
RegisterContextKDP_x86_64 (lldb_private::Thread &thread,
uint32_t concrete_frame_idx);
virtual
~RegisterContextKDP_x86_64();
protected:
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
};
#endif // liblldb_RegisterContextKDP_x86_64_h_

View File

@ -0,0 +1,247 @@
//===-- ThreadKDP.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ThreadKDP.h"
#include "llvm/Support/MachO.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/State.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Unwind.h"
#include "lldb/Breakpoint/WatchpointLocation.h"
#include "ProcessKDP.h"
#include "ProcessKDPLog.h"
#include "RegisterContextKDP_arm.h"
#include "RegisterContextKDP_i386.h"
#include "RegisterContextKDP_x86_64.h"
#include "Plugins/Process/Utility/UnwindLLDB.h"
#if defined(__APPLE__)
#include "UnwindMacOSXFrameBackchain.h"
#endif
using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
// Thread Registers
//----------------------------------------------------------------------
ThreadKDP::ThreadKDP (ProcessKDP &process, lldb::tid_t tid) :
Thread(process, tid),
m_thread_name (),
m_dispatch_queue_name (),
m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
{
ProcessKDPLog::LogIf(KDP_LOG_THREAD, "%p: ThreadKDP::ThreadKDP (pid = %i, tid = 0x%4.4x)", this, m_process.GetID(), GetID());
}
ThreadKDP::~ThreadKDP ()
{
ProcessKDPLog::LogIf(KDP_LOG_THREAD, "%p: ThreadKDP::~ThreadKDP (pid = %i, tid = 0x%4.4x)", this, m_process.GetID(), GetID());
DestroyThread();
}
const char *
ThreadKDP::GetInfo ()
{
return NULL;
}
const char *
ThreadKDP::GetName ()
{
if (m_thread_name.empty())
return NULL;
return m_thread_name.c_str();
}
const char *
ThreadKDP::GetQueueName ()
{
return NULL;
}
bool
ThreadKDP::WillResume (StateType resume_state)
{
ClearStackFrames();
// Call the Thread::WillResume first. If we stop at a signal, the stop info
// class for signal will set the resume signal that we need below. The signal
// stuff obeys the Process::UnixSignal defaults.
Thread::WillResume(resume_state);
lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
log->Printf ("Resuming thread: %4.4x with state: %s.", GetID(), StateAsCString(resume_state));
// ProcessKDP &process = GetKDPProcess();
// switch (resume_state)
// {
// case eStateSuspended:
// case eStateStopped:
// // Don't append anything for threads that should stay stopped.
// break;
//
// case eStateRunning:
// case eStateStepping:
// break;
//
// default:
// break;
// }
return true;
}
void
ThreadKDP::RefreshStateAfterStop()
{
// Invalidate all registers in our register context. We don't set "force" to
// true because the stop reply packet might have had some register values
// that were expedited and these will already be copied into the register
// context by the time this function gets called. The KDPRegisterContext
// class has been made smart enough to detect when it needs to invalidate
// which registers are valid by putting hooks in the register read and
// register supply functions where they check the process stop ID and do
// the right thing.
const bool force = false;
GetRegisterContext()->InvalidateIfNeeded (force);
}
Unwind *
ThreadKDP::GetUnwinder ()
{
if (m_unwinder_ap.get() == NULL)
{
const ArchSpec target_arch (GetProcess().GetTarget().GetArchitecture ());
const llvm::Triple::ArchType machine = target_arch.GetMachine();
switch (machine)
{
case llvm::Triple::x86_64:
case llvm::Triple::x86:
case llvm::Triple::arm:
case llvm::Triple::thumb:
m_unwinder_ap.reset (new UnwindLLDB (*this));
break;
default:
#if defined(__APPLE__)
m_unwinder_ap.reset (new UnwindMacOSXFrameBackchain (*this));
#endif
break;
}
}
return m_unwinder_ap.get();
}
void
ThreadKDP::ClearStackFrames ()
{
Unwind *unwinder = GetUnwinder ();
if (unwinder)
unwinder->Clear();
Thread::ClearStackFrames();
}
bool
ThreadKDP::ThreadIDIsValid (lldb::tid_t thread)
{
return thread != 0;
}
void
ThreadKDP::Dump(Log *log, uint32_t index)
{
}
bool
ThreadKDP::ShouldStop (bool &step_more)
{
return true;
}
lldb::RegisterContextSP
ThreadKDP::GetRegisterContext ()
{
if (m_reg_context_sp.get() == NULL)
m_reg_context_sp = CreateRegisterContextForFrame (NULL);
return m_reg_context_sp;
}
lldb::RegisterContextSP
ThreadKDP::CreateRegisterContextForFrame (StackFrame *frame)
{
lldb::RegisterContextSP reg_ctx_sp;
uint32_t concrete_frame_idx = 0;
if (frame)
concrete_frame_idx = frame->GetConcreteFrameIndex ();
if (concrete_frame_idx == 0)
{
switch (GetKDPProcess().GetCommunication().GetCPUType())
{
case llvm::MachO::CPUTypeARM:
reg_ctx_sp.reset (new RegisterContextKDP_arm (*this, concrete_frame_idx));
break;
case llvm::MachO::CPUTypeI386:
reg_ctx_sp.reset (new RegisterContextKDP_i386 (*this, concrete_frame_idx));
break;
case llvm::MachO::CPUTypeX86_64:
reg_ctx_sp.reset (new RegisterContextKDP_x86_64 (*this, concrete_frame_idx));
break;
default:
assert (!"Add CPU type support in KDP");
break;
}
}
else if (m_unwinder_ap.get())
reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
return reg_ctx_sp;
}
lldb::StopInfoSP
ThreadKDP::GetPrivateStopReason ()
{
const uint32_t process_stop_id = GetProcess().GetStopID();
if (m_thread_stop_reason_stop_id != process_stop_id ||
(m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
{
// TODO: can we query the initial state of the thread here?
// For now I am just going to pretend that a SIGSTOP happened.
SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
// If GetKDPProcess().SetThreadStopInfo() doesn't find a stop reason
// for this thread, then m_actual_stop_info_sp will not ever contain
// a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
// check will never be able to tell us if we have the correct stop info
// for this thread and we will continually send qThreadStopInfo packets
// down to the remote KDP server, so we need to keep our own notion
// of the stop ID that m_actual_stop_info_sp is valid for (even if it
// contains nothing). We use m_thread_stop_reason_stop_id for this below.
// m_thread_stop_reason_stop_id = process_stop_id;
// m_actual_stop_info_sp.reset();
}
return m_actual_stop_info_sp;
}

View File

@ -0,0 +1,115 @@
//===-- ThreadKDP.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_ThreadKDP_h_
#define liblldb_ThreadKDP_h_
#include <string>
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
class ProcessKDP;
class ThreadKDP : public lldb_private::Thread
{
public:
ThreadKDP (ProcessKDP &process,
lldb::tid_t tid);
virtual
~ThreadKDP ();
virtual bool
WillResume (lldb::StateType resume_state);
virtual void
RefreshStateAfterStop();
virtual const char *
GetInfo ();
virtual const char *
GetName ();
virtual const char *
GetQueueName ();
virtual lldb::RegisterContextSP
GetRegisterContext ();
virtual lldb::RegisterContextSP
CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
virtual void
ClearStackFrames ();
ProcessKDP &
GetKDPProcess ()
{
return (ProcessKDP &)m_process;
}
void
Dump (lldb_private::Log *log, uint32_t index);
static bool
ThreadIDIsValid (lldb::tid_t thread);
bool
ShouldStop (bool &step_more);
const char *
GetBasicInfoAsString ();
void
SetName (const char *name)
{
if (name && name[0])
m_thread_name.assign (name);
else
m_thread_name.clear();
}
lldb::addr_t
GetThreadDispatchQAddr ()
{
return m_thread_dispatch_qaddr;
}
void
SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr)
{
m_thread_dispatch_qaddr = thread_dispatch_qaddr;
}
protected:
friend class ProcessKDP;
//------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
std::string m_thread_name;
std::string m_dispatch_queue_name;
lldb::addr_t m_thread_dispatch_qaddr;
//------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
virtual lldb_private::Unwind *
GetUnwinder ();
virtual lldb::StopInfoSP
GetPrivateStopReason ();
};
#endif // liblldb_ThreadKDP_h_

View File

@ -11,46 +11,13 @@
#define liblldb_RegisterContextMach_arm_h_
// C Includes
#include <mach/mach_types.h>
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
// BCR address match type
#define BCR_M_IMVA_MATCH ((uint32_t)(0u << 21))
#define BCR_M_CONTEXT_ID_MATCH ((uint32_t)(1u << 21))
#define BCR_M_IMVA_MISMATCH ((uint32_t)(2u << 21))
#define BCR_M_RESERVED ((uint32_t)(3u << 21))
// Link a BVR/BCR or WVR/WCR pair to another
#define E_ENABLE_LINKING ((uint32_t)(1u << 20))
// Byte Address Select
#define BAS_IMVA_PLUS_0 ((uint32_t)(1u << 5))
#define BAS_IMVA_PLUS_1 ((uint32_t)(1u << 6))
#define BAS_IMVA_PLUS_2 ((uint32_t)(1u << 7))
#define BAS_IMVA_PLUS_3 ((uint32_t)(1u << 8))
#define BAS_IMVA_0_1 ((uint32_t)(3u << 5))
#define BAS_IMVA_2_3 ((uint32_t)(3u << 7))
#define BAS_IMVA_ALL ((uint32_t)(0xfu << 5))
// Break only in privileged or user mode
#define S_RSVD ((uint32_t)(0u << 1))
#define S_PRIV ((uint32_t)(1u << 1))
#define S_USER ((uint32_t)(2u << 1))
#define S_PRIV_USER ((S_PRIV) | (S_USER))
#define BCR_ENABLE ((uint32_t)(1u))
#define WCR_ENABLE ((uint32_t)(1u))
// Watchpoint load/store
#define WCR_LOAD ((uint32_t)(1u << 3))
#define WCR_STORE ((uint32_t)(1u << 4))
class RegisterContextMach_arm : public lldb_private::RegisterContext
class RegisterContextMach_arm : public RegisterContextDarwin_arm
{
public:
@ -59,242 +26,31 @@ public:
virtual
~RegisterContextMach_arm();
virtual void
InvalidateAllRegisters ();
virtual size_t
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
GetRegisterInfoAtIndex (uint32_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
GetRegisterSet (uint32_t set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &reg_value);
virtual bool
WriteRegister (const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &reg_value);
virtual bool
ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
virtual bool
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
virtual uint32_t
NumSupportedHardwareBreakpoints ();
virtual uint32_t
SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
virtual bool
ClearHardwareBreakpoint (uint32_t hw_idx);
virtual uint32_t
NumSupportedHardwareWatchpoints ();
virtual uint32_t
SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
virtual bool
ClearHardwareWatchpoint (uint32_t hw_index);
struct GPR
{
uint32_t r[16]; // R0-R15
uint32_t cpsr; // CPSR
};
struct FPU
{
union {
uint32_t s[32];
uint64_t d[16];
} floats;
uint32_t fpscr;
};
// struct NeonReg
// {
// uint8_t bytes[16];
// };
//
// struct VFPv3
// {
// union {
// uint32_t s[32];
// uint64_t d[32];
// NeonReg q[16];
// } v3;
// uint32_t fpscr;
// };
struct EXC
{
uint32_t exception;
uint32_t fsr; /* Fault status */
uint32_t far; /* Virtual Fault Address */
};
struct DBG
{
uint32_t bvr[16];
uint32_t bcr[16];
uint32_t wvr[16];
uint32_t wcr[16];
};
static void
LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);
protected:
enum
{
GPRRegSet = 1,
FPURegSet = 2,
EXCRegSet = 3,
DBGRegSet = 4,
};
enum
{
GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
EXCWordCount = sizeof(EXC)/sizeof(uint32_t),
DBGWordCount = sizeof(DBG)/sizeof(uint32_t)
};
enum
{
Read = 0,
Write = 1,
kNumErrors = 2
};
GPR gpr;
FPU fpu;
EXC exc;
DBG dbg;
int gpr_errs[2]; // Read/Write errors
int fpu_errs[2]; // Read/Write errors
int exc_errs[2]; // Read/Write errors
int dbg_errs[2]; // Read/Write errors
void
InvalidateAllRegisterStates()
{
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
}
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
int
GetError (int flavor, uint32_t err_idx) const
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
// When getting all errors, just OR all values together to see if
// we got any kind of error.
case GPRRegSet: return gpr_errs[err_idx];
case FPURegSet: return fpu_errs[err_idx];
case EXCRegSet: return exc_errs[err_idx];
case DBGRegSet: return dbg_errs[err_idx];
default: break;
}
}
return -1;
}
bool
SetError (int flavor, uint32_t err_idx, int err)
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
case GPRRegSet:
gpr_errs[err_idx] = err;
return true;
case FPURegSet:
fpu_errs[err_idx] = err;
return true;
case EXCRegSet:
exc_errs[err_idx] = err;
return true;
case DBGRegSet:
exc_errs[err_idx] = err;
return true;
default: break;
}
}
return false;
}
bool
RegisterSetIsCached (int set) const
{
return GetError(set, Read) == 0;
}
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
int
ReadGPR (bool force);
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
int
ReadFPU (bool force);
DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg);
int
ReadEXC (bool force);
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
int
ReadDBG (bool force);
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
int
WriteGPR ();
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
int
WriteFPU ();
int
WriteEXC ();
int
WriteDBG ();
int
ReadRegisterSet (uint32_t set, bool force);
int
WriteRegisterSet (uint32_t set);
static uint32_t
GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
static int
GetSetForNativeRegNum (int reg_num);
static size_t
GetRegisterInfosCount ();
static const lldb_private::RegisterInfo *
GetRegisterInfos ();
DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg);
};
#endif // liblldb_RegisterContextMach_arm_h_

View File

@ -14,237 +14,36 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
class RegisterContextMach_i386 : public lldb_private::RegisterContext
class RegisterContextMach_i386 : public RegisterContextDarwin_i386
{
public:
RegisterContextMach_i386(lldb_private::Thread &thread,
uint32_t concrete_frame_idx);
RegisterContextMach_i386(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
virtual
~RegisterContextMach_i386();
virtual void
InvalidateAllRegisters ();
virtual size_t
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
GetRegisterInfoAtIndex (uint32_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
GetRegisterSet (uint32_t set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
virtual bool
WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
virtual bool
ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
virtual bool
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
virtual bool
HardwareSingleStep (bool enable);
struct GPR
{
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
uint32_t edi;
uint32_t esi;
uint32_t ebp;
uint32_t esp;
uint32_t ss;
uint32_t eflags;
uint32_t eip;
uint32_t cs;
uint32_t ds;
uint32_t es;
uint32_t fs;
uint32_t gs;
};
struct MMSReg
{
uint8_t bytes[10];
uint8_t pad[6];
};
struct XMMReg
{
uint8_t bytes[16];
};
struct FPU
{
uint32_t pad[2];
uint16_t fcw;
uint16_t fsw;
uint8_t ftw;
uint8_t pad1;
uint16_t fop;
uint32_t ip;
uint16_t cs;
uint16_t pad2;
uint32_t dp;
uint16_t ds;
uint16_t pad3;
uint32_t mxcsr;
uint32_t mxcsrmask;
MMSReg stmm[8];
XMMReg xmm[8];
uint8_t pad4[14*16];
int pad5;
};
struct EXC
{
uint32_t trapno;
uint32_t err;
uint32_t faultvaddr;
};
protected:
enum
{
GPRRegSet = 1,
FPURegSet = 2,
EXCRegSet = 3
};
enum
{
GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
EXCWordCount = sizeof(EXC)/sizeof(uint32_t)
};
enum
{
Read = 0,
Write = 1,
kNumErrors = 2
};
GPR gpr;
FPU fpu;
EXC exc;
kern_return_t gpr_errs[2]; // Read/Write errors
kern_return_t fpu_errs[2]; // Read/Write errors
kern_return_t exc_errs[2]; // Read/Write errors
void
InvalidateAllRegisterStates()
{
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
}
kern_return_t
GetError (int flavor, uint32_t err_idx) const
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
// When getting all errors, just OR all values together to see if
// we got any kind of error.
case GPRRegSet: return gpr_errs[err_idx];
case FPURegSet: return fpu_errs[err_idx];
case EXCRegSet: return exc_errs[err_idx];
default: break;
}
}
return -1;
}
bool
SetError (int flavor, uint32_t err_idx, kern_return_t err)
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
case GPRRegSet:
gpr_errs[err_idx] = err;
return true;
case FPURegSet:
fpu_errs[err_idx] = err;
return true;
case EXCRegSet:
exc_errs[err_idx] = err;
return true;
default: break;
}
}
return false;
}
bool
RegisterSetIsCached (int set) const
{
return GetError(set, Read) == KERN_SUCCESS;
}
void
LogGPR (lldb_private::Log *log, const char *title);
kern_return_t
ReadGPR (bool force);
kern_return_t
ReadFPU (bool force);
kern_return_t
ReadEXC (bool force);
kern_return_t
WriteGPR ();
kern_return_t
WriteFPU ();
kern_return_t
WriteEXC ();
kern_return_t
ReadRegisterSet (uint32_t set, bool force);
kern_return_t
WriteRegisterSet (uint32_t set);
static uint32_t
GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
static int
GetSetForNativeRegNum (int reg_num);
static size_t
GetRegisterInfosCount ();
static const lldb_private::RegisterInfo *
GetRegisterInfos ();
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
};
#endif // liblldb_RegisterContextMach_i386_h_

View File

@ -1,4 +1,4 @@
//===-- RegisterContextMach_x86_64.h ----------------------------*- C++ -*-===//
//===-- RegisterContextMach_x86_64.h ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -14,242 +14,36 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
class RegisterContextMach_x86_64 : public lldb_private::RegisterContext
class RegisterContextMach_x86_64 : public RegisterContextDarwin_x86_64
{
public:
RegisterContextMach_x86_64 (lldb_private::Thread &thread,
uint32_t concrete_frame_idx);
RegisterContextMach_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
virtual
~RegisterContextMach_x86_64();
virtual void
InvalidateAllRegisters ();
virtual size_t
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
GetRegisterInfoAtIndex (uint32_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
GetRegisterSet (uint32_t set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
virtual bool
WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
virtual bool
ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
virtual bool
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
virtual bool
HardwareSingleStep (bool enable);
struct GPR
{
uint64_t rax;
uint64_t rbx;
uint64_t rcx;
uint64_t rdx;
uint64_t rdi;
uint64_t rsi;
uint64_t rbp;
uint64_t rsp;
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t rip;
uint64_t rflags;
uint64_t cs;
uint64_t fs;
uint64_t gs;
};
struct MMSReg
{
uint8_t bytes[10];
uint8_t pad[6];
};
struct XMMReg
{
uint8_t bytes[16];
};
struct FPU
{
uint32_t pad[2];
uint16_t fcw; // "fctrl"
uint16_t fsw; // "fstat"
uint8_t ftw; // "ftag"
uint8_t pad1;
uint16_t fop; // "fop"
uint32_t ip; // "fioff"
uint16_t cs; // "fiseg"
uint16_t pad2;
uint32_t dp; // "fooff"
uint16_t ds; // "foseg"
uint16_t pad3;
uint32_t mxcsr;
uint32_t mxcsrmask;
MMSReg stmm[8];
XMMReg xmm[16];
uint8_t pad4[6*16];
int pad5;
};
struct EXC
{
uint32_t trapno;
uint32_t err;
uint64_t faultvaddr;
};
protected:
enum
{
GPRRegSet = 4,
FPURegSet = 5,
EXCRegSet = 6
};
enum
{
GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
EXCWordCount = sizeof(EXC)/sizeof(uint32_t)
};
enum
{
Read = 0,
Write = 1,
kNumErrors = 2
};
GPR gpr;
FPU fpu;
EXC exc;
kern_return_t gpr_errs[2]; // Read/Write errors
kern_return_t fpu_errs[2]; // Read/Write errors
kern_return_t exc_errs[2]; // Read/Write errors
void
InvalidateAllRegisterStates()
{
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
}
kern_return_t
GetError (int flavor, uint32_t err_idx) const
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
// When getting all errors, just OR all values together to see if
// we got any kind of error.
case GPRRegSet: return gpr_errs[err_idx];
case FPURegSet: return fpu_errs[err_idx];
case EXCRegSet: return exc_errs[err_idx];
default: break;
}
}
return -1;
}
bool
SetError (int flavor, uint32_t err_idx, kern_return_t err)
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
case GPRRegSet:
gpr_errs[err_idx] = err;
return true;
case FPURegSet:
fpu_errs[err_idx] = err;
return true;
case EXCRegSet:
exc_errs[err_idx] = err;
return true;
default: break;
}
}
return false;
}
bool
RegisterSetIsCached (int set) const
{
return GetError(set, Read) == KERN_SUCCESS;
}
void
LogGPR (lldb_private::Log *log, const char *format, ...);
kern_return_t
ReadGPR (bool force);
kern_return_t
ReadFPU (bool force);
kern_return_t
ReadEXC (bool force);
kern_return_t
WriteGPR ();
kern_return_t
WriteFPU ();
kern_return_t
WriteEXC ();
kern_return_t
ReadRegisterSet (uint32_t set, bool force);
kern_return_t
WriteRegisterSet (uint32_t set);
static uint32_t
GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
static int
GetSetForNativeRegNum (int reg_num);
static size_t
GetRegisterInfosCount ();
static const lldb_private::RegisterInfo *
GetRegisterInfos ();
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
};
#endif // liblldb_RegisterContextMach_x86_64_h_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,348 @@
//===-- RegisterContextDarwin_arm.h -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextDarwin_arm_h_
#define liblldb_RegisterContextDarwin_arm_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
// BCR address match type
#define BCR_M_IMVA_MATCH ((uint32_t)(0u << 21))
#define BCR_M_CONTEXT_ID_MATCH ((uint32_t)(1u << 21))
#define BCR_M_IMVA_MISMATCH ((uint32_t)(2u << 21))
#define BCR_M_RESERVED ((uint32_t)(3u << 21))
// Link a BVR/BCR or WVR/WCR pair to another
#define E_ENABLE_LINKING ((uint32_t)(1u << 20))
// Byte Address Select
#define BAS_IMVA_PLUS_0 ((uint32_t)(1u << 5))
#define BAS_IMVA_PLUS_1 ((uint32_t)(1u << 6))
#define BAS_IMVA_PLUS_2 ((uint32_t)(1u << 7))
#define BAS_IMVA_PLUS_3 ((uint32_t)(1u << 8))
#define BAS_IMVA_0_1 ((uint32_t)(3u << 5))
#define BAS_IMVA_2_3 ((uint32_t)(3u << 7))
#define BAS_IMVA_ALL ((uint32_t)(0xfu << 5))
// Break only in privileged or user mode
#define S_RSVD ((uint32_t)(0u << 1))
#define S_PRIV ((uint32_t)(1u << 1))
#define S_USER ((uint32_t)(2u << 1))
#define S_PRIV_USER ((S_PRIV) | (S_USER))
#define BCR_ENABLE ((uint32_t)(1u))
#define WCR_ENABLE ((uint32_t)(1u))
// Watchpoint load/store
#define WCR_LOAD ((uint32_t)(1u << 3))
#define WCR_STORE ((uint32_t)(1u << 4))
class RegisterContextDarwin_arm : public lldb_private::RegisterContext
{
public:
RegisterContextDarwin_arm(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
virtual
~RegisterContextDarwin_arm();
virtual void
InvalidateAllRegisters ();
virtual size_t
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
GetRegisterInfoAtIndex (uint32_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
GetRegisterSet (uint32_t set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &reg_value);
virtual bool
WriteRegister (const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &reg_value);
virtual bool
ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
virtual bool
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
virtual uint32_t
NumSupportedHardwareBreakpoints ();
virtual uint32_t
SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
virtual bool
ClearHardwareBreakpoint (uint32_t hw_idx);
virtual uint32_t
NumSupportedHardwareWatchpoints ();
virtual uint32_t
SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
virtual bool
ClearHardwareWatchpoint (uint32_t hw_index);
struct GPR
{
uint32_t r[16]; // R0-R15
uint32_t cpsr; // CPSR
};
struct FPU
{
union {
uint32_t s[32];
uint64_t d[16];
} floats;
uint32_t fpscr;
};
// struct NeonReg
// {
// uint8_t bytes[16];
// };
//
// struct VFPv3
// {
// union {
// uint32_t s[32];
// uint64_t d[32];
// NeonReg q[16];
// } v3;
// uint32_t fpscr;
// };
struct EXC
{
uint32_t exception;
uint32_t fsr; /* Fault status */
uint32_t far; /* Virtual Fault Address */
};
struct DBG
{
uint32_t bvr[16];
uint32_t bcr[16];
uint32_t wvr[16];
uint32_t wcr[16];
};
static void
LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);
protected:
enum
{
GPRRegSet = 1,
FPURegSet = 2,
EXCRegSet = 3,
DBGRegSet = 4,
};
enum
{
GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
EXCWordCount = sizeof(EXC)/sizeof(uint32_t),
DBGWordCount = sizeof(DBG)/sizeof(uint32_t)
};
enum
{
Read = 0,
Write = 1,
kNumErrors = 2
};
GPR gpr;
FPU fpu;
EXC exc;
DBG dbg;
int gpr_errs[2]; // Read/Write errors
int fpu_errs[2]; // Read/Write errors
int exc_errs[2]; // Read/Write errors
int dbg_errs[2]; // Read/Write errors
void
InvalidateAllRegisterStates()
{
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
}
int
GetError (int flavor, uint32_t err_idx) const
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
// When getting all errors, just OR all values together to see if
// we got any kind of error.
case GPRRegSet: return gpr_errs[err_idx];
case FPURegSet: return fpu_errs[err_idx];
case EXCRegSet: return exc_errs[err_idx];
case DBGRegSet: return dbg_errs[err_idx];
default: break;
}
}
return -1;
}
bool
SetError (int flavor, uint32_t err_idx, int err)
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
case GPRRegSet:
gpr_errs[err_idx] = err;
return true;
case FPURegSet:
fpu_errs[err_idx] = err;
return true;
case EXCRegSet:
exc_errs[err_idx] = err;
return true;
case DBGRegSet:
exc_errs[err_idx] = err;
return true;
default: break;
}
}
return false;
}
bool
RegisterSetIsCached (int set) const
{
return GetError(set, Read) == 0;
}
int
ReadGPR (bool force);
int
ReadFPU (bool force);
int
ReadEXC (bool force);
int
ReadDBG (bool force);
int
WriteGPR ();
int
WriteFPU ();
int
WriteEXC ();
int
WriteDBG ();
// Subclasses override these to do the actual reading.
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
{
return -1;
}
int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
return -1;
}
int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
return -1;
}
int
DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg)
{
return -1;
}
int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return -1;
}
int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return -1;
}
int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
return -1;
}
int
DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg)
{
return -1;
}
int
ReadRegisterSet (uint32_t set, bool force);
int
WriteRegisterSet (uint32_t set);
static uint32_t
GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
static int
GetSetForNativeRegNum (int reg_num);
static size_t
GetRegisterInfosCount ();
static const lldb_private::RegisterInfo *
GetRegisterInfos ();
};
#endif // liblldb_RegisterContextDarwin_arm_h_

View File

@ -0,0 +1,971 @@
//===-- RegisterContextDarwin_i386.cpp --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Host/Endian.h"
// Project includes
#include "RegisterContextDarwin_i386.h"
using namespace lldb;
using namespace lldb_private;
enum
{
gpr_eax = 0,
gpr_ebx,
gpr_ecx,
gpr_edx,
gpr_edi,
gpr_esi,
gpr_ebp,
gpr_esp,
gpr_ss,
gpr_eflags,
gpr_eip,
gpr_cs,
gpr_ds,
gpr_es,
gpr_fs,
gpr_gs,
fpu_fcw,
fpu_fsw,
fpu_ftw,
fpu_fop,
fpu_ip,
fpu_cs,
fpu_dp,
fpu_ds,
fpu_mxcsr,
fpu_mxcsrmask,
fpu_stmm0,
fpu_stmm1,
fpu_stmm2,
fpu_stmm3,
fpu_stmm4,
fpu_stmm5,
fpu_stmm6,
fpu_stmm7,
fpu_xmm0,
fpu_xmm1,
fpu_xmm2,
fpu_xmm3,
fpu_xmm4,
fpu_xmm5,
fpu_xmm6,
fpu_xmm7,
exc_trapno,
exc_err,
exc_faultvaddr,
k_num_registers,
// Aliases
fpu_fctrl = fpu_fcw,
fpu_fstat = fpu_fsw,
fpu_ftag = fpu_ftw,
fpu_fiseg = fpu_cs,
fpu_fioff = fpu_ip,
fpu_foseg = fpu_ds,
fpu_fooff = fpu_dp
};
enum
{
gcc_eax = 0,
gcc_ecx,
gcc_edx,
gcc_ebx,
gcc_ebp,
gcc_esp,
gcc_esi,
gcc_edi,
gcc_eip,
gcc_eflags
};
enum
{
dwarf_eax = 0,
dwarf_ecx,
dwarf_edx,
dwarf_ebx,
dwarf_esp,
dwarf_ebp,
dwarf_esi,
dwarf_edi,
dwarf_eip,
dwarf_eflags,
dwarf_stmm0 = 11,
dwarf_stmm1,
dwarf_stmm2,
dwarf_stmm3,
dwarf_stmm4,
dwarf_stmm5,
dwarf_stmm6,
dwarf_stmm7,
dwarf_xmm0 = 21,
dwarf_xmm1,
dwarf_xmm2,
dwarf_xmm3,
dwarf_xmm4,
dwarf_xmm5,
dwarf_xmm6,
dwarf_xmm7
};
enum
{
gdb_eax = 0,
gdb_ecx = 1,
gdb_edx = 2,
gdb_ebx = 3,
gdb_esp = 4,
gdb_ebp = 5,
gdb_esi = 6,
gdb_edi = 7,
gdb_eip = 8,
gdb_eflags = 9,
gdb_cs = 10,
gdb_ss = 11,
gdb_ds = 12,
gdb_es = 13,
gdb_fs = 14,
gdb_gs = 15,
gdb_stmm0 = 16,
gdb_stmm1 = 17,
gdb_stmm2 = 18,
gdb_stmm3 = 19,
gdb_stmm4 = 20,
gdb_stmm5 = 21,
gdb_stmm6 = 22,
gdb_stmm7 = 23,
gdb_fctrl = 24, gdb_fcw = gdb_fctrl,
gdb_fstat = 25, gdb_fsw = gdb_fstat,
gdb_ftag = 26, gdb_ftw = gdb_ftag,
gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg,
gdb_fioff = 28, gdb_ip = gdb_fioff,
gdb_foseg = 29, gdb_fpu_ds = gdb_foseg,
gdb_fooff = 30, gdb_dp = gdb_fooff,
gdb_fop = 31,
gdb_xmm0 = 32,
gdb_xmm1 = 33,
gdb_xmm2 = 34,
gdb_xmm3 = 35,
gdb_xmm4 = 36,
gdb_xmm5 = 37,
gdb_xmm6 = 38,
gdb_xmm7 = 39,
gdb_mxcsr = 40,
gdb_mm0 = 41,
gdb_mm1 = 42,
gdb_mm2 = 43,
gdb_mm3 = 44,
gdb_mm4 = 45,
gdb_mm5 = 46,
gdb_mm6 = 47,
gdb_mm7 = 48
};
RegisterContextDarwin_i386::RegisterContextDarwin_i386 (Thread &thread, uint32_t concrete_frame_idx) :
RegisterContext(thread, concrete_frame_idx),
gpr(),
fpu(),
exc()
{
uint32_t i;
for (i=0; i<kNumErrors; i++)
{
gpr_errs[i] = -1;
fpu_errs[i] = -1;
exc_errs[i] = -1;
}
}
RegisterContextDarwin_i386::~RegisterContextDarwin_i386()
{
}
#define GPR_OFFSET(reg) (offsetof (RegisterContextDarwin_i386::GPR, reg))
#define FPU_OFFSET(reg) (offsetof (RegisterContextDarwin_i386::FPU, reg) + sizeof (RegisterContextDarwin_i386::GPR))
#define EXC_OFFSET(reg) (offsetof (RegisterContextDarwin_i386::EXC, reg) + sizeof (RegisterContextDarwin_i386::GPR) + sizeof (RegisterContextDarwin_i386::FPU))
// These macros will auto define the register name, alt name, register size,
// register offset, encoding, format and native register. This ensures that
// the register state structures are defined correctly and have the correct
// sizes and offsets.
#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex
#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex
#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }
#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextDarwin_i386::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex
#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_i386::GPR) + sizeof (RegisterContextDarwin_i386::FPU) + sizeof (RegisterContextDarwin_i386::EXC))
static RegisterInfo g_register_infos[] =
{
// Macro auto defines most stuff GCC DWARF GENERIC GDB LLDB
// =============================== ======================= =================== ========================= ================== =================
{ DEFINE_GPR(eax , NULL) , { gcc_eax , dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , gpr_eax }},
{ DEFINE_GPR(ebx , NULL) , { gcc_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , gpr_ebx }},
{ DEFINE_GPR(ecx , NULL) , { gcc_ecx , dwarf_ecx , LLDB_INVALID_REGNUM , gdb_ecx , gpr_ecx }},
{ DEFINE_GPR(edx , NULL) , { gcc_edx , dwarf_edx , LLDB_INVALID_REGNUM , gdb_edx , gpr_edx }},
{ DEFINE_GPR(edi , NULL) , { gcc_edi , dwarf_edi , LLDB_INVALID_REGNUM , gdb_edi , gpr_edi }},
{ DEFINE_GPR(esi , NULL) , { gcc_esi , dwarf_esi , LLDB_INVALID_REGNUM , gdb_esi , gpr_esi }},
{ DEFINE_GPR(ebp , "fp") , { gcc_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , gpr_ebp }},
{ DEFINE_GPR(esp , "sp") , { gcc_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , gpr_esp }},
{ DEFINE_GPR(ss , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ss , gpr_ss }},
{ DEFINE_GPR(eflags , "flags") , { gcc_eflags , dwarf_eflags , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , gpr_eflags }},
{ DEFINE_GPR(eip , "pc") , { gcc_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , gpr_eip }},
{ DEFINE_GPR(cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_cs , gpr_cs }},
{ DEFINE_GPR(ds , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ds , gpr_ds }},
{ DEFINE_GPR(es , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_es , gpr_es }},
{ DEFINE_GPR(fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fs , gpr_fs }},
{ DEFINE_GPR(gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gs , gpr_gs }},
{ DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fcw , fpu_fcw }},
{ DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fsw , fpu_fsw }},
{ DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ftw , fpu_ftw }},
{ DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fop , fpu_fop }},
{ DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ip , fpu_ip }},
{ DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_cs , fpu_cs }},
{ DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_dp , fpu_dp }},
{ DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ds , fpu_ds }},
{ DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_mxcsr , fpu_mxcsr }},
{ DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsrmask}},
{ DEFINE_FPU_VECT(stmm,0) },
{ DEFINE_FPU_VECT(stmm,1) },
{ DEFINE_FPU_VECT(stmm,2) },
{ DEFINE_FPU_VECT(stmm,3) },
{ DEFINE_FPU_VECT(stmm,4) },
{ DEFINE_FPU_VECT(stmm,5) },
{ DEFINE_FPU_VECT(stmm,6) },
{ DEFINE_FPU_VECT(stmm,7) },
{ DEFINE_FPU_VECT(xmm,0) },
{ DEFINE_FPU_VECT(xmm,1) },
{ DEFINE_FPU_VECT(xmm,2) },
{ DEFINE_FPU_VECT(xmm,3) },
{ DEFINE_FPU_VECT(xmm,4) },
{ DEFINE_FPU_VECT(xmm,5) },
{ DEFINE_FPU_VECT(xmm,6) },
{ DEFINE_FPU_VECT(xmm,7) },
{ DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_trapno }},
{ DEFINE_EXC(err) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_err }},
{ DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_faultvaddr }}
};
static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
void
RegisterContextDarwin_i386::InvalidateAllRegisters ()
{
InvalidateAllRegisterStates();
}
size_t
RegisterContextDarwin_i386::GetRegisterCount ()
{
assert(k_num_register_infos == k_num_registers);
return k_num_registers;
}
const RegisterInfo *
RegisterContextDarwin_i386::GetRegisterInfoAtIndex (uint32_t reg)
{
assert(k_num_register_infos == k_num_registers);
if (reg < k_num_registers)
return &g_register_infos[reg];
return NULL;
}
size_t
RegisterContextDarwin_i386::GetRegisterInfosCount ()
{
return k_num_register_infos;
}
const RegisterInfo *
RegisterContextDarwin_i386::GetRegisterInfos ()
{
return g_register_infos;
}
// General purpose registers
static uint32_t
g_gpr_regnums[] =
{
gpr_eax,
gpr_ebx,
gpr_ecx,
gpr_edx,
gpr_edi,
gpr_esi,
gpr_ebp,
gpr_esp,
gpr_ss,
gpr_eflags,
gpr_eip,
gpr_cs,
gpr_ds,
gpr_es,
gpr_fs,
gpr_gs
};
// Floating point registers
static uint32_t
g_fpu_regnums[] =
{
fpu_fcw,
fpu_fsw,
fpu_ftw,
fpu_fop,
fpu_ip,
fpu_cs,
fpu_dp,
fpu_ds,
fpu_mxcsr,
fpu_mxcsrmask,
fpu_stmm0,
fpu_stmm1,
fpu_stmm2,
fpu_stmm3,
fpu_stmm4,
fpu_stmm5,
fpu_stmm6,
fpu_stmm7,
fpu_xmm0,
fpu_xmm1,
fpu_xmm2,
fpu_xmm3,
fpu_xmm4,
fpu_xmm5,
fpu_xmm6,
fpu_xmm7
};
// Exception registers
static uint32_t
g_exc_regnums[] =
{
exc_trapno,
exc_err,
exc_faultvaddr
};
// Number of registers in each register set
const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
//----------------------------------------------------------------------
// Register set definitions. The first definitions at register set index
// of zero is for all registers, followed by other registers sets. The
// register information for the all register set need not be filled in.
//----------------------------------------------------------------------
static const RegisterSet g_reg_sets[] =
{
{ "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums, },
{ "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums },
{ "Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums }
};
const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
size_t
RegisterContextDarwin_i386::GetRegisterSetCount ()
{
return k_num_regsets;
}
const RegisterSet *
RegisterContextDarwin_i386::GetRegisterSet (uint32_t reg_set)
{
if (reg_set < k_num_regsets)
return &g_reg_sets[reg_set];
return NULL;
}
//----------------------------------------------------------------------
// Register information definitions for 32 bit i386.
//----------------------------------------------------------------------
int
RegisterContextDarwin_i386::GetSetForNativeRegNum (int reg_num)
{
if (reg_num < fpu_fcw)
return GPRRegSet;
else if (reg_num < exc_trapno)
return FPURegSet;
else if (reg_num < k_num_registers)
return EXCRegSet;
return -1;
}
void
RegisterContextDarwin_i386::LogGPR(Log *log, const char *title)
{
if (log)
{
if (title)
log->Printf ("%s", title);
for (uint32_t i=0; i<k_num_gpr_registers; i++)
{
uint32_t reg = gpr_eax + i;
log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&gpr.eax)[reg]);
}
}
}
int
RegisterContextDarwin_i386::ReadGPR (bool force)
{
int set = GPRRegSet;
if (force || !RegisterSetIsCached(set))
{
SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
}
return GetError(set, Read);
}
int
RegisterContextDarwin_i386::ReadFPU (bool force)
{
int set = FPURegSet;
if (force || !RegisterSetIsCached(set))
{
SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
}
return GetError(set, Read);
}
int
RegisterContextDarwin_i386::ReadEXC (bool force)
{
int set = EXCRegSet;
if (force || !RegisterSetIsCached(set))
{
SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
}
return GetError(set, Read);
}
int
RegisterContextDarwin_i386::WriteGPR ()
{
int set = GPRRegSet;
if (!RegisterSetIsCached(set))
{
SetError (set, Write, -1);
return -1;
}
SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr));
SetError (set, Read, -1);
return GetError(set, Write);
}
int
RegisterContextDarwin_i386::WriteFPU ()
{
int set = FPURegSet;
if (!RegisterSetIsCached(set))
{
SetError (set, Write, -1);
return -1;
}
SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu));
SetError (set, Read, -1);
return GetError(set, Write);
}
int
RegisterContextDarwin_i386::WriteEXC ()
{
int set = EXCRegSet;
if (!RegisterSetIsCached(set))
{
SetError (set, Write, -1);
return -1;
}
SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc));
SetError (set, Read, -1);
return GetError(set, Write);
}
int
RegisterContextDarwin_i386::ReadRegisterSet (uint32_t set, bool force)
{
switch (set)
{
case GPRRegSet: return ReadGPR(force);
case FPURegSet: return ReadFPU(force);
case EXCRegSet: return ReadEXC(force);
default: break;
}
return -1;
}
int
RegisterContextDarwin_i386::WriteRegisterSet (uint32_t set)
{
// Make sure we have a valid context to set.
if (RegisterSetIsCached(set))
{
switch (set)
{
case GPRRegSet: return WriteGPR();
case FPURegSet: return WriteFPU();
case EXCRegSet: return WriteEXC();
default: break;
}
}
return -1;
}
bool
RegisterContextDarwin_i386::ReadRegister (const RegisterInfo *reg_info,
RegisterValue &value)
{
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
int set = RegisterContextDarwin_i386::GetSetForNativeRegNum (reg);
if (set == -1)
return false;
if (ReadRegisterSet(set, false) != 0)
return false;
switch (reg)
{
case gpr_eax:
case gpr_ebx:
case gpr_ecx:
case gpr_edx:
case gpr_edi:
case gpr_esi:
case gpr_ebp:
case gpr_esp:
case gpr_ss:
case gpr_eflags:
case gpr_eip:
case gpr_cs:
case gpr_ds:
case gpr_es:
case gpr_fs:
case gpr_gs:
value = (&gpr.eax)[reg - gpr_eax];
break;
case fpu_fcw:
value = fpu.fcw;
break;
case fpu_fsw:
value = fpu.fsw;
break;
case fpu_ftw:
value = fpu.ftw;
break;
case fpu_fop:
value = fpu.fop;
break;
case fpu_ip:
value = fpu.ip;
break;
case fpu_cs:
value = fpu.cs;
break;
case fpu_dp:
value = fpu.dp;
break;
case fpu_ds:
value = fpu.ds;
break;
case fpu_mxcsr:
value = fpu.mxcsr;
break;
case fpu_mxcsrmask:
value = fpu.mxcsrmask;
break;
case fpu_stmm0:
case fpu_stmm1:
case fpu_stmm2:
case fpu_stmm3:
case fpu_stmm4:
case fpu_stmm5:
case fpu_stmm6:
case fpu_stmm7:
// These values don't fit into scalar types,
// RegisterContext::ReadRegisterBytes() must be used for these
// registers
//::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes, 10);
return false;
case fpu_xmm0:
case fpu_xmm1:
case fpu_xmm2:
case fpu_xmm3:
case fpu_xmm4:
case fpu_xmm5:
case fpu_xmm6:
case fpu_xmm7:
// These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
// must be used for these registers
//::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes, 16);
return false;
case exc_trapno:
value = exc.trapno;
break;
case exc_err:
value = exc.err;
break;
case exc_faultvaddr:
value = exc.faultvaddr;
break;
default:
return false;
}
return true;
}
bool
RegisterContextDarwin_i386::WriteRegister (const RegisterInfo *reg_info,
const RegisterValue &value)
{
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
int set = GetSetForNativeRegNum (reg);
if (set == -1)
return false;
if (ReadRegisterSet(set, false) != 0)
return false;
switch (reg)
{
case gpr_eax:
case gpr_ebx:
case gpr_ecx:
case gpr_edx:
case gpr_edi:
case gpr_esi:
case gpr_ebp:
case gpr_esp:
case gpr_ss:
case gpr_eflags:
case gpr_eip:
case gpr_cs:
case gpr_ds:
case gpr_es:
case gpr_fs:
case gpr_gs:
(&gpr.eax)[reg - gpr_eax] = value.GetAsUInt32();
break;
case fpu_fcw:
fpu.fcw = value.GetAsUInt16();
break;
case fpu_fsw:
fpu.fsw = value.GetAsUInt16();
break;
case fpu_ftw:
fpu.ftw = value.GetAsUInt8();
break;
case fpu_fop:
fpu.fop = value.GetAsUInt16();
break;
case fpu_ip:
fpu.ip = value.GetAsUInt32();
break;
case fpu_cs:
fpu.cs = value.GetAsUInt16();
break;
case fpu_dp:
fpu.dp = value.GetAsUInt32();
break;
case fpu_ds:
fpu.ds = value.GetAsUInt16();
break;
case fpu_mxcsr:
fpu.mxcsr = value.GetAsUInt32();
break;
case fpu_mxcsrmask:
fpu.mxcsrmask = value.GetAsUInt32();
break;
case fpu_stmm0:
case fpu_stmm1:
case fpu_stmm2:
case fpu_stmm3:
case fpu_stmm4:
case fpu_stmm5:
case fpu_stmm6:
case fpu_stmm7:
// These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
// must be used for these registers
::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize());
return false;
case fpu_xmm0:
case fpu_xmm1:
case fpu_xmm2:
case fpu_xmm3:
case fpu_xmm4:
case fpu_xmm5:
case fpu_xmm6:
case fpu_xmm7:
// These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
// must be used for these registers
::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize());
return false;
case exc_trapno:
exc.trapno = value.GetAsUInt32();
break;
case exc_err:
exc.err = value.GetAsUInt32();
break;
case exc_faultvaddr:
exc.faultvaddr = value.GetAsUInt32();
break;
default:
return false;
}
return WriteRegisterSet(set) == 0;
}
bool
RegisterContextDarwin_i386::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
{
data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
if (data_sp &&
ReadGPR (false) == 0 &&
ReadFPU (false) == 0 &&
ReadEXC (false) == 0)
{
uint8_t *dst = data_sp->GetBytes();
::memcpy (dst, &gpr, sizeof(gpr));
dst += sizeof(gpr);
::memcpy (dst, &fpu, sizeof(fpu));
dst += sizeof(gpr);
::memcpy (dst, &exc, sizeof(exc));
return true;
}
return false;
}
bool
RegisterContextDarwin_i386::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
{
if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
{
const uint8_t *src = data_sp->GetBytes();
::memcpy (&gpr, src, sizeof(gpr));
src += sizeof(gpr);
::memcpy (&fpu, src, sizeof(fpu));
src += sizeof(gpr);
::memcpy (&exc, src, sizeof(exc));
uint32_t success_count = 0;
if (WriteGPR() == 0)
++success_count;
if (WriteFPU() == 0)
++success_count;
if (WriteEXC() == 0)
++success_count;
return success_count == 3;
}
return false;
}
uint32_t
RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
{
if (kind == eRegisterKindGeneric)
{
switch (reg)
{
case LLDB_REGNUM_GENERIC_PC: return gpr_eip;
case LLDB_REGNUM_GENERIC_SP: return gpr_esp;
case LLDB_REGNUM_GENERIC_FP: return gpr_ebp;
case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
case LLDB_REGNUM_GENERIC_RA:
default:
break;
}
}
else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
{
switch (reg)
{
case dwarf_eax: return gpr_eax;
case dwarf_ecx: return gpr_ecx;
case dwarf_edx: return gpr_edx;
case dwarf_ebx: return gpr_ebx;
case dwarf_esp: return gpr_esp;
case dwarf_ebp: return gpr_ebp;
case dwarf_esi: return gpr_esi;
case dwarf_edi: return gpr_edi;
case dwarf_eip: return gpr_eip;
case dwarf_eflags: return gpr_eflags;
case dwarf_stmm0: return fpu_stmm0;
case dwarf_stmm1: return fpu_stmm1;
case dwarf_stmm2: return fpu_stmm2;
case dwarf_stmm3: return fpu_stmm3;
case dwarf_stmm4: return fpu_stmm4;
case dwarf_stmm5: return fpu_stmm5;
case dwarf_stmm6: return fpu_stmm6;
case dwarf_stmm7: return fpu_stmm7;
case dwarf_xmm0: return fpu_xmm0;
case dwarf_xmm1: return fpu_xmm1;
case dwarf_xmm2: return fpu_xmm2;
case dwarf_xmm3: return fpu_xmm3;
case dwarf_xmm4: return fpu_xmm4;
case dwarf_xmm5: return fpu_xmm5;
case dwarf_xmm6: return fpu_xmm6;
case dwarf_xmm7: return fpu_xmm7;
default:
break;
}
}
else if (kind == eRegisterKindGDB)
{
switch (reg)
{
case gdb_eax : return gpr_eax;
case gdb_ebx : return gpr_ebx;
case gdb_ecx : return gpr_ecx;
case gdb_edx : return gpr_edx;
case gdb_esi : return gpr_esi;
case gdb_edi : return gpr_edi;
case gdb_ebp : return gpr_ebp;
case gdb_esp : return gpr_esp;
case gdb_eip : return gpr_eip;
case gdb_eflags : return gpr_eflags;
case gdb_cs : return gpr_cs;
case gdb_ss : return gpr_ss;
case gdb_ds : return gpr_ds;
case gdb_es : return gpr_es;
case gdb_fs : return gpr_fs;
case gdb_gs : return gpr_gs;
case gdb_stmm0 : return fpu_stmm0;
case gdb_stmm1 : return fpu_stmm1;
case gdb_stmm2 : return fpu_stmm2;
case gdb_stmm3 : return fpu_stmm3;
case gdb_stmm4 : return fpu_stmm4;
case gdb_stmm5 : return fpu_stmm5;
case gdb_stmm6 : return fpu_stmm6;
case gdb_stmm7 : return fpu_stmm7;
case gdb_fctrl : return fpu_fctrl;
case gdb_fstat : return fpu_fstat;
case gdb_ftag : return fpu_ftag;
case gdb_fiseg : return fpu_fiseg;
case gdb_fioff : return fpu_fioff;
case gdb_foseg : return fpu_foseg;
case gdb_fooff : return fpu_fooff;
case gdb_fop : return fpu_fop;
case gdb_xmm0 : return fpu_xmm0;
case gdb_xmm1 : return fpu_xmm1;
case gdb_xmm2 : return fpu_xmm2;
case gdb_xmm3 : return fpu_xmm3;
case gdb_xmm4 : return fpu_xmm4;
case gdb_xmm5 : return fpu_xmm5;
case gdb_xmm6 : return fpu_xmm6;
case gdb_xmm7 : return fpu_xmm7;
case gdb_mxcsr : return fpu_mxcsr;
default:
break;
}
}
else if (kind == eRegisterKindLLDB)
{
return reg;
}
return LLDB_INVALID_REGNUM;
}
bool
RegisterContextDarwin_i386::HardwareSingleStep (bool enable)
{
if (ReadGPR(false) != 0)
return false;
const uint32_t trace_bit = 0x100u;
if (enable)
{
// If the trace bit is already set, there is nothing to do
if (gpr.eflags & trace_bit)
return true;
else
gpr.eflags |= trace_bit;
}
else
{
// If the trace bit is already cleared, there is nothing to do
if (gpr.eflags & trace_bit)
gpr.eflags &= ~trace_bit;
else
return true;
}
return WriteGPR() == 0;
}

View File

@ -0,0 +1,287 @@
//===-- RegisterContextDarwin_i386.h ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextDarwin_i386_h_
#define liblldb_RegisterContextDarwin_i386_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
class RegisterContextDarwin_i386 : public lldb_private::RegisterContext
{
public:
RegisterContextDarwin_i386(lldb_private::Thread &thread,
uint32_t concrete_frame_idx);
virtual
~RegisterContextDarwin_i386();
virtual void
InvalidateAllRegisters ();
virtual size_t
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
GetRegisterInfoAtIndex (uint32_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
GetRegisterSet (uint32_t set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
virtual bool
WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
virtual bool
ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
virtual bool
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
virtual bool
HardwareSingleStep (bool enable);
struct GPR
{
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
uint32_t edi;
uint32_t esi;
uint32_t ebp;
uint32_t esp;
uint32_t ss;
uint32_t eflags;
uint32_t eip;
uint32_t cs;
uint32_t ds;
uint32_t es;
uint32_t fs;
uint32_t gs;
};
struct MMSReg
{
uint8_t bytes[10];
uint8_t pad[6];
};
struct XMMReg
{
uint8_t bytes[16];
};
struct FPU
{
uint32_t pad[2];
uint16_t fcw;
uint16_t fsw;
uint8_t ftw;
uint8_t pad1;
uint16_t fop;
uint32_t ip;
uint16_t cs;
uint16_t pad2;
uint32_t dp;
uint16_t ds;
uint16_t pad3;
uint32_t mxcsr;
uint32_t mxcsrmask;
MMSReg stmm[8];
XMMReg xmm[8];
uint8_t pad4[14*16];
int pad5;
};
struct EXC
{
uint32_t trapno;
uint32_t err;
uint32_t faultvaddr;
};
protected:
enum
{
GPRRegSet = 1,
FPURegSet = 2,
EXCRegSet = 3
};
enum
{
GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
EXCWordCount = sizeof(EXC)/sizeof(uint32_t)
};
enum
{
Read = 0,
Write = 1,
kNumErrors = 2
};
GPR gpr;
FPU fpu;
EXC exc;
int gpr_errs[2]; // Read/Write errors
int fpu_errs[2]; // Read/Write errors
int exc_errs[2]; // Read/Write errors
void
InvalidateAllRegisterStates()
{
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
}
int
GetError (int flavor, uint32_t err_idx) const
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
// When getting all errors, just OR all values together to see if
// we got any kind of error.
case GPRRegSet: return gpr_errs[err_idx];
case FPURegSet: return fpu_errs[err_idx];
case EXCRegSet: return exc_errs[err_idx];
default: break;
}
}
return -1;
}
bool
SetError (int flavor, uint32_t err_idx, int err)
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
case GPRRegSet:
gpr_errs[err_idx] = err;
return true;
case FPURegSet:
fpu_errs[err_idx] = err;
return true;
case EXCRegSet:
exc_errs[err_idx] = err;
return true;
default: break;
}
}
return false;
}
bool
RegisterSetIsCached (int set) const
{
return GetError(set, Read) == 0;
}
void
LogGPR (lldb_private::Log *log, const char *title);
int
ReadGPR (bool force);
int
ReadFPU (bool force);
int
ReadEXC (bool force);
int
WriteGPR ();
int
WriteFPU ();
int
WriteEXC ();
// Subclasses override these to do the actual reading.
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
{
return -1;
}
int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
return -1;
}
int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
return -1;
}
int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return -1;
}
int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return -1;
}
int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
return -1;
}
int
ReadRegisterSet (uint32_t set, bool force);
int
WriteRegisterSet (uint32_t set);
static uint32_t
GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
static int
GetSetForNativeRegNum (int reg_num);
static size_t
GetRegisterInfosCount ();
static const lldb_private::RegisterInfo *
GetRegisterInfos ();
};
#endif // liblldb_RegisterContextDarwin_i386_h_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,293 @@
//===-- RegisterContextDarwin_x86_64.h --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextDarwin_x86_64_h_
#define liblldb_RegisterContextDarwin_x86_64_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
class RegisterContextDarwin_x86_64 : public lldb_private::RegisterContext
{
public:
RegisterContextDarwin_x86_64 (lldb_private::Thread &thread,
uint32_t concrete_frame_idx);
virtual
~RegisterContextDarwin_x86_64();
virtual void
InvalidateAllRegisters ();
virtual size_t
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
GetRegisterInfoAtIndex (uint32_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
GetRegisterSet (uint32_t set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
virtual bool
WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
virtual bool
ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
virtual bool
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
virtual uint32_t
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
virtual bool
HardwareSingleStep (bool enable);
struct GPR
{
uint64_t rax;
uint64_t rbx;
uint64_t rcx;
uint64_t rdx;
uint64_t rdi;
uint64_t rsi;
uint64_t rbp;
uint64_t rsp;
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t rip;
uint64_t rflags;
uint64_t cs;
uint64_t fs;
uint64_t gs;
};
struct MMSReg
{
uint8_t bytes[10];
uint8_t pad[6];
};
struct XMMReg
{
uint8_t bytes[16];
};
struct FPU
{
uint32_t pad[2];
uint16_t fcw; // "fctrl"
uint16_t fsw; // "fstat"
uint8_t ftw; // "ftag"
uint8_t pad1;
uint16_t fop; // "fop"
uint32_t ip; // "fioff"
uint16_t cs; // "fiseg"
uint16_t pad2;
uint32_t dp; // "fooff"
uint16_t ds; // "foseg"
uint16_t pad3;
uint32_t mxcsr;
uint32_t mxcsrmask;
MMSReg stmm[8];
XMMReg xmm[16];
uint8_t pad4[6*16];
int pad5;
};
struct EXC
{
uint32_t trapno;
uint32_t err;
uint64_t faultvaddr;
};
protected:
enum
{
GPRRegSet = 4,
FPURegSet = 5,
EXCRegSet = 6
};
enum
{
GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
EXCWordCount = sizeof(EXC)/sizeof(uint32_t)
};
enum
{
Read = 0,
Write = 1,
kNumErrors = 2
};
GPR gpr;
FPU fpu;
EXC exc;
int gpr_errs[2]; // Read/Write errors
int fpu_errs[2]; // Read/Write errors
int exc_errs[2]; // Read/Write errors
void
InvalidateAllRegisterStates()
{
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
}
int
GetError (int flavor, uint32_t err_idx) const
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
// When getting all errors, just OR all values together to see if
// we got any kind of error.
case GPRRegSet: return gpr_errs[err_idx];
case FPURegSet: return fpu_errs[err_idx];
case EXCRegSet: return exc_errs[err_idx];
default: break;
}
}
return -1;
}
bool
SetError (int flavor, uint32_t err_idx, int err)
{
if (err_idx < kNumErrors)
{
switch (flavor)
{
case GPRRegSet:
gpr_errs[err_idx] = err;
return true;
case FPURegSet:
fpu_errs[err_idx] = err;
return true;
case EXCRegSet:
exc_errs[err_idx] = err;
return true;
default: break;
}
}
return false;
}
bool
RegisterSetIsCached (int set) const
{
return GetError(set, Read) == 0;
}
void
LogGPR (lldb_private::Log *log, const char *format, ...);
int
ReadGPR (bool force);
int
ReadFPU (bool force);
int
ReadEXC (bool force);
int
WriteGPR ();
int
WriteFPU ();
int
WriteEXC ();
// Subclasses override these to do the actual reading.
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
{
return -1;
}
int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
return -1;
}
int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
return -1;
}
int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return -1;
}
int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return -1;
}
int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
return -1;
}
int
ReadRegisterSet (uint32_t set, bool force);
int
WriteRegisterSet (uint32_t set);
static uint32_t
GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
static int
GetSetForNativeRegNum (int reg_num);
static size_t
GetRegisterInfosCount ();
static const lldb_private::RegisterInfo *
GetRegisterInfos ();
};
#endif // liblldb_RegisterContextDarwin_x86_64_h_

View File

@ -31,5 +31,116 @@ enum
gcc_cpsr
};
enum
{
// Name Nr Rel Offset Size Type Raw value
gdb_arm_r0 = 0, // 0 0 4 int32_t
gdb_arm_r1 = 1, // 1 4 4 int32_t
gdb_arm_r2 = 2, // 2 8 4 int32_t
gdb_arm_r3 = 3, // 3 12 4 int32_t
gdb_arm_r4 = 4, // 4 16 4 int32_t
gdb_arm_r5 = 5, // 5 20 4 int32_t
gdb_arm_r6 = 6, // 6 24 4 int32_t
gdb_arm_r7 = 7, // 7 28 4 int32_t
gdb_arm_r8 = 8, // 8 32 4 int32_t
gdb_arm_r9 = 9, // 9 36 4 int32_t
gdb_arm_r10 = 10, // 10 40 4 int32_t
gdb_arm_r11 = 11, // 11 44 4 int32_t
gdb_arm_r12 = 12, // 12 48 4 int32_t
gdb_arm_sp = 13, // 13 52 4 int32_t
gdb_arm_lr = 14, // 14 56 4 int32_t
gdb_arm_pc = 15, // 15 60 4 int32_t
gdb_arm_f0 = 16, // 16 64 12 _arm_ext_littlebyte_bigword
gdb_arm_f1 = 17, // 17 76 12 _arm_ext_littlebyte_bigword
gdb_arm_f2 = 18, // 18 88 12 _arm_ext_littlebyte_bigword
gdb_arm_f3 = 19, // 19 100 12 _arm_ext_littlebyte_bigword
gdb_arm_f4 = 20, // 20 112 12 _arm_ext_littlebyte_bigword
gdb_arm_f5 = 21, // 21 124 12 _arm_ext_littlebyte_bigword
gdb_arm_f6 = 22, // 22 136 12 _arm_ext_littlebyte_bigword
gdb_arm_f7 = 23, // 23 148 12 _arm_ext_littlebyte_bigword
gdb_arm_f8 = 24, // 24 160 12 _arm_ext_littlebyte_bigword
gdb_arm_cpsr = 25, // 25 172 4 int32_t
gdb_arm_s0 = 26, // 26 176 4 _ieee_single_little
gdb_arm_s1 = 27, // 27 180 4 _ieee_single_little
gdb_arm_s2 = 28, // 28 184 4 _ieee_single_little
gdb_arm_s3 = 29, // 29 188 4 _ieee_single_little
gdb_arm_s4 = 30, // 30 192 4 _ieee_single_little
gdb_arm_s5 = 31, // 31 196 4 _ieee_single_little
gdb_arm_s6 = 32, // 32 200 4 _ieee_single_little
gdb_arm_s7 = 33, // 33 204 4 _ieee_single_little
gdb_arm_s8 = 34, // 34 208 4 _ieee_single_little
gdb_arm_s9 = 35, // 35 212 4 _ieee_single_little
gdb_arm_s10 = 36, // 36 216 4 _ieee_single_little
gdb_arm_s11 = 37, // 37 220 4 _ieee_single_little
gdb_arm_s12 = 38, // 38 224 4 _ieee_single_little
gdb_arm_s13 = 39, // 39 228 4 _ieee_single_little
gdb_arm_s14 = 40, // 40 232 4 _ieee_single_little
gdb_arm_s15 = 41, // 41 236 4 _ieee_single_little
gdb_arm_s16 = 42, // 42 240 4 _ieee_single_little
gdb_arm_s17 = 43, // 43 244 4 _ieee_single_little
gdb_arm_s18 = 44, // 44 248 4 _ieee_single_little
gdb_arm_s19 = 45, // 45 252 4 _ieee_single_little
gdb_arm_s20 = 46, // 46 256 4 _ieee_single_little
gdb_arm_s21 = 47, // 47 260 4 _ieee_single_little
gdb_arm_s22 = 48, // 48 264 4 _ieee_single_little
gdb_arm_s23 = 49, // 49 268 4 _ieee_single_little
gdb_arm_s24 = 50, // 50 272 4 _ieee_single_little
gdb_arm_s25 = 51, // 51 276 4 _ieee_single_little
gdb_arm_s26 = 52, // 52 280 4 _ieee_single_little
gdb_arm_s27 = 53, // 53 284 4 _ieee_single_little
gdb_arm_s28 = 54, // 54 288 4 _ieee_single_little
gdb_arm_s29 = 55, // 55 292 4 _ieee_single_little
gdb_arm_s30 = 56, // 56 296 4 _ieee_single_little
gdb_arm_s31 = 57, // 57 300 4 _ieee_single_little
gdb_arm_fpscr = 58, // 58 304 4 int32_t
gdb_arm_d16 = 59, // 59 308 8 _ieee_double_little
gdb_arm_d17 = 60, // 60 316 8 _ieee_double_little
gdb_arm_d18 = 61, // 61 324 8 _ieee_double_little
gdb_arm_d19 = 62, // 62 332 8 _ieee_double_little
gdb_arm_d20 = 63, // 63 340 8 _ieee_double_little
gdb_arm_d21 = 64, // 64 348 8 _ieee_double_little
gdb_arm_d22 = 65, // 65 356 8 _ieee_double_little
gdb_arm_d23 = 66, // 66 364 8 _ieee_double_little
gdb_arm_d24 = 67, // 67 372 8 _ieee_double_little
gdb_arm_d25 = 68, // 68 380 8 _ieee_double_little
gdb_arm_d26 = 69, // 69 388 8 _ieee_double_little
gdb_arm_d27 = 70, // 70 396 8 _ieee_double_little
gdb_arm_d28 = 71, // 71 404 8 _ieee_double_little
gdb_arm_d29 = 72, // 72 412 8 _ieee_double_little
gdb_arm_d30 = 73, // 73 420 8 _ieee_double_little
gdb_arm_d31 = 74, // 74 428 8 _ieee_double_little
gdb_arm_d0 = 75, // 0 436 8 _ieee_double_little
gdb_arm_d1 = 76, // 1 444 8 _ieee_double_little
gdb_arm_d2 = 77, // 2 452 8 _ieee_double_little
gdb_arm_d3 = 78, // 3 460 8 _ieee_double_little
gdb_arm_d4 = 79, // 4 468 8 _ieee_double_little
gdb_arm_d5 = 80, // 5 476 8 _ieee_double_little
gdb_arm_d6 = 81, // 6 484 8 _ieee_double_little
gdb_arm_d7 = 82, // 7 492 8 _ieee_double_little
gdb_arm_d8 = 83, // 8 500 8 _ieee_double_little
gdb_arm_d9 = 84, // 9 508 8 _ieee_double_little
gdb_arm_d10 = 85, // 10 516 8 _ieee_double_little
gdb_arm_d11 = 86, // 11 524 8 _ieee_double_little
gdb_arm_d12 = 87, // 12 532 8 _ieee_double_little
gdb_arm_d13 = 88, // 13 540 8 _ieee_double_little
gdb_arm_d14 = 89, // 14 548 8 _ieee_double_little
gdb_arm_d15 = 90, // 15 556 8 _ieee_double_little
gdb_arm_q0 = 91, // 16 564 16 _vec128
gdb_arm_q1 = 92, // 17 580 16 _vec128
gdb_arm_q2 = 93, // 18 596 16 _vec128
gdb_arm_q3 = 94, // 19 612 16 _vec128
gdb_arm_q4 = 95, // 20 628 16 _vec128
gdb_arm_q5 = 96, // 21 644 16 _vec128
gdb_arm_q6 = 97, // 22 660 16 _vec128
gdb_arm_q7 = 98, // 23 676 16 _vec128
gdb_arm_q8 = 99, // 24 692 16 _vec128
gdb_arm_q9 = 100, // 25 708 16 _vec128
gdb_arm_q10 = 101, // 26 724 16 _vec128
gdb_arm_q11 = 102, // 27 740 16 _vec128
gdb_arm_q12 = 103, // 28 756 16 _vec128
gdb_arm_q13 = 104, // 29 772 16 _vec128
gdb_arm_q14 = 105, // 30 788 16 _vec128
gdb_arm_q15 = 106 // 31 804 16 _vec128
};
#endif // utility_ARM_GCC_Registers_h_