diff options
32 files changed, 5810 insertions, 3944 deletions
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 354335e4d9f..e13ef5dc5c5 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -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; }; diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index 49ec7c96191..b063d1647d7 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -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... diff --git a/lldb/source/Host/macosx/Symbols.cpp b/lldb/source/Host/macosx/Symbols.cpp index c6d2f08db07..aadb93cf88e 100644 --- a/lldb/source/Host/macosx/Symbols.cpp +++ b/lldb/source/Host/macosx/Symbols.cpp @@ -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; + } + } + } + } } } } diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp index 609e6fc2c3a..d59600ce173 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp @@ -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(); diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h b/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h index c2066f56269..7ab49553222 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h @@ -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; } diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index e90b0efee90..083cb1f114b 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -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) { diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp index 225159347e2..02d662bc2bc 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp @@ -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); diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp index 2d9522bbe3a..f84eec36840 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp @@ -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; +} + diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h index 83c8790562b..8e9d8b2235e 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h @@ -140,6 +140,9 @@ public: lldb_private::ProcessLaunchInfo &launch_info); + //------------------------------------------------------------------ + // Public Request Packets + //------------------------------------------------------------------ bool SendRequestConnect (uint16_t reply_port, uint16_t exc_port, @@ -152,6 +155,24 @@ public: 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 (); uint32_t @@ -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 diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index 77d3d1ced2b..6d33ea28634 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -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; } diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h index c967e2f41ed..36497130818 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -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), diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp new file mode 100644 index 00000000000..fcc68658f2f --- /dev/null +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp @@ -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; +} + + diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h new file mode 100644 index 00000000000..1e547289d9c --- /dev/null +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h @@ -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_ diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp new file mode 100644 index 00000000000..7b7fc0f5fee --- /dev/null +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp @@ -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); +} + + diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h new file mode 100644 index 00000000000..641e49d8dc7 --- /dev/null +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h @@ -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_ diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp new file mode 100644 index 00000000000..dc5a47cb1a9 --- /dev/null +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp @@ -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; +} diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h new file mode 100644 index 00000000000..f1d41cb8302 --- /dev/null +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h @@ -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_ diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp new file mode 100644 index 00000000000..dac551762f3 --- /dev/null +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp @@ -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; +} + + diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h new file mode 100644 index 00000000000..95c2f0577e4 --- /dev/null +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h @@ -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_ diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.cpp index 4f3fe1a53b2..51991dad770 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.cpp +++ b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.cpp @@ -15,1206 +15,72 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/RegisterValue.h" -#include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" - // Project includes -#include "ARM_GCC_Registers.h" -#include "ARM_DWARF_Registers.h" -#include "ProcessMacOSXLog.h" +//#include "ProcessMacOSXLog.h" using namespace lldb; using namespace lldb_private; -enum -{ - gpr_r0 = 0, - gpr_r1, - gpr_r2, - gpr_r3, - gpr_r4, - gpr_r5, - gpr_r6, - gpr_r7, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, gpr_sp = gpr_r13, - gpr_r14, gpr_lr = gpr_r14, - gpr_r15, gpr_pc = gpr_r15, - gpr_cpsr, - - fpu_s0, - fpu_s1, - fpu_s2, - fpu_s3, - fpu_s4, - fpu_s5, - fpu_s6, - fpu_s7, - fpu_s8, - fpu_s9, - fpu_s10, - fpu_s11, - fpu_s12, - fpu_s13, - fpu_s14, - fpu_s15, - fpu_s16, - fpu_s17, - fpu_s18, - fpu_s19, - fpu_s20, - fpu_s21, - fpu_s22, - fpu_s23, - fpu_s24, - fpu_s25, - fpu_s26, - fpu_s27, - fpu_s28, - fpu_s29, - fpu_s30, - fpu_s31, - fpu_fpscr, - - exc_exception, - exc_fsr, - exc_far, - - dbg_bvr0, - dbg_bvr1, - dbg_bvr2, - dbg_bvr3, - dbg_bvr4, - dbg_bvr5, - dbg_bvr6, - dbg_bvr7, - dbg_bvr8, - dbg_bvr9, - dbg_bvr10, - dbg_bvr11, - dbg_bvr12, - dbg_bvr13, - dbg_bvr14, - dbg_bvr15, - - dbg_bcr0, - dbg_bcr1, - dbg_bcr2, - dbg_bcr3, - dbg_bcr4, - dbg_bcr5, - dbg_bcr6, - dbg_bcr7, - dbg_bcr8, - dbg_bcr9, - dbg_bcr10, - dbg_bcr11, - dbg_bcr12, - dbg_bcr13, - dbg_bcr14, - dbg_bcr15, - - dbg_wvr0, - dbg_wvr1, - dbg_wvr2, - dbg_wvr3, - dbg_wvr4, - dbg_wvr5, - dbg_wvr6, - dbg_wvr7, - dbg_wvr8, - dbg_wvr9, - dbg_wvr10, - dbg_wvr11, - dbg_wvr12, - dbg_wvr13, - dbg_wvr14, - dbg_wvr15, - - dbg_wcr0, - dbg_wcr1, - dbg_wcr2, - dbg_wcr3, - dbg_wcr4, - dbg_wcr5, - dbg_wcr6, - dbg_wcr7, - dbg_wcr8, - dbg_wcr9, - dbg_wcr10, - dbg_wcr11, - dbg_wcr12, - dbg_wcr13, - dbg_wcr14, - dbg_wcr15, - - k_num_registers -}; - RegisterContextMach_arm::RegisterContextMach_arm(Thread &thread, uint32_t concrete_frame_idx) : - RegisterContext(thread, concrete_frame_idx), - gpr(), - fpu(), - exc() + RegisterContextDarwin_arm (thread, concrete_frame_idx) { - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - fpu_errs[i] = -1; - exc_errs[i] = -1; - } } RegisterContextMach_arm::~RegisterContextMach_arm() { } - -#define GPR_OFFSET(idx) ((idx) * 4) -#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextMach_arm::GPR)) -#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextMach_arm::GPR) + sizeof (RegisterContextMach_arm::FPU)) -#define DBG_OFFSET(reg) (offsetof (RegisterContextMach_arm::DBG, reg) + sizeof (RegisterContextMach_arm::GPR) + sizeof (RegisterContextMach_arm::FPU) + sizeof (RegisterContextMach_arm::EXC)) - -#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextMach_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i } -#define REG_CONTEXT_SIZE (sizeof (RegisterContextMach_arm::GPR) + sizeof (RegisterContextMach_arm::FPU) + sizeof (RegisterContextMach_arm::EXC)) -// General purpose registers -static RegisterInfo -g_register_infos[] = -{ -// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC LLDB NATIVE -// ====== ======= == ============= ============= ============ =============== =============== ========= ========== -{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_INVALID_REGNUM, gpr_r0 }}, -{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_INVALID_REGNUM, gpr_r1 }}, -{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_INVALID_REGNUM, gpr_r2 }}, -{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_INVALID_REGNUM, gpr_r3 }}, -{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gpr_r4 }}, -{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gpr_r5 }}, -{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gpr_r6 }}, -{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gpr_r7 }}, -{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gpr_r8 }}, -{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gpr_r9 }}, -{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gpr_r10 }}, -{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gpr_r11 }}, -{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gpr_r12 }}, -{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gpr_sp }}, -{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gpr_lr }}, -{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gpr_pc }}, -{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gpr_cpsr }}, - -{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, fpu_s0 }}, -{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, fpu_s1 }}, -{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, fpu_s2 }}, -{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, fpu_s3 }}, -{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, fpu_s4 }}, -{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, fpu_s5 }}, -{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, fpu_s6 }}, -{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, fpu_s7 }}, -{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, fpu_s8 }}, -{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, fpu_s9 }}, -{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, fpu_s10 }}, -{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, fpu_s11 }}, -{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, fpu_s12 }}, -{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, fpu_s13 }}, -{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, fpu_s14 }}, -{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, fpu_s15 }}, -{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, fpu_s16 }}, -{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, fpu_s17 }}, -{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, fpu_s18 }}, -{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, fpu_s19 }}, -{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, fpu_s20 }}, -{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, fpu_s21 }}, -{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, fpu_s22 }}, -{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, fpu_s23 }}, -{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, fpu_s24 }}, -{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, fpu_s25 }}, -{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, fpu_s26 }}, -{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, fpu_s27 }}, -{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, fpu_s28 }}, -{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, fpu_s29 }}, -{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, fpu_s30 }}, -{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, fpu_s31 }}, -{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpscr }}, - -{ "exception",NULL, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }}, -{ "fsr", NULL, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }}, -{ "far", NULL, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }}, - -{ DEFINE_DBG (bvr, 0) }, -{ DEFINE_DBG (bvr, 0) }, -{ DEFINE_DBG (bvr, 1) }, -{ DEFINE_DBG (bvr, 2) }, -{ DEFINE_DBG (bvr, 3) }, -{ DEFINE_DBG (bvr, 4) }, -{ DEFINE_DBG (bvr, 5) }, -{ DEFINE_DBG (bvr, 6) }, -{ DEFINE_DBG (bvr, 7) }, -{ DEFINE_DBG (bvr, 8) }, -{ DEFINE_DBG (bvr, 9) }, -{ DEFINE_DBG (bvr, 10) }, -{ DEFINE_DBG (bvr, 11) }, -{ DEFINE_DBG (bvr, 12) }, -{ DEFINE_DBG (bvr, 13) }, -{ DEFINE_DBG (bvr, 14) }, -{ DEFINE_DBG (bvr, 15) }, - -{ DEFINE_DBG (bcr, 0) }, -{ DEFINE_DBG (bcr, 0) }, -{ DEFINE_DBG (bcr, 1) }, -{ DEFINE_DBG (bcr, 2) }, -{ DEFINE_DBG (bcr, 3) }, -{ DEFINE_DBG (bcr, 4) }, -{ DEFINE_DBG (bcr, 5) }, -{ DEFINE_DBG (bcr, 6) }, -{ DEFINE_DBG (bcr, 7) }, -{ DEFINE_DBG (bcr, 8) }, -{ DEFINE_DBG (bcr, 9) }, -{ DEFINE_DBG (bcr, 10) }, -{ DEFINE_DBG (bcr, 11) }, -{ DEFINE_DBG (bcr, 12) }, -{ DEFINE_DBG (bcr, 13) }, -{ DEFINE_DBG (bcr, 14) }, -{ DEFINE_DBG (bcr, 15) }, - -{ DEFINE_DBG (wvr, 0) }, -{ DEFINE_DBG (wvr, 0) }, -{ DEFINE_DBG (wvr, 1) }, -{ DEFINE_DBG (wvr, 2) }, -{ DEFINE_DBG (wvr, 3) }, -{ DEFINE_DBG (wvr, 4) }, -{ DEFINE_DBG (wvr, 5) }, -{ DEFINE_DBG (wvr, 6) }, -{ DEFINE_DBG (wvr, 7) }, -{ DEFINE_DBG (wvr, 8) }, -{ DEFINE_DBG (wvr, 9) }, -{ DEFINE_DBG (wvr, 10) }, -{ DEFINE_DBG (wvr, 11) }, -{ DEFINE_DBG (wvr, 12) }, -{ DEFINE_DBG (wvr, 13) }, -{ DEFINE_DBG (wvr, 14) }, -{ DEFINE_DBG (wvr, 15) }, - -{ DEFINE_DBG (wcr, 0) }, -{ DEFINE_DBG (wcr, 0) }, -{ DEFINE_DBG (wcr, 1) }, -{ DEFINE_DBG (wcr, 2) }, -{ DEFINE_DBG (wcr, 3) }, -{ DEFINE_DBG (wcr, 4) }, -{ DEFINE_DBG (wcr, 5) }, -{ DEFINE_DBG (wcr, 6) }, -{ DEFINE_DBG (wcr, 7) }, -{ DEFINE_DBG (wcr, 8) }, -{ DEFINE_DBG (wcr, 9) }, -{ DEFINE_DBG (wcr, 10) }, -{ DEFINE_DBG (wcr, 11) }, -{ DEFINE_DBG (wcr, 12) }, -{ DEFINE_DBG (wcr, 13) }, -{ DEFINE_DBG (wcr, 14) }, -{ DEFINE_DBG (wcr, 15) } -}; - -// General purpose registers -static uint32_t -g_gpr_regnums[] = -{ - gpr_r0, - gpr_r1, - gpr_r2, - gpr_r3, - gpr_r4, - gpr_r5, - gpr_r6, - gpr_r7, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_sp, - gpr_lr, - gpr_pc, - gpr_cpsr -}; - -// Floating point registers -static uint32_t -g_fpu_regnums[] = -{ - fpu_s0, - fpu_s1, - fpu_s2, - fpu_s3, - fpu_s4, - fpu_s5, - fpu_s6, - fpu_s7, - fpu_s8, - fpu_s9, - fpu_s10, - fpu_s11, - fpu_s12, - fpu_s13, - fpu_s14, - fpu_s15, - fpu_s16, - fpu_s17, - fpu_s18, - fpu_s19, - fpu_s20, - fpu_s21, - fpu_s22, - fpu_s23, - fpu_s24, - fpu_s25, - fpu_s26, - fpu_s27, - fpu_s28, - fpu_s29, - fpu_s30, - fpu_s31, - fpu_fpscr, -}; - -// Exception registers - -static uint32_t -g_exc_regnums[] = -{ - exc_exception, - exc_fsr, - exc_far, -}; - -static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); - -void -RegisterContextMach_arm::InvalidateAllRegisters () -{ - InvalidateAllRegisterStates(); -} - - -size_t -RegisterContextMach_arm::GetRegisterCount () -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; -} - -const RegisterInfo * -RegisterContextMach_arm::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 -RegisterContextMach_arm::GetRegisterInfosCount () -{ - return k_num_register_infos; -} - -const RegisterInfo * -RegisterContextMach_arm::GetRegisterInfos () -{ - return g_register_infos; -} - - -// 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 -RegisterContextMach_arm::GetRegisterSetCount () -{ - return k_num_regsets; -} - -const RegisterSet * -RegisterContextMach_arm::GetRegisterSet (uint32_t reg_set) -{ - if (reg_set < k_num_regsets) - return &g_reg_sets[reg_set]; - return NULL; -} - - -//---------------------------------------------------------------------- -// Register information defintions for 32 bit i386. -//---------------------------------------------------------------------- -int -RegisterContextMach_arm::GetSetForNativeRegNum (int reg) -{ - if (reg < fpu_s0) - return GPRRegSet; - else if (reg < exc_exception) - return FPURegSet; - else if (reg < k_num_registers) - return EXCRegSet; - return -1; -} - int -RegisterContextMach_arm::ReadGPR (bool force) +RegisterContextMach_arm::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) { - int set = GPRRegSet; - if (force || !RegisterSetIsCached(set)) - { - mach_msg_type_number_t count = GPRWordCount; - SetError(GPRRegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&gpr, &count)); - } - return GetError(GPRRegSet, Read); + mach_msg_type_number_t count = GPRWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count); } int -RegisterContextMach_arm::ReadFPU (bool force) +RegisterContextMach_arm::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) { - int set = FPURegSet; - if (force || !RegisterSetIsCached(set)) - { - mach_msg_type_number_t count = FPUWordCount; - SetError(FPURegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&fpu, &count)); - } - return GetError(FPURegSet, Read); + mach_msg_type_number_t count = FPUWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count); } int -RegisterContextMach_arm::ReadEXC (bool force) +RegisterContextMach_arm::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) { - int set = EXCRegSet; - if (force || !RegisterSetIsCached(set)) - { - mach_msg_type_number_t count = EXCWordCount; - SetError(EXCRegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&exc, &count)); - } - return GetError(EXCRegSet, Read); + mach_msg_type_number_t count = EXCWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count); } int -RegisterContextMach_arm::ReadDBG (bool force) +RegisterContextMach_arm::DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg) { - int set = DBGRegSet; - if (force || !RegisterSetIsCached(set)) - { - mach_msg_type_number_t count = DBGWordCount; - SetError(DBGRegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&dbg, &count)); - } - return GetError(DBGRegSet, Read); + mach_msg_type_number_t count = DBGWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&dbg, &count); } int -RegisterContextMach_arm::WriteGPR () +RegisterContextMach_arm::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) { - int set = GPRRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError(GPRRegSet, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&gpr, GPRWordCount)); - return GetError(GPRRegSet, Write); + return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); } int -RegisterContextMach_arm::WriteFPU () +RegisterContextMach_arm::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) { - int set = FPURegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError(FPURegSet, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&fpu, FPUWordCount)); - return GetError(FPURegSet, Write); + return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); } int -RegisterContextMach_arm::WriteEXC () +RegisterContextMach_arm::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) { - int set = EXCRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError(EXCRegSet, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&exc, EXCWordCount)); - return GetError(EXCRegSet, Write); + return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); } int -RegisterContextMach_arm::WriteDBG () -{ - int set = DBGRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError(DBGRegSet, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&dbg, DBGWordCount)); - return GetError(DBGRegSet, Write); -} - - -int -RegisterContextMach_arm::ReadRegisterSet (uint32_t set, bool force) -{ - switch (set) - { - case GPRRegSet: return ReadGPR(force); - case FPURegSet: return ReadFPU(force); - case EXCRegSet: return ReadEXC(force); - case DBGRegSet: return ReadDBG(force); - default: break; - } - return KERN_INVALID_ARGUMENT; -} - -int -RegisterContextMach_arm::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(); - case DBGRegSet: return WriteDBG(); - default: break; - } - } - return KERN_INVALID_ARGUMENT; -} - -void -RegisterContextMach_arm::LogDBGRegisters (Log *log, const DBG& dbg) -{ - if (log) - { - for (uint32_t i=0; i<16; i++) - log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }", - i, i, dbg.bvr[i], dbg.bcr[i], - i, i, dbg.wvr[i], dbg.wcr[i]); - } -} - - -bool -RegisterContextMach_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = RegisterContextMach_arm::GetSetForNativeRegNum (reg); - - if (set == -1) - return false; - - if (ReadRegisterSet(set, false) != KERN_SUCCESS) - return false; - - switch (reg) - { - case gpr_r0: - case gpr_r1: - case gpr_r2: - case gpr_r3: - case gpr_r4: - case gpr_r5: - case gpr_r6: - case gpr_r7: - case gpr_r8: - case gpr_r9: - case gpr_r10: - case gpr_r11: - case gpr_r12: - case gpr_sp: - case gpr_lr: - case gpr_pc: - case gpr_cpsr: - value.SetUInt32 (gpr.r[reg - gpr_r0]); - break; - - case fpu_s0: - case fpu_s1: - case fpu_s2: - case fpu_s3: - case fpu_s4: - case fpu_s5: - case fpu_s6: - case fpu_s7: - case fpu_s8: - case fpu_s9: - case fpu_s10: - case fpu_s11: - case fpu_s12: - case fpu_s13: - case fpu_s14: - case fpu_s15: - case fpu_s16: - case fpu_s17: - case fpu_s18: - case fpu_s19: - case fpu_s20: - case fpu_s21: - case fpu_s22: - case fpu_s23: - case fpu_s24: - case fpu_s25: - case fpu_s26: - case fpu_s27: - case fpu_s28: - case fpu_s29: - case fpu_s30: - case fpu_s31: - value.SetUInt32 (fpu.floats.s[reg], RegisterValue::eTypeFloat); - break; - - case fpu_fpscr: - value.SetUInt32 (fpu.fpscr); - break; - - case exc_exception: - value.SetUInt32 (exc.exception); - break; - case exc_fsr: - value.SetUInt32 (exc.fsr); - break; - case exc_far: - value.SetUInt32 (exc.far); - break; - - default: - value.SetValueToInvalid(); - return false; - - } - return true; -} - - -bool -RegisterContextMach_arm::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) != KERN_SUCCESS) - return false; - - switch (reg) - { - case gpr_r0: - case gpr_r1: - case gpr_r2: - case gpr_r3: - case gpr_r4: - case gpr_r5: - case gpr_r6: - case gpr_r7: - case gpr_r8: - case gpr_r9: - case gpr_r10: - case gpr_r11: - case gpr_r12: - case gpr_sp: - case gpr_lr: - case gpr_pc: - case gpr_cpsr: - gpr.r[reg - gpr_r0] = value.GetAsUInt32(); - break; - - case fpu_s0: - case fpu_s1: - case fpu_s2: - case fpu_s3: - case fpu_s4: - case fpu_s5: - case fpu_s6: - case fpu_s7: - case fpu_s8: - case fpu_s9: - case fpu_s10: - case fpu_s11: - case fpu_s12: - case fpu_s13: - case fpu_s14: - case fpu_s15: - case fpu_s16: - case fpu_s17: - case fpu_s18: - case fpu_s19: - case fpu_s20: - case fpu_s21: - case fpu_s22: - case fpu_s23: - case fpu_s24: - case fpu_s25: - case fpu_s26: - case fpu_s27: - case fpu_s28: - case fpu_s29: - case fpu_s30: - case fpu_s31: - fpu.floats.s[reg] = value.GetAsUInt32(); - break; - - case fpu_fpscr: - fpu.fpscr = value.GetAsUInt32(); - break; - - case exc_exception: - exc.exception = value.GetAsUInt32(); - break; - case exc_fsr: - exc.fsr = value.GetAsUInt32(); - break; - case exc_far: - exc.far = value.GetAsUInt32(); - break; - - default: - return false; - - } - return WriteRegisterSet(set) == KERN_SUCCESS; -} - -bool -RegisterContextMach_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && - ReadGPR (false) == KERN_SUCCESS && - ReadFPU (false) == KERN_SUCCESS && - ReadEXC (false) == KERN_SUCCESS) - { - 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 -RegisterContextMach_arm::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() == KERN_SUCCESS) - ++success_count; - if (WriteFPU() == KERN_SUCCESS) - ++success_count; - if (WriteEXC() == KERN_SUCCESS) - ++success_count; - return success_count == 3; - } - return false; -} - -uint32_t -RegisterContextMach_arm::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg) -{ - if (kind == eRegisterKindGeneric) - { - switch (reg) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_pc; - case LLDB_REGNUM_GENERIC_SP: return gpr_sp; - case LLDB_REGNUM_GENERIC_FP: return gpr_r7; - case LLDB_REGNUM_GENERIC_RA: return gpr_lr; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr; - default: - break; - } - } - else if (kind == eRegisterKindDWARF) - { - switch (reg) - { - case dwarf_r0: return gpr_r0; - case dwarf_r1: return gpr_r1; - case dwarf_r2: return gpr_r2; - case dwarf_r3: return gpr_r3; - case dwarf_r4: return gpr_r4; - case dwarf_r5: return gpr_r5; - case dwarf_r6: return gpr_r6; - case dwarf_r7: return gpr_r7; - case dwarf_r8: return gpr_r8; - case dwarf_r9: return gpr_r9; - case dwarf_r10: return gpr_r10; - case dwarf_r11: return gpr_r11; - case dwarf_r12: return gpr_r12; - case dwarf_sp: return gpr_sp; - case dwarf_lr: return gpr_lr; - case dwarf_pc: return gpr_pc; - case dwarf_spsr: return gpr_cpsr; - - case dwarf_s0: return fpu_s0; - case dwarf_s1: return fpu_s1; - case dwarf_s2: return fpu_s2; - case dwarf_s3: return fpu_s3; - case dwarf_s4: return fpu_s4; - case dwarf_s5: return fpu_s5; - case dwarf_s6: return fpu_s6; - case dwarf_s7: return fpu_s7; - case dwarf_s8: return fpu_s8; - case dwarf_s9: return fpu_s9; - case dwarf_s10: return fpu_s10; - case dwarf_s11: return fpu_s11; - case dwarf_s12: return fpu_s12; - case dwarf_s13: return fpu_s13; - case dwarf_s14: return fpu_s14; - case dwarf_s15: return fpu_s15; - case dwarf_s16: return fpu_s16; - case dwarf_s17: return fpu_s17; - case dwarf_s18: return fpu_s18; - case dwarf_s19: return fpu_s19; - case dwarf_s20: return fpu_s20; - case dwarf_s21: return fpu_s21; - case dwarf_s22: return fpu_s22; - case dwarf_s23: return fpu_s23; - case dwarf_s24: return fpu_s24; - case dwarf_s25: return fpu_s25; - case dwarf_s26: return fpu_s26; - case dwarf_s27: return fpu_s27; - case dwarf_s28: return fpu_s28; - case dwarf_s29: return fpu_s29; - case dwarf_s30: return fpu_s30; - case dwarf_s31: return fpu_s31; - - default: - break; - } - } - else if (kind == eRegisterKindGCC) - { - switch (reg) - { - case gcc_r0: return gpr_r0; - case gcc_r1: return gpr_r1; - case gcc_r2: return gpr_r2; - case gcc_r3: return gpr_r3; - case gcc_r4: return gpr_r4; - case gcc_r5: return gpr_r5; - case gcc_r6: return gpr_r6; - case gcc_r7: return gpr_r7; - case gcc_r8: return gpr_r8; - case gcc_r9: return gpr_r9; - case gcc_r10: return gpr_r10; - case gcc_r11: return gpr_r11; - case gcc_r12: return gpr_r12; - case gcc_sp: return gpr_sp; - case gcc_lr: return gpr_lr; - case gcc_pc: return gpr_pc; - case gcc_cpsr: return gpr_cpsr; - } - } - else if (kind == eRegisterKindLLDB) - { - return reg; - } - return LLDB_INVALID_REGNUM; -} - - -uint32_t -RegisterContextMach_arm::NumSupportedHardwareBreakpoints () -{ -#if defined (__arm__) - // Set the init value to something that will let us know that we need to - // autodetect how many breakpoints are supported dynamically... - static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX; - if (g_num_supported_hw_breakpoints == UINT32_MAX) - { - // Set this to zero in case we can't tell if there are any HW breakpoints - g_num_supported_hw_breakpoints = 0; - - uint32_t register_DBGDIDR; - - asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); - g_num_supported_hw_breakpoints = bits(register_DBGDIDR, 27, 24); - // Zero is reserved for the BRP count, so don't increment it if it is zero - if (g_num_supported_hw_breakpoints > 0) - g_num_supported_hw_breakpoints++; - ProcessMacOSXLog::LogIf(PD_LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_breakpoints); - - } - return g_num_supported_hw_breakpoints; -#else - // TODO: figure out remote case here! - return 6; -#endif -} - -uint32_t -RegisterContextMach_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) +RegisterContextMach_arm::DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg) { - // Make sure our address isn't bogus - if (addr & 1) - return LLDB_INVALID_INDEX32; - - int kret = ReadDBG (false); - - if (kret == KERN_SUCCESS) - { - const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); - uint32_t i; - for (i=0; i<num_hw_breakpoints; ++i) - { - if ((dbg.bcr[i] & BCR_ENABLE) == 0) - break; // We found an available hw breakpoint slot (in i) - } - - // See if we found an available hw breakpoint slot above - if (i < num_hw_breakpoints) - { - // Make sure bits 1:0 are clear in our address - dbg.bvr[i] = addr & ~((lldb::addr_t)3); - - if (size == 2 || addr & 2) - { - uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; - - // We have a thumb breakpoint - // We have an ARM breakpoint - dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch - byte_addr_select | // Set the correct byte address select so we only trigger on the correct opcode - S_USER | // Which modes should this breakpoint stop in? - BCR_ENABLE; // Enable this hardware breakpoint - ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextMach_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)", - addr, - size, - i, - i, - dbg.bvr[i], - dbg.bcr[i]); - } - else if (size == 4) - { - // We have an ARM breakpoint - dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch - BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA - S_USER | // Which modes should this breakpoint stop in? - BCR_ENABLE; // Enable this hardware breakpoint - ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextMach_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)", - addr, - size, - i, - i, - dbg.bvr[i], - dbg.bcr[i]); - } - - kret = WriteDBG(); - ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextMach_arm::EnableHardwareBreakpoint() WriteDBG() => 0x%8.8x.", kret); - - if (kret == KERN_SUCCESS) - return i; - } - else - { - ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextMach_arm::EnableHardwareBreakpoint(addr = %8.8p, size = %u) => all hardware breakpoint resources are being used.", addr, size); - } - } - - return LLDB_INVALID_INDEX32; -} - -bool -RegisterContextMach_arm::ClearHardwareBreakpoint (uint32_t hw_index) -{ - int kret = ReadDBG (false); - - const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); - if (kret == KERN_SUCCESS) - { - if (hw_index < num_hw_points) - { - dbg.bcr[hw_index] = 0; - ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextMach_arm::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x BCR%u = 0x%8.8x", - hw_index, - hw_index, - dbg.bvr[hw_index], - hw_index, - dbg.bcr[hw_index]); - - kret = WriteDBG(); - - if (kret == KERN_SUCCESS) - return true; - } - } - return false; -} - -uint32_t -RegisterContextMach_arm::NumSupportedHardwareWatchpoints () -{ -#if defined (__arm__) - // Set the init value to something that will let us know that we need to - // autodetect how many watchpoints are supported dynamically... - static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX; - if (g_num_supported_hw_watchpoints == UINT32_MAX) - { - // Set this to zero in case we can't tell if there are any HW breakpoints - g_num_supported_hw_watchpoints = 0; - - uint32_t register_DBGDIDR; - asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); - g_num_supported_hw_watchpoints = bits(register_DBGDIDR, 31, 28) + 1; - ProcessMacOSXLog::LogIf(PD_LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_watchpoints); - } - return g_num_supported_hw_watchpoints; -#else - // TODO: figure out remote case here! - return 2; -#endif -} - - -uint32_t -RegisterContextMach_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write) -{ - ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write); - - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - - // Can't watch zero bytes - if (size == 0) - return LLDB_INVALID_INDEX32; - - // We must watch for either read or write - if (read == false && write == false) - return LLDB_INVALID_INDEX32; - - // Can't watch more than 4 bytes per WVR/WCR pair - if (size > 4) - return LLDB_INVALID_INDEX32; - - // We can only watch up to four bytes that follow a 4 byte aligned address - // per watchpoint register pair. Since we have at most so we can only watch - // until the next 4 byte boundary and we need to make sure we can properly - // encode this. - uint32_t addr_word_offset = addr % 4; - ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset); - - uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset; - ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask); - if (byte_mask > 0xfu) - return LLDB_INVALID_INDEX32; - - // Read the debug state - int kret = ReadDBG (false); - - if (kret == KERN_SUCCESS) - { - // Check to make sure we have the needed hardware support - uint32_t i = 0; - - for (i=0; i<num_hw_watchpoints; ++i) - { - if ((dbg.wcr[i] & WCR_ENABLE) == 0) - break; // We found an available hw breakpoint slot (in i) - } - - // See if we found an available hw breakpoint slot above - if (i < num_hw_watchpoints) - { - // Make the byte_mask into a valid Byte Address Select mask - uint32_t byte_address_select = byte_mask << 5; - // Make sure bits 1:0 are clear in our address - dbg.wvr[i] = addr & ~((lldb::addr_t)3); - dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA that we will watch - S_USER | // Stop only in user mode - (read ? WCR_LOAD : 0) | // Stop on read access? - (write ? WCR_STORE : 0) | // Stop on write access? - WCR_ENABLE; // Enable this watchpoint; - - kret = WriteDBG(); - ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret); - - if (kret == KERN_SUCCESS) - return i; - } - else - { - ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); - } - } - return LLDB_INVALID_INDEX32; -} - -bool -RegisterContextMach_arm::ClearHardwareWatchpoint (uint32_t hw_index) -{ - int kret = ReadDBG (false); - - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (kret == KERN_SUCCESS) - { - if (hw_index < num_hw_points) - { - dbg.wcr[hw_index] = 0; - ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextMach_arm::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x", - hw_index, - hw_index, - dbg.wvr[hw_index], - hw_index, - dbg.wcr[hw_index]); - - kret = WriteDBG(); - - if (kret == KERN_SUCCESS) - return true; - } - } - return false; + return ::thread_set_state(tid, flavor, (thread_state_t)&dbg, DBGWordCount); } diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.h b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.h index 23fd08e656c..bf2f06ce9d8 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.h +++ b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_arm.h @@ -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 ®_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 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); - + virtual int + DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr); + int - ReadDBG (bool force); - + DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu); + int - WriteGPR (); - + DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc); + int - WriteFPU (); - + DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg); + int - WriteEXC (); - + DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr); + int - WriteDBG (); - + DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu); + int - ReadRegisterSet (uint32_t set, bool force); - + DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc); + 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_ diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.cpp index be1a10f5df2..62b50956678 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.cpp +++ b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.cpp @@ -13,965 +13,59 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/RegisterValue.h" -#include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" - // Project includes #include "RegisterContextMach_i386.h" -#include "ProcessMacOSXLog.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 -}; -RegisterContextMach_i386::RegisterContextMach_i386 (Thread &thread, uint32_t concrete_frame_idx) : - RegisterContext(thread, concrete_frame_idx), - gpr(), - fpu(), - exc() +RegisterContextMach_i386::RegisterContextMach_i386(Thread &thread, uint32_t concrete_frame_idx) : + RegisterContextDarwin_i386 (thread, concrete_frame_idx) { - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - fpu_errs[i] = -1; - exc_errs[i] = -1; - } } RegisterContextMach_i386::~RegisterContextMach_i386() { } - - -#define GPR_OFFSET(reg) (offsetof (RegisterContextMach_i386::GPR, reg)) -#define FPU_OFFSET(reg) (offsetof (RegisterContextMach_i386::FPU, reg) + sizeof (RegisterContextMach_i386::GPR)) -#define EXC_OFFSET(reg) (offsetof (RegisterContextMach_i386::EXC, reg) + sizeof (RegisterContextMach_i386::GPR) + sizeof (RegisterContextMach_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(((RegisterContextMach_i386::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex -#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextMach_i386::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex -#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextMach_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(((RegisterContextMach_i386::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex -#define REG_CONTEXT_SIZE (sizeof (RegisterContextMach_i386::GPR) + sizeof (RegisterContextMach_i386::FPU) + sizeof (RegisterContextMach_i386::EXC)) - -static RegisterInfo g_register_infos[] = -{ -// Macro auto defines most stuff GCC REG KIND NUM DWARF REG KIND NUM GENERIC REG KIND NUM GDB REG KIND NUM LLDB REG KIND NUM -// =============================== ======================= =================== ========================== ========================== ================= - { 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 -RegisterContextMach_i386::InvalidateAllRegisters () -{ - InvalidateAllRegisterStates(); -} - - -size_t -RegisterContextMach_i386::GetRegisterCount () -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; -} - -const RegisterInfo * -RegisterContextMach_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 -RegisterContextMach_i386::GetRegisterInfosCount () -{ - return k_num_register_infos; -} - -const RegisterInfo * -RegisterContextMach_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 -RegisterContextMach_i386::GetRegisterSetCount () -{ - return k_num_regsets; -} - -const RegisterSet * -RegisterContextMach_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 -RegisterContextMach_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 -RegisterContextMach_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]); - } - } -} - - - -kern_return_t -RegisterContextMach_i386::ReadGPR (bool force) -{ - int set = GPRRegSet; - if (force || !RegisterSetIsCached(set)) - { - mach_msg_type_number_t count = GPRWordCount; - SetError(set, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&gpr, &count)); - LogGPR (ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_THREAD).get(), "RegisterContextMach_i386::ReadGPR()"); - } - return GetError(set, Read); -} - -kern_return_t -RegisterContextMach_i386::ReadFPU (bool force) -{ - int set = FPURegSet; - if (force || !RegisterSetIsCached(set)) - { - mach_msg_type_number_t count = FPUWordCount; - SetError(set, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&fpu, &count)); - } - return GetError(set, Read); -} - -kern_return_t -RegisterContextMach_i386::ReadEXC (bool force) -{ - int set = EXCRegSet; - if (force || !RegisterSetIsCached(set)) - { - mach_msg_type_number_t count = EXCWordCount; - SetError(set, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&exc, &count)); - } - return GetError(set, Read); -} - -kern_return_t -RegisterContextMach_i386::WriteGPR () -{ - int set = GPRRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&gpr, GPRWordCount)); - SetError (set, Read, -1); - return GetError(set, Write); -} - -kern_return_t -RegisterContextMach_i386::WriteFPU () -{ - int set = FPURegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&fpu, FPUWordCount)); - SetError (set, Read, -1); - return GetError(set, Write); -} - -kern_return_t -RegisterContextMach_i386::WriteEXC () -{ - int set = EXCRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&exc, EXCWordCount)); - SetError (set, Read, -1); - return GetError(set, Write); -} - -kern_return_t -RegisterContextMach_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 KERN_INVALID_ARGUMENT; -} - -kern_return_t -RegisterContextMach_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 KERN_INVALID_ARGUMENT; -} - -bool -RegisterContextMach_i386::ReadRegister (const RegisterInfo *reg_info, - RegisterValue &value) +RegisterContextMach_i386::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) { - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = RegisterContextMach_i386::GetSetForNativeRegNum (reg); - - if (set == -1) - return false; - - if (ReadRegisterSet(set, false) != KERN_SUCCESS) - 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; + mach_msg_type_number_t count = GPRWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count); } - -bool -RegisterContextMach_i386::WriteRegister (const RegisterInfo *reg_info, - const RegisterValue &value) +int +RegisterContextMach_i386::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) { - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = GetSetForNativeRegNum (reg); - - if (set == -1) - return false; - - if (ReadRegisterSet(set, false) != KERN_SUCCESS) - 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) == KERN_SUCCESS; + mach_msg_type_number_t count = FPUWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count); } -bool -RegisterContextMach_i386::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) +int +RegisterContextMach_i386::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) { - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && - ReadGPR (false) == KERN_SUCCESS && - ReadFPU (false) == KERN_SUCCESS && - ReadEXC (false) == KERN_SUCCESS) - { - 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; + mach_msg_type_number_t count = EXCWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count); } -bool -RegisterContextMach_i386::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) +int +RegisterContextMach_i386::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) { - 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() == KERN_SUCCESS) - ++success_count; - if (WriteFPU() == KERN_SUCCESS) - ++success_count; - if (WriteEXC() == KERN_SUCCESS) - ++success_count; - return success_count == 3; - } - return false; + return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); } - -uint32_t -RegisterContextMach_i386::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg) +int +RegisterContextMach_i386::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) { - 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; + return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); } - -bool -RegisterContextMach_i386::HardwareSingleStep (bool enable) +int +RegisterContextMach_i386::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) { - if (ReadGPR(false) != KERN_SUCCESS) - 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() == KERN_SUCCESS; + return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); } - diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.h b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.h index c066107d78c..59d0b0b2920 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.h +++ b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_i386.h @@ -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_ diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.cpp index 7cdcbbb3975..8dab2e54206 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.cpp +++ b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.cpp @@ -13,1055 +13,58 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/RegisterValue.h" -#include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" - // Project includes #include "RegisterContextMach_x86_64.h" -#include "ProcessMacOSXLog.h" using namespace lldb; using namespace lldb_private; -enum -{ - gpr_rax = 0, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - 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, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15, - - 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_dwarf_regnums -{ - gcc_dwarf_gpr_rax = 0, - gcc_dwarf_gpr_rdx, - gcc_dwarf_gpr_rcx, - gcc_dwarf_gpr_rbx, - gcc_dwarf_gpr_rsi, - gcc_dwarf_gpr_rdi, - gcc_dwarf_gpr_rbp, - gcc_dwarf_gpr_rsp, - gcc_dwarf_gpr_r8, - gcc_dwarf_gpr_r9, - gcc_dwarf_gpr_r10, - gcc_dwarf_gpr_r11, - gcc_dwarf_gpr_r12, - gcc_dwarf_gpr_r13, - gcc_dwarf_gpr_r14, - gcc_dwarf_gpr_r15, - gcc_dwarf_gpr_rip, - gcc_dwarf_fpu_xmm0, - gcc_dwarf_fpu_xmm1, - gcc_dwarf_fpu_xmm2, - gcc_dwarf_fpu_xmm3, - gcc_dwarf_fpu_xmm4, - gcc_dwarf_fpu_xmm5, - gcc_dwarf_fpu_xmm6, - gcc_dwarf_fpu_xmm7, - gcc_dwarf_fpu_xmm8, - gcc_dwarf_fpu_xmm9, - gcc_dwarf_fpu_xmm10, - gcc_dwarf_fpu_xmm11, - gcc_dwarf_fpu_xmm12, - gcc_dwarf_fpu_xmm13, - gcc_dwarf_fpu_xmm14, - gcc_dwarf_fpu_xmm15, - gcc_dwarf_fpu_stmm0, - gcc_dwarf_fpu_stmm1, - gcc_dwarf_fpu_stmm2, - gcc_dwarf_fpu_stmm3, - gcc_dwarf_fpu_stmm4, - gcc_dwarf_fpu_stmm5, - gcc_dwarf_fpu_stmm6, - gcc_dwarf_fpu_stmm7, - -}; -enum gdb_regnums +RegisterContextMach_x86_64::RegisterContextMach_x86_64(Thread &thread, uint32_t concrete_frame_idx) : +RegisterContextDarwin_x86_64 (thread, concrete_frame_idx) { - gdb_gpr_rax = 0, - gdb_gpr_rbx = 1, - gdb_gpr_rcx = 2, - gdb_gpr_rdx = 3, - gdb_gpr_rsi = 4, - gdb_gpr_rdi = 5, - gdb_gpr_rbp = 6, - gdb_gpr_rsp = 7, - gdb_gpr_r8 = 8, - gdb_gpr_r9 = 9, - gdb_gpr_r10 = 10, - gdb_gpr_r11 = 11, - gdb_gpr_r12 = 12, - gdb_gpr_r13 = 13, - gdb_gpr_r14 = 14, - gdb_gpr_r15 = 15, - gdb_gpr_rip = 16, - gdb_gpr_rflags = 17, - gdb_gpr_cs = 18, - gdb_gpr_ss = 19, - gdb_gpr_ds = 20, - gdb_gpr_es = 21, - gdb_gpr_fs = 22, - gdb_gpr_gs = 23, - gdb_fpu_stmm0 = 24, - gdb_fpu_stmm1 = 25, - gdb_fpu_stmm2 = 26, - gdb_fpu_stmm3 = 27, - gdb_fpu_stmm4 = 28, - gdb_fpu_stmm5 = 29, - gdb_fpu_stmm6 = 30, - gdb_fpu_stmm7 = 31, - gdb_fpu_fctrl = 32, gdb_fpu_fcw = gdb_fpu_fctrl, - gdb_fpu_fstat = 33, gdb_fpu_fsw = gdb_fpu_fstat, - gdb_fpu_ftag = 34, gdb_fpu_ftw = gdb_fpu_ftag, - gdb_fpu_fiseg = 35, gdb_fpu_cs = gdb_fpu_fiseg, - gdb_fpu_fioff = 36, gdb_fpu_ip = gdb_fpu_fioff, - gdb_fpu_foseg = 37, gdb_fpu_ds = gdb_fpu_foseg, - gdb_fpu_fooff = 38, gdb_fpu_dp = gdb_fpu_fooff, - gdb_fpu_fop = 39, - gdb_fpu_xmm0 = 40, - gdb_fpu_xmm1 = 41, - gdb_fpu_xmm2 = 42, - gdb_fpu_xmm3 = 43, - gdb_fpu_xmm4 = 44, - gdb_fpu_xmm5 = 45, - gdb_fpu_xmm6 = 46, - gdb_fpu_xmm7 = 47, - gdb_fpu_xmm8 = 48, - gdb_fpu_xmm9 = 49, - gdb_fpu_xmm10 = 50, - gdb_fpu_xmm11 = 51, - gdb_fpu_xmm12 = 52, - gdb_fpu_xmm13 = 53, - gdb_fpu_xmm14 = 54, - gdb_fpu_xmm15 = 55, - gdb_fpu_mxcsr = 56, -}; - -RegisterContextMach_x86_64::RegisterContextMach_x86_64 (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; - } } RegisterContextMach_x86_64::~RegisterContextMach_x86_64() { } -#define GPR_OFFSET(reg) (offsetof (RegisterContextMach_x86_64::GPR, reg)) -#define FPU_OFFSET(reg) (offsetof (RegisterContextMach_x86_64::FPU, reg) + sizeof (RegisterContextMach_x86_64::GPR)) -#define EXC_OFFSET(reg) (offsetof (RegisterContextMach_x86_64::EXC, reg) + sizeof (RegisterContextMach_x86_64::GPR) + sizeof (RegisterContextMach_x86_64::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(((RegisterContextMach_x86_64::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex -#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextMach_x86_64::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex -#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextMach_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } -#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextMach_x86_64::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex - -#define REG_CONTEXT_SIZE (sizeof (RegisterContextMach_x86_64::GPR) + sizeof (RegisterContextMach_x86_64::FPU) + sizeof (RegisterContextMach_x86_64::EXC)) - -// General purpose registers for 64 bit -static RegisterInfo g_register_infos[] = -{ -// Macro auto defines most stuff GCC REG KIND NUM DWARF REG KIND NUM GENERIC REG KIND NUM GDB REG KIND NUM LLDB REG KIND NUM -// =============================== ======================= =================== ========================== ========================== ===================== - { DEFINE_GPR (rax , NULL) , { gcc_dwarf_gpr_rax , gcc_dwarf_gpr_rax , LLDB_INVALID_REGNUM , gdb_gpr_rax , gpr_rax }}, - { DEFINE_GPR (rbx , NULL) , { gcc_dwarf_gpr_rbx , gcc_dwarf_gpr_rbx , LLDB_INVALID_REGNUM , gdb_gpr_rbx , gpr_rbx }}, - { DEFINE_GPR (rcx , NULL) , { gcc_dwarf_gpr_rcx , gcc_dwarf_gpr_rcx , LLDB_INVALID_REGNUM , gdb_gpr_rcx , gpr_rcx }}, - { DEFINE_GPR (rdx , NULL) , { gcc_dwarf_gpr_rdx , gcc_dwarf_gpr_rdx , LLDB_INVALID_REGNUM , gdb_gpr_rdx , gpr_rdx }}, - { DEFINE_GPR (rdi , NULL) , { gcc_dwarf_gpr_rdi , gcc_dwarf_gpr_rdi , LLDB_INVALID_REGNUM , gdb_gpr_rdi , gpr_rdi }}, - { DEFINE_GPR (rsi , NULL) , { gcc_dwarf_gpr_rsi , gcc_dwarf_gpr_rsi , LLDB_INVALID_REGNUM , gdb_gpr_rsi , gpr_rsi }}, - { DEFINE_GPR (rbp , "fp") , { gcc_dwarf_gpr_rbp , gcc_dwarf_gpr_rbp , LLDB_REGNUM_GENERIC_FP , gdb_gpr_rbp , gpr_rbp }}, - { DEFINE_GPR (rsp , "sp") , { gcc_dwarf_gpr_rsp , gcc_dwarf_gpr_rsp , LLDB_REGNUM_GENERIC_SP , gdb_gpr_rsp , gpr_rsp }}, - { DEFINE_GPR (r8 , NULL) , { gcc_dwarf_gpr_r8 , gcc_dwarf_gpr_r8 , LLDB_INVALID_REGNUM , gdb_gpr_r8 , gpr_r8 }}, - { DEFINE_GPR (r9 , NULL) , { gcc_dwarf_gpr_r9 , gcc_dwarf_gpr_r9 , LLDB_INVALID_REGNUM , gdb_gpr_r9 , gpr_r9 }}, - { DEFINE_GPR (r10 , NULL) , { gcc_dwarf_gpr_r10 , gcc_dwarf_gpr_r10 , LLDB_INVALID_REGNUM , gdb_gpr_r10 , gpr_r10 }}, - { DEFINE_GPR (r11 , NULL) , { gcc_dwarf_gpr_r11 , gcc_dwarf_gpr_r11 , LLDB_INVALID_REGNUM , gdb_gpr_r11 , gpr_r11 }}, - { DEFINE_GPR (r12 , NULL) , { gcc_dwarf_gpr_r12 , gcc_dwarf_gpr_r12 , LLDB_INVALID_REGNUM , gdb_gpr_r12 , gpr_r12 }}, - { DEFINE_GPR (r13 , NULL) , { gcc_dwarf_gpr_r13 , gcc_dwarf_gpr_r13 , LLDB_INVALID_REGNUM , gdb_gpr_r13 , gpr_r13 }}, - { DEFINE_GPR (r14 , NULL) , { gcc_dwarf_gpr_r14 , gcc_dwarf_gpr_r14 , LLDB_INVALID_REGNUM , gdb_gpr_r14 , gpr_r14 }}, - { DEFINE_GPR (r15 , NULL) , { gcc_dwarf_gpr_r15 , gcc_dwarf_gpr_r15 , LLDB_INVALID_REGNUM , gdb_gpr_r15 , gpr_r15 }}, - { DEFINE_GPR (rip , "pc") , { gcc_dwarf_gpr_rip , gcc_dwarf_gpr_rip , LLDB_REGNUM_GENERIC_PC , gdb_gpr_rip , gpr_rip }}, - { DEFINE_GPR (rflags, "flags") , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_gpr_rflags , gpr_rflags }}, - { DEFINE_GPR (cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gpr_cs , gpr_cs }}, - { DEFINE_GPR (fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gpr_fs , gpr_fs }}, - { DEFINE_GPR (gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gpr_gs , gpr_gs }}, - - { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_fcw , fpu_fcw }}, - { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_fsw , fpu_fsw }}, - { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_ftw , fpu_ftw }}, - { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_fop , fpu_fop }}, - { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_ip , fpu_ip }}, - { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_cs , fpu_cs }}, - { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_dp , fpu_dp }}, - { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_ds , fpu_ds }}, - { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_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_FPU_VECT(xmm,8) }, - { DEFINE_FPU_VECT(xmm,9) }, - { DEFINE_FPU_VECT(xmm,10) }, - { DEFINE_FPU_VECT(xmm,11) }, - { DEFINE_FPU_VECT(xmm,12) }, - { DEFINE_FPU_VECT(xmm,13) }, - { DEFINE_FPU_VECT(xmm,14) }, - { DEFINE_FPU_VECT(xmm,15) }, - - { 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 -RegisterContextMach_x86_64::InvalidateAllRegisters () -{ - InvalidateAllRegisterStates(); -} - - -size_t -RegisterContextMach_x86_64::GetRegisterCount () -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; -} - - -const RegisterInfo * -RegisterContextMach_x86_64::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 -RegisterContextMach_x86_64::GetRegisterInfosCount () -{ - return k_num_register_infos; -} - -const lldb_private::RegisterInfo * -RegisterContextMach_x86_64::GetRegisterInfos () -{ - return g_register_infos; -} - - - -static uint32_t g_gpr_regnums[] = -{ - gpr_rax, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs -}; - -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, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15 -}; - -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 -RegisterContextMach_x86_64::GetRegisterSetCount () -{ - return k_num_regsets; -} - -const RegisterSet * -RegisterContextMach_x86_64::GetRegisterSet (uint32_t reg_set) -{ - if (reg_set < k_num_regsets) - return &g_reg_sets[reg_set]; - return NULL; -} - int -RegisterContextMach_x86_64::GetSetForNativeRegNum (int reg_num) +RegisterContextMach_x86_64::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) { - 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; + mach_msg_type_number_t count = GPRWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count); } -void -RegisterContextMach_x86_64::LogGPR(Log *log, const char *format, ...) -{ - if (log) - { - if (format) - { - va_list args; - va_start (args, format); - log->VAPrintf (format, args); - va_end (args); - } - for (uint32_t i=0; i<k_num_gpr_registers; i++) - { - uint32_t reg = gpr_rax + i; - log->Printf("%12s = 0x%16.16llx", g_register_infos[reg].name, (&gpr.rax)[reg]); - } - } -} - -kern_return_t -RegisterContextMach_x86_64::ReadGPR (bool force) -{ - int set = GPRRegSet; - if (force || !RegisterSetIsCached(set)) - { - mach_msg_type_number_t count = GPRWordCount; - SetError(GPRRegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&gpr, &count)); - LogSP log (ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_THREAD)); - if (log) - LogGPR (log.get(), "RegisterContextMach_x86_64::ReadGPR(thread = 0x%4.4x)", GetThreadID()); - } - return GetError(GPRRegSet, Read); -} - -kern_return_t -RegisterContextMach_x86_64::ReadFPU (bool force) -{ - int set = FPURegSet; - if (force || !RegisterSetIsCached(set)) - { - mach_msg_type_number_t count = FPUWordCount; - SetError(FPURegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&fpu, &count)); - } - return GetError(FPURegSet, Read); -} - -kern_return_t -RegisterContextMach_x86_64::ReadEXC (bool force) -{ - int set = EXCRegSet; - if (force || !RegisterSetIsCached(set)) - { - mach_msg_type_number_t count = EXCWordCount; - SetError(EXCRegSet, Read, ::thread_get_state(GetThreadID(), set, (thread_state_t)&exc, &count)); - } - return GetError(EXCRegSet, Read); -} - -kern_return_t -RegisterContextMach_x86_64::WriteGPR () -{ - int set = GPRRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - LogSP log (ProcessMacOSXLog::GetLogIfAllCategoriesSet (PD_LOG_THREAD)); - if (log) - LogGPR (log.get(), "RegisterContextMach_x86_64::WriteGPR (thread = 0x%4.4x)", GetThreadID()); - SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&gpr, GPRWordCount)); - SetError (set, Read, -1); - return GetError (set, Write); -} - -kern_return_t -RegisterContextMach_x86_64::WriteFPU () -{ - int set = FPURegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&fpu, FPUWordCount)); - SetError (set, Read, -1); - return GetError (set, Write); -} - -kern_return_t -RegisterContextMach_x86_64::WriteEXC () -{ - int set = EXCRegSet; - if (!RegisterSetIsCached(set)) - { - SetError (set, Write, -1); - return KERN_INVALID_ARGUMENT; - } - SetError (set, Write, ::thread_set_state(GetThreadID(), set, (thread_state_t)&exc, EXCWordCount)); - SetError (set, Read, -1); - return GetError (set, Write); -} - -kern_return_t -RegisterContextMach_x86_64::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 KERN_INVALID_ARGUMENT; -} - -kern_return_t -RegisterContextMach_x86_64::WriteRegisterSet(uint32_t set) -{ - // Make sure we have a valid context to set. - switch (set) - { - case GPRRegSet: return WriteGPR (); - case FPURegSet: return WriteFPU (); - case EXCRegSet: return WriteEXC (); - default: break; - } - return KERN_INVALID_ARGUMENT; -} - - -bool -RegisterContextMach_x86_64::ReadRegister (const RegisterInfo *reg_info, - RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = RegisterContextMach_x86_64::GetSetForNativeRegNum (reg); - if (set == -1) - return false; - - if (ReadRegisterSet(set, false) != KERN_SUCCESS) - return false; - - switch (reg) - { - case gpr_rax: - case gpr_rbx: - case gpr_rcx: - case gpr_rdx: - case gpr_rdi: - case gpr_rsi: - case gpr_rbp: - case gpr_rsp: - case gpr_r8: - case gpr_r9: - case gpr_r10: - case gpr_r11: - case gpr_r12: - case gpr_r13: - case gpr_r14: - case gpr_r15: - case gpr_rip: - case gpr_rflags: - case gpr_cs: - case gpr_fs: - case gpr_gs: - value = (&gpr.rax)[reg - gpr_rax]; - 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: - value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder()); - break; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - case fpu_xmm8: - case fpu_xmm9: - case fpu_xmm10: - case fpu_xmm11: - case fpu_xmm12: - case fpu_xmm13: - case fpu_xmm14: - case fpu_xmm15: - value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder()); - break; - - 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 -RegisterContextMach_x86_64::WriteRegister (const RegisterInfo *reg_info, - const RegisterValue &value) +int +RegisterContextMach_x86_64::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) { - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - int set = RegisterContextMach_x86_64::GetSetForNativeRegNum (reg); - - if (set == -1) - return false; - - if (ReadRegisterSet(set, false) != KERN_SUCCESS) - return false; - - switch (reg) - { - case gpr_rax: - case gpr_rbx: - case gpr_rcx: - case gpr_rdx: - case gpr_rdi: - case gpr_rsi: - case gpr_rbp: - case gpr_rsp: - case gpr_r8: - case gpr_r9: - case gpr_r10: - case gpr_r11: - case gpr_r12: - case gpr_r13: - case gpr_r14: - case gpr_r15: - case gpr_rip: - case gpr_rflags: - case gpr_cs: - case gpr_fs: - case gpr_gs: - (&gpr.rax)[reg - gpr_rax] = value.GetAsUInt64(); - 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: - ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize()); - break; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - case fpu_xmm8: - case fpu_xmm9: - case fpu_xmm10: - case fpu_xmm11: - case fpu_xmm12: - case fpu_xmm13: - case fpu_xmm14: - case fpu_xmm15: - ::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.GetAsUInt64(); - break; - - default: - return false; - } - return WriteRegisterSet(set) == KERN_SUCCESS; + mach_msg_type_number_t count = FPUWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count); } -bool -RegisterContextMach_x86_64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) +int +RegisterContextMach_x86_64::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) { - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && - ReadGPR (false) == KERN_SUCCESS && - ReadFPU (false) == KERN_SUCCESS && - ReadEXC (false) == KERN_SUCCESS) - { - 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; + mach_msg_type_number_t count = EXCWordCount; + return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count); } -bool -RegisterContextMach_x86_64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) +int +RegisterContextMach_x86_64::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) { - 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() == KERN_SUCCESS) - ++success_count; - if (WriteFPU() == KERN_SUCCESS) - ++success_count; - if (WriteEXC() == KERN_SUCCESS) - ++success_count; - return success_count == 3; - } - return false; + return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); } - -uint32_t -RegisterContextMach_x86_64::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg) +int +RegisterContextMach_x86_64::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) { - if (kind == eRegisterKindGeneric) - { - switch (reg) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_rip; - case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; - case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; - case LLDB_REGNUM_GENERIC_RA: - default: - break; - } - } - else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) - { - switch (reg) - { - case gcc_dwarf_gpr_rax: return gpr_rax; - case gcc_dwarf_gpr_rdx: return gpr_rdx; - case gcc_dwarf_gpr_rcx: return gpr_rcx; - case gcc_dwarf_gpr_rbx: return gpr_rbx; - case gcc_dwarf_gpr_rsi: return gpr_rsi; - case gcc_dwarf_gpr_rdi: return gpr_rdi; - case gcc_dwarf_gpr_rbp: return gpr_rbp; - case gcc_dwarf_gpr_rsp: return gpr_rsp; - case gcc_dwarf_gpr_r8: return gpr_r8; - case gcc_dwarf_gpr_r9: return gpr_r9; - case gcc_dwarf_gpr_r10: return gpr_r10; - case gcc_dwarf_gpr_r11: return gpr_r11; - case gcc_dwarf_gpr_r12: return gpr_r12; - case gcc_dwarf_gpr_r13: return gpr_r13; - case gcc_dwarf_gpr_r14: return gpr_r14; - case gcc_dwarf_gpr_r15: return gpr_r15; - case gcc_dwarf_gpr_rip: return gpr_rip; - case gcc_dwarf_fpu_xmm0: return fpu_xmm0; - case gcc_dwarf_fpu_xmm1: return fpu_xmm1; - case gcc_dwarf_fpu_xmm2: return fpu_xmm2; - case gcc_dwarf_fpu_xmm3: return fpu_xmm3; - case gcc_dwarf_fpu_xmm4: return fpu_xmm4; - case gcc_dwarf_fpu_xmm5: return fpu_xmm5; - case gcc_dwarf_fpu_xmm6: return fpu_xmm6; - case gcc_dwarf_fpu_xmm7: return fpu_xmm7; - case gcc_dwarf_fpu_xmm8: return fpu_xmm8; - case gcc_dwarf_fpu_xmm9: return fpu_xmm9; - case gcc_dwarf_fpu_xmm10: return fpu_xmm10; - case gcc_dwarf_fpu_xmm11: return fpu_xmm11; - case gcc_dwarf_fpu_xmm12: return fpu_xmm12; - case gcc_dwarf_fpu_xmm13: return fpu_xmm13; - case gcc_dwarf_fpu_xmm14: return fpu_xmm14; - case gcc_dwarf_fpu_xmm15: return fpu_xmm15; - case gcc_dwarf_fpu_stmm0: return fpu_stmm0; - case gcc_dwarf_fpu_stmm1: return fpu_stmm1; - case gcc_dwarf_fpu_stmm2: return fpu_stmm2; - case gcc_dwarf_fpu_stmm3: return fpu_stmm3; - case gcc_dwarf_fpu_stmm4: return fpu_stmm4; - case gcc_dwarf_fpu_stmm5: return fpu_stmm5; - case gcc_dwarf_fpu_stmm6: return fpu_stmm6; - case gcc_dwarf_fpu_stmm7: return fpu_stmm7; - default: - break; - } - } - else if (kind == eRegisterKindGDB) - { - switch (reg) - { - case gdb_gpr_rax : return gpr_rax; - case gdb_gpr_rbx : return gpr_rbx; - case gdb_gpr_rcx : return gpr_rcx; - case gdb_gpr_rdx : return gpr_rdx; - case gdb_gpr_rsi : return gpr_rsi; - case gdb_gpr_rdi : return gpr_rdi; - case gdb_gpr_rbp : return gpr_rbp; - case gdb_gpr_rsp : return gpr_rsp; - case gdb_gpr_r8 : return gpr_r8; - case gdb_gpr_r9 : return gpr_r9; - case gdb_gpr_r10 : return gpr_r10; - case gdb_gpr_r11 : return gpr_r11; - case gdb_gpr_r12 : return gpr_r12; - case gdb_gpr_r13 : return gpr_r13; - case gdb_gpr_r14 : return gpr_r14; - case gdb_gpr_r15 : return gpr_r15; - case gdb_gpr_rip : return gpr_rip; - case gdb_gpr_rflags : return gpr_rflags; - case gdb_gpr_cs : return gpr_cs; - case gdb_gpr_ss : return gpr_gs; // HACK: For now for "ss", just copy what is in "gs" - case gdb_gpr_ds : return gpr_gs; // HACK: For now for "ds", just copy what is in "gs" - case gdb_gpr_es : return gpr_gs; // HACK: For now for "es", just copy what is in "gs" - case gdb_gpr_fs : return gpr_fs; - case gdb_gpr_gs : return gpr_gs; - case gdb_fpu_stmm0 : return fpu_stmm0; - case gdb_fpu_stmm1 : return fpu_stmm1; - case gdb_fpu_stmm2 : return fpu_stmm2; - case gdb_fpu_stmm3 : return fpu_stmm3; - case gdb_fpu_stmm4 : return fpu_stmm4; - case gdb_fpu_stmm5 : return fpu_stmm5; - case gdb_fpu_stmm6 : return fpu_stmm6; - case gdb_fpu_stmm7 : return fpu_stmm7; - case gdb_fpu_fctrl : return fpu_fctrl; - case gdb_fpu_fstat : return fpu_fstat; - case gdb_fpu_ftag : return fpu_ftag; - case gdb_fpu_fiseg : return fpu_fiseg; - case gdb_fpu_fioff : return fpu_fioff; - case gdb_fpu_foseg : return fpu_foseg; - case gdb_fpu_fooff : return fpu_fooff; - case gdb_fpu_fop : return fpu_fop; - case gdb_fpu_xmm0 : return fpu_xmm0; - case gdb_fpu_xmm1 : return fpu_xmm1; - case gdb_fpu_xmm2 : return fpu_xmm2; - case gdb_fpu_xmm3 : return fpu_xmm3; - case gdb_fpu_xmm4 : return fpu_xmm4; - case gdb_fpu_xmm5 : return fpu_xmm5; - case gdb_fpu_xmm6 : return fpu_xmm6; - case gdb_fpu_xmm7 : return fpu_xmm7; - case gdb_fpu_xmm8 : return fpu_xmm8; - case gdb_fpu_xmm9 : return fpu_xmm9; - case gdb_fpu_xmm10 : return fpu_xmm10; - case gdb_fpu_xmm11 : return fpu_xmm11; - case gdb_fpu_xmm12 : return fpu_xmm12; - case gdb_fpu_xmm13 : return fpu_xmm13; - case gdb_fpu_xmm14 : return fpu_xmm14; - case gdb_fpu_xmm15 : return fpu_xmm15; - case gdb_fpu_mxcsr : return fpu_mxcsr; - default: - break; - } - } - else if (kind == eRegisterKindLLDB) - { - return reg; - } - return LLDB_INVALID_REGNUM; + return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); } -bool -RegisterContextMach_x86_64::HardwareSingleStep (bool enable) +int +RegisterContextMach_x86_64::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) { - if (ReadGPR(true) != KERN_SUCCESS) - return false; - - const uint64_t trace_bit = 0x100ull; - if (enable) - { - - if (gpr.rflags & trace_bit) - return true; // trace bit is already set, there is nothing to do - else - gpr.rflags |= trace_bit; - } - else - { - if (gpr.rflags & trace_bit) - gpr.rflags &= ~trace_bit; - else - return true; // trace bit is clear, there is nothing to do - } - - return WriteGPR() == KERN_SUCCESS; + return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); } diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.h b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.h index e8217222da1..26b83c44adf 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.h +++ b/lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.h @@ -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_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp new file mode 100644 index 00000000000..47418a1c587 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -0,0 +1,1216 @@ +//===-- RegisterContextDarwin_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 "RegisterContextDarwin_arm.h" + +// C Includes +#include <mach/mach_types.h> +#include <mach/thread_act.h> + +// 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 "ARM_GCC_Registers.h" +#include "ARM_DWARF_Registers.h" +#include "ProcessMacOSXLog.h" + +using namespace lldb; +using namespace lldb_private; + +enum +{ + gpr_r0 = 0, + gpr_r1, + gpr_r2, + gpr_r3, + gpr_r4, + gpr_r5, + gpr_r6, + gpr_r7, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, gpr_sp = gpr_r13, + gpr_r14, gpr_lr = gpr_r14, + gpr_r15, gpr_pc = gpr_r15, + gpr_cpsr, + + fpu_s0, + fpu_s1, + fpu_s2, + fpu_s3, + fpu_s4, + fpu_s5, + fpu_s6, + fpu_s7, + fpu_s8, + fpu_s9, + fpu_s10, + fpu_s11, + fpu_s12, + fpu_s13, + fpu_s14, + fpu_s15, + fpu_s16, + fpu_s17, + fpu_s18, + fpu_s19, + fpu_s20, + fpu_s21, + fpu_s22, + fpu_s23, + fpu_s24, + fpu_s25, + fpu_s26, + fpu_s27, + fpu_s28, + fpu_s29, + fpu_s30, + fpu_s31, + fpu_fpscr, + + exc_exception, + exc_fsr, + exc_far, + + dbg_bvr0, + dbg_bvr1, + dbg_bvr2, + dbg_bvr3, + dbg_bvr4, + dbg_bvr5, + dbg_bvr6, + dbg_bvr7, + dbg_bvr8, + dbg_bvr9, + dbg_bvr10, + dbg_bvr11, + dbg_bvr12, + dbg_bvr13, + dbg_bvr14, + dbg_bvr15, + + dbg_bcr0, + dbg_bcr1, + dbg_bcr2, + dbg_bcr3, + dbg_bcr4, + dbg_bcr5, + dbg_bcr6, + dbg_bcr7, + dbg_bcr8, + dbg_bcr9, + dbg_bcr10, + dbg_bcr11, + dbg_bcr12, + dbg_bcr13, + dbg_bcr14, + dbg_bcr15, + + dbg_wvr0, + dbg_wvr1, + dbg_wvr2, + dbg_wvr3, + dbg_wvr4, + dbg_wvr5, + dbg_wvr6, + dbg_wvr7, + dbg_wvr8, + dbg_wvr9, + dbg_wvr10, + dbg_wvr11, + dbg_wvr12, + dbg_wvr13, + dbg_wvr14, + dbg_wvr15, + + dbg_wcr0, + dbg_wcr1, + dbg_wcr2, + dbg_wcr3, + dbg_wcr4, + dbg_wcr5, + dbg_wcr6, + dbg_wcr7, + dbg_wcr8, + dbg_wcr9, + dbg_wcr10, + dbg_wcr11, + dbg_wcr12, + dbg_wcr13, + dbg_wcr14, + dbg_wcr15, + + k_num_registers +}; + + +RegisterContextDarwin_arm::RegisterContextDarwin_arm(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_arm::~RegisterContextDarwin_arm() +{ +} + + +#define GPR_OFFSET(idx) ((idx) * 4) +#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR)) +#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU)) +#define DBG_OFFSET(reg) (offsetof (RegisterContextDarwin_arm::DBG, reg) + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC)) + +#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i } +#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC)) + +static RegisterInfo g_register_infos[] = { +// General purpose registers +// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE +// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= +{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_INVALID_REGNUM, gdb_arm_r0, gpr_r0 }}, +{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_INVALID_REGNUM, gdb_arm_r1, gpr_r1 }}, +{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_INVALID_REGNUM, gdb_arm_r2, gpr_r2 }}, +{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_INVALID_REGNUM, gdb_arm_r3, gpr_r3 }}, +{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, gpr_r4 }}, +{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, gpr_r5 }}, +{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, gpr_r6 }}, +{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, gpr_r7 }}, +{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, gpr_r8 }}, +{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, gpr_r9 }}, +{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, gpr_r10 }}, +{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, gpr_r11 }}, +{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, gpr_r12 }}, +{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, gpr_sp }}, +{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, gpr_lr }}, +{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, gpr_pc }}, +{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, gpr_cpsr }}, + +{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, fpu_s0 }}, +{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, fpu_s1 }}, +{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, fpu_s2 }}, +{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, fpu_s3 }}, +{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, fpu_s4 }}, +{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, fpu_s5 }}, +{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, fpu_s6 }}, +{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, fpu_s7 }}, +{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, fpu_s8 }}, +{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, fpu_s9 }}, +{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, fpu_s10 }}, +{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, fpu_s11 }}, +{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, fpu_s12 }}, +{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, fpu_s13 }}, +{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, fpu_s14 }}, +{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, fpu_s15 }}, +{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, fpu_s16 }}, +{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, fpu_s17 }}, +{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, fpu_s18 }}, +{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, fpu_s19 }}, +{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, fpu_s20 }}, +{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, fpu_s21 }}, +{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, fpu_s22 }}, +{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, fpu_s23 }}, +{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, fpu_s24 }}, +{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, fpu_s25 }}, +{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, fpu_s26 }}, +{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, fpu_s27 }}, +{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, fpu_s28 }}, +{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, fpu_s29 }}, +{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, fpu_s30 }}, +{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, fpu_s31 }}, +{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, fpu_fpscr }}, + +{ "exception",NULL, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }}, +{ "fsr", NULL, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }}, +{ "far", NULL, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }}, + +{ DEFINE_DBG (bvr, 0) }, +{ DEFINE_DBG (bvr, 1) }, +{ DEFINE_DBG (bvr, 2) }, +{ DEFINE_DBG (bvr, 3) }, +{ DEFINE_DBG (bvr, 4) }, +{ DEFINE_DBG (bvr, 5) }, +{ DEFINE_DBG (bvr, 6) }, +{ DEFINE_DBG (bvr, 7) }, +{ DEFINE_DBG (bvr, 8) }, +{ DEFINE_DBG (bvr, 9) }, +{ DEFINE_DBG (bvr, 10) }, +{ DEFINE_DBG (bvr, 11) }, +{ DEFINE_DBG (bvr, 12) }, +{ DEFINE_DBG (bvr, 13) }, +{ DEFINE_DBG (bvr, 14) }, +{ DEFINE_DBG (bvr, 15) }, + +{ DEFINE_DBG (bcr, 0) }, +{ DEFINE_DBG (bcr, 1) }, +{ DEFINE_DBG (bcr, 2) }, +{ DEFINE_DBG (bcr, 3) }, +{ DEFINE_DBG (bcr, 4) }, +{ DEFINE_DBG (bcr, 5) }, +{ DEFINE_DBG (bcr, 6) }, +{ DEFINE_DBG (bcr, 7) }, +{ DEFINE_DBG (bcr, 8) }, +{ DEFINE_DBG (bcr, 9) }, +{ DEFINE_DBG (bcr, 10) }, +{ DEFINE_DBG (bcr, 11) }, +{ DEFINE_DBG (bcr, 12) }, +{ DEFINE_DBG (bcr, 13) }, +{ DEFINE_DBG (bcr, 14) }, +{ DEFINE_DBG (bcr, 15) }, + +{ DEFINE_DBG (wvr, 0) }, +{ DEFINE_DBG (wvr, 1) }, +{ DEFINE_DBG (wvr, 2) }, +{ DEFINE_DBG (wvr, 3) }, +{ DEFINE_DBG (wvr, 4) }, +{ DEFINE_DBG (wvr, 5) }, +{ DEFINE_DBG (wvr, 6) }, +{ DEFINE_DBG (wvr, 7) }, +{ DEFINE_DBG (wvr, 8) }, +{ DEFINE_DBG (wvr, 9) }, +{ DEFINE_DBG (wvr, 10) }, +{ DEFINE_DBG (wvr, 11) }, +{ DEFINE_DBG (wvr, 12) }, +{ DEFINE_DBG (wvr, 13) }, +{ DEFINE_DBG (wvr, 14) }, +{ DEFINE_DBG (wvr, 15) }, + +{ DEFINE_DBG (wcr, 0) }, +{ DEFINE_DBG (wcr, 1) }, +{ DEFINE_DBG (wcr, 2) }, +{ DEFINE_DBG (wcr, 3) }, +{ DEFINE_DBG (wcr, 4) }, +{ DEFINE_DBG (wcr, 5) }, +{ DEFINE_DBG (wcr, 6) }, +{ DEFINE_DBG (wcr, 7) }, +{ DEFINE_DBG (wcr, 8) }, +{ DEFINE_DBG (wcr, 9) }, +{ DEFINE_DBG (wcr, 10) }, +{ DEFINE_DBG (wcr, 11) }, +{ DEFINE_DBG (wcr, 12) }, +{ DEFINE_DBG (wcr, 13) }, +{ DEFINE_DBG (wcr, 14) }, +{ DEFINE_DBG (wcr, 15) } +}; + +// General purpose registers +static uint32_t +g_gpr_regnums[] = +{ + gpr_r0, + gpr_r1, + gpr_r2, + gpr_r3, + gpr_r4, + gpr_r5, + gpr_r6, + gpr_r7, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_sp, + gpr_lr, + gpr_pc, + gpr_cpsr +}; + +// Floating point registers +static uint32_t +g_fpu_regnums[] = +{ + fpu_s0, + fpu_s1, + fpu_s2, + fpu_s3, + fpu_s4, + fpu_s5, + fpu_s6, + fpu_s7, + fpu_s8, + fpu_s9, + fpu_s10, + fpu_s11, + fpu_s12, + fpu_s13, + fpu_s14, + fpu_s15, + fpu_s16, + fpu_s17, + fpu_s18, + fpu_s19, + fpu_s20, + fpu_s21, + fpu_s22, + fpu_s23, + fpu_s24, + fpu_s25, + fpu_s26, + fpu_s27, + fpu_s28, + fpu_s29, + fpu_s30, + fpu_s31, + fpu_fpscr, +}; + +// Exception registers + +static uint32_t +g_exc_regnums[] = +{ + exc_exception, + exc_fsr, + exc_far, +}; + +static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); + +void +RegisterContextDarwin_arm::InvalidateAllRegisters () +{ + InvalidateAllRegisterStates(); +} + + +size_t +RegisterContextDarwin_arm::GetRegisterCount () +{ + assert(k_num_register_infos == k_num_registers); + return k_num_registers; +} + +const RegisterInfo * +RegisterContextDarwin_arm::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_arm::GetRegisterInfosCount () +{ + return k_num_register_infos; +} + +const RegisterInfo * +RegisterContextDarwin_arm::GetRegisterInfos () +{ + return g_register_infos; +} + + +// 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_arm::GetRegisterSetCount () +{ + return k_num_regsets; +} + +const RegisterSet * +RegisterContextDarwin_arm::GetRegisterSet (uint32_t reg_set) +{ + if (reg_set < k_num_regsets) + return &g_reg_sets[reg_set]; + return NULL; +} + + +//---------------------------------------------------------------------- +// Register information defintions for 32 bit i386. +//---------------------------------------------------------------------- +int +RegisterContextDarwin_arm::GetSetForNativeRegNum (int reg) +{ + if (reg < fpu_s0) + return GPRRegSet; + else if (reg < exc_exception) + return FPURegSet; + else if (reg < k_num_registers) + return EXCRegSet; + return -1; +} + +int +RegisterContextDarwin_arm::ReadGPR (bool force) +{ + int set = GPRRegSet; + if (force || !RegisterSetIsCached(set)) + { + SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr)); + } + return GetError(GPRRegSet, Read); +} + +int +RegisterContextDarwin_arm::ReadFPU (bool force) +{ + int set = FPURegSet; + if (force || !RegisterSetIsCached(set)) + { + SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu)); + } + return GetError(FPURegSet, Read); +} + +int +RegisterContextDarwin_arm::ReadEXC (bool force) +{ + int set = EXCRegSet; + if (force || !RegisterSetIsCached(set)) + { + SetError(set, Read, DoReadEXC(GetThreadID(), set, exc)); + } + return GetError(EXCRegSet, Read); +} + +int +RegisterContextDarwin_arm::ReadDBG (bool force) +{ + int set = DBGRegSet; + if (force || !RegisterSetIsCached(set)) + { + SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg)); + } + return GetError(DBGRegSet, Read); +} + +int +RegisterContextDarwin_arm::WriteGPR () +{ + int set = GPRRegSet; + if (!RegisterSetIsCached(set)) + { + SetError (set, Write, -1); + return KERN_INVALID_ARGUMENT; + } + SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr)); + SetError (set, Read, -1); + return GetError(GPRRegSet, Write); +} + +int +RegisterContextDarwin_arm::WriteFPU () +{ + int set = FPURegSet; + if (!RegisterSetIsCached(set)) + { + SetError (set, Write, -1); + return KERN_INVALID_ARGUMENT; + } + SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu)); + SetError (set, Read, -1); + return GetError(FPURegSet, Write); +} + +int +RegisterContextDarwin_arm::WriteEXC () +{ + int set = EXCRegSet; + if (!RegisterSetIsCached(set)) + { + SetError (set, Write, -1); + return KERN_INVALID_ARGUMENT; + } + SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc)); + SetError (set, Read, -1); + return GetError(EXCRegSet, Write); +} + +int +RegisterContextDarwin_arm::WriteDBG () +{ + int set = DBGRegSet; + if (!RegisterSetIsCached(set)) + { + SetError (set, Write, -1); + return KERN_INVALID_ARGUMENT; + } + SetError (set, Write, DoWriteDBG(GetThreadID(), set, dbg)); + SetError (set, Read, -1); + return GetError(DBGRegSet, Write); +} + + +int +RegisterContextDarwin_arm::ReadRegisterSet (uint32_t set, bool force) +{ + switch (set) + { + case GPRRegSet: return ReadGPR(force); + case FPURegSet: return ReadFPU(force); + case EXCRegSet: return ReadEXC(force); + case DBGRegSet: return ReadDBG(force); + default: break; + } + return KERN_INVALID_ARGUMENT; +} + +int +RegisterContextDarwin_arm::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(); + case DBGRegSet: return WriteDBG(); + default: break; + } + } + return KERN_INVALID_ARGUMENT; +} + +void +RegisterContextDarwin_arm::LogDBGRegisters (Log *log, const DBG& dbg) +{ + if (log) + { + for (uint32_t i=0; i<16; i++) + log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }", + i, i, dbg.bvr[i], dbg.bcr[i], + i, i, dbg.wvr[i], dbg.wcr[i]); + } +} + + +bool +RegisterContextDarwin_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = RegisterContextDarwin_arm::GetSetForNativeRegNum (reg); + + if (set == -1) + return false; + + if (ReadRegisterSet(set, false) != KERN_SUCCESS) + return false; + + switch (reg) + { + case gpr_r0: + case gpr_r1: + case gpr_r2: + case gpr_r3: + case gpr_r4: + case gpr_r5: + case gpr_r6: + case gpr_r7: + case gpr_r8: + case gpr_r9: + case gpr_r10: + case gpr_r11: + case gpr_r12: + case gpr_sp: + case gpr_lr: + case gpr_pc: + case gpr_cpsr: + value.SetUInt32 (gpr.r[reg - gpr_r0]); + break; + + case fpu_s0: + case fpu_s1: + case fpu_s2: + case fpu_s3: + case fpu_s4: + case fpu_s5: + case fpu_s6: + case fpu_s7: + case fpu_s8: + case fpu_s9: + case fpu_s10: + case fpu_s11: + case fpu_s12: + case fpu_s13: + case fpu_s14: + case fpu_s15: + case fpu_s16: + case fpu_s17: + case fpu_s18: + case fpu_s19: + case fpu_s20: + case fpu_s21: + case fpu_s22: + case fpu_s23: + case fpu_s24: + case fpu_s25: + case fpu_s26: + case fpu_s27: + case fpu_s28: + case fpu_s29: + case fpu_s30: + case fpu_s31: + value.SetUInt32 (fpu.floats.s[reg], RegisterValue::eTypeFloat); + break; + + case fpu_fpscr: + value.SetUInt32 (fpu.fpscr); + break; + + case exc_exception: + value.SetUInt32 (exc.exception); + break; + case exc_fsr: + value.SetUInt32 (exc.fsr); + break; + case exc_far: + value.SetUInt32 (exc.far); + break; + + default: + value.SetValueToInvalid(); + return false; + + } + return true; +} + + +bool +RegisterContextDarwin_arm::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) != KERN_SUCCESS) + return false; + + switch (reg) + { + case gpr_r0: + case gpr_r1: + case gpr_r2: + case gpr_r3: + case gpr_r4: + case gpr_r5: + case gpr_r6: + case gpr_r7: + case gpr_r8: + case gpr_r9: + case gpr_r10: + case gpr_r11: + case gpr_r12: + case gpr_sp: + case gpr_lr: + case gpr_pc: + case gpr_cpsr: + gpr.r[reg - gpr_r0] = value.GetAsUInt32(); + break; + + case fpu_s0: + case fpu_s1: + case fpu_s2: + case fpu_s3: + case fpu_s4: + case fpu_s5: + case fpu_s6: + case fpu_s7: + case fpu_s8: + case fpu_s9: + case fpu_s10: + case fpu_s11: + case fpu_s12: + case fpu_s13: + case fpu_s14: + case fpu_s15: + case fpu_s16: + case fpu_s17: + case fpu_s18: + case fpu_s19: + case fpu_s20: + case fpu_s21: + case fpu_s22: + case fpu_s23: + case fpu_s24: + case fpu_s25: + case fpu_s26: + case fpu_s27: + case fpu_s28: + case fpu_s29: + case fpu_s30: + case fpu_s31: + fpu.floats.s[reg] = value.GetAsUInt32(); + break; + + case fpu_fpscr: + fpu.fpscr = value.GetAsUInt32(); + break; + + case exc_exception: + exc.exception = value.GetAsUInt32(); + break; + case exc_fsr: + exc.fsr = value.GetAsUInt32(); + break; + case exc_far: + exc.far = value.GetAsUInt32(); + break; + + default: + return false; + + } + return WriteRegisterSet(set) == KERN_SUCCESS; +} + +bool +RegisterContextDarwin_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) +{ + data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); + if (data_sp && + ReadGPR (false) == KERN_SUCCESS && + ReadFPU (false) == KERN_SUCCESS && + ReadEXC (false) == KERN_SUCCESS) + { + 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_arm::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() == KERN_SUCCESS) + ++success_count; + if (WriteFPU() == KERN_SUCCESS) + ++success_count; + if (WriteEXC() == KERN_SUCCESS) + ++success_count; + return success_count == 3; + } + return false; +} + +uint32_t +RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg) +{ + if (kind == eRegisterKindGeneric) + { + switch (reg) + { + case LLDB_REGNUM_GENERIC_PC: return gpr_pc; + case LLDB_REGNUM_GENERIC_SP: return gpr_sp; + case LLDB_REGNUM_GENERIC_FP: return gpr_r7; + case LLDB_REGNUM_GENERIC_RA: return gpr_lr; + case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr; + default: + break; + } + } + else if (kind == eRegisterKindDWARF) + { + switch (reg) + { + case dwarf_r0: return gpr_r0; + case dwarf_r1: return gpr_r1; + case dwarf_r2: return gpr_r2; + case dwarf_r3: return gpr_r3; + case dwarf_r4: return gpr_r4; + case dwarf_r5: return gpr_r5; + case dwarf_r6: return gpr_r6; + case dwarf_r7: return gpr_r7; + case dwarf_r8: return gpr_r8; + case dwarf_r9: return gpr_r9; + case dwarf_r10: return gpr_r10; + case dwarf_r11: return gpr_r11; + case dwarf_r12: return gpr_r12; + case dwarf_sp: return gpr_sp; + case dwarf_lr: return gpr_lr; + case dwarf_pc: return gpr_pc; + case dwarf_spsr: return gpr_cpsr; + + case dwarf_s0: return fpu_s0; + case dwarf_s1: return fpu_s1; + case dwarf_s2: return fpu_s2; + case dwarf_s3: return fpu_s3; + case dwarf_s4: return fpu_s4; + case dwarf_s5: return fpu_s5; + case dwarf_s6: return fpu_s6; + case dwarf_s7: return fpu_s7; + case dwarf_s8: return fpu_s8; + case dwarf_s9: return fpu_s9; + case dwarf_s10: return fpu_s10; + case dwarf_s11: return fpu_s11; + case dwarf_s12: return fpu_s12; + case dwarf_s13: return fpu_s13; + case dwarf_s14: return fpu_s14; + case dwarf_s15: return fpu_s15; + case dwarf_s16: return fpu_s16; + case dwarf_s17: return fpu_s17; + case dwarf_s18: return fpu_s18; + case dwarf_s19: return fpu_s19; + case dwarf_s20: return fpu_s20; + case dwarf_s21: return fpu_s21; + case dwarf_s22: return fpu_s22; + case dwarf_s23: return fpu_s23; + case dwarf_s24: return fpu_s24; + case dwarf_s25: return fpu_s25; + case dwarf_s26: return fpu_s26; + case dwarf_s27: return fpu_s27; + case dwarf_s28: return fpu_s28; + case dwarf_s29: return fpu_s29; + case dwarf_s30: return fpu_s30; + case dwarf_s31: return fpu_s31; + + default: + break; + } + } + else if (kind == eRegisterKindGCC) + { + switch (reg) + { + case gcc_r0: return gpr_r0; + case gcc_r1: return gpr_r1; + case gcc_r2: return gpr_r2; + case gcc_r3: return gpr_r3; + case gcc_r4: return gpr_r4; + case gcc_r5: return gpr_r5; + case gcc_r6: return gpr_r6; + case gcc_r7: return gpr_r7; + case gcc_r8: return gpr_r8; + case gcc_r9: return gpr_r9; + case gcc_r10: return gpr_r10; + case gcc_r11: return gpr_r11; + case gcc_r12: return gpr_r12; + case gcc_sp: return gpr_sp; + case gcc_lr: return gpr_lr; + case gcc_pc: return gpr_pc; + case gcc_cpsr: return gpr_cpsr; + } + } + else if (kind == eRegisterKindLLDB) + { + return reg; + } + return LLDB_INVALID_REGNUM; +} + + +uint32_t +RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints () +{ +#if defined (__arm__) + // Set the init value to something that will let us know that we need to + // autodetect how many breakpoints are supported dynamically... + static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX; + if (g_num_supported_hw_breakpoints == UINT32_MAX) + { + // Set this to zero in case we can't tell if there are any HW breakpoints + g_num_supported_hw_breakpoints = 0; + + uint32_t register_DBGDIDR; + + asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); + g_num_supported_hw_breakpoints = bits(register_DBGDIDR, 27, 24); + // Zero is reserved for the BRP count, so don't increment it if it is zero + if (g_num_supported_hw_breakpoints > 0) + g_num_supported_hw_breakpoints++; + ProcessMacOSXLog::LogIf(PD_LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_breakpoints); + + } + return g_num_supported_hw_breakpoints; +#else + // TODO: figure out remote case here! + return 6; +#endif +} + +uint32_t +RegisterContextDarwin_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) +{ + // Make sure our address isn't bogus + if (addr & 1) + return LLDB_INVALID_INDEX32; + + int kret = ReadDBG (false); + + if (kret == KERN_SUCCESS) + { + const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); + uint32_t i; + for (i=0; i<num_hw_breakpoints; ++i) + { + if ((dbg.bcr[i] & BCR_ENABLE) == 0) + break; // We found an available hw breakpoint slot (in i) + } + + // See if we found an available hw breakpoint slot above + if (i < num_hw_breakpoints) + { + // Make sure bits 1:0 are clear in our address + dbg.bvr[i] = addr & ~((lldb::addr_t)3); + + if (size == 2 || addr & 2) + { + uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; + + // We have a thumb breakpoint + // We have an ARM breakpoint + dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch + byte_addr_select | // Set the correct byte address select so we only trigger on the correct opcode + S_USER | // Which modes should this breakpoint stop in? + BCR_ENABLE; // Enable this hardware breakpoint + ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextDarwin_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)", + addr, + size, + i, + i, + dbg.bvr[i], + dbg.bcr[i]); + } + else if (size == 4) + { + // We have an ARM breakpoint + dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch + BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA + S_USER | // Which modes should this breakpoint stop in? + BCR_ENABLE; // Enable this hardware breakpoint + ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextDarwin_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)", + addr, + size, + i, + i, + dbg.bvr[i], + dbg.bcr[i]); + } + + kret = WriteDBG(); + ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextDarwin_arm::EnableHardwareBreakpoint() WriteDBG() => 0x%8.8x.", kret); + + if (kret == KERN_SUCCESS) + return i; + } + else + { + ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextDarwin_arm::EnableHardwareBreakpoint(addr = %8.8p, size = %u) => all hardware breakpoint resources are being used.", addr, size); + } + } + + return LLDB_INVALID_INDEX32; +} + +bool +RegisterContextDarwin_arm::ClearHardwareBreakpoint (uint32_t hw_index) +{ + int kret = ReadDBG (false); + + const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); + if (kret == KERN_SUCCESS) + { + if (hw_index < num_hw_points) + { + dbg.bcr[hw_index] = 0; + ProcessMacOSXLog::LogIf(PD_LOG_BREAKPOINTS, "RegisterContextDarwin_arm::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x BCR%u = 0x%8.8x", + hw_index, + hw_index, + dbg.bvr[hw_index], + hw_index, + dbg.bcr[hw_index]); + + kret = WriteDBG(); + + if (kret == KERN_SUCCESS) + return true; + } + } + return false; +} + +uint32_t +RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints () +{ +#if defined (__arm__) + // Set the init value to something that will let us know that we need to + // autodetect how many watchpoints are supported dynamically... + static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX; + if (g_num_supported_hw_watchpoints == UINT32_MAX) + { + // Set this to zero in case we can't tell if there are any HW breakpoints + g_num_supported_hw_watchpoints = 0; + + uint32_t register_DBGDIDR; + asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); + g_num_supported_hw_watchpoints = bits(register_DBGDIDR, 31, 28) + 1; + ProcessMacOSXLog::LogIf(PD_LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_watchpoints); + } + return g_num_supported_hw_watchpoints; +#else + // TODO: figure out remote case here! + return 2; +#endif +} + + +uint32_t +RegisterContextDarwin_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write) +{ + ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextDarwin_arm::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write); + + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + + // Can't watch zero bytes + if (size == 0) + return LLDB_INVALID_INDEX32; + + // We must watch for either read or write + if (read == false && write == false) + return LLDB_INVALID_INDEX32; + + // Can't watch more than 4 bytes per WVR/WCR pair + if (size > 4) + return LLDB_INVALID_INDEX32; + + // We can only watch up to four bytes that follow a 4 byte aligned address + // per watchpoint register pair. Since we have at most so we can only watch + // until the next 4 byte boundary and we need to make sure we can properly + // encode this. + uint32_t addr_word_offset = addr % 4; + ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextDarwin_arm::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset); + + uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset; + ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextDarwin_arm::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask); + if (byte_mask > 0xfu) + return LLDB_INVALID_INDEX32; + + // Read the debug state + int kret = ReadDBG (false); + + if (kret == KERN_SUCCESS) + { + // Check to make sure we have the needed hardware support + uint32_t i = 0; + + for (i=0; i<num_hw_watchpoints; ++i) + { + if ((dbg.wcr[i] & WCR_ENABLE) == 0) + break; // We found an available hw breakpoint slot (in i) + } + + // See if we found an available hw breakpoint slot above + if (i < num_hw_watchpoints) + { + // Make the byte_mask into a valid Byte Address Select mask + uint32_t byte_address_select = byte_mask << 5; + // Make sure bits 1:0 are clear in our address + dbg.wvr[i] = addr & ~((lldb::addr_t)3); + dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA that we will watch + S_USER | // Stop only in user mode + (read ? WCR_LOAD : 0) | // Stop on read access? + (write ? WCR_STORE : 0) | // Stop on write access? + WCR_ENABLE; // Enable this watchpoint; + + kret = WriteDBG(); + ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextDarwin_arm::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret); + + if (kret == KERN_SUCCESS) + return i; + } + else + { + ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextDarwin_arm::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); + } + } + return LLDB_INVALID_INDEX32; +} + +bool +RegisterContextDarwin_arm::ClearHardwareWatchpoint (uint32_t hw_index) +{ + int kret = ReadDBG (false); + + const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); + if (kret == KERN_SUCCESS) + { + if (hw_index < num_hw_points) + { + dbg.wcr[hw_index] = 0; + ProcessMacOSXLog::LogIf(PD_LOG_WATCHPOINTS, "RegisterContextDarwin_arm::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x", + hw_index, + hw_index, + dbg.wvr[hw_index], + hw_index, + dbg.wcr[hw_index]); + + kret = WriteDBG(); + + if (kret == KERN_SUCCESS) + return true; + } + } + return false; +} + + diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h new file mode 100644 index 00000000000..cc0f1829b5a --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h @@ -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 ®_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 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_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp new file mode 100644 index 00000000000..9b419eb66c8 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp @@ -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; +} + + + diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h new file mode 100644 index 00000000000..773aa627cd8 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h @@ -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_ diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp new file mode 100644 index 00000000000..19badb442da --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp @@ -0,0 +1,1056 @@ +//===-- RegisterContextDarwin_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 +// 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_x86_64.h" + +using namespace lldb; +using namespace lldb_private; + +enum +{ + gpr_rax = 0, + gpr_rbx, + gpr_rcx, + gpr_rdx, + gpr_rdi, + gpr_rsi, + gpr_rbp, + gpr_rsp, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_r14, + gpr_r15, + gpr_rip, + gpr_rflags, + gpr_cs, + 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, + fpu_xmm8, + fpu_xmm9, + fpu_xmm10, + fpu_xmm11, + fpu_xmm12, + fpu_xmm13, + fpu_xmm14, + fpu_xmm15, + + 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_dwarf_regnums +{ + gcc_dwarf_gpr_rax = 0, + gcc_dwarf_gpr_rdx, + gcc_dwarf_gpr_rcx, + gcc_dwarf_gpr_rbx, + gcc_dwarf_gpr_rsi, + gcc_dwarf_gpr_rdi, + gcc_dwarf_gpr_rbp, + gcc_dwarf_gpr_rsp, + gcc_dwarf_gpr_r8, + gcc_dwarf_gpr_r9, + gcc_dwarf_gpr_r10, + gcc_dwarf_gpr_r11, + gcc_dwarf_gpr_r12, + gcc_dwarf_gpr_r13, + gcc_dwarf_gpr_r14, + gcc_dwarf_gpr_r15, + gcc_dwarf_gpr_rip, + gcc_dwarf_fpu_xmm0, + gcc_dwarf_fpu_xmm1, + gcc_dwarf_fpu_xmm2, + gcc_dwarf_fpu_xmm3, + gcc_dwarf_fpu_xmm4, + gcc_dwarf_fpu_xmm5, + gcc_dwarf_fpu_xmm6, + gcc_dwarf_fpu_xmm7, + gcc_dwarf_fpu_xmm8, + gcc_dwarf_fpu_xmm9, + gcc_dwarf_fpu_xmm10, + gcc_dwarf_fpu_xmm11, + gcc_dwarf_fpu_xmm12, + gcc_dwarf_fpu_xmm13, + gcc_dwarf_fpu_xmm14, + gcc_dwarf_fpu_xmm15, + gcc_dwarf_fpu_stmm0, + gcc_dwarf_fpu_stmm1, + gcc_dwarf_fpu_stmm2, + gcc_dwarf_fpu_stmm3, + gcc_dwarf_fpu_stmm4, + gcc_dwarf_fpu_stmm5, + gcc_dwarf_fpu_stmm6, + gcc_dwarf_fpu_stmm7, + +}; + +enum gdb_regnums +{ + gdb_gpr_rax = 0, + gdb_gpr_rbx = 1, + gdb_gpr_rcx = 2, + gdb_gpr_rdx = 3, + gdb_gpr_rsi = 4, + gdb_gpr_rdi = 5, + gdb_gpr_rbp = 6, + gdb_gpr_rsp = 7, + gdb_gpr_r8 = 8, + gdb_gpr_r9 = 9, + gdb_gpr_r10 = 10, + gdb_gpr_r11 = 11, + gdb_gpr_r12 = 12, + gdb_gpr_r13 = 13, + gdb_gpr_r14 = 14, + gdb_gpr_r15 = 15, + gdb_gpr_rip = 16, + gdb_gpr_rflags = 17, + gdb_gpr_cs = 18, + gdb_gpr_ss = 19, + gdb_gpr_ds = 20, + gdb_gpr_es = 21, + gdb_gpr_fs = 22, + gdb_gpr_gs = 23, + gdb_fpu_stmm0 = 24, + gdb_fpu_stmm1 = 25, + gdb_fpu_stmm2 = 26, + gdb_fpu_stmm3 = 27, + gdb_fpu_stmm4 = 28, + gdb_fpu_stmm5 = 29, + gdb_fpu_stmm6 = 30, + gdb_fpu_stmm7 = 31, + gdb_fpu_fctrl = 32, gdb_fpu_fcw = gdb_fpu_fctrl, + gdb_fpu_fstat = 33, gdb_fpu_fsw = gdb_fpu_fstat, + gdb_fpu_ftag = 34, gdb_fpu_ftw = gdb_fpu_ftag, + gdb_fpu_fiseg = 35, gdb_fpu_cs = gdb_fpu_fiseg, + gdb_fpu_fioff = 36, gdb_fpu_ip = gdb_fpu_fioff, + gdb_fpu_foseg = 37, gdb_fpu_ds = gdb_fpu_foseg, + gdb_fpu_fooff = 38, gdb_fpu_dp = gdb_fpu_fooff, + gdb_fpu_fop = 39, + gdb_fpu_xmm0 = 40, + gdb_fpu_xmm1 = 41, + gdb_fpu_xmm2 = 42, + gdb_fpu_xmm3 = 43, + gdb_fpu_xmm4 = 44, + gdb_fpu_xmm5 = 45, + gdb_fpu_xmm6 = 46, + gdb_fpu_xmm7 = 47, + gdb_fpu_xmm8 = 48, + gdb_fpu_xmm9 = 49, + gdb_fpu_xmm10 = 50, + gdb_fpu_xmm11 = 51, + gdb_fpu_xmm12 = 52, + gdb_fpu_xmm13 = 53, + gdb_fpu_xmm14 = 54, + gdb_fpu_xmm15 = 55, + gdb_fpu_mxcsr = 56, +}; + +RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64 (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_x86_64::~RegisterContextDarwin_x86_64() +{ +} + +#define GPR_OFFSET(reg) (offsetof (RegisterContextDarwin_x86_64::GPR, reg)) +#define FPU_OFFSET(reg) (offsetof (RegisterContextDarwin_x86_64::FPU, reg) + sizeof (RegisterContextDarwin_x86_64::GPR)) +#define EXC_OFFSET(reg) (offsetof (RegisterContextDarwin_x86_64::EXC, reg) + sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::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_x86_64::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex +#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex +#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } +#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex + +#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU) + sizeof (RegisterContextDarwin_x86_64::EXC)) + +// General purpose registers for 64 bit +static RegisterInfo g_register_infos[] = +{ +// Macro auto defines most stuff GCC DWARF GENERIC GDB LLDB +// =============================== ====================== =================== ========================== ==================== ===================== + { DEFINE_GPR (rax , NULL) , { gcc_dwarf_gpr_rax , gcc_dwarf_gpr_rax , LLDB_INVALID_REGNUM , gdb_gpr_rax , gpr_rax }}, + { DEFINE_GPR (rbx , NULL) , { gcc_dwarf_gpr_rbx , gcc_dwarf_gpr_rbx , LLDB_INVALID_REGNUM , gdb_gpr_rbx , gpr_rbx }}, + { DEFINE_GPR (rcx , NULL) , { gcc_dwarf_gpr_rcx , gcc_dwarf_gpr_rcx , LLDB_INVALID_REGNUM , gdb_gpr_rcx , gpr_rcx }}, + { DEFINE_GPR (rdx , NULL) , { gcc_dwarf_gpr_rdx , gcc_dwarf_gpr_rdx , LLDB_INVALID_REGNUM , gdb_gpr_rdx , gpr_rdx }}, + { DEFINE_GPR (rdi , NULL) , { gcc_dwarf_gpr_rdi , gcc_dwarf_gpr_rdi , LLDB_INVALID_REGNUM , gdb_gpr_rdi , gpr_rdi }}, + { DEFINE_GPR (rsi , NULL) , { gcc_dwarf_gpr_rsi , gcc_dwarf_gpr_rsi , LLDB_INVALID_REGNUM , gdb_gpr_rsi , gpr_rsi }}, + { DEFINE_GPR (rbp , "fp") , { gcc_dwarf_gpr_rbp , gcc_dwarf_gpr_rbp , LLDB_REGNUM_GENERIC_FP , gdb_gpr_rbp , gpr_rbp }}, + { DEFINE_GPR (rsp , "sp") , { gcc_dwarf_gpr_rsp , gcc_dwarf_gpr_rsp , LLDB_REGNUM_GENERIC_SP , gdb_gpr_rsp , gpr_rsp }}, + { DEFINE_GPR (r8 , NULL) , { gcc_dwarf_gpr_r8 , gcc_dwarf_gpr_r8 , LLDB_INVALID_REGNUM , gdb_gpr_r8 , gpr_r8 }}, + { DEFINE_GPR (r9 , NULL) , { gcc_dwarf_gpr_r9 , gcc_dwarf_gpr_r9 , LLDB_INVALID_REGNUM , gdb_gpr_r9 , gpr_r9 }}, + { DEFINE_GPR (r10 , NULL) , { gcc_dwarf_gpr_r10 , gcc_dwarf_gpr_r10 , LLDB_INVALID_REGNUM , gdb_gpr_r10 , gpr_r10 }}, + { DEFINE_GPR (r11 , NULL) , { gcc_dwarf_gpr_r11 , gcc_dwarf_gpr_r11 , LLDB_INVALID_REGNUM , gdb_gpr_r11 , gpr_r11 }}, + { DEFINE_GPR (r12 , NULL) , { gcc_dwarf_gpr_r12 , gcc_dwarf_gpr_r12 , LLDB_INVALID_REGNUM , gdb_gpr_r12 , gpr_r12 }}, + { DEFINE_GPR (r13 , NULL) , { gcc_dwarf_gpr_r13 , gcc_dwarf_gpr_r13 , LLDB_INVALID_REGNUM , gdb_gpr_r13 , gpr_r13 }}, + { DEFINE_GPR (r14 , NULL) , { gcc_dwarf_gpr_r14 , gcc_dwarf_gpr_r14 , LLDB_INVALID_REGNUM , gdb_gpr_r14 , gpr_r14 }}, + { DEFINE_GPR (r15 , NULL) , { gcc_dwarf_gpr_r15 , gcc_dwarf_gpr_r15 , LLDB_INVALID_REGNUM , gdb_gpr_r15 , gpr_r15 }}, + { DEFINE_GPR (rip , "pc") , { gcc_dwarf_gpr_rip , gcc_dwarf_gpr_rip , LLDB_REGNUM_GENERIC_PC , gdb_gpr_rip , gpr_rip }}, + { DEFINE_GPR (rflags, "flags") , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags , gpr_rflags }}, + { DEFINE_GPR (cs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gpr_cs , gpr_cs }}, + { DEFINE_GPR (fs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gpr_fs , gpr_fs }}, + { DEFINE_GPR (gs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gpr_gs , gpr_gs }}, + + { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_fcw , fpu_fcw }}, + { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_fsw , fpu_fsw }}, + { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_ftw , fpu_ftw }}, + { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_fop , fpu_fop }}, + { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_ip , fpu_ip }}, + { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_cs , fpu_cs }}, + { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_dp , fpu_dp }}, + { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_ds , fpu_ds }}, + { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_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_FPU_VECT(xmm,8) }, + { DEFINE_FPU_VECT(xmm,9) }, + { DEFINE_FPU_VECT(xmm,10) }, + { DEFINE_FPU_VECT(xmm,11) }, + { DEFINE_FPU_VECT(xmm,12) }, + { DEFINE_FPU_VECT(xmm,13) }, + { DEFINE_FPU_VECT(xmm,14) }, + { DEFINE_FPU_VECT(xmm,15) }, + + { 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_x86_64::InvalidateAllRegisters () +{ + InvalidateAllRegisterStates(); +} + + +size_t +RegisterContextDarwin_x86_64::GetRegisterCount () +{ + assert(k_num_register_infos == k_num_registers); + return k_num_registers; +} + + +const RegisterInfo * +RegisterContextDarwin_x86_64::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_x86_64::GetRegisterInfosCount () +{ + return k_num_register_infos; +} + +const lldb_private::RegisterInfo * +RegisterContextDarwin_x86_64::GetRegisterInfos () +{ + return g_register_infos; +} + + + +static uint32_t g_gpr_regnums[] = +{ + gpr_rax, + gpr_rbx, + gpr_rcx, + gpr_rdx, + gpr_rdi, + gpr_rsi, + gpr_rbp, + gpr_rsp, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_r14, + gpr_r15, + gpr_rip, + gpr_rflags, + gpr_cs, + gpr_fs, + gpr_gs +}; + +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, + fpu_xmm8, + fpu_xmm9, + fpu_xmm10, + fpu_xmm11, + fpu_xmm12, + fpu_xmm13, + fpu_xmm14, + fpu_xmm15 +}; + +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_x86_64::GetRegisterSetCount () +{ + return k_num_regsets; +} + +const RegisterSet * +RegisterContextDarwin_x86_64::GetRegisterSet (uint32_t reg_set) +{ + if (reg_set < k_num_regsets) + return &g_reg_sets[reg_set]; + return NULL; +} + +int +RegisterContextDarwin_x86_64::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_x86_64::LogGPR(Log *log, const char *format, ...) +{ + if (log) + { + if (format) + { + va_list args; + va_start (args, format); + log->VAPrintf (format, args); + va_end (args); + } + for (uint32_t i=0; i<k_num_gpr_registers; i++) + { + uint32_t reg = gpr_rax + i; + log->Printf("%12s = 0x%16.16llx", g_register_infos[reg].name, (&gpr.rax)[reg]); + } + } +} + +int +RegisterContextDarwin_x86_64::ReadGPR (bool force) +{ + int set = GPRRegSet; + if (force || !RegisterSetIsCached(set)) + { + SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr)); + } + return GetError(GPRRegSet, Read); +} + +int +RegisterContextDarwin_x86_64::ReadFPU (bool force) +{ + int set = FPURegSet; + if (force || !RegisterSetIsCached(set)) + { + SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu)); + } + return GetError(FPURegSet, Read); +} + +int +RegisterContextDarwin_x86_64::ReadEXC (bool force) +{ + int set = EXCRegSet; + if (force || !RegisterSetIsCached(set)) + { + SetError(set, Read, DoReadEXC(GetThreadID(), set, exc)); + } + return GetError(EXCRegSet, Read); +} + +int +RegisterContextDarwin_x86_64::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_x86_64::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_x86_64::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_x86_64::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_x86_64::WriteRegisterSet(uint32_t set) +{ + // Make sure we have a valid context to set. + switch (set) + { + case GPRRegSet: return WriteGPR (); + case FPURegSet: return WriteFPU (); + case EXCRegSet: return WriteEXC (); + default: break; + } + return -1; +} + + +bool +RegisterContextDarwin_x86_64::ReadRegister (const RegisterInfo *reg_info, + RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum (reg); + if (set == -1) + return false; + + if (ReadRegisterSet(set, false) != 0) + return false; + + switch (reg) + { + case gpr_rax: + case gpr_rbx: + case gpr_rcx: + case gpr_rdx: + case gpr_rdi: + case gpr_rsi: + case gpr_rbp: + case gpr_rsp: + case gpr_r8: + case gpr_r9: + case gpr_r10: + case gpr_r11: + case gpr_r12: + case gpr_r13: + case gpr_r14: + case gpr_r15: + case gpr_rip: + case gpr_rflags: + case gpr_cs: + case gpr_fs: + case gpr_gs: + value = (&gpr.rax)[reg - gpr_rax]; + 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: + value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder()); + break; + + case fpu_xmm0: + case fpu_xmm1: + case fpu_xmm2: + case fpu_xmm3: + case fpu_xmm4: + case fpu_xmm5: + case fpu_xmm6: + case fpu_xmm7: + case fpu_xmm8: + case fpu_xmm9: + case fpu_xmm10: + case fpu_xmm11: + case fpu_xmm12: + case fpu_xmm13: + case fpu_xmm14: + case fpu_xmm15: + value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder()); + break; + + 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_x86_64::WriteRegister (const RegisterInfo *reg_info, + const RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum (reg); + + if (set == -1) + return false; + + if (ReadRegisterSet(set, false) != 0) + return false; + + switch (reg) + { + case gpr_rax: + case gpr_rbx: + case gpr_rcx: + case gpr_rdx: + case gpr_rdi: + case gpr_rsi: + case gpr_rbp: + case gpr_rsp: + case gpr_r8: + case gpr_r9: + case gpr_r10: + case gpr_r11: + case gpr_r12: + case gpr_r13: + case gpr_r14: + case gpr_r15: + case gpr_rip: + case gpr_rflags: + case gpr_cs: + case gpr_fs: + case gpr_gs: + (&gpr.rax)[reg - gpr_rax] = value.GetAsUInt64(); + 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: + ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize()); + break; + + case fpu_xmm0: + case fpu_xmm1: + case fpu_xmm2: + case fpu_xmm3: + case fpu_xmm4: + case fpu_xmm5: + case fpu_xmm6: + case fpu_xmm7: + case fpu_xmm8: + case fpu_xmm9: + case fpu_xmm10: + case fpu_xmm11: + case fpu_xmm12: + case fpu_xmm13: + case fpu_xmm14: + case fpu_xmm15: + ::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.GetAsUInt64(); + break; + + default: + return false; + } + return WriteRegisterSet(set) == 0; +} + +bool +RegisterContextDarwin_x86_64::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_x86_64::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_x86_64::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg) +{ + if (kind == eRegisterKindGeneric) + { + switch (reg) + { + case LLDB_REGNUM_GENERIC_PC: return gpr_rip; + case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; + case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; + case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; + case LLDB_REGNUM_GENERIC_RA: + default: + break; + } + } + else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) + { + switch (reg) + { + case gcc_dwarf_gpr_rax: return gpr_rax; + case gcc_dwarf_gpr_rdx: return gpr_rdx; + case gcc_dwarf_gpr_rcx: return gpr_rcx; + case gcc_dwarf_gpr_rbx: return gpr_rbx; + case gcc_dwarf_gpr_rsi: return gpr_rsi; + case gcc_dwarf_gpr_rdi: return gpr_rdi; + case gcc_dwarf_gpr_rbp: return gpr_rbp; + case gcc_dwarf_gpr_rsp: return gpr_rsp; + case gcc_dwarf_gpr_r8: return gpr_r8; + case gcc_dwarf_gpr_r9: return gpr_r9; + case gcc_dwarf_gpr_r10: return gpr_r10; + case gcc_dwarf_gpr_r11: return gpr_r11; + case gcc_dwarf_gpr_r12: return gpr_r12; + case gcc_dwarf_gpr_r13: return gpr_r13; + case gcc_dwarf_gpr_r14: return gpr_r14; + case gcc_dwarf_gpr_r15: return gpr_r15; + case gcc_dwarf_gpr_rip: return gpr_rip; + case gcc_dwarf_fpu_xmm0: return fpu_xmm0; + case gcc_dwarf_fpu_xmm1: return fpu_xmm1; + case gcc_dwarf_fpu_xmm2: return fpu_xmm2; + case gcc_dwarf_fpu_xmm3: return fpu_xmm3; + case gcc_dwarf_fpu_xmm4: return fpu_xmm4; + case gcc_dwarf_fpu_xmm5: return fpu_xmm5; + case gcc_dwarf_fpu_xmm6: return fpu_xmm6; + case gcc_dwarf_fpu_xmm7: return fpu_xmm7; + case gcc_dwarf_fpu_xmm8: return fpu_xmm8; + case gcc_dwarf_fpu_xmm9: return fpu_xmm9; + case gcc_dwarf_fpu_xmm10: return fpu_xmm10; + case gcc_dwarf_fpu_xmm11: return fpu_xmm11; + case gcc_dwarf_fpu_xmm12: return fpu_xmm12; + case gcc_dwarf_fpu_xmm13: return fpu_xmm13; + case gcc_dwarf_fpu_xmm14: return fpu_xmm14; + case gcc_dwarf_fpu_xmm15: return fpu_xmm15; + case gcc_dwarf_fpu_stmm0: return fpu_stmm0; + case gcc_dwarf_fpu_stmm1: return fpu_stmm1; + case gcc_dwarf_fpu_stmm2: return fpu_stmm2; + case gcc_dwarf_fpu_stmm3: return fpu_stmm3; + case gcc_dwarf_fpu_stmm4: return fpu_stmm4; + case gcc_dwarf_fpu_stmm5: return fpu_stmm5; + case gcc_dwarf_fpu_stmm6: return fpu_stmm6; + case gcc_dwarf_fpu_stmm7: return fpu_stmm7; + default: + break; + } + } + else if (kind == eRegisterKindGDB) + { + switch (reg) + { + case gdb_gpr_rax : return gpr_rax; + case gdb_gpr_rbx : return gpr_rbx; + case gdb_gpr_rcx : return gpr_rcx; + case gdb_gpr_rdx : return gpr_rdx; + case gdb_gpr_rsi : return gpr_rsi; + case gdb_gpr_rdi : return gpr_rdi; + case gdb_gpr_rbp : return gpr_rbp; + case gdb_gpr_rsp : return gpr_rsp; + case gdb_gpr_r8 : return gpr_r8; + case gdb_gpr_r9 : return gpr_r9; + case gdb_gpr_r10 : return gpr_r10; + case gdb_gpr_r11 : return gpr_r11; + case gdb_gpr_r12 : return gpr_r12; + case gdb_gpr_r13 : return gpr_r13; + case gdb_gpr_r14 : return gpr_r14; + case gdb_gpr_r15 : return gpr_r15; + case gdb_gpr_rip : return gpr_rip; + case gdb_gpr_rflags : return gpr_rflags; + case gdb_gpr_cs : return gpr_cs; + case gdb_gpr_ss : return gpr_gs; // HACK: For now for "ss", just copy what is in "gs" + case gdb_gpr_ds : return gpr_gs; // HACK: For now for "ds", just copy what is in "gs" + case gdb_gpr_es : return gpr_gs; // HACK: For now for "es", just copy what is in "gs" + case gdb_gpr_fs : return gpr_fs; + case gdb_gpr_gs : return gpr_gs; + case gdb_fpu_stmm0 : return fpu_stmm0; + case gdb_fpu_stmm1 : return fpu_stmm1; + case gdb_fpu_stmm2 : return fpu_stmm2; + case gdb_fpu_stmm3 : return fpu_stmm3; + case gdb_fpu_stmm4 : return fpu_stmm4; + case gdb_fpu_stmm5 : return fpu_stmm5; + case gdb_fpu_stmm6 : return fpu_stmm6; + case gdb_fpu_stmm7 : return fpu_stmm7; + case gdb_fpu_fctrl : return fpu_fctrl; + case gdb_fpu_fstat : return fpu_fstat; + case gdb_fpu_ftag : return fpu_ftag; + case gdb_fpu_fiseg : return fpu_fiseg; + case gdb_fpu_fioff : return fpu_fioff; + case gdb_fpu_foseg : return fpu_foseg; + case gdb_fpu_fooff : return fpu_fooff; + case gdb_fpu_fop : return fpu_fop; + case gdb_fpu_xmm0 : return fpu_xmm0; + case gdb_fpu_xmm1 : return fpu_xmm1; + case gdb_fpu_xmm2 : return fpu_xmm2; + case gdb_fpu_xmm3 : return fpu_xmm3; + case gdb_fpu_xmm4 : return fpu_xmm4; + case gdb_fpu_xmm5 : return fpu_xmm5; + case gdb_fpu_xmm6 : return fpu_xmm6; + case gdb_fpu_xmm7 : return fpu_xmm7; + case gdb_fpu_xmm8 : return fpu_xmm8; + case gdb_fpu_xmm9 : return fpu_xmm9; + case gdb_fpu_xmm10 : return fpu_xmm10; + case gdb_fpu_xmm11 : return fpu_xmm11; + case gdb_fpu_xmm12 : return fpu_xmm12; + case gdb_fpu_xmm13 : return fpu_xmm13; + case gdb_fpu_xmm14 : return fpu_xmm14; + case gdb_fpu_xmm15 : return fpu_xmm15; + case gdb_fpu_mxcsr : return fpu_mxcsr; + default: + break; + } + } + else if (kind == eRegisterKindLLDB) + { + return reg; + } + return LLDB_INVALID_REGNUM; +} + +bool +RegisterContextDarwin_x86_64::HardwareSingleStep (bool enable) +{ + if (ReadGPR(true) != 0) + return false; + + const uint64_t trace_bit = 0x100ull; + if (enable) + { + + if (gpr.rflags & trace_bit) + return true; // trace bit is already set, there is nothing to do + else + gpr.rflags |= trace_bit; + } + else + { + if (gpr.rflags & trace_bit) + gpr.rflags &= ~trace_bit; + else + return true; // trace bit is clear, there is nothing to do + } + + return WriteGPR() == 0; +} + diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h new file mode 100644 index 00000000000..b2ed0859092 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h @@ -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_ diff --git a/lldb/source/Utility/ARM_GCC_Registers.h b/lldb/source/Utility/ARM_GCC_Registers.h index e315b69bb27..974d01bfc78 100644 --- a/lldb/source/Utility/ARM_GCC_Registers.h +++ b/lldb/source/Utility/ARM_GCC_Registers.h @@ -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_ |