aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins')
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp47
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp58
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h24
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp157
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h6
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp36
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp4
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp115
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h36
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp159
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h24
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp2
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.h6
-rw-r--r--source/Plugins/Instruction/ARM/EmulationStateARM.h2
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp2
-rw-r--r--source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp19
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp85
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h5
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp2
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp61
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h8
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp541
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h111
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp113
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h52
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp44
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.h3
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp196
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h27
-rw-r--r--source/Plugins/Process/POSIX/POSIXThread.cpp156
-rw-r--r--source/Plugins/Process/POSIX/POSIXThread.h16
-rw-r--r--source/Plugins/Process/POSIX/ProcessMessage.cpp6
-rw-r--r--source/Plugins/Process/POSIX/ProcessMessage.h14
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.cpp103
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.h8
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp78
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h29
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp90
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h29
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp129
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h15
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp96
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextLinux_i386.h29
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp151
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h15
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX.h50
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp318
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h95
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp634
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h95
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp238
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h138
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp666
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h462
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_i386.cpp551
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_i386.h169
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_mips64.h104
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_x86.h541
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp1563
-rw-r--r--source/Plugins/Process/POSIX/RegisterContext_x86_64.h347
-rw-r--r--source/Plugins/Process/POSIX/RegisterInfos_i386.h207
-rw-r--r--source/Plugins/Process/POSIX/RegisterInfos_mips64.h74
-rw-r--r--source/Plugins/Process/POSIX/RegisterInfos_x86_64.h409
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.cpp456
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.h17
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.cpp11
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp69
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp4
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp16
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp18
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp68
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h47
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp68
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h54
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp94
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h58
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp92
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h58
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.cpp25
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp41
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp497
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h70
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp623
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h75
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp6
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h156
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp219
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h10
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp37
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.h3
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAttribute.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp32
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h3
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp30
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h43
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp41
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp42
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp39
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h23
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp10
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDefines.h1
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp12
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.h15
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp8
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationList.h8
-rw-r--r--source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h10
-rw-r--r--source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp9
-rw-r--r--source/Plugins/SymbolFile/DWARF/NameToDIE.cpp1
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp150
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h64
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp2
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp4
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp19
135 files changed, 8740 insertions, 4370 deletions
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index 4685c3e759e0..f27c294a4abd 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -580,32 +580,13 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
bool
ABIMacOSX_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
{
- uint32_t reg_kind = unwind_plan.GetRegisterKind();
- uint32_t lr_reg_num = LLDB_INVALID_REGNUM;
- uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
- uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
-
- switch (reg_kind)
- {
- case eRegisterKindDWARF:
- case eRegisterKindGCC:
- lr_reg_num = dwarf_lr;
- sp_reg_num = dwarf_sp;
- pc_reg_num = dwarf_pc;
- break;
-
- case eRegisterKindGeneric:
- lr_reg_num = LLDB_REGNUM_GENERIC_RA;
- sp_reg_num = LLDB_REGNUM_GENERIC_SP;
- pc_reg_num = LLDB_REGNUM_GENERIC_PC;
- break;
- }
-
- if (lr_reg_num == LLDB_INVALID_REGNUM ||
- sp_reg_num == LLDB_INVALID_REGNUM ||
- pc_reg_num == LLDB_INVALID_REGNUM)
- return false;
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+ uint32_t lr_reg_num = dwarf_lr;
+ uint32_t sp_reg_num = dwarf_sp;
+ uint32_t pc_reg_num = dwarf_pc;
+
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
@@ -626,14 +607,15 @@ ABIMacOSX_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
bool
ABIMacOSX_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
{
- uint32_t fp_reg_num = dwarf_r7; // apple uses r7 for all frames. Normal arm uses r11;
+ unwind_plan.Clear ();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t fp_reg_num = dwarf_r7; // apple uses r7 for all frames. Normal arm uses r11
uint32_t pc_reg_num = dwarf_pc;
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
- unwind_plan.Clear ();
- unwind_plan.SetRegisterKind (eRegisterKindDWARF);
row->SetCFARegister (fp_reg_num);
row->SetCFAOffset (2 * ptr_size);
row->SetOffset (0);
@@ -649,6 +631,11 @@ ABIMacOSX_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
return true;
}
+// cf. "ARMv6 Function Calling Conventions"
+// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
+// and "ARMv7 Function Calling Conventions"
+// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv7FunctionCallingConventions.html
+
// ARMv7 on iOS general purpose reg rules:
// r0-r3 not preserved (used for argument passing)
// r4-r6 preserved
@@ -672,7 +659,7 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info)
{
if (reg_info)
{
- // Volatile registers include: r0, r1, r2, r3, r9, r12, r13
+ // Volatile registers are: r0, r1, r2, r3, r9, r12, r13 (aka sp)
const char *name = reg_info->name;
if (name[0] == 'r')
{
@@ -686,7 +673,7 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info)
return true; // r1
case '2':
case '3':
- return name[2] == '\0'; // r12 - r13
+ return name[3] == '\0'; // r12, r13 (sp)
default:
break;
}
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index deb531d937a0..ecf44b9c4f73 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -235,12 +235,22 @@ ABIMacOSX_i386::GetRedZoneSize () const
ABISP
ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
{
- static ABISP g_abi_sp;
+ static ABISP g_abi_mac_sp;
+ static ABISP g_abi_other_sp;
if (arch.GetTriple().getArch() == llvm::Triple::x86)
{
- if (!g_abi_sp)
- g_abi_sp.reset (new ABIMacOSX_i386);
- return g_abi_sp;
+ if (arch.GetTriple().isOSDarwin())
+ {
+ if (!g_abi_mac_sp)
+ g_abi_mac_sp.reset (new ABIMacOSX_i386(true));
+ return g_abi_mac_sp;
+ }
+ else
+ {
+ if (!g_abi_other_sp)
+ g_abi_other_sp.reset (new ABIMacOSX_i386(false));
+ return g_abi_other_sp;
+ }
}
return ABISP();
}
@@ -823,37 +833,12 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
bool
ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
{
- uint32_t reg_kind = unwind_plan.GetRegisterKind();
- uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
- uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
-
- switch (reg_kind)
- {
- case eRegisterKindDWARF:
- sp_reg_num = dwarf_esp;
- pc_reg_num = dwarf_eip;
- break;
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- case eRegisterKindGCC:
- sp_reg_num = gcc_esp;
- pc_reg_num = gcc_eip;
- break;
-
- case eRegisterKindGDB:
- sp_reg_num = gdb_esp;
- pc_reg_num = gdb_eip;
- break;
-
- case eRegisterKindGeneric:
- sp_reg_num = LLDB_REGNUM_GENERIC_SP;
- pc_reg_num = LLDB_REGNUM_GENERIC_PC;
- break;
- }
+ uint32_t sp_reg_num = dwarf_esp;
+ uint32_t pc_reg_num = dwarf_eip;
- if (sp_reg_num == LLDB_INVALID_REGNUM ||
- pc_reg_num == LLDB_INVALID_REGNUM)
- return false;
-
UnwindPlan::RowSP row(new UnwindPlan::Row);
row->SetCFARegister (sp_reg_num);
row->SetCFAOffset (4);
@@ -867,6 +852,9 @@ ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
bool
ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
{
+ unwind_plan.Clear ();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
uint32_t fp_reg_num = dwarf_ebp;
uint32_t sp_reg_num = dwarf_esp;
uint32_t pc_reg_num = dwarf_eip;
@@ -874,15 +862,13 @@ ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
- unwind_plan.Clear ();
- unwind_plan.SetRegisterKind (eRegisterKindDWARF);
row->SetCFARegister (fp_reg_num);
row->SetCFAOffset (2 * ptr_size);
row->SetOffset (0);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
- row->SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size * 0, true);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("i386 default unwind plan");
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
index 8c2d945e6342..5428d0c1e44e 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
@@ -79,9 +79,21 @@ public:
virtual bool
CallFrameAddressIsValid (lldb::addr_t cfa)
{
- // Make sure the stack call frame addresses are are 8 byte aligned
- if (cfa & (8ull - 1ull))
- return false; // Not 8 byte aligned
+ // Darwin call frame addresses must be 16-byte aligned, but other OS's
+ // only need 4-byte alignment. Otherwise the ABI matches, so we have
+ // this one minor override here.
+ if (target_is_darwin)
+ {
+ // Make sure the stack call frame addresses are are 16 byte aligned
+ if (cfa & (16ull - 1ull))
+ return false; // Not 16 byte aligned
+ }
+ else
+ {
+ // Make sure the stack call frame addresses are are 4 byte aligned
+ if (cfa & (4ull - 1ull))
+ return false; // Not 4 byte aligned
+ }
if (cfa == 0)
return false; // Zero is not a valid stack address
return true;
@@ -132,7 +144,11 @@ protected:
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABIMacOSX_i386(bool is_darwin) : lldb_private::ABI(),
+ target_is_darwin(is_darwin)
+ { } // Call CreateInstance instead.
+
+ bool target_is_darwin;
};
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
index a904d8b649ca..a8cf714a13b3 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -354,7 +354,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
const RegisterInfo *reg_info = NULL;
if (arg1_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("rdi", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
if (log)
log->Printf("About to write arg1 (0x%" PRIx64 ") into %s", (uint64_t)*arg1_ptr, reg_info->name);
@@ -363,7 +363,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (arg2_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("rsi", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
if (log)
log->Printf("About to write arg2 (0x%" PRIx64 ") into %s", (uint64_t)*arg2_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg2_ptr))
@@ -371,7 +371,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (arg3_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("rdx", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3);
if (log)
log->Printf("About to write arg3 (0x%" PRIx64 ") into %s", (uint64_t)*arg3_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg3_ptr))
@@ -379,7 +379,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (arg4_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("rcx", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4);
if (log)
log->Printf("About to write arg4 (0x%" PRIx64 ") into %s", (uint64_t)*arg4_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg4_ptr))
@@ -387,7 +387,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (arg5_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("r8", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5);
if (log)
log->Printf("About to write arg5 (0x%" PRIx64 ") into %s", (uint64_t)*arg5_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg5_ptr))
@@ -395,7 +395,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
if (arg6_ptr)
{
- reg_info = reg_ctx->GetRegisterInfoByName("r9", 0);
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6);
if (log)
log->Printf("About to write arg6 (0x%" PRIx64 ") into %s", (uint64_t)*arg6_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg6_ptr))
@@ -415,32 +415,75 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
sp &= ~(0xfull); // 16-byte alignment
- // The return address is pushed onto the stack (yes after the alignment...)
sp -= 8;
+ Error error;
+ const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ ProcessSP process_sp (thread.GetProcess());
+
RegisterValue reg_value;
- reg_value.SetUInt64 (return_addr);
+#if 0
+ // This code adds an extra frame so that we don't lose the function that we came from
+ // by pushing the PC and the FP and then writing the current FP to point to the FP value
+ // we just pushed. It is disabled for now until the stack backtracing code can be debugged.
+
+ // Save current PC
+ const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+ if (reg_ctx->ReadRegister(pc_reg_info, reg_value))
+ {
+ if (log)
+ log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64());
+
+ if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error))
+ return false;
+
+ sp -= 8;
+
+ // Save current FP
+ if (reg_ctx->ReadRegister(fp_reg_info, reg_value))
+ {
+ if (log)
+ log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64());
+
+ if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error))
+ return false;
+ }
+ // Setup FP backchain
+ reg_value.SetUInt64 (sp);
+
+ if (log)
+ log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64());
+
+ if (!reg_ctx->WriteRegister(fp_reg_info, reg_value))
+ {
+ return false;
+ }
+
+ sp -= 8;
+ }
+#endif
+
if (log)
- log->Printf("Pushing the return address onto the stack: new SP 0x%" PRIx64 ", return address 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr);
+ log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr);
- const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfoByName("rip");
- Error error (reg_ctx->WriteRegisterValueToMemory(pc_reg_info, sp, pc_reg_info->byte_size, reg_value));
- if (error.Fail())
+ // Save return address onto the stack
+ if (!process_sp->WritePointerToMemory(sp, return_addr, error))
return false;
// %rsp is set to the actual stack value.
if (log)
- log->Printf("Writing SP (0x%" PRIx64 ") down", (uint64_t)sp);
+ log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
- if (!reg_ctx->WriteRegisterFromUnsigned (reg_ctx->GetRegisterInfoByName("rsp"), sp))
+ if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
return false;
// %rip is set to the address of the called function.
if (log)
- log->Printf("Writing new IP (0x%" PRIx64 ") down", (uint64_t)func_addr);
+ log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr);
if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
return false;
@@ -506,12 +549,12 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread,
uint32_t argument_register_ids[6];
- argument_register_ids[0] = reg_ctx->GetRegisterInfoByName("rdi", 0)->kinds[eRegisterKindLLDB];
- argument_register_ids[1] = reg_ctx->GetRegisterInfoByName("rsi", 0)->kinds[eRegisterKindLLDB];
- argument_register_ids[2] = reg_ctx->GetRegisterInfoByName("rdx", 0)->kinds[eRegisterKindLLDB];
- argument_register_ids[3] = reg_ctx->GetRegisterInfoByName("rcx", 0)->kinds[eRegisterKindLLDB];
- argument_register_ids[4] = reg_ctx->GetRegisterInfoByName("r8", 0)->kinds[eRegisterKindLLDB];
- argument_register_ids[5] = reg_ctx->GetRegisterInfoByName("r9", 0)->kinds[eRegisterKindLLDB];
+ argument_register_ids[0] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)->kinds[eRegisterKindLLDB];
+ argument_register_ids[1] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)->kinds[eRegisterKindLLDB];
+ argument_register_ids[2] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)->kinds[eRegisterKindLLDB];
+ argument_register_ids[3] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)->kinds[eRegisterKindLLDB];
+ argument_register_ids[4] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)->kinds[eRegisterKindLLDB];
+ argument_register_ids[5] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6)->kinds[eRegisterKindLLDB];
unsigned int current_argument_register = 0;
@@ -1085,33 +1128,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
bool
ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
{
- uint32_t reg_kind = unwind_plan.GetRegisterKind();
- uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
- uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t sp_reg_num = gcc_dwarf_rsp;
+ uint32_t pc_reg_num = gcc_dwarf_rip;
- switch (reg_kind)
- {
- case eRegisterKindDWARF:
- case eRegisterKindGCC:
- sp_reg_num = gcc_dwarf_rsp;
- pc_reg_num = gcc_dwarf_rip;
- break;
-
- case eRegisterKindGDB:
- sp_reg_num = gdb_rsp;
- pc_reg_num = gdb_rip;
- break;
-
- case eRegisterKindGeneric:
- sp_reg_num = LLDB_REGNUM_GENERIC_SP;
- pc_reg_num = LLDB_REGNUM_GENERIC_PC;
- break;
- }
-
- if (sp_reg_num == LLDB_INVALID_REGNUM ||
- pc_reg_num == LLDB_INVALID_REGNUM)
- return false;
-
UnwindPlan::RowSP row(new UnwindPlan::Row);
row->SetCFARegister (sp_reg_num);
row->SetCFAOffset (8);
@@ -1125,48 +1147,23 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
bool
ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
{
- uint32_t reg_kind = unwind_plan.GetRegisterKind();
- uint32_t fp_reg_num = LLDB_INVALID_REGNUM;
- uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
- uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
-
- switch (reg_kind)
- {
- case eRegisterKindDWARF:
- case eRegisterKindGCC:
- fp_reg_num = gcc_dwarf_rbp;
- sp_reg_num = gcc_dwarf_rsp;
- pc_reg_num = gcc_dwarf_rip;
- break;
-
- case eRegisterKindGDB:
- fp_reg_num = gdb_rbp;
- sp_reg_num = gdb_rsp;
- pc_reg_num = gdb_rip;
- break;
-
- case eRegisterKindGeneric:
- fp_reg_num = LLDB_REGNUM_GENERIC_FP;
- sp_reg_num = LLDB_REGNUM_GENERIC_SP;
- pc_reg_num = LLDB_REGNUM_GENERIC_PC;
- break;
- }
-
- if (fp_reg_num == LLDB_INVALID_REGNUM ||
- sp_reg_num == LLDB_INVALID_REGNUM ||
- pc_reg_num == LLDB_INVALID_REGNUM)
- return false;
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+ uint32_t fp_reg_num = gcc_dwarf_rbp;
+ uint32_t sp_reg_num = gcc_dwarf_rsp;
+ uint32_t pc_reg_num = gcc_dwarf_rip;
+
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
- row->SetCFARegister (LLDB_REGNUM_GENERIC_FP);
+ row->SetCFARegister (gcc_dwarf_rbp);
row->SetCFAOffset (2 * ptr_size);
row->SetOffset (0);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
- row->SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size * 0, true);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("x86_64 default unwind plan");
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
index b10181960e89..d9d6fd7af79a 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -76,9 +76,9 @@ public:
virtual bool
CallFrameAddressIsValid (lldb::addr_t cfa)
{
- // Make sure the stack call frame addresses are are 8 byte aligned
- if (cfa & (8ull - 1ull))
- return false; // Not 8 byte aligned
+ // Make sure the stack call frame addresses are 16 byte aligned
+ if (cfa & (16ull - 1ull))
+ return false; // Not 16 byte aligned
if (cfa == 0)
return false; // Zero is not a valid stack address
return true;
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index e920d70cd596..61c3c64d4fc3 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -38,7 +38,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/StackFrame.h"
-#include <regex.h>
+#include "lldb/Core/RegularExpression.h"
using namespace lldb;
using namespace lldb_private;
@@ -369,20 +369,14 @@ public:
}
}
- if (!s_regex_compiled)
- {
- ::regcomp(&s_regex, "[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED);
- s_regex_compiled = true;
- }
+ static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED);
- ::regmatch_t matches[3];
+ RegularExpression::Match matches(3);
- if (!::regexec(&s_regex, out_string, sizeof(matches) / sizeof(::regmatch_t), matches, 0))
+ if (s_regex.Execute(out_string, &matches))
{
- if (matches[1].rm_so != -1)
- m_opcode_name.assign(out_string + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
- if (matches[2].rm_so != -1)
- m_mnemonics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
+ matches.GetMatchAtIndex(out_string, 1, m_opcode_name);
+ matches.GetMatchAtIndex(out_string, 2, m_mnemonics);
}
}
}
@@ -415,13 +409,9 @@ protected:
LazyBool m_does_branch;
bool m_is_valid;
bool m_using_file_addr;
-
- static bool s_regex_compiled;
- static ::regex_t s_regex;
};
-bool InstructionLLVMC::s_regex_compiled = false;
-::regex_t InstructionLLVMC::s_regex;
+
DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner):
m_is_valid(true)
@@ -651,9 +641,15 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
}
// Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions,
- // so hardcode the primary disassembler to thumb mode.
+ // so hardcode the primary disassembler to thumb mode. Same for Cortex-M4 (armv7em).
+ //
+ // Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32
+ // instructions defined in ARMv7-A.
+
if (arch.GetTriple().getArch() == llvm::Triple::arm
- && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em))
+ && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m
+ || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em
+ || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))
{
triple = thumb_arch.GetTriple().getTriple().c_str();
}
@@ -796,7 +792,7 @@ int DisassemblerLLVMC::OpInfo (uint64_t PC,
default:
break;
case 1:
- bzero (tag_bug, sizeof(::LLVMOpInfo1));
+ memset (tag_bug, 0, sizeof(::LLVMOpInfo1));
break;
}
return 0;
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
index 2604ae670164..c079d0fc381f 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
@@ -19,7 +19,7 @@
#include "lldb/Core/Log.h"
#include "lldb/Target/Process.h"
-#if defined(__linux__) or defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__)
#include "Plugins/Process/elf-core/ProcessElfCore.h"
#endif
@@ -57,7 +57,7 @@ ParseAuxvEntry(DataExtractor &data,
DataBufferSP
AuxVector::GetAuxvData()
{
-#if defined(__linux__) or defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__)
if (m_process->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
return static_cast<ProcessElfCore *>(m_process)->GetAuxvData();
#endif
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 3e1b52938f49..3c5dcc5222af 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -30,17 +31,14 @@ ResolveRendezvousAddress(Process *process)
addr_t info_location;
addr_t info_addr;
Error error;
- size_t size;
info_location = process->GetImageInfoAddress();
if (info_location == LLDB_INVALID_ADDRESS)
return LLDB_INVALID_ADDRESS;
- info_addr = 0;
- size = process->DoReadMemory(info_location, &info_addr,
- process->GetAddressByteSize(), error);
- if (size != process->GetAddressByteSize() || error.Fail())
+ info_addr = process->ReadPointerFromMemory(info_location, error);
+ if (error.Fail())
return LLDB_INVALID_ADDRESS;
if (info_addr == 0)
@@ -58,6 +56,8 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
m_added_soentries(),
m_removed_soentries()
{
+ m_thread_info.valid = false;
+
// Cache a copy of the executable path
if (m_process)
{
@@ -88,19 +88,19 @@ DYLDRendezvous::Resolve()
if (cursor == LLDB_INVALID_ADDRESS)
return false;
- if (!(cursor = ReadMemory(cursor, &info.version, word_size)))
+ if (!(cursor = ReadWord(cursor, &info.version, word_size)))
return false;
- if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))
+ if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
return false;
- if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))
+ if (!(cursor = ReadPointer(cursor, &info.brk)))
return false;
- if (!(cursor = ReadMemory(cursor, &info.state, word_size)))
+ if (!(cursor = ReadWord(cursor, &info.state, word_size)))
return false;
- if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))
+ if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
return false;
// The rendezvous was successfully read. Update our internal state.
@@ -234,16 +234,27 @@ DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
}
addr_t
-DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)
+DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size)
{
- size_t bytes_read;
Error error;
- bytes_read = m_process->DoReadMemory(addr, dst, size, error);
- if (bytes_read != size || error.Fail())
+ *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
+ if (error.Fail())
return 0;
- return addr + bytes_read;
+ return addr + size;
+}
+
+addr_t
+DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst)
+{
+ Error error;
+
+ *dst = m_process->ReadPointerFromMemory(addr, error);
+ if (error.Fail())
+ return 0;
+
+ return addr + m_process->GetAddressByteSize();
}
std::string
@@ -275,23 +286,38 @@ DYLDRendezvous::ReadStringFromMemory(addr_t addr)
bool
DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
{
- size_t address_size = m_process->GetAddressByteSize();
-
entry.clear();
+
+ entry.link_addr = addr;
- if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))
+ if (!(addr = ReadPointer(addr, &entry.base_addr)))
return false;
+
+ // mips adds an extra load offset field to the link map struct on
+ // FreeBSD and NetBSD (need to validate other OSes).
+ // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57
+ const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
+ if (arch.GetCore() == ArchSpec::eCore_mips64)
+ {
+ assert (arch.GetTriple().getOS() == llvm::Triple::FreeBSD ||
+ arch.GetTriple().getOS() == llvm::Triple::NetBSD);
+ addr_t mips_l_offs;
+ if (!(addr = ReadPointer(addr, &mips_l_offs)))
+ return false;
+ if (mips_l_offs != 0 && mips_l_offs != entry.base_addr)
+ return false;
+ }
- if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))
+ if (!(addr = ReadPointer(addr, &entry.path_addr)))
return false;
- if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))
+ if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
return false;
- if (!(addr = ReadMemory(addr, &entry.next, address_size)))
+ if (!(addr = ReadPointer(addr, &entry.next)))
return false;
- if (!(addr = ReadMemory(addr, &entry.prev, address_size)))
+ if (!(addr = ReadPointer(addr, &entry.prev)))
return false;
entry.path = ReadStringFromMemory(entry.path_addr);
@@ -299,6 +325,51 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
return true;
}
+
+bool
+DYLDRendezvous::FindMetadata(const char *name, PThreadField field, uint32_t& value)
+{
+ Target& target = m_process->GetTarget();
+
+ SymbolContextList list;
+ if (!target.GetImages().FindSymbolsWithNameAndType (ConstString(name), eSymbolTypeAny, list))
+ return false;
+
+ Address address = list[0].symbol->GetAddress();
+ addr_t addr = address.GetLoadAddress (&target);
+ if (addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ Error error;
+ value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(addr + field*sizeof(uint32_t), sizeof(uint32_t), 0, error);
+ if (error.Fail())
+ return false;
+
+ if (field == eSize)
+ value /= 8; // convert bits to bytes
+
+ return true;
+}
+
+const DYLDRendezvous::ThreadInfo&
+DYLDRendezvous::GetThreadInfo()
+{
+ if (!m_thread_info.valid)
+ {
+ bool ok = true;
+
+ ok &= FindMetadata ("_thread_db_pthread_dtvp", eOffset, m_thread_info.dtv_offset);
+ ok &= FindMetadata ("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
+ ok &= FindMetadata ("_thread_db_link_map_l_tls_modid", eOffset, m_thread_info.modid_offset);
+ ok &= FindMetadata ("_thread_db_dtv_t_pointer_val", eOffset, m_thread_info.tls_offset);
+
+ if (ok)
+ m_thread_info.valid = true;
+ }
+
+ return m_thread_info;
+}
+
void
DYLDRendezvous::DumpToLog(Log *log) const
{
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index 67e7228a38de..ca0089317998 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -48,6 +48,16 @@ class DYLDRendezvous {
};
public:
+ // Various metadata supplied by the inferior's threading library to describe
+ // the per-thread state.
+ struct ThreadInfo {
+ bool valid; // whether we read valid metadata
+ uint32_t dtv_offset; // offset of DTV pointer within pthread
+ uint32_t dtv_slot_size; // size of one DTV slot
+ uint32_t modid_offset; // offset of module ID within link_map
+ uint32_t tls_offset; // offset of TLS pointer within DTV slot
+ };
+
DYLDRendezvous(lldb_private::Process *process);
/// Update the internal snapshot of runtime linker rendezvous and recompute
@@ -100,6 +110,10 @@ public:
lldb::addr_t
GetLDBase() const { return m_current.ldbase; }
+ /// @returns the thread layout metadata from the inferiors thread library.
+ const ThreadInfo&
+ GetThreadInfo();
+
/// @returns true if modules have been loaded into the inferior since the
/// last call to Resolve().
bool
@@ -128,6 +142,7 @@ public:
/// This object is a rough analogue to the struct link_map object which
/// actually lives in the inferiors memory.
struct SOEntry {
+ lldb::addr_t link_addr; ///< Address of this link_map.
lldb::addr_t base_addr; ///< Base address of the loaded object.
lldb::addr_t path_addr; ///< String naming the shared object.
lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
@@ -142,6 +157,7 @@ public:
}
void clear() {
+ link_addr = 0;
base_addr = 0;
path_addr = 0;
dyn_addr = 0;
@@ -194,12 +210,22 @@ protected:
/// Resolve().
SOEntryList m_removed_soentries;
- /// Reads @p size bytes from the inferiors address space starting at @p
- /// addr.
+ /// Threading metadata read from the inferior.
+ ThreadInfo m_thread_info;
+
+ /// Reads an unsigned integer of @p size bytes from the inferior's address
+ /// space starting at @p addr.
///
/// @returns addr + size if the read was successful and false otherwise.
lldb::addr_t
- ReadMemory(lldb::addr_t addr, void *dst, size_t size);
+ ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size);
+
+ /// Reads an address from the inferior's address space starting at @p addr.
+ ///
+ /// @returns addr + target address size if the read was successful and
+ /// 0 otherwise.
+ lldb::addr_t
+ ReadPointer(lldb::addr_t addr, lldb::addr_t *dst);
/// Reads a null-terminated C string from the memory location starting at @p
/// addr.
@@ -225,6 +251,10 @@ protected:
/// supplied by the runtime linker.
bool
TakeSnapshot(SOEntryList &entry_list);
+
+ enum PThreadField { eSize, eNElem, eOffset };
+
+ bool FindMetadata(const char *name, PThreadField field, uint32_t& value);
};
#endif
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 91c7cd3dfca7..4284558c4409 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -123,7 +123,7 @@ DynamicLoaderPOSIXDYLD::DidAttach()
{
ModuleList module_list;
module_list.Append(executable);
- UpdateLoadedSections(executable, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
LoadAllCurrentModules();
m_process->GetTarget().ModulesDidLoad(module_list);
}
@@ -144,7 +144,7 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
{
ModuleList module_list;
module_list.Append(executable);
- UpdateLoadedSections(executable, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
ProbeEntry();
m_process->GetTarget().ModulesDidLoad(module_list);
}
@@ -209,11 +209,15 @@ DynamicLoaderPOSIXDYLD::CanLoadImage()
}
void
-DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
+DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
{
- ObjectFile *obj_file = module->GetObjectFile();
- SectionList *sections = obj_file->GetSectionList();
SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
+ const SectionList *sections = GetSectionListFromModule(module);
+
+ assert(sections && "SectionList missing from loaded module.");
+
+ m_loaded_modules[module] = link_map_addr;
+
const size_t num_sections = sections->GetSize();
for (unsigned i = 0; i < num_sections; ++i)
@@ -234,6 +238,24 @@ DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
}
void
+DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module)
+{
+ SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
+ const SectionList *sections = GetSectionListFromModule(module);
+
+ assert(sections && "SectionList missing from unloaded module.");
+
+ m_loaded_modules.erase(module);
+
+ const size_t num_sections = sections->GetSize();
+ for (size_t i = 0; i < num_sections; ++i)
+ {
+ SectionSP section_sp (sections->GetSectionAtIndex(i));
+ load_list.SetSectionUnloaded(section_sp);
+ }
+}
+
+void
DynamicLoaderPOSIXDYLD::ProbeEntry()
{
Breakpoint *entry_break;
@@ -242,7 +264,7 @@ DynamicLoaderPOSIXDYLD::ProbeEntry()
if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
return;
- entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();
+ entry_break = m_process->GetTarget().CreateBreakpoint(entry, true, false).get();
entry_break->SetCallback(EntryBreakpointHit, this, true);
entry_break->SetBreakpointKind("shared-library-event");
}
@@ -275,7 +297,7 @@ DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint()
if (m_dyld_bid == LLDB_INVALID_BREAK_ID)
{
- Breakpoint *dyld_break = target.CreateBreakpoint (break_addr, true).get();
+ Breakpoint *dyld_break = target.CreateBreakpoint (break_addr, true, false).get();
dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
dyld_break->SetBreakpointKind ("shared-library-event");
m_dyld_bid = dyld_break->GetID();
@@ -319,10 +341,14 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
for (I = m_rendezvous.loaded_begin(); I != E; ++I)
{
FileSpec file(I->path.c_str(), true);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
if (module_sp.get())
+ {
loaded_modules.AppendIfNeeded(module_sp);
+ new_modules.Append(module_sp);
+ }
}
+ m_process->GetTarget().ModulesDidLoad(new_modules);
}
if (m_rendezvous.ModulesDidUnload())
@@ -336,10 +362,15 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
ModuleSpec module_spec (file);
ModuleSP module_sp =
loaded_modules.FindFirstModule (module_spec);
+
if (module_sp.get())
+ {
old_modules.Append(module_sp);
+ UnloadSections(module_sp);
+ }
}
loaded_modules.Remove(old_modules);
+ m_process->GetTarget().ModulesDidUnload(old_modules, false);
}
}
@@ -404,21 +435,43 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
ModuleList module_list;
if (!m_rendezvous.Resolve())
+ {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf("DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD rendezvous address",
+ __FUNCTION__);
return;
+ }
+
+ // The rendezvous class doesn't enumerate the main module, so track
+ // that ourselves here.
+ ModuleSP executable = GetTargetExecutable();
+ m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
+
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
{
- FileSpec file(I->path.c_str(), false);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ const char *module_path = I->path.c_str();
+ FileSpec file(module_path, false);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
if (module_sp.get())
+ {
module_list.Append(module_sp);
+ }
+ else
+ {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf("DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64,
+ __FUNCTION__, module_path, I->base_addr);
+ }
}
m_process->GetTarget().ModulesDidLoad(module_list);
}
ModuleSP
-DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)
+DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr)
{
Target &target = m_process->GetTarget();
ModuleList &modules = target.GetImages();
@@ -427,11 +480,11 @@ DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_ad
ModuleSpec module_spec (file, target.GetArchitecture());
if ((module_sp = modules.FindFirstModule (module_spec)))
{
- UpdateLoadedSections(module_sp, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr);
}
else if ((module_sp = target.GetSharedModule(module_spec)))
{
- UpdateLoadedSections(module_sp, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr);
}
return module_sp;
@@ -479,3 +532,83 @@ DynamicLoaderPOSIXDYLD::GetEntryPoint()
m_entry_point = static_cast<addr_t>(I->value);
return m_entry_point;
}
+
+const SectionList *
+DynamicLoaderPOSIXDYLD::GetSectionListFromModule(const ModuleSP module) const
+{
+ SectionList *sections = nullptr;
+ if (module.get())
+ {
+ ObjectFile *obj_file = module->GetObjectFile();
+ if (obj_file)
+ {
+ sections = obj_file->GetSectionList();
+ }
+ }
+ return sections;
+}
+
+static int ReadInt(Process *process, addr_t addr)
+{
+ Error error;
+ int value = (int)process->ReadUnsignedIntegerFromMemory(addr, sizeof(uint32_t), 0, error);
+ if (error.Fail())
+ return -1;
+ else
+ return value;
+}
+
+static addr_t ReadPointer(Process *process, addr_t addr)
+{
+ Error error;
+ addr_t value = process->ReadPointerFromMemory(addr, error);
+ if (error.Fail())
+ return LLDB_INVALID_ADDRESS;
+ else
+ return value;
+}
+
+lldb::addr_t
+DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread)
+{
+ auto it = m_loaded_modules.find (module);
+ if (it == m_loaded_modules.end())
+ return LLDB_INVALID_ADDRESS;
+
+ addr_t link_map = it->second;
+ if (link_map == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ const DYLDRendezvous::ThreadInfo &metadata = m_rendezvous.GetThreadInfo();
+ if (!metadata.valid)
+ return LLDB_INVALID_ADDRESS;
+
+ // Get the thread pointer.
+ addr_t tp = thread->GetThreadPointer ();
+ if (tp == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ // Find the module's modid.
+ int modid = ReadInt (m_process, link_map + metadata.modid_offset);
+ if (modid == -1)
+ return LLDB_INVALID_ADDRESS;
+
+ // Lookup the DTV stucture for this thread.
+ addr_t dtv_ptr = tp + metadata.dtv_offset;
+ addr_t dtv = ReadPointer (m_process, dtv_ptr);
+ if (dtv == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ // Find the TLS block for this module.
+ addr_t dtv_slot = dtv + metadata.dtv_slot_size*modid;
+ addr_t tls_block = ReadPointer (m_process, dtv_slot + metadata.tls_offset);
+
+ Module *mod = module.get();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: "
+ "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%i, tls_block=0x%" PRIx64 "\n",
+ mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block);
+
+ return tls_block;
+}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 0476e45d0465..7997b34195a4 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -61,6 +61,9 @@ public:
virtual lldb_private::Error
CanLoadImage();
+ virtual lldb::addr_t
+ GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread);
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -95,6 +98,9 @@ protected:
/// Rendezvous breakpoint.
lldb::break_id_t m_dyld_bid;
+ /// Loaded module list. (link map for each module)
+ std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> m_loaded_modules;
+
/// Enables a breakpoint on a function called by the runtime
/// linker each time a module is loaded or unloaded.
void
@@ -117,15 +123,24 @@ protected:
///
/// @param module The module to traverse.
///
+ /// @param link_map_addr The virtual address of the link map for the @p module.
+ ///
/// @param base_addr The virtual base address @p module is loaded at.
void
- UpdateLoadedSections(lldb::ModuleSP module,
- lldb::addr_t base_addr = 0);
+ UpdateLoadedSections(lldb::ModuleSP module,
+ lldb::addr_t link_map_addr,
+ lldb::addr_t base_addr);
+
+ /// Removes the loaded sections from the target in @p module.
+ ///
+ /// @param module The module to traverse.
+ void
+ UnloadSections(const lldb::ModuleSP module);
/// Locates or creates a module given by @p file and updates/loads the
/// resulting module at the virtual base address @p base_addr.
lldb::ModuleSP
- LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr);
+ LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr);
/// Resolves the entry point for the current inferior process and sets a
/// breakpoint at that address.
@@ -165,6 +180,9 @@ protected:
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
+
+ const lldb_private::SectionList *
+ GetSectionListFromModule(const lldb::ModuleSP module) const;
};
#endif // liblldb_DynamicLoaderPOSIXDYLD_H_
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 2dd04dd8733d..db03f4536188 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -196,7 +196,7 @@ EmulateInstructionARM::GetPluginDescriptionStatic ()
EmulateInstruction *
EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
{
- if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
+ if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(inst_type))
{
if (arch.GetTriple().getArch() == llvm::Triple::arm)
{
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index b926dc0deb4a..a3c294ae7a05 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -79,7 +79,7 @@ public:
InstructionType inst_type);
static bool
- SupportsEmulatingIntructionsOfTypeStatic (InstructionType inst_type)
+ SupportsEmulatingInstructionsOfTypeStatic (InstructionType inst_type)
{
switch (inst_type)
{
@@ -149,9 +149,9 @@ public:
// }
virtual bool
- SupportsEmulatingIntructionsOfType (InstructionType inst_type)
+ SupportsEmulatingInstructionsOfType (InstructionType inst_type)
{
- return SupportsEmulatingIntructionsOfTypeStatic (inst_type);
+ return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
}
virtual bool
diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.h b/source/Plugins/Instruction/ARM/EmulationStateARM.h
index 8d84abc75614..ad596a3c2779 100644
--- a/source/Plugins/Instruction/ARM/EmulationStateARM.h
+++ b/source/Plugins/Instruction/ARM/EmulationStateARM.h
@@ -80,7 +80,7 @@ public:
const lldb_private::RegisterValue &reg_value);
private:
uint32_t m_gpr[17];
- struct sd_regs
+ struct _sd_regs
{
union
{
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 247d7b0e7fe4..d18b4c75ae7b 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -402,7 +402,7 @@ ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
FileSpecList filter_modules;
BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
- return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
+ return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, false);
}
void
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index 1ec5f3d733a0..32574e3ef2f0 100644
--- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -9,7 +9,24 @@
#include "ObjectContainerBSDArchive.h"
+#ifdef _WIN32
+// Defines from ar, missing on Windows
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+typedef struct ar_hdr
+{
+ char ar_name[16];
+ char ar_date[12];
+ char ar_uid[6], ar_gid[6];
+ char ar_mode[8];
+ char ar_size[10];
+ char ar_fmag[2];
+} ar_hdr;
+#else
#include <ar.h>
+#endif
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBuffer.h"
@@ -444,7 +461,7 @@ ObjectContainerBSDArchive::Dump (Stream *s) const
s->Indent();
const size_t num_archs = GetNumArchitectures();
const size_t num_objects = GetNumObjects();
- s->Printf("ObjectContainerBSDArchive, num_archs = %lu, num_objects = %lu", num_archs, num_objects);
+ s->Printf("ObjectContainerBSDArchive, num_archs = %zu, num_objects = %zu", num_archs, num_objects);
uint32_t i;
ArchSpec arch;
s->IndentMore();
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 2e9f6903280c..163e713bedb2 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -21,7 +21,9 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Target.h"
#include "lldb/Host/Host.h"
#include "llvm/ADT/PointerUnion.h"
@@ -514,7 +516,7 @@ ObjectFileELF::GetDependentModules(FileSpecList &files)
}
Address
-ObjectFileELF::GetImageInfoAddress()
+ObjectFileELF::GetImageInfoAddress(Target *target)
{
if (!ParseDynamicSymbols())
return Address();
@@ -545,6 +547,17 @@ ObjectFileELF::GetImageInfoAddress()
addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
return Address(dynsym_section_sp, offset);
}
+ else if (symbol.d_tag == DT_MIPS_RLD_MAP && target)
+ {
+ addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
+ addr_t dyn_base = dynsym_section_sp->GetLoadBaseAddress(target);
+ if (dyn_base == LLDB_INVALID_ADDRESS)
+ return Address();
+ Address addr;
+ Error error;
+ if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr))
+ return addr;
+ }
}
return Address();
@@ -1280,6 +1293,11 @@ ObjectFileELF::FindDynamicSymbol(unsigned tag)
unsigned
ObjectFileELF::PLTRelocationType()
{
+ // DT_PLTREL
+ // This member specifies the type of relocation entry to which the
+ // procedure linkage table refers. The d_val member holds DT_REL or
+ // DT_RELA, as appropriate. All relocations in a procedure linkage table
+ // must use the same relocation.
const ELFDynamic *symbol = FindDynamicSymbol(DT_PLTREL);
if (symbol)
@@ -1304,7 +1322,10 @@ ParsePLTRelocations(Symtab *symbol_table,
ELFRelocation rel(rel_type);
ELFSymbol symbol;
lldb::offset_t offset = 0;
- const elf_xword plt_entsize = plt_hdr->sh_entsize;
+ // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16 bytes.
+ // So round the entsize up by the alignment if addralign is set.
+ const elf_xword plt_entsize = plt_hdr->sh_addralign ?
+ llvm::RoundUpToAlignment (plt_hdr->sh_entsize, plt_hdr->sh_addralign) : plt_hdr->sh_entsize;
const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
@@ -1479,10 +1500,17 @@ ObjectFileELF::GetSymtab()
if (symtab)
symbol_id += ParseSymbolTable (m_symtab_ap.get(), symbol_id, symtab);
- // Synthesize trampoline symbols to help navigate the PLT.
+ // DT_JMPREL
+ // If present, this entry's d_ptr member holds the address of relocation
+ // entries associated solely with the procedure linkage table. Separating
+ // these relocation entries lets the dynamic linker ignore them during
+ // process initialization, if lazy binding is enabled. If this entry is
+ // present, the related entries of types DT_PLTRELSZ and DT_PLTREL must
+ // also be present.
const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL);
if (symbol)
{
+ // Synthesize trampoline symbols to help navigate the PLT.
addr_t addr = symbol->d_ptr;
Section *reloc_section = section_list->FindSectionContainingFileAddress(addr).get();
if (reloc_section)
@@ -1498,6 +1526,57 @@ ObjectFileELF::GetSymtab()
return m_symtab_ap.get();
}
+Symbol *
+ObjectFileELF::ResolveSymbolForAddress(const Address& so_addr, bool verify_unique)
+{
+ if (!m_symtab_ap.get())
+ return nullptr; // GetSymtab() should be called first.
+
+ const SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return nullptr;
+
+ if (DWARFCallFrameInfo *eh_frame = GetUnwindTable().GetEHFrameInfo())
+ {
+ AddressRange range;
+ if (eh_frame->GetAddressRange (so_addr, range))
+ {
+ const addr_t file_addr = range.GetBaseAddress().GetFileAddress();
+ Symbol * symbol = verify_unique ? m_symtab_ap->FindSymbolContainingFileAddress(file_addr) : nullptr;
+ if (symbol)
+ return symbol;
+
+ // Note that a (stripped) symbol won't be found by GetSymtab()...
+ lldb::SectionSP eh_sym_section_sp = section_list->FindSectionContainingFileAddress(file_addr);
+ if (eh_sym_section_sp.get())
+ {
+ addr_t section_base = eh_sym_section_sp->GetFileAddress();
+ addr_t offset = file_addr - section_base;
+ uint64_t symbol_id = m_symtab_ap->GetNumSymbols();
+
+ Symbol eh_symbol(
+ symbol_id, // Symbol table index.
+ "???", // Symbol name.
+ false, // Is the symbol name mangled?
+ eSymbolTypeCode, // Type of this symbol.
+ true, // Is this globally visible?
+ false, // Is this symbol debug info?
+ false, // Is this symbol a trampoline?
+ true, // Is this symbol artificial?
+ eh_sym_section_sp, // Section in which this symbol is defined or null.
+ offset, // Offset in section or symbol value.
+ range.GetByteSize(), // Size in bytes of this symbol.
+ true, // Size is valid.
+ 0); // Symbol flags.
+ if (symbol_id == m_symtab_ap->AddSymbol(eh_symbol))
+ return m_symtab_ap->SymbolAtIndex(symbol_id);
+ }
+ }
+ }
+ return nullptr;
+}
+
+
bool
ObjectFileELF::IsStripped ()
{
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 2365101f4275..ede886fb4f60 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -102,6 +102,9 @@ public:
virtual lldb_private::Symtab *
GetSymtab();
+ virtual lldb_private::Symbol *
+ ResolveSymbolForAddress(const lldb_private::Address& so_addr, bool verify_unique);
+
virtual bool
IsStripped ();
@@ -124,7 +127,7 @@ public:
GetDependentModules(lldb_private::FileSpecList& files);
virtual lldb_private::Address
- GetImageInfoAddress();
+ GetImageInfoAddress(lldb_private::Target *target);
virtual lldb_private::Address
GetEntryPointAddress ();
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index 4cfe38e5840f..37b324197350 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -144,7 +144,7 @@ OperatingSystemPython::GetDynamicRegisterInfo ()
if (!dictionary)
return NULL;
- m_register_info_ap.reset (new DynamicRegisterInfo (dictionary));
+ m_register_info_ap.reset (new DynamicRegisterInfo (dictionary, m_process->GetTarget().GetArchitecture().GetByteOrder()));
assert (m_register_info_ap->GetNumRegisters() > 0);
assert (m_register_info_ap->GetNumRegisterSets() > 0);
}
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index dc0917255d9b..da29c16ac3ab 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -10,10 +10,13 @@
#include "lldb/lldb-python.h"
#include "PlatformFreeBSD.h"
+#include "lldb/Host/Config.h"
// C Includes
#include <stdio.h>
+#ifndef LLDB_DISABLE_POSIX
#include <sys/utsname.h>
+#endif
// C++ Includes
// Other libraries and framework includes
@@ -153,6 +156,26 @@ PlatformFreeBSD::~PlatformFreeBSD()
{
}
+//TODO:VK: inherit PlatformPOSIX
+lldb_private::Error
+PlatformFreeBSD::RunShellCommand (const char *command,
+ const char *working_dir,
+ int *status_ptr,
+ int *signo_ptr,
+ std::string *command_output,
+ uint32_t timeout_sec)
+{
+ if (IsHost())
+ return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ return Error("unable to run a remote command without a platform");
+ }
+}
+
Error
PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
@@ -162,10 +185,10 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
{
Error error;
// Nothing special to do here, just use the actual file and architecture
-
+
char exe_path[PATH_MAX];
FileSpec resolved_exe_file (exe_file);
-
+
if (IsHost())
{
// If we have "ls" as the exe_file, resolve the executable location based on
@@ -175,10 +198,10 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
exe_file.GetPath(exe_path, sizeof(exe_path));
resolved_exe_file.SetFile(exe_path, true);
}
-
+
if (!resolved_exe_file.Exists())
resolved_exe_file.ResolveExecutableLocation ();
-
+
if (resolved_exe_file.Exists())
error.Clear();
else
@@ -214,7 +237,6 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
}
}
-
if (error.Success())
{
ModuleSpec module_spec (resolved_exe_file, exe_arch);
@@ -225,7 +247,7 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
module_search_paths_ptr,
NULL,
NULL);
-
+
if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
{
exe_module_sp.reset();
@@ -256,12 +278,12 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
else
error.SetErrorToGenericError();
}
-
+
if (idx > 0)
arch_names.PutCString (", ");
arch_names.PutCString (platform_arch.GetArchitectureName());
}
-
+
if (error.Fail() || !exe_module_sp)
{
error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
@@ -271,11 +293,6 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
}
}
}
- else
- {
- error.SetErrorStringWithFormat ("'%s' does not exist",
- exe_file.GetPath().c_str());
- }
return error;
}
@@ -636,13 +653,23 @@ PlatformFreeBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
void
PlatformFreeBSD::GetStatus (Stream &strm)
{
+#ifndef LLDB_DISABLE_POSIX
struct utsname un;
- if (uname(&un)) {
- strm << "FreeBSD";
- return;
- }
+ strm << " Host: ";
+
+ ::memset(&un, 0, sizeof(utsname));
+ if (uname(&un) == -1)
+ strm << "FreeBSD" << '\n';
+ strm << un.sysname << ' ' << un.release;
+ if (un.nodename[0] != '\0')
+ strm << " (" << un.nodename << ')';
+ strm << '\n';
+
+ // Dump a common information about the platform status.
strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
+#endif
+
Platform::GetStatus(strm);
}
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
index 4aa158eb6e87..11d1cd609779 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -72,6 +72,14 @@ public:
// lldb_private::Platform functions
//------------------------------------------------------------
virtual lldb_private::Error
+ RunShellCommand (const char *command,
+ const char *working_dir,
+ int *status_ptr,
+ int *signo_ptr,
+ std::string *command_output,
+ uint32_t timeout_sec);
+
+ virtual lldb_private::Error
ResolveExecutable (const lldb_private::FileSpec &exe_file,
const lldb_private::ArchSpec &arch,
lldb::ModuleSP &module_sp,
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
new file mode 100644
index 000000000000..34316c484276
--- /dev/null
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -0,0 +1,541 @@
+//===-- PlatformPOSIX.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformPOSIX.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/File.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformPOSIX::PlatformPOSIX (bool is_host) :
+Platform(is_host), // This is the local host platform
+m_remote_platform_sp ()
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformPOSIX::~PlatformPOSIX()
+{
+}
+
+lldb_private::OptionGroupOptions*
+PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter)
+{
+ if (m_options.get() == NULL)
+ {
+ m_options.reset(new OptionGroupOptions(interpreter));
+ m_options->Append(new OptionGroupPlatformRSync());
+ m_options->Append(new OptionGroupPlatformSSH());
+ m_options->Append(new OptionGroupPlatformCaching());
+ }
+ return m_options.get();
+}
+
+lldb_private::Error
+PlatformPOSIX::RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
+{
+ if (IsHost())
+ return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ return Error("unable to run a remote command without a platform");
+ }
+}
+
+uint32_t
+PlatformPOSIX::MakeDirectory (const std::string &path,
+ mode_t mode)
+{
+ if (IsHost())
+ {
+ return Host::MakeDirectory (path.c_str(), mode);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->MakeDirectory(path, mode);
+ return Platform::MakeDirectory(path,mode);
+}
+
+lldb::user_id_t
+PlatformPOSIX::OpenFile (const FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ Error &error)
+{
+ if (IsHost())
+ {
+ return Host::OpenFile(file_spec, flags, mode, error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error);
+ return Platform::OpenFile(file_spec, flags, mode, error);
+}
+
+bool
+PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error)
+{
+ if (IsHost())
+ {
+ return Host::CloseFile(fd, error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->CloseFile(fd, error);
+ return Platform::CloseFile(fd, error);
+}
+
+uint64_t
+PlatformPOSIX::ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
+{
+ if (IsHost())
+ {
+ return Host::ReadFile(fd, offset, dst, dst_len, error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error);
+ return Platform::ReadFile(fd, offset, dst, dst_len, error);
+}
+
+uint64_t
+PlatformPOSIX::WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
+{
+ if (IsHost())
+ {
+ return Host::WriteFile(fd, offset, src, src_len, error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error);
+
+ return Platform::WriteFile(fd, offset, src, src_len, error);
+}
+
+static uint32_t
+chown_file(Platform *platform,
+ const char* path,
+ uint32_t uid = UINT32_MAX,
+ uint32_t gid = UINT32_MAX)
+{
+ if (!platform || !path || *path == 0)
+ return UINT32_MAX;
+
+ if (uid == UINT32_MAX && gid == UINT32_MAX)
+ return 0; // pretend I did chown correctly - actually I just didn't care
+
+ StreamString command;
+ command.PutCString("chown ");
+ if (uid != UINT32_MAX)
+ command.Printf("%d",uid);
+ if (gid != UINT32_MAX)
+ command.Printf(":%d",gid);
+ command.Printf("%s",path);
+ int status;
+ platform->RunShellCommand(command.GetData(),
+ NULL,
+ &status,
+ NULL,
+ NULL,
+ 10);
+ return status;
+}
+
+lldb_private::Error
+PlatformPOSIX::PutFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination,
+ uint32_t uid,
+ uint32_t gid)
+{
+ if (IsHost())
+ {
+ if (FileSpec::Equal(source, destination, true))
+ return Error();
+ // cp src dst
+ // chown uid:gid dst
+ std::string src_path (source.GetPath());
+ if (src_path.empty())
+ return Error("unable to get file path for source");
+ std::string dst_path (destination.GetPath());
+ if (dst_path.empty())
+ return Error("unable to get file path for destination");
+ StreamString command;
+ command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
+ int status;
+ RunShellCommand(command.GetData(),
+ NULL,
+ &status,
+ NULL,
+ NULL,
+ 10);
+ if (status != 0)
+ return Error("unable to perform copy");
+ if (uid == UINT32_MAX && gid == UINT32_MAX)
+ return Error();
+ if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
+ return Error("unable to perform chown");
+ return Error();
+ }
+ else if (IsRemote() && m_remote_platform_sp)
+ {
+ if (GetSupportsRSync())
+ {
+ std::string src_path (source.GetPath());
+ if (src_path.empty())
+ return Error("unable to get file path for source");
+ std::string dst_path (destination.GetPath());
+ if (dst_path.empty())
+ return Error("unable to get file path for destination");
+ StreamString command;
+ if (GetIgnoresRemoteHostname())
+ {
+ if (!GetRSyncPrefix())
+ command.Printf("rsync %s %s %s",
+ GetRSyncOpts(),
+ src_path.c_str(),
+ dst_path.c_str());
+ else
+ command.Printf("rsync %s %s %s%s",
+ GetRSyncOpts(),
+ src_path.c_str(),
+ GetRSyncPrefix(),
+ dst_path.c_str());
+ }
+ else
+ command.Printf("rsync %s %s %s:%s",
+ GetRSyncOpts(),
+ src_path.c_str(),
+ GetHostname(),
+ dst_path.c_str());
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[PutFile] Running command: %s\n", command.GetData());
+ int retcode;
+ Host::RunShellCommand(command.GetData(),
+ NULL,
+ &retcode,
+ NULL,
+ NULL,
+ 60);
+ if (retcode == 0)
+ {
+ // Don't chown a local file for a remote system
+// if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
+// return Error("unable to perform chown");
+ return Error();
+ }
+ // if we are still here rsync has failed - let's try the slow way before giving up
+ }
+ // open
+ // read, write, read, write, ...
+ // close
+ // chown uid:gid dst
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[PutFile] Using block by block transfer....\n");
+ File source_file(source, File::eOpenOptionRead, File::ePermissionsUserRW);
+ if (!source_file.IsValid())
+ return Error("unable to open source file");
+ Error error;
+ lldb::user_id_t dest_file = OpenFile (destination,
+ File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
+ File::ePermissionsUserRWX | File::ePermissionsGroupRX | File::ePermissionsWorldRX,
+ error);
+ if (log)
+ log->Printf ("dest_file = %" PRIu64 "\n", dest_file);
+ if (error.Fail())
+ return error;
+ if (dest_file == UINT64_MAX)
+ return Error("unable to open target file");
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+ uint64_t offset = 0;
+ while (error.Success())
+ {
+ size_t bytes_read = buffer_sp->GetByteSize();
+ error = source_file.Read(buffer_sp->GetBytes(), bytes_read);
+ if (bytes_read)
+ {
+ WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error);
+ offset += bytes_read;
+ }
+ else
+ break;
+ }
+ CloseFile(dest_file, error);
+ if (uid == UINT32_MAX && gid == UINT32_MAX)
+ return error;
+ // This is remopve, don't chown a local file...
+// std::string dst_path (destination.GetPath());
+// if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
+// return Error("unable to perform chown");
+ return error;
+ }
+ return Platform::PutFile(source,destination,uid,gid);
+}
+
+lldb::user_id_t
+PlatformPOSIX::GetFileSize (const FileSpec& file_spec)
+{
+ if (IsHost())
+ {
+ return Host::GetFileSize(file_spec);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetFileSize(file_spec);
+ return Platform::GetFileSize(file_spec);
+}
+
+bool
+PlatformPOSIX::GetFileExists (const FileSpec& file_spec)
+{
+ if (IsHost())
+ {
+ return file_spec.Exists();
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetFileExists(file_spec);
+ return Platform::GetFileExists(file_spec);
+}
+
+uint32_t
+PlatformPOSIX::GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error)
+{
+ if (IsHost())
+ {
+ return File::GetPermissions(file_spec.GetPath().c_str(), error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetFilePermissions(file_spec, error);
+ return Platform::GetFilePermissions(file_spec, error);
+
+}
+
+
+lldb_private::Error
+PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path */,
+ const lldb_private::FileSpec& destination /* local file path */)
+{
+ // Check the args, first.
+ std::string src_path (source.GetPath());
+ if (src_path.empty())
+ return Error("unable to get file path for source");
+ std::string dst_path (destination.GetPath());
+ if (dst_path.empty())
+ return Error("unable to get file path for destination");
+ if (IsHost())
+ {
+ if (FileSpec::Equal(source, destination, true))
+ return Error("local scenario->source and destination are the same file path: no operation performed");
+ // cp src dst
+ StreamString cp_command;
+ cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
+ int status;
+ RunShellCommand(cp_command.GetData(),
+ NULL,
+ &status,
+ NULL,
+ NULL,
+ 10);
+ if (status != 0)
+ return Error("unable to perform copy");
+ return Error();
+ }
+ else if (IsRemote() && m_remote_platform_sp)
+ {
+ if (GetSupportsRSync())
+ {
+ StreamString command;
+ if (GetIgnoresRemoteHostname())
+ {
+ if (!GetRSyncPrefix())
+ command.Printf("rsync %s %s %s",
+ GetRSyncOpts(),
+ src_path.c_str(),
+ dst_path.c_str());
+ else
+ command.Printf("rsync %s %s%s %s",
+ GetRSyncOpts(),
+ GetRSyncPrefix(),
+ src_path.c_str(),
+ dst_path.c_str());
+ }
+ else
+ command.Printf("rsync %s %s:%s %s",
+ GetRSyncOpts(),
+ m_remote_platform_sp->GetHostname(),
+ src_path.c_str(),
+ dst_path.c_str());
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[GetFile] Running command: %s\n", command.GetData());
+ int retcode;
+ Host::RunShellCommand(command.GetData(),
+ NULL,
+ &retcode,
+ NULL,
+ NULL,
+ 60);
+ if (retcode == 0)
+ return Error();
+ // If we are here, rsync has failed - let's try the slow way before giving up
+ }
+ // open src and dst
+ // read/write, read/write, read/write, ...
+ // close src
+ // close dst
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[GetFile] Using block by block transfer....\n");
+ Error error;
+ user_id_t fd_src = OpenFile (source,
+ File::eOpenOptionRead,
+ File::ePermissionsDefault,
+ error);
+
+ if (fd_src == UINT64_MAX)
+ return Error("unable to open source file");
+
+ uint32_t permissions = GetFilePermissions(source, error);
+
+ if (permissions == 0)
+ permissions = File::ePermissionsDefault;
+
+ user_id_t fd_dst = Host::OpenFile(destination,
+ File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
+ permissions,
+ error);
+
+ if (fd_dst == UINT64_MAX)
+ {
+ if (error.Success())
+ error.SetErrorString("unable to open destination file");
+ }
+
+ if (error.Success())
+ {
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+ uint64_t offset = 0;
+ error.Clear();
+ while (error.Success())
+ {
+ const uint64_t n_read = ReadFile (fd_src,
+ offset,
+ buffer_sp->GetBytes(),
+ buffer_sp->GetByteSize(),
+ error);
+ if (error.Fail())
+ break;
+ if (n_read == 0)
+ break;
+ if (Host::WriteFile(fd_dst,
+ offset,
+ buffer_sp->GetBytes(),
+ n_read,
+ error) != n_read)
+ {
+ if (!error.Fail())
+ error.SetErrorString("unable to write to destination file");
+ break;
+ }
+ offset += n_read;
+ }
+ }
+ // Ignore the close error of src.
+ if (fd_src != UINT64_MAX)
+ CloseFile(fd_src, error);
+ // And close the dst file descriptot.
+ if (fd_dst != UINT64_MAX && !Host::CloseFile(fd_dst, error))
+ {
+ if (!error.Fail())
+ error.SetErrorString("unable to close destination file");
+
+ }
+ return error;
+ }
+ return Platform::GetFile(source,destination);
+}
+
+std::string
+PlatformPOSIX::GetPlatformSpecificConnectionInformation()
+{
+ StreamString stream;
+ if (GetSupportsRSync())
+ {
+ stream.PutCString("rsync");
+ if ( (GetRSyncOpts() && *GetRSyncOpts()) ||
+ (GetRSyncPrefix() && *GetRSyncPrefix()) ||
+ GetIgnoresRemoteHostname())
+ {
+ stream.Printf(", options: ");
+ if (GetRSyncOpts() && *GetRSyncOpts())
+ stream.Printf("'%s' ",GetRSyncOpts());
+ stream.Printf(", prefix: ");
+ if (GetRSyncPrefix() && *GetRSyncPrefix())
+ stream.Printf("'%s' ",GetRSyncPrefix());
+ if (GetIgnoresRemoteHostname())
+ stream.Printf("ignore remote-hostname ");
+ }
+ }
+ if (GetSupportsSSH())
+ {
+ stream.PutCString("ssh");
+ if (GetSSHOpts() && *GetSSHOpts())
+ stream.Printf(", options: '%s' ",GetSSHOpts());
+ }
+ if (GetLocalCacheDirectory() && *GetLocalCacheDirectory())
+ stream.Printf("cache dir: %s",GetLocalCacheDirectory());
+ if (stream.GetSize())
+ return stream.GetData();
+ else
+ return "";
+}
+
+bool
+PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec,
+ uint64_t &low,
+ uint64_t &high)
+{
+ if (IsHost())
+ return Platform::CalculateMD5 (file_spec, low, high);
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->CalculateMD5(file_spec, low, high);
+ return false;
+}
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
new file mode 100644
index 000000000000..4119e452bf7f
--- /dev/null
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -0,0 +1,111 @@
+//===-- PlatformPOSIX.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_PlatformPOSIX_h_
+#define liblldb_PlatformPOSIX_h_
+
+// C Includes
+// C++ Includes
+
+#include <memory>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/Options.h"
+#include "lldb/Target/Platform.h"
+
+class PlatformPOSIX : public lldb_private::Platform
+{
+public:
+ PlatformPOSIX (bool is_host);
+
+ virtual
+ ~PlatformPOSIX();
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ virtual lldb_private::OptionGroupOptions*
+ GetConnectionOptions (lldb_private::CommandInterpreter& interpreter);
+
+ virtual lldb_private::Error
+ PutFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination,
+ uint32_t uid = UINT32_MAX,
+ uint32_t gid = UINT32_MAX);
+
+ virtual lldb::user_id_t
+ OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ lldb_private::Error &error);
+
+ virtual bool
+ CloseFile (lldb::user_id_t fd,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ lldb_private::Error &error);
+
+ virtual lldb::user_id_t
+ GetFileSize (const lldb_private::FileSpec& file_spec);
+
+ virtual lldb_private::Error
+ GetFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination);
+
+ virtual lldb_private::Error
+ RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
+
+ virtual uint32_t
+ MakeDirectory (const std::string &path,
+ mode_t mode);
+
+ virtual bool
+ GetFileExists (const lldb_private::FileSpec& file_spec);
+
+ virtual uint32_t
+ GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error);
+
+ virtual std::string
+ GetPlatformSpecificConnectionInformation();
+
+ virtual bool
+ CalculateMD5 (const lldb_private::FileSpec& file_spec,
+ uint64_t &low,
+ uint64_t &high);
+
+protected:
+ std::auto_ptr<lldb_private::OptionGroupOptions> m_options;
+
+ lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote POSIX-compliant OS
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformPOSIX);
+
+};
+
+#endif // liblldb_PlatformPOSIX_h_
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 684d1921e920..4aeec032d712 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -10,9 +10,12 @@
#include "lldb/lldb-python.h"
#include "PlatformRemoteGDBServer.h"
+#include "lldb/Host/Config.h"
// C Includes
+#ifndef LLDB_DISABLE_POSIX
#include <sys/sysctl.h>
+#endif
// C++ Includes
// Other libraries and framework includes
@@ -107,7 +110,11 @@ PlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file,
const FileSpecList *module_search_paths_ptr)
{
Error error;
- error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented");
+ //error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented");
+ if (m_gdb_client.GetFileExists(exe_file))
+ return error;
+ // TODO: get the remote end to somehow resolve this file
+ error.SetErrorString("file not found on remote end");
return error;
}
@@ -230,6 +237,11 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args)
error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
}
}
+
+ if (error.Success())
+ {
+
+ }
return error;
}
@@ -324,6 +336,12 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
break;
}
}
+
+ ArchSpec arch_spec = launch_info.GetArchitecture();
+ const char *arch_triple = arch_spec.GetTriple().str().c_str();
+
+ m_gdb_client.SendLaunchArchPacket(arch_triple);
+
const uint32_t old_packet_timeout = m_gdb_client.SetPacketTimeout (5);
int arg_packet_err = m_gdb_client.SendArgumentsPacket (argv);
m_gdb_client.SetPacketTimeout (old_packet_timeout);
@@ -360,7 +378,8 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
{
if (IsConnected())
{
- uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort();
+ lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid);
if (port == 0)
{
@@ -394,15 +413,22 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
if (process_sp)
{
char connect_url[256];
+ const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
+ const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
+ int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
const int connect_url_len = ::snprintf (connect_url,
sizeof(connect_url),
"connect://%s:%u",
- GetHostname (),
- port);
+ override_hostname ? override_hostname : GetHostname (),
+ port + port_offset);
assert (connect_url_len < (int)sizeof(connect_url));
error = process_sp->ConnectRemote (NULL, connect_url);
if (error.Success())
error = process_sp->Attach(attach_info);
+ else if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ {
+ m_gdb_client.KillSpawnedProcess(debugserver_pid);
+ }
}
}
}
@@ -415,4 +441,83 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
return process_sp;
}
+uint32_t
+PlatformRemoteGDBServer::MakeDirectory (const std::string &path,
+ mode_t mode)
+{
+ return m_gdb_client.MakeDirectory(path,mode);
+}
+
+lldb::user_id_t
+PlatformRemoteGDBServer::OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ Error &error)
+{
+ return m_gdb_client.OpenFile (file_spec, flags, mode, error);
+}
+
+bool
+PlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd, Error &error)
+{
+ return m_gdb_client.CloseFile (fd, error);
+}
+
+lldb::user_id_t
+PlatformRemoteGDBServer::GetFileSize (const lldb_private::FileSpec& file_spec)
+{
+ return m_gdb_client.GetFileSize(file_spec);
+}
+uint32_t
+PlatformRemoteGDBServer::GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error)
+{
+ return m_gdb_client.GetFilePermissions(file_spec, error);
+}
+
+uint64_t
+PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
+{
+ return m_gdb_client.ReadFile (fd, offset, dst, dst_len, error);
+}
+
+uint64_t
+PlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
+{
+ return m_gdb_client.WriteFile (fd, offset, src, src_len, error);
+}
+
+lldb_private::Error
+PlatformRemoteGDBServer::PutFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination,
+ uint32_t uid,
+ uint32_t gid)
+{
+ return Platform::PutFile(source,destination,uid,gid);
+}
+
+bool
+PlatformRemoteGDBServer::GetFileExists (const lldb_private::FileSpec& file_spec)
+{
+ return m_gdb_client.GetFileExists (file_spec);
+}
+
+lldb_private::Error
+PlatformRemoteGDBServer::RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
+{
+ return m_gdb_client.RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+}
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 22b3dd49be54..70db6bafacd2 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -134,6 +134,58 @@ public:
virtual lldb_private::Error
DisconnectRemote ();
+
+ virtual uint32_t
+ MakeDirectory (const std::string &path,
+ mode_t mode);
+
+ virtual lldb::user_id_t
+ OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ lldb_private::Error &error);
+
+ virtual bool
+ CloseFile (lldb::user_id_t fd,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *data_ptr,
+ uint64_t len,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* data,
+ uint64_t len,
+ lldb_private::Error &error);
+
+ virtual lldb::user_id_t
+ GetFileSize (const lldb_private::FileSpec& file_spec);
+
+ virtual lldb_private::Error
+ PutFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination,
+ uint32_t uid = UINT32_MAX,
+ uint32_t gid = UINT32_MAX);
+
+ virtual bool
+ GetFileExists (const lldb_private::FileSpec& file_spec);
+
+ virtual uint32_t
+ GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error);
+
+ virtual lldb_private::Error
+ RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
protected:
GDBRemoteCommunicationClient m_gdb_client;
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index ea26d972b860..952ec95f5873 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -122,11 +122,47 @@ ProcessFreeBSD::Terminate()
{
}
+Error
+ProcessFreeBSD::DoDetach(bool keep_stopped)
+{
+ Error error;
+ if (keep_stopped)
+ {
+ error.SetErrorString("Detaching with keep_stopped true is not currently supported on FreeBSD.");
+ return error;
+ }
+
+ error = m_monitor->Detach(GetID());
+
+ if (error.Success())
+ SetPrivateState(eStateDetached);
+
+ return error;
+}
+
bool
ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
- // XXX haxx
- new_thread_list = old_thread_list;
-
- return false;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIu64 ")", __FUNCTION__, GetID());
+
+ bool has_updated = false;
+ const lldb::pid_t pid = GetID();
+ // Update the process thread list with this new thread.
+ // FIXME: We should be using tid, not pid.
+ assert(m_monitor);
+ ThreadSP thread_sp (old_thread_list.FindThreadByID (pid, false));
+ if (!thread_sp) {
+ ProcessSP me = this->shared_from_this();
+ thread_sp.reset(new POSIXThread(*me, pid));
+ has_updated = true;
+ }
+
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s() updated tid = %" PRIu64, __FUNCTION__, pid);
+
+ new_thread_list.AddThread(thread_sp);
+
+ return has_updated; // the list has been updated
}
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
index 5f79b74cad30..fb549745b80c 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
@@ -54,6 +54,9 @@ public:
ProcessFreeBSD(lldb_private::Target& target,
lldb_private::Listener &listener);
+ virtual lldb_private::Error
+ DoDetach(bool keep_stopped);
+
virtual bool
UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 9fd51d2d640a..3833fa6baf85 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -70,12 +70,12 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
if (log) {
- log->Printf("ptrace(%s, %lu, %p, %x) called from file %s line %d",
+ log->Printf("ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d",
reqName, pid, addr, data, file, line);
if (req == PT_IO) {
struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr;
- log->Printf("PT_IO: op=%s offs=%zx size=%ld",
+ log->Printf("PT_IO: op=%s offs=%zx size=%zu",
Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len);
}
}
@@ -704,23 +704,16 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
m_operation_thread(LLDB_INVALID_HOST_THREAD),
m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_pid(LLDB_INVALID_PROCESS_ID),
- m_server_mutex(Mutex::eMutexTypeRecursive),
m_terminal_fd(-1),
- m_client_fd(-1),
- m_server_fd(-1)
+ m_operation(0)
{
- std::unique_ptr<LaunchArgs> args;
-
- args.reset(new LaunchArgs(this, module, argv, envp,
- stdin_path, stdout_path, stderr_path, working_dir));
+ std::unique_ptr<LaunchArgs> args(new LaunchArgs(this, module, argv, envp,
+ stdin_path, stdout_path, stderr_path,
+ working_dir));
- // Server/client descriptors.
- if (!EnableIPC())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Monitor failed to initialize.");
- }
+ sem_init(&m_operation_pending, 0, 0);
+ sem_init(&m_operation_done, 0, 0);
StartLaunchOpThread(args.get(), error);
if (!error.Success())
@@ -765,21 +758,14 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
m_operation_thread(LLDB_INVALID_HOST_THREAD),
m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_pid(pid),
- m_server_mutex(Mutex::eMutexTypeRecursive),
m_terminal_fd(-1),
- m_client_fd(-1),
- m_server_fd(-1)
+ m_operation(0)
{
- std::unique_ptr<AttachArgs> args;
+ sem_init(&m_operation_pending, 0, 0);
+ sem_init(&m_operation_done, 0, 0);
- args.reset(new AttachArgs(this, pid));
- // Server/client descriptors.
- if (!EnableIPC())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Monitor failed to initialize.");
- }
+ std::unique_ptr<AttachArgs> args(new AttachArgs(this, pid));
StartAttachOpThread(args.get(), error);
if (!error.Success())
@@ -855,7 +841,6 @@ ProcessMonitor::Launch(LaunchArgs *args)
{
ProcessMonitor *monitor = args->m_monitor;
ProcessFreeBSD &process = monitor->GetProcess();
- lldb::ProcessSP processSP = process.shared_from_this();
const char **argv = args->m_argv;
const char **envp = args->m_envp;
const char *stdin_path = args->m_stdin_path;
@@ -868,21 +853,10 @@ ProcessMonitor::Launch(LaunchArgs *args)
char err_str[err_len];
lldb::pid_t pid;
- lldb::ThreadSP inferior;
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
-
// Propagate the environment if one is not supplied.
if (envp == NULL || envp[0] == NULL)
envp = const_cast<const char **>(environ);
- // Pseudo terminal setup.
- if (!terminal.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, err_str, err_len))
- {
- args->m_error.SetErrorToGenericError();
- args->m_error.SetErrorString("Could not open controlling TTY.");
- goto FINISH;
- }
-
if ((pid = terminal.Fork(err_str, err_len)) == -1)
{
args->m_error.SetErrorToGenericError();
@@ -1002,32 +976,12 @@ ProcessMonitor::Launch(LaunchArgs *args)
if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error))
goto FINISH;
- // Update the process thread list with this new thread.
- inferior.reset(process.CreateNewPOSIXThread(*processSP, pid));
- if (log)
- log->Printf ("ProcessMonitor::%s() adding pid = %" PRIu64, __FUNCTION__, pid);
- process.GetThreadList().AddThread(inferior);
-
- // Let our process instance know the thread has stopped.
- process.SendMessage(ProcessMessage::Trace(pid));
+ process.SendMessage(ProcessMessage::Attach(pid));
FINISH:
return args->m_error.Success();
}
-bool
-ProcessMonitor::EnableIPC()
-{
- int fd[2];
-
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd))
- return false;
-
- m_client_fd = fd[0];
- m_server_fd = fd[1];
- return true;
-}
-
void
ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error)
{
@@ -1059,9 +1013,6 @@ ProcessMonitor::Attach(AttachArgs *args)
ProcessMonitor *monitor = args->m_monitor;
ProcessFreeBSD &process = monitor->GetProcess();
- lldb::ProcessSP processSP = process.shared_from_this();
- ThreadList &tl = process.GetThreadList();
- lldb::ThreadSP inferior;
if (pid <= 1)
{
@@ -1084,14 +1035,9 @@ ProcessMonitor::Attach(AttachArgs *args)
goto FINISH;
}
- // Update the process thread list with the attached thread.
- inferior.reset(process.CreateNewPOSIXThread(*processSP, pid));
- tl.AddThread(inferior);
+ process.SendMessage(ProcessMessage::Attach(pid));
- // Let our process instance know the thread has stopped.
- process.SendMessage(ProcessMessage::Trace(pid));
-
- FINISH:
+FINISH:
return args->m_error.Success();
}
@@ -1393,78 +1339,37 @@ void
ProcessMonitor::ServeOperation(OperationArgs *args)
{
int status;
- pollfd fdset;
ProcessMonitor *monitor = args->m_monitor;
- fdset.fd = monitor->m_server_fd;
- fdset.events = POLLIN | POLLPRI;
- fdset.revents = 0;
-
// We are finised with the arguments and are ready to go. Sync with the
// parent thread and start serving operations on the inferior.
sem_post(&args->m_semaphore);
for (;;)
{
- if ((status = poll(&fdset, 1, -1)) < 0)
- {
- switch (errno)
- {
- default:
- assert(false && "Unexpected poll() failure!");
- continue;
+ // wait for next pending operation
+ sem_wait(&monitor->m_operation_pending);
- case EINTR: continue; // Just poll again.
- case EBADF: return; // Connection terminated.
- }
- }
-
- assert(status == 1 && "Too many descriptors!");
+ monitor->m_operation->Execute(monitor);
- if (fdset.revents & POLLIN)
- {
- Operation *op = NULL;
-
- READ_AGAIN:
- if ((status = read(fdset.fd, &op, sizeof(op))) < 0)
- {
- // There is only one acceptable failure.
- assert(errno == EINTR);
- goto READ_AGAIN;
- }
- if (status == 0)
- continue; // Poll again. The connection probably terminated.
- assert(status == sizeof(op));
- op->Execute(monitor);
- write(fdset.fd, &op, sizeof(op));
- }
+ // notify calling thread that operation is complete
+ sem_post(&monitor->m_operation_done);
}
}
void
ProcessMonitor::DoOperation(Operation *op)
{
- int status;
- Operation *ack = NULL;
- Mutex::Locker lock(m_server_mutex);
+ Mutex::Locker lock(m_operation_mutex);
- // FIXME: Do proper error checking here.
- write(m_client_fd, &op, sizeof(op));
+ m_operation = op;
-READ_AGAIN:
- if ((status = read(m_client_fd, &ack, sizeof(ack))) < 0)
- {
- // If interrupted by a signal handler try again. Otherwise the monitor
- // thread probably died and we have a stale file descriptor -- abort the
- // operation.
- if (errno == EINTR)
- goto READ_AGAIN;
- return;
- }
+ // notify operation thread that an operation is ready to be processed
+ sem_post(&m_operation_pending);
- assert(status == sizeof(ack));
- assert(ack == op && "Invalid monitor thread response!");
+ // wait for operation to complete
+ sem_wait(&m_operation_done);
}
size_t
@@ -1556,6 +1461,12 @@ ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, un
}
bool
+ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value)
+{
+ return false;
+}
+
+bool
ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)
{
bool result;
@@ -1648,9 +1559,36 @@ ProcessMonitor::StopMonitor()
{
StopMonitoringChildProcess();
StopOpThread();
- CloseFD(m_terminal_fd);
- CloseFD(m_client_fd);
- CloseFD(m_server_fd);
+ sem_destroy(&m_operation_pending);
+ sem_destroy(&m_operation_done);
+
+ // Note: ProcessPOSIX passes the m_terminal_fd file descriptor to
+ // Process::SetSTDIOFileDescriptor, which in turn transfers ownership of
+ // the descriptor to a ConnectionFileDescriptor object. Consequently
+ // even though still has the file descriptor, we shouldn't close it here.
+}
+
+// FIXME: On Linux, when a new thread is created, we receive to notifications,
+// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the
+// child thread id as additional information, and (2) a SIGSTOP|SI_USER from
+// the new child thread indicating that it has is stopped because we attached.
+// We have no guarantee of the order in which these arrive, but we need both
+// before we are ready to proceed. We currently keep a list of threads which
+// have sent the initial SIGSTOP|SI_USER event. Then when we receive the
+// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred
+// we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
+//
+// Right now, the above logic is in ProcessPOSIX, so we need a definition of
+// this function in the FreeBSD ProcessMonitor implementation even if it isn't
+// logically needed.
+//
+// We really should figure out what actually happens on FreeBSD and move the
+// Linux-specific logic out of ProcessPOSIX as needed.
+
+bool
+ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid)
+{
+ return true;
}
void
@@ -1665,13 +1603,3 @@ ProcessMonitor::StopOpThread()
Host::ThreadJoin(m_operation_thread, &result, NULL);
m_operation_thread = LLDB_INVALID_HOST_THREAD;
}
-
-void
-ProcessMonitor::CloseFD(int &fd)
-{
- if (fd != -1)
- {
- close(fd);
- fd = -1;
- }
-}
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index ce66c03f2f8c..4a9b48370444 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -160,6 +160,10 @@ public:
bool
WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
+ /// Reads the value of the thread-specific pointer for a given thread ID.
+ bool
+ ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value);
+
/// Writes a ptrace_lwpinfo structure corresponding to the given thread ID
/// to the memory region pointed to by @p lwpinfo.
bool
@@ -193,6 +197,10 @@ public:
void
StopMonitor();
+ // Waits for the initial stop message from a new thread.
+ bool
+ WaitForInitialTIDStop(lldb::tid_t tid);
+
private:
ProcessFreeBSD *m_process;
@@ -200,12 +208,17 @@ private:
lldb::thread_t m_monitor_thread;
lldb::pid_t m_pid;
-
- lldb_private::Mutex m_server_mutex;
int m_terminal_fd;
- int m_client_fd;
- int m_server_fd;
+ // current operation which must be executed on the privileged thread
+ Operation *m_operation;
+ lldb_private::Mutex m_operation_mutex;
+
+ // semaphores notified when Operation is ready to be processed and when
+ // the operation is complete.
+ sem_t m_operation_pending;
+ sem_t m_operation_done;
+
struct OperationArgs
{
OperationArgs(ProcessMonitor *monitor);
@@ -252,9 +265,6 @@ private:
static bool
Launch(LaunchArgs *args);
- bool
- EnableIPC();
-
struct AttachArgs : OperationArgs
{
AttachArgs(ProcessMonitor *monitor,
@@ -314,9 +324,6 @@ private:
/// Stops the operation thread used to attach/launch a process.
void
StopOpThread();
-
- void
- CloseFD(int &fd);
};
#endif // #ifndef liblldb_ProcessMonitor_H_
diff --git a/source/Plugins/Process/POSIX/POSIXThread.cpp b/source/Plugins/Process/POSIX/POSIXThread.cpp
index 93c296679df2..16399748c544 100644
--- a/source/Plugins/Process/POSIX/POSIXThread.cpp
+++ b/source/Plugins/Process/POSIX/POSIXThread.cpp
@@ -29,10 +29,12 @@
#include "ProcessPOSIX.h"
#include "ProcessPOSIXLog.h"
#include "ProcessMonitor.h"
-#include "RegisterContext_i386.h"
-#include "RegisterContext_x86_64.h"
-#include "RegisterContextPOSIX.h"
+#include "RegisterContextPOSIXProcessMonitor_mips64.h"
+#include "RegisterContextPOSIXProcessMonitor_x86.h"
+#include "RegisterContextLinux_i386.h"
#include "RegisterContextLinux_x86_64.h"
+#include "RegisterContextFreeBSD_i386.h"
+#include "RegisterContextFreeBSD_mips64.h"
#include "RegisterContextFreeBSD_x86_64.h"
#include "UnwindLLDB.h"
@@ -46,7 +48,8 @@ POSIXThread::POSIXThread(Process &process, lldb::tid_t tid)
m_frame_ap (),
m_breakpoint (),
m_thread_name_valid (false),
- m_thread_name ()
+ m_thread_name (),
+ m_posix_thread(NULL)
{
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
@@ -138,34 +141,66 @@ POSIXThread::GetRegisterContext()
{
if (!m_reg_context_sp)
{
- ArchSpec arch = Host::GetArchitecture();
+ m_posix_thread = NULL;
- switch (arch.GetCore())
+ RegisterInfoInterface *reg_interface = NULL;
+ const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
+
+ switch (target_arch.GetCore())
{
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- m_reg_context_sp.reset(new RegisterContext_i386(*this, 0));
- break;
-
- case ArchSpec::eCore_x86_64_x86_64:
- switch (arch.GetTriple().getOS())
+ case ArchSpec::eCore_mips64:
{
- case llvm::Triple::FreeBSD:
- m_reg_context_sp.reset(new RegisterContextFreeBSD_x86_64(*this, 0));
- break;
- case llvm::Triple::Linux:
- m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
- break;
- default:
- assert(false && "OS not supported");
- break;
+ RegisterInfoInterface *reg_interface = NULL;
+
+ switch (target_arch.GetTriple().getOS())
+ {
+ case llvm::Triple::FreeBSD:
+ reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
+ break;
+ default:
+ assert(false && "OS not supported");
+ break;
+ }
+
+ if (reg_interface)
+ {
+ RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ }
+ break;
}
- break;
+
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ case ArchSpec::eCore_x86_64_x86_64:
+ {
+ switch (target_arch.GetTriple().getOS())
+ {
+ case llvm::Triple::FreeBSD:
+ reg_interface = new RegisterContextFreeBSD_x86_64(target_arch);
+ break;
+ case llvm::Triple::Linux:
+ reg_interface = new RegisterContextLinux_x86_64(target_arch);
+ break;
+ default:
+ assert(false && "OS not supported");
+ break;
+ }
+
+ if (reg_interface)
+ {
+ RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ }
+ break;
+ }
+
+ default:
+ assert(false && "CPU type not supported!");
+ break;
}
}
return m_reg_context_sp;
@@ -195,6 +230,17 @@ POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
return reg_ctx_sp;
}
+lldb::addr_t
+POSIXThread::GetThreadPointer ()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ addr_t addr;
+ if (monitor.ReadThreadPointer (GetID(), addr))
+ return addr;
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
bool
POSIXThread::CalculateStopInfo()
{
@@ -314,6 +360,10 @@ POSIXThread::Notify(const ProcessMessage &message)
case ProcessMessage::eNewThreadMessage:
ThreadNotify(message);
break;
+
+ case ProcessMessage::eExecMessage:
+ ExecNotify(message);
+ break;
}
}
@@ -328,7 +378,7 @@ POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp)
bool wp_read = wp->WatchpointRead();
bool wp_write = wp->WatchpointWrite();
uint32_t wp_hw_index = wp->GetHardwareIndex();
- RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
if (reg_ctx)
wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
wp_read, wp_write,
@@ -365,7 +415,7 @@ POSIXThread::FindVacantWatchpointIndex()
uint32_t hw_index = LLDB_INVALID_INDEX32;
uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
uint32_t wp_idx;
- RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
if (reg_ctx)
{
for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
@@ -387,7 +437,7 @@ POSIXThread::BreakNotify(const ProcessMessage &message)
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
assert(GetRegisterContext());
- status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint();
+ status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint();
assert(status && "Breakpoint update failed!");
// With our register state restored, resolve the breakpoint object
@@ -399,31 +449,22 @@ POSIXThread::BreakNotify(const ProcessMessage &message)
lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
// If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
- if (bp_site && bp_site->ValidForThisThread(this))
+ // we create a stop reason with should_stop=false. If there is no breakpoint location, then report
+ // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will
+ // be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+ if (bp_site)
{
lldb::break_id_t bp_id = bp_site->GetID();
- if (GetProcess()->GetThreadList().SetSelectedThreadByID(GetID()))
+ if (bp_site->ValidForThisThread(this))
SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
else
- assert(false && "Invalid thread ID during BreakNotify.");
- }
- else
- {
- const ThreadSpec *spec = bp_site ?
- bp_site->GetOwnerAtIndex(0)->GetOptionsNoCreate()->GetThreadSpecNoCreate() : 0;
-
- if (spec && spec->TIDMatches(*this))
- assert(false && "BreakpointSite is invalid for the current ThreadSpec.");
- else
{
- if (!m_stop_info_sp) {
- StopInfoSP invalid_stop_info_sp;
- SetStopInfo (invalid_stop_info_sp);
- }
+ const bool should_stop = false;
+ SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop));
}
}
+ else
+ SetStopInfo(StopInfoSP());
}
void
@@ -436,7 +477,7 @@ POSIXThread::WatchNotify(const ProcessMessage &message)
log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8"
PRIx64, __FUNCTION__, halt_addr);
- RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
if (reg_ctx)
{
uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
@@ -532,22 +573,26 @@ POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
llvm_unreachable("CPU type not supported!");
break;
+ case ArchSpec::eCore_mips64:
case ArchSpec::eCore_x86_32_i386:
case ArchSpec::eCore_x86_32_i486:
case ArchSpec::eCore_x86_32_i486sx:
case ArchSpec::eCore_x86_64_x86_64:
{
- RegisterContextSP base = GetRegisterContext();
- if (base) {
- RegisterContextPOSIX &context = static_cast<RegisterContextPOSIX &>(*base);
- reg = context.GetRegisterIndexFromOffset(offset);
- }
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ reg = reg_ctx->GetRegisterIndexFromOffset(offset);
}
break;
}
return reg;
}
+void
+POSIXThread::ExecNotify(const ProcessMessage &message)
+{
+ SetStopInfo (StopInfo::CreateStopReasonWithExec(*this));
+}
+
const char *
POSIXThread::GetRegisterName(unsigned reg)
{
@@ -560,6 +605,7 @@ POSIXThread::GetRegisterName(unsigned reg)
assert(false && "CPU type not supported!");
break;
+ case ArchSpec::eCore_mips64:
case ArchSpec::eCore_x86_32_i386:
case ArchSpec::eCore_x86_32_i486:
case ArchSpec::eCore_x86_32_i486sx:
diff --git a/source/Plugins/Process/POSIX/POSIXThread.h b/source/Plugins/Process/POSIX/POSIXThread.h
index d051d23860df..51d6645f209d 100644
--- a/source/Plugins/Process/POSIX/POSIXThread.h
+++ b/source/Plugins/Process/POSIX/POSIXThread.h
@@ -21,7 +21,7 @@
class ProcessMessage;
class ProcessMonitor;
-class RegisterContextPOSIX;
+class POSIXBreakpointProtocol;
//------------------------------------------------------------------------------
// @class POSIXThread
@@ -59,6 +59,9 @@ public:
virtual lldb::RegisterContextSP
CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ virtual lldb::addr_t
+ GetThreadPointer ();
+
//--------------------------------------------------------------------------
// These functions provide a mapping from the register offset
// back to the register index or name for use in debugging or log
@@ -92,15 +95,12 @@ public:
uint32_t FindVacantWatchpointIndex();
protected:
- RegisterContextPOSIX *
- GetRegisterContextPOSIX ()
+ POSIXBreakpointProtocol *
+ GetPOSIXBreakpointProtocol ()
{
if (!m_reg_context_sp)
m_reg_context_sp = GetRegisterContext();
-#if 0
- return dynamic_cast<RegisterContextPOSIX*>(m_reg_context_sp.get());
-#endif
- return (RegisterContextPOSIX *)m_reg_context_sp.get();
+ return m_posix_thread;
}
std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
@@ -109,6 +109,7 @@ protected:
bool m_thread_name_valid;
std::string m_thread_name;
+ POSIXBreakpointProtocol *m_posix_thread;
ProcessMonitor &
GetMonitor();
@@ -125,6 +126,7 @@ protected:
void CrashNotify(const ProcessMessage &message);
void ThreadNotify(const ProcessMessage &message);
void ExitNotify(const ProcessMessage &message);
+ void ExecNotify(const ProcessMessage &message);
lldb_private::Unwind *
GetUnwinder();
diff --git a/source/Plugins/Process/POSIX/ProcessMessage.cpp b/source/Plugins/Process/POSIX/ProcessMessage.cpp
index 60a29e07cea8..5c53627f9e0b 100644
--- a/source/Plugins/Process/POSIX/ProcessMessage.cpp
+++ b/source/Plugins/Process/POSIX/ProcessMessage.cpp
@@ -218,6 +218,9 @@ ProcessMessage::PrintKind(Kind kind)
case eInvalidMessage:
str = "eInvalidMessage";
break;
+ case eAttachMessage:
+ str = "eAttachMessage";
+ break;
case eExitMessage:
str = "eExitMessage";
break;
@@ -245,6 +248,9 @@ ProcessMessage::PrintKind(Kind kind)
case eNewThreadMessage:
str = "eNewThreadMessage";
break;
+ case eExecMessage:
+ str = "eExecMessage";
+ break;
}
#endif
diff --git a/source/Plugins/Process/POSIX/ProcessMessage.h b/source/Plugins/Process/POSIX/ProcessMessage.h
index c6c460c13445..40462d0f0e13 100644
--- a/source/Plugins/Process/POSIX/ProcessMessage.h
+++ b/source/Plugins/Process/POSIX/ProcessMessage.h
@@ -23,6 +23,7 @@ public:
enum Kind
{
eInvalidMessage,
+ eAttachMessage,
eExitMessage,
eLimboMessage,
eSignalMessage,
@@ -31,7 +32,8 @@ public:
eBreakpointMessage,
eWatchpointMessage,
eCrashMessage,
- eNewThreadMessage
+ eNewThreadMessage,
+ eExecMessage
};
enum CrashReason
@@ -79,6 +81,11 @@ public:
lldb::tid_t GetTID() const { return m_tid; }
+ /// Indicates that the process @p pid has successfully attached.
+ static ProcessMessage Attach(lldb::pid_t pid) {
+ return ProcessMessage(pid, eAttachMessage);
+ }
+
/// Indicates that the thread @p tid is about to exit with status @p status.
static ProcessMessage Limbo(lldb::tid_t tid, int status) {
return ProcessMessage(tid, eLimboMessage, status);
@@ -127,6 +134,11 @@ public:
return ProcessMessage(tid, eExitMessage, status);
}
+ /// Indicates that the thread @p pid has exec'd.
+ static ProcessMessage Exec(lldb::tid_t tid) {
+ return ProcessMessage(tid, eExecMessage);
+ }
+
int GetExitStatus() const {
assert(GetKind() == eExitMessage || GetKind() == eLimboMessage);
return m_status;
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index f04631ddf914..70ad3a66d9ef 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -289,12 +289,11 @@ ProcessPOSIX::GetImageInfoAddress()
{
Target *target = &GetTarget();
ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress();
+ Address addr = obj_file->GetImageInfoAddress(target);
- if (addr.IsValid())
+ if (addr.IsValid())
return addr.GetLoadAddress(target);
- else
- return LLDB_INVALID_ADDRESS;
+ return LLDB_INVALID_ADDRESS;
}
Error
@@ -319,34 +318,6 @@ ProcessPOSIX::DoHalt(bool &caused_stop)
}
Error
-ProcessPOSIX::DoDetach(bool keep_stopped)
-{
- Error error;
- if (keep_stopped)
- {
- // FIXME: If you want to implement keep_stopped,
- // this would be the place to do it.
- error.SetErrorString("Detaching with keep_stopped true is not currently supported on this platform.");
- return error;
- }
-
- Mutex::Locker lock(m_thread_list.GetMutex());
-
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- error = m_monitor->Detach(thread->GetID());
- }
-
- if (error.Success())
- SetPrivateState(eStateDetached);
-
- return error;
-}
-
-Error
ProcessPOSIX::DoSignal(int signal)
{
Error error;
@@ -381,6 +352,31 @@ ProcessPOSIX::DoDestroy()
}
void
+ProcessPOSIX::DoDidExec()
+{
+ Target *target = &GetTarget();
+ if (target)
+ {
+ PlatformSP platform_sp (target->GetPlatform());
+ assert (platform_sp.get());
+ if (platform_sp)
+ {
+ ProcessInstanceInfo process_info;
+ platform_sp->GetProcessInfo(GetID(), process_info);
+ ModuleSP exe_module_sp;
+ FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+ Error error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(),
+ target->GetArchitecture(),
+ exe_module_sp,
+ executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+ if (!error.Success())
+ return;
+ target->SetExecutableModule(exe_module_sp, true);
+ }
+ }
+}
+
+void
ProcessPOSIX::SendMessage(const ProcessMessage &message)
{
Mutex::Locker lock(m_message_mutex);
@@ -395,6 +391,10 @@ ProcessPOSIX::SendMessage(const ProcessMessage &message)
case ProcessMessage::eInvalidMessage:
return;
+ case ProcessMessage::eAttachMessage:
+ SetPrivateState(eStateStopped);
+ return;
+
case ProcessMessage::eLimboMessage:
assert(thread);
thread->SetState(eStateStopped);
@@ -442,15 +442,38 @@ ProcessPOSIX::SendMessage(const ProcessMessage &message)
case ProcessMessage::eBreakpointMessage:
case ProcessMessage::eTraceMessage:
case ProcessMessage::eWatchpointMessage:
- case ProcessMessage::eNewThreadMessage:
case ProcessMessage::eCrashMessage:
assert(thread);
thread->SetState(eStateStopped);
StopAllThreads(message.GetTID());
SetPrivateState(eStateStopped);
break;
+
+ case ProcessMessage::eNewThreadMessage:
+ {
+ lldb::tid_t new_tid = message.GetChildTID();
+ if (WaitingForInitialStop(new_tid))
+ {
+ m_monitor->WaitForInitialTIDStop(new_tid);
+ }
+ assert(thread);
+ thread->SetState(eStateStopped);
+ StopAllThreads(message.GetTID());
+ SetPrivateState(eStateStopped);
+ break;
}
+ case ProcessMessage::eExecMessage:
+ {
+ assert(thread);
+ thread->SetState(eStateStopped);
+ StopAllThreads(message.GetTID());
+ SetPrivateState(eStateStopped);
+ break;
+ }
+ }
+
+
m_message_queue.push(message);
}
@@ -473,6 +496,12 @@ ProcessPOSIX::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
return added_to_set;
}
+bool
+ProcessPOSIX::WaitingForInitialStop(lldb::tid_t stop_tid)
+{
+ return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
+}
+
POSIXThread *
ProcessPOSIX::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid)
{
@@ -499,8 +528,6 @@ ProcessPOSIX::RefreshStateAfterStop()
lldb::tid_t tid = message.GetTID();
if (log)
log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
- POSIXThread *thread = static_cast<POSIXThread*>(
- GetThreadList().FindThreadByID(tid, false).get());
if (message.GetKind() == ProcessMessage::eNewThreadMessage)
{
@@ -517,6 +544,8 @@ ProcessPOSIX::RefreshStateAfterStop()
m_thread_list.RefreshStateAfterStop();
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ GetThreadList().FindThreadByID(tid, false).get());
if (thread)
thread->Notify(message);
@@ -813,19 +842,21 @@ ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thre
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
+ bool has_updated = false;
// Update the process thread list with this new thread.
// FIXME: We should be using tid, not pid.
assert(m_monitor);
ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
if (!thread_sp) {
thread_sp.reset(CreateNewPOSIXThread(*this, GetID()));
+ has_updated = true;
}
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
new_thread_list.AddThread(thread_sp);
- return new_thread_list.GetSize(false) > 0;
+ return has_updated; // the list has been updated
}
ByteOrder
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.h b/source/Plugins/Process/POSIX/ProcessPOSIX.h
index 48b19bac47e7..790041be321a 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.h
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.h
@@ -70,7 +70,7 @@ public:
DoHalt(bool &caused_stop);
virtual lldb_private::Error
- DoDetach(bool keep_stopped);
+ DoDetach(bool keep_stopped) = 0;
virtual lldb_private::Error
DoSignal(int signal);
@@ -79,6 +79,9 @@ public:
DoDestroy();
virtual void
+ DoDidExec();
+
+ virtual void
RefreshStateAfterStop();
virtual bool
@@ -167,6 +170,9 @@ public:
bool
AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
+ bool
+ WaitingForInitialStop(lldb::tid_t stop_tid);
+
virtual POSIXThread *
CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid);
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp
new file mode 100644
index 000000000000..50ec8d414a12
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp
@@ -0,0 +1,78 @@
+//===-- RegisterContextFreeBSD_i386.cpp ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "RegisterContextPOSIX_x86.h"
+#include "RegisterContextFreeBSD_i386.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// http://svnweb.freebsd.org/base/head/sys/x86/include/reg.h
+struct GPR
+{
+ uint32_t fs;
+ uint32_t es;
+ uint32_t ds;
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t ebp;
+ uint32_t isp;
+ uint32_t ebx;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t eax;
+ uint32_t trapno;
+ uint32_t err;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+ uint32_t esp;
+ uint32_t ss;
+ uint32_t gs;
+};
+
+#define DR_SIZE 0
+#define DR_OFFSET(reg_index) 0
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_I386_STRUCT
+#include "RegisterInfos_i386.h"
+#undef DECLARE_REGISTER_INFOS_I386_STRUCT
+
+RegisterContextFreeBSD_i386::RegisterContextFreeBSD_i386(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
+}
+
+RegisterContextFreeBSD_i386::~RegisterContextFreeBSD_i386()
+{
+}
+
+size_t
+RegisterContextFreeBSD_i386::GetGPRSize()
+{
+ return sizeof(GPR);
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_i386::GetRegisterInfo()
+{
+ switch (m_target_arch.GetCore())
+ {
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ return g_register_infos_i386;
+ default:
+ assert(false && "Unhandled target architecture.");
+ return NULL;
+ }
+}
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h
new file mode 100644
index 000000000000..4ec2ad3e9706
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h
@@ -0,0 +1,29 @@
+//===-- RegisterContextFreeBSD_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_RegisterContextFreeBSD_i386_H_
+#define liblldb_RegisterContextFreeBSD_i386_H_
+
+#include "RegisterContextPOSIX.h"
+
+class RegisterContextFreeBSD_i386
+ : public RegisterInfoInterface
+{
+public:
+ RegisterContextFreeBSD_i386(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextFreeBSD_i386();
+
+ size_t
+ GetGPRSize();
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp
new file mode 100644
index 000000000000..4714251fd2dc
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp
@@ -0,0 +1,90 @@
+//===-- RegisterContextFreeBSD_mips64.cpp ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include <vector>
+#include "RegisterContextPOSIX_mips64.h"
+#include "RegisterContextFreeBSD_mips64.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// http://svnweb.freebsd.org/base/head/sys/mips/include/regnum.h
+typedef struct _GPR
+{
+ uint64_t zero;
+ uint64_t r1;
+ uint64_t r2;
+ uint64_t r3;
+ uint64_t r4;
+ uint64_t r5;
+ uint64_t r6;
+ uint64_t r7;
+ 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 r16;
+ uint64_t r17;
+ uint64_t r18;
+ uint64_t r19;
+ uint64_t r20;
+ uint64_t r21;
+ uint64_t r22;
+ uint64_t r23;
+ uint64_t r24;
+ uint64_t r25;
+ uint64_t r26;
+ uint64_t r27;
+ uint64_t gp;
+ uint64_t sp;
+ uint64_t r30;
+ uint64_t ra;
+ uint64_t sr;
+ uint64_t mullo;
+ uint64_t mulhi;
+ uint64_t badvaddr;
+ uint64_t cause;
+ uint64_t pc;
+ uint64_t ic;
+ uint64_t dummy;
+} GPR;
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_mips64 to declare our g_register_infos_mips64 structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_MIPS64_STRUCT
+#include "RegisterInfos_mips64.h"
+#undef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
+
+RegisterContextFreeBSD_mips64::RegisterContextFreeBSD_mips64(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
+}
+
+RegisterContextFreeBSD_mips64::~RegisterContextFreeBSD_mips64()
+{
+}
+
+size_t
+RegisterContextFreeBSD_mips64::GetGPRSize()
+{
+ return sizeof(GPR);
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_mips64::GetRegisterInfo()
+{
+ assert (m_target_arch.GetCore() == ArchSpec::eCore_mips64);
+ return g_register_infos_mips64;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h
new file mode 100644
index 000000000000..9ee767955347
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h
@@ -0,0 +1,29 @@
+//===-- RegisterContextFreeBSD_mips64.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_RegisterContextFreeBSD_mips64_H_
+#define liblldb_RegisterContextFreeBSD_mips64_H_
+
+#include "RegisterContextPOSIX.h"
+
+class RegisterContextFreeBSD_mips64:
+ public RegisterInfoInterface
+{
+public:
+ RegisterContextFreeBSD_mips64(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextFreeBSD_mips64();
+
+ size_t
+ GetGPRSize();
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
index 0fb9dc1cb3dc..471734580fff 100644
--- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
@@ -1,4 +1,4 @@
-//===-- RegisterContextFreeBSD_x86_64.h ------------------------*- C++ -*-===//
+//===-- RegisterContextFreeBSD_x86_64.cpp ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,27 +7,15 @@
//
//===---------------------------------------------------------------------===//
-#include "RegisterContextFreeBSD_x86_64.h"
#include <vector>
+#include "RegisterContextPOSIX_x86.h"
+#include "RegisterContextFreeBSD_i386.h"
+#include "RegisterContextFreeBSD_x86_64.h"
using namespace lldb_private;
+using namespace lldb;
-// Computes the offset of the given GPR in the user data area.
-#define GPR_OFFSET(regname) \
- (offsetof(GPR, regname))
-
-// Update the FreeBSD specific information (offset and size).
-#define UPDATE_GPR_INFO(reg) \
-do { \
- GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \
- GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
-} while(false);
-
-#define UPDATE_I386_GPR_INFO(i386_reg, reg) \
-do { \
- GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
-} while(false);
-
+// http://svnweb.freebsd.org/base/head/sys/x86/include/reg.h
typedef struct _GPR
{
uint64_t r15;
@@ -58,15 +46,47 @@ typedef struct _GPR
uint64_t ss;
} GPR;
-// Use a singleton function to avoid global constructors in shared libraries.
-static std::vector<RegisterInfo> & GetRegisterContext () {
- static std::vector<RegisterInfo> g_register_infos;
- return g_register_infos;
+#define DR_SIZE 0
+#define DR_OFFSET(reg_index) 0
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_X86_64_STRUCT
+#include "RegisterInfos_x86_64.h"
+#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
+
+static const RegisterInfo *
+GetRegisterInfo_i386(const lldb_private::ArchSpec& arch)
+{
+ static std::vector<lldb_private::RegisterInfo> g_register_infos;
+
+ // Allocate RegisterInfo only once
+ if (g_register_infos.empty())
+ {
+ // Copy the register information from base class
+ std::unique_ptr<RegisterContextFreeBSD_i386> reg_interface(new RegisterContextFreeBSD_i386 (arch));
+ const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
+ g_register_infos.insert(g_register_infos.end(), &base_info[0], &base_info[k_num_registers_i386]);
+
+ //---------------------------------------------------------------------------
+ // Include RegisterInfos_x86_64 to update the g_register_infos structure
+ // with x86_64 offsets.
+ //---------------------------------------------------------------------------
+ #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+ #include "RegisterInfos_x86_64.h"
+ #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+ }
+
+ return &g_register_infos[0];
}
+RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
+}
-RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(Thread &thread, uint32_t concrete_frame_idx):
- RegisterContext_x86_64(thread, concrete_frame_idx)
+RegisterContextFreeBSD_x86_64::~RegisterContextFreeBSD_x86_64()
{
}
@@ -79,58 +99,17 @@ RegisterContextFreeBSD_x86_64::GetGPRSize()
const RegisterInfo *
RegisterContextFreeBSD_x86_64::GetRegisterInfo()
{
- // Allocate RegisterInfo only once
- if (GetRegisterContext().empty())
+ switch (m_target_arch.GetCore())
{
- // Copy the register information from base class
- const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
- if (base_info)
- {
- GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
- // Update the FreeBSD specific register information (offset and size).
- UpdateRegisterInfo();
- }
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ return GetRegisterInfo_i386 (m_target_arch);
+ case ArchSpec::eCore_x86_64_x86_64:
+ return g_register_infos_x86_64;
+ default:
+ assert(false && "Unhandled target architecture.");
+ return NULL;
}
- return &GetRegisterContext()[0];
-}
-
-void
-RegisterContextFreeBSD_x86_64::UpdateRegisterInfo()
-{
- UPDATE_GPR_INFO(rax);
- UPDATE_GPR_INFO(rbx);
- UPDATE_GPR_INFO(rcx);
- UPDATE_GPR_INFO(rdx);
- UPDATE_GPR_INFO(rdi);
- UPDATE_GPR_INFO(rsi);
- UPDATE_GPR_INFO(rbp);
- UPDATE_GPR_INFO(rsp);
- UPDATE_GPR_INFO(r8);
- UPDATE_GPR_INFO(r9);
- UPDATE_GPR_INFO(r10);
- UPDATE_GPR_INFO(r11);
- UPDATE_GPR_INFO(r12);
- UPDATE_GPR_INFO(r13);
- UPDATE_GPR_INFO(r14);
- UPDATE_GPR_INFO(r15);
- UPDATE_GPR_INFO(rip);
- UPDATE_GPR_INFO(rflags);
- UPDATE_GPR_INFO(cs);
- UPDATE_GPR_INFO(fs);
- UPDATE_GPR_INFO(gs);
- UPDATE_GPR_INFO(ss);
- UPDATE_GPR_INFO(ds);
- UPDATE_GPR_INFO(es);
-
- UPDATE_I386_GPR_INFO(eax, rax);
- UPDATE_I386_GPR_INFO(ebx, rbx);
- UPDATE_I386_GPR_INFO(ecx, rcx);
- UPDATE_I386_GPR_INFO(edx, rdx);
- UPDATE_I386_GPR_INFO(edi, rdi);
- UPDATE_I386_GPR_INFO(esi, rsi);
- UPDATE_I386_GPR_INFO(ebp, rbp);
- UPDATE_I386_GPR_INFO(esp, rsp);
- UPDATE_I386_GPR_INFO(eip, rip);
- UPDATE_I386_GPR_INFO(eflags, rflags);
}
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
index ffff40a9c65b..731bb0ea6bcc 100644
--- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
@@ -1,4 +1,4 @@
-//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===//
+//===-- RegisterContextFreeBSD_x86_64.h -------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,23 +10,20 @@
#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_
#define liblldb_RegisterContextFreeBSD_x86_64_H_
-#include "Plugins/Process/POSIX/RegisterContext_x86_64.h"
+#include "RegisterContextPOSIX.h"
class RegisterContextFreeBSD_x86_64:
- public RegisterContext_x86_64
+ public RegisterInfoInterface
{
public:
- RegisterContextFreeBSD_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+ RegisterContextFreeBSD_x86_64(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextFreeBSD_x86_64();
size_t
GetGPRSize();
-protected:
- virtual const lldb_private::RegisterInfo *
+ const lldb_private::RegisterInfo *
GetRegisterInfo();
-
- virtual void
- UpdateRegisterInfo();
};
#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp
new file mode 100644
index 000000000000..0828efbc6c3c
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp
@@ -0,0 +1,96 @@
+//===-- RegisterContextLinux_i386.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "RegisterContextPOSIX_x86.h"
+#include "RegisterContextLinux_i386.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+struct GPR
+{
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t ebp;
+ uint32_t eax;
+ uint32_t ds;
+ uint32_t es;
+ uint32_t fs;
+ uint32_t gs;
+ uint32_t orig_ax;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+ uint32_t esp;
+ uint32_t ss;
+};
+
+struct UserArea
+{
+ GPR regs; // General purpose registers.
+ int32_t fpvalid; // True if FPU is being used.
+ FXSAVE i387; // FPU registers.
+ uint32_t tsize; // Text segment size.
+ uint32_t dsize; // Data segment size.
+ uint32_t ssize; // Stack segment size.
+ uint32_t start_code; // VM address of text.
+ uint32_t start_stack; // VM address of stack bottom (top in rsp).
+ int32_t signal; // Signal causing core dump.
+ int32_t reserved; // Unused.
+ uint32_t ar0; // Location of GPR's.
+ uint32_t fpstate; // Location of FPR's. Should be a FXSTATE *, but this
+ // has to be 32-bits even on 64-bit systems.
+ uint32_t magic; // Identifier for core dumps.
+ char u_comm[32]; // Command causing core dump.
+ uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).
+};
+
+#define DR_SIZE sizeof(UserArea::u_debugreg[0])
+#define DR_OFFSET(reg_index) \
+ (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index]))
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_I386_STRUCT
+#include "RegisterInfos_i386.h"
+#undef DECLARE_REGISTER_INFOS_I386_STRUCT
+
+RegisterContextLinux_i386::RegisterContextLinux_i386(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
+}
+
+RegisterContextLinux_i386::~RegisterContextLinux_i386()
+{
+}
+
+size_t
+RegisterContextLinux_i386::GetGPRSize()
+{
+ return sizeof(GPR);
+}
+
+const RegisterInfo *
+RegisterContextLinux_i386::GetRegisterInfo()
+{
+ switch (m_target_arch.GetCore())
+ {
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ return g_register_infos_i386;
+ default:
+ assert(false && "Unhandled target architecture.");
+ return NULL;
+ }
+}
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h
new file mode 100644
index 000000000000..81afdbf8b1cf
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h
@@ -0,0 +1,29 @@
+//===-- RegisterContextLinux_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_RegisterContextLinux_i386_H_
+#define liblldb_RegisterContextLinux_i386_H_
+
+#include "RegisterContextPOSIX.h"
+
+class RegisterContextLinux_i386
+ : public RegisterInfoInterface
+{
+public:
+ RegisterContextLinux_i386(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextLinux_i386();
+
+ size_t
+ GetGPRSize();
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
index c1aea2a41a1f..5434ddfcf38b 100644
--- a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
+++ b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
@@ -1,4 +1,4 @@
-//===-- RegisterContextLinux_x86_64.h --------------------------*- C++ -*-===//
+//===-- RegisterContextLinux_x86_64.cpp ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,36 +7,13 @@
//
//===---------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
-#include "RegisterContextLinux_x86_64.h"
#include <vector>
+#include "RegisterContextPOSIX_x86.h"
+#include "RegisterContextLinux_i386.h"
+#include "RegisterContextLinux_x86_64.h"
using namespace lldb_private;
-
-// Computes the offset of the given GPR in the user data area.
-#define GPR_OFFSET(regname) \
- (offsetof(GPR, regname))
-
-// Update the Linux specific information (offset and size).
-#define UPDATE_GPR_INFO(reg) \
-do { \
- GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \
- GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
-} while(false);
-
-#define UPDATE_I386_GPR_INFO(i386_reg, reg) \
-do { \
- GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
-} while(false);
-
-#define DR_OFFSET(reg_index) \
- (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index]))
-
-#define UPDATE_DR_INFO(reg_index) \
-do { \
- GetRegisterContext()[dr##reg_index].byte_size = sizeof(UserArea::u_debugreg[0]); \
- GetRegisterContext()[dr##reg_index].byte_offset = DR_OFFSET(reg_index); \
-} while(false);
+using namespace lldb;
typedef struct _GPR
{
@@ -69,8 +46,6 @@ typedef struct _GPR
uint64_t gs;
} GPR;
-typedef RegisterContext_x86_64::FXSAVE FXSAVE;
-
struct UserArea
{
GPR gpr; // General purpose registers.
@@ -94,14 +69,48 @@ struct UserArea
uint64_t fault_address; // Control register CR3.
};
-// Use a singleton function to avoid global constructors in shared libraries.
-static std::vector<RegisterInfo> & GetRegisterContext () {
- static std::vector<RegisterInfo> g_register_infos;
- return g_register_infos;
+#define DR_SIZE sizeof(UserArea::u_debugreg[0])
+#define DR_OFFSET(reg_index) \
+ (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index]))
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_X86_64_STRUCT
+#include "RegisterInfos_x86_64.h"
+#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
+
+static const RegisterInfo *
+GetRegisterInfo_i386(const lldb_private::ArchSpec &arch)
+{
+ static std::vector<lldb_private::RegisterInfo> g_register_infos;
+
+ // Allocate RegisterInfo only once
+ if (g_register_infos.empty())
+ {
+ // Copy the register information from base class
+ std::unique_ptr<RegisterContextLinux_i386> reg_interface(new RegisterContextLinux_i386 (arch));
+ const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
+ g_register_infos.insert(g_register_infos.end(), &base_info[0], &base_info[k_num_registers_i386]);
+
+ //---------------------------------------------------------------------------
+ // Include RegisterInfos_x86_64 to update the g_register_infos structure
+ // with x86_64 offsets.
+ //---------------------------------------------------------------------------
+ #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+ #include "RegisterInfos_x86_64.h"
+ #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+ }
+
+ return &g_register_infos[0];
+}
+
+RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
}
-RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, uint32_t concrete_frame_idx):
- RegisterContext_x86_64(thread, concrete_frame_idx)
+RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64()
{
}
@@ -114,67 +123,17 @@ RegisterContextLinux_x86_64::GetGPRSize()
const RegisterInfo *
RegisterContextLinux_x86_64::GetRegisterInfo()
{
- // Allocate RegisterInfo only once
- if (GetRegisterContext().empty())
+ switch (m_target_arch.GetCore())
{
- // Copy the register information from base class
- const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
- if (base_info)
- {
- GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
- // Update the Linux specific register information (offset and size).
- UpdateRegisterInfo();
- }
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ return GetRegisterInfo_i386 (m_target_arch);
+ case ArchSpec::eCore_x86_64_x86_64:
+ return g_register_infos_x86_64;
+ default:
+ assert(false && "Unhandled target architecture.");
+ return NULL;
}
- return &GetRegisterContext()[0];
-}
-
-void
-RegisterContextLinux_x86_64::UpdateRegisterInfo()
-{
- UPDATE_GPR_INFO(rax);
- UPDATE_GPR_INFO(rbx);
- UPDATE_GPR_INFO(rcx);
- UPDATE_GPR_INFO(rdx);
- UPDATE_GPR_INFO(rdi);
- UPDATE_GPR_INFO(rsi);
- UPDATE_GPR_INFO(rbp);
- UPDATE_GPR_INFO(rsp);
- UPDATE_GPR_INFO(r8);
- UPDATE_GPR_INFO(r9);
- UPDATE_GPR_INFO(r10);
- UPDATE_GPR_INFO(r11);
- UPDATE_GPR_INFO(r12);
- UPDATE_GPR_INFO(r13);
- UPDATE_GPR_INFO(r14);
- UPDATE_GPR_INFO(r15);
- UPDATE_GPR_INFO(rip);
- UPDATE_GPR_INFO(rflags);
- UPDATE_GPR_INFO(cs);
- UPDATE_GPR_INFO(fs);
- UPDATE_GPR_INFO(gs);
- UPDATE_GPR_INFO(ss);
- UPDATE_GPR_INFO(ds);
- UPDATE_GPR_INFO(es);
-
- UPDATE_I386_GPR_INFO(eax, rax);
- UPDATE_I386_GPR_INFO(ebx, rbx);
- UPDATE_I386_GPR_INFO(ecx, rcx);
- UPDATE_I386_GPR_INFO(edx, rdx);
- UPDATE_I386_GPR_INFO(edi, rdi);
- UPDATE_I386_GPR_INFO(esi, rsi);
- UPDATE_I386_GPR_INFO(ebp, rbp);
- UPDATE_I386_GPR_INFO(esp, rsp);
- UPDATE_I386_GPR_INFO(eip, rip);
- UPDATE_I386_GPR_INFO(eflags, rflags);
-
- UPDATE_DR_INFO(0);
- UPDATE_DR_INFO(1);
- UPDATE_DR_INFO(2);
- UPDATE_DR_INFO(3);
- UPDATE_DR_INFO(4);
- UPDATE_DR_INFO(5);
- UPDATE_DR_INFO(6);
- UPDATE_DR_INFO(7);
}
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
index 1509ef55b8dc..21c809b5dc33 100644
--- a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
+++ b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
@@ -10,23 +10,20 @@
#ifndef liblldb_RegisterContextLinux_x86_64_H_
#define liblldb_RegisterContextLinux_x86_64_H_
-#include "Plugins/Process/POSIX/RegisterContext_x86_64.h"
+#include "RegisterContextPOSIX.h"
-class RegisterContextLinux_x86_64:
- public RegisterContext_x86_64
+class RegisterContextLinux_x86_64
+ : public RegisterInfoInterface
{
public:
- RegisterContextLinux_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+ RegisterContextLinux_x86_64(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextLinux_x86_64();
size_t
GetGPRSize();
-protected:
- virtual const lldb_private::RegisterInfo *
+ const lldb_private::RegisterInfo *
GetRegisterInfo();
-
- virtual void
- UpdateRegisterInfo();
};
#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
index 63ae01e83a90..e48c528403e3 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
@@ -13,20 +13,19 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
#include "lldb/Target/RegisterContext.h"
//------------------------------------------------------------------------------
-/// @class RegisterContextPOSIX
+/// @class POSIXBreakpointProtocol
///
/// @brief Extends RegisterClass with a few virtual operations useful on POSIX.
-class RegisterContextPOSIX
- : public lldb_private::RegisterContext
+class POSIXBreakpointProtocol
{
public:
- RegisterContextPOSIX(lldb_private::Thread &thread,
- uint32_t concrete_frame_idx)
- : RegisterContext(thread, concrete_frame_idx)
+ POSIXBreakpointProtocol()
{ m_watchpoints_initialized = false; }
+ virtual ~POSIXBreakpointProtocol() {}
/// Updates the register state of the associated thread after hitting a
/// breakpoint (if that make sense for the architecture). Default
@@ -35,36 +34,61 @@ public:
///
/// @return
/// True if the operation succeeded and false otherwise.
- virtual bool UpdateAfterBreakpoint() { return true; }
+ virtual bool UpdateAfterBreakpoint() = 0;
/// Determines the index in lldb's register file given a kernel byte offset.
virtual unsigned
- GetRegisterIndexFromOffset(unsigned offset) { return LLDB_INVALID_REGNUM; }
+ GetRegisterIndexFromOffset(unsigned offset) = 0;
// Checks to see if a watchpoint specified by hw_index caused the inferior
// to stop.
virtual bool
- IsWatchpointHit (uint32_t hw_index) { return false; }
+ IsWatchpointHit (uint32_t hw_index) = 0;
// Resets any watchpoints that have been hit.
virtual bool
- ClearWatchpointHits () { return false; }
+ ClearWatchpointHits () = 0;
// Returns the watchpoint address associated with a watchpoint hardware
// index.
virtual lldb::addr_t
- GetWatchpointAddress (uint32_t hw_index) { return LLDB_INVALID_ADDRESS; }
+ GetWatchpointAddress (uint32_t hw_index) = 0;
virtual bool
- IsWatchpointVacant (uint32_t hw_index) { return false; }
+ IsWatchpointVacant (uint32_t hw_index) = 0;
virtual bool
SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size,
bool read, bool write,
- uint32_t hw_index) { return false; }
+ uint32_t hw_index) = 0;
+
+ // From lldb_private::RegisterContext
+ virtual uint32_t
+ NumSupportedHardwareWatchpoints () = 0;
protected:
bool m_watchpoints_initialized;
};
+//------------------------------------------------------------------------------
+/// @class RegisterInfoInterface
+///
+/// @brief RegisterInfo interface to patch RegisterInfo structure for archs.
+class RegisterInfoInterface
+{
+public:
+ RegisterInfoInterface(const lldb_private::ArchSpec& target_arch) : m_target_arch(target_arch) {}
+ virtual ~RegisterInfoInterface () {}
+
+ virtual size_t
+ GetGPRSize () = 0;
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfo () = 0;
+
+public:
+ lldb_private::ArchSpec m_target_arch;
+};
+
#endif // #ifndef liblldb_RegisterContextPOSIX_H_
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp
new file mode 100644
index 000000000000..f70d00e98a3e
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp
@@ -0,0 +1,318 @@
+//===-- RegisterContextPOSIXProcessMonitor_mips64.h ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Core/RegisterValue.h"
+
+#include "RegisterContextPOSIX_mips64.h"
+#include "ProcessPOSIX.h"
+#include "RegisterContextPOSIXProcessMonitor_mips64.h"
+#include "ProcessMonitor.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+#define REG_CONTEXT_SIZE (GetGPRSize())
+
+RegisterContextPOSIXProcessMonitor_mips64::RegisterContextPOSIXProcessMonitor_mips64(Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info)
+ : RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info)
+{
+}
+
+ProcessMonitor &
+RegisterContextPOSIXProcessMonitor_mips64::GetMonitor()
+{
+ ProcessSP base = CalculateProcess();
+ ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ return process->GetMonitor();
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ReadGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ReadFPR()
+{
+ // XXX not yet implemented
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::WriteGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::WriteFPR()
+{
+ // XXX not yet implemented
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const unsigned reg,
+ RegisterValue &value)
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg),
+ GetRegisterName(reg),
+ GetRegisterSize(reg),
+ value);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const unsigned reg,
+ const RegisterValue &value)
+{
+ unsigned reg_to_write = reg;
+ RegisterValue value_to_write = value;
+
+ // Check if this is a subregister of a full register.
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+ if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
+ {
+ RegisterValue full_value;
+ uint32_t full_reg = reg_info->invalidate_regs[0];
+ const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
+
+ // Read the full register.
+ if (ReadRegister(full_reg_info, full_value))
+ {
+ Error error;
+ ByteOrder byte_order = GetByteOrder();
+ uint8_t dst[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the full register.
+ const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
+ dst,
+ sizeof(dst),
+ byte_order,
+ error);
+ if (error.Success() && dest_size)
+ {
+ uint8_t src[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the source data.
+ const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
+ if (error.Success() && src_size && (src_size < dest_size))
+ {
+ // Copy the src bytes to the destination.
+ memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
+ // Set this full register as the value to write.
+ value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
+ value_to_write.SetType(full_reg_info);
+ reg_to_write = full_reg;
+ }
+ }
+ }
+ }
+
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg_to_write),
+ GetRegisterName(reg_to_write),
+ value_to_write);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+ if (!reg_info)
+ return false;
+
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ if (IsFPR(reg))
+ {
+ if (!ReadFPR())
+ return false;
+ }
+ else
+ {
+ uint32_t full_reg = reg;
+ bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
+
+ if (is_subreg)
+ {
+ // Read the full aligned 64-bit register.
+ full_reg = reg_info->invalidate_regs[0];
+ }
+
+ bool success = ReadRegister(full_reg, value);
+
+ if (success)
+ {
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
+ if (is_subreg && (reg_info->byte_offset & 0x1))
+ value.SetUInt64(value.GetAsUInt64() >> 8);
+
+ // If our return byte size was greater than the return value reg size, then
+ // use the type specified by reg_info rather than the uint64_t default
+ if (value.GetByteSize() > reg_info->byte_size)
+ value.SetType(reg_info);
+ }
+ return success;
+ }
+
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ if (IsGPR(reg))
+ return WriteRegister(reg, value);
+
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues(DataBufferSP &data_sp)
+{
+ bool success = false;
+ data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+ if (data_sp && ReadGPR () && ReadFPR ())
+ {
+ uint8_t *dst = data_sp->GetBytes();
+ success = dst != 0;
+
+ if (success)
+ {
+ ::memcpy (dst, &m_gpr_mips64, GetGPRSize());
+ dst += GetGPRSize();
+ }
+ }
+ return success;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::WriteAllRegisterValues(const DataBufferSP &data_sp)
+{
+ bool success = false;
+ if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+ {
+ uint8_t *src = data_sp->GetBytes();
+ if (src)
+ {
+ ::memcpy (&m_gpr_mips64, src, GetGPRSize());
+
+ if (WriteGPR())
+ {
+ src += GetGPRSize();
+ }
+ }
+ }
+ return success;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpoint(addr_t addr, size_t size,
+ bool read, bool write)
+{
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+ uint32_t hw_index;
+
+ for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+ {
+ if (IsWatchpointVacant(hw_index))
+ return SetHardwareWatchpointWithIndex(addr, size,
+ read, write,
+ hw_index);
+ }
+
+ return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep(bool enable)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint()
+{
+ // PC points one byte past the int3 responsible for the breakpoint.
+ lldb::addr_t pc;
+
+ if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+ return false;
+
+ SetPC(pc - 1);
+ return true;
+}
+
+unsigned
+RegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg;
+ for (reg = 0; reg < k_num_registers_mips64; reg++)
+ {
+ if (GetRegisterInfo()[reg].byte_offset == offset)
+ break;
+ }
+ assert(reg < k_num_registers_mips64 && "Invalid register offset.");
+ return reg;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits()
+{
+ return false;
+}
+
+addr_t
+RegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress(uint32_t hw_index)
+{
+ return LLDB_INVALID_ADDRESS;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
+ bool read, bool write,
+ uint32_t hw_index)
+{
+ return false;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints()
+{
+ return 0;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h
new file mode 100644
index 000000000000..8f545eef0d5e
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h
@@ -0,0 +1,95 @@
+//===-- RegisterContextPOSIXProcessMonitor_mips64.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_RegisterContextPOSIXProcessMonitor_mips64_H_
+#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
+
+#include "Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h"
+
+class RegisterContextPOSIXProcessMonitor_mips64:
+ public RegisterContextPOSIX_mips64,
+ public POSIXBreakpointProtocol
+{
+public:
+ RegisterContextPOSIXProcessMonitor_mips64(lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info);
+
+protected:
+ bool
+ ReadGPR();
+
+ bool
+ ReadFPR();
+
+ bool
+ WriteGPR();
+
+ bool
+ WriteFPR();
+
+ // lldb_private::RegisterContext
+ bool
+ ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
+
+ bool
+ WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
+
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+ uint32_t
+ SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write);
+
+ bool
+ ClearHardwareWatchpoint(uint32_t hw_index);
+
+ bool
+ HardwareSingleStep(bool enable);
+
+ // POSIXBreakpointProtocol
+ bool
+ UpdateAfterBreakpoint();
+
+ unsigned
+ GetRegisterIndexFromOffset(unsigned offset);
+
+ bool
+ IsWatchpointHit(uint32_t hw_index);
+
+ bool
+ ClearWatchpointHits();
+
+ lldb::addr_t
+ GetWatchpointAddress(uint32_t hw_index);
+
+ bool
+ IsWatchpointVacant(uint32_t hw_index);
+
+ bool
+ SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index);
+
+ uint32_t
+ NumSupportedHardwareWatchpoints();
+
+private:
+ ProcessMonitor &
+ GetMonitor();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
new file mode 100644
index 000000000000..98e0bce68678
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -0,0 +1,634 @@
+//===-- RegisterContextPOSIXProcessMonitor_x86.h ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Core/RegisterValue.h"
+
+#include "ProcessPOSIX.h"
+#include "RegisterContextPOSIXProcessMonitor_x86.h"
+#include "ProcessMonitor.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// Support ptrace extensions even when compiled without required kernel support
+#ifndef NT_X86_XSTATE
+ #define NT_X86_XSTATE 0x202
+#endif
+
+#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(FPR))
+
+static uint32_t
+size_and_rw_bits(size_t size, bool read, bool write)
+{
+ uint32_t rw;
+
+ if (read)
+ rw = 0x3; // READ or READ/WRITE
+ else if (write)
+ rw = 0x1; // WRITE
+ else
+ assert(0 && "read and write cannot both be false");
+
+ switch (size)
+ {
+ case 1:
+ return rw;
+ case 2:
+ return (0x1 << 2) | rw;
+ case 4:
+ return (0x3 << 2) | rw;
+ case 8:
+ return (0x2 << 2) | rw;
+ default:
+ assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
+ }
+}
+
+RegisterContextPOSIXProcessMonitor_x86_64::RegisterContextPOSIXProcessMonitor_x86_64(Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info)
+ : RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info)
+{
+}
+
+ProcessMonitor &
+RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor()
+{
+ ProcessSP base = CalculateProcess();
+ ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ return process->GetMonitor();
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ if (GetFPRType() == eFXSAVE)
+ return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+ if (GetFPRType() == eXSAVE)
+ return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ if (GetFPRType() == eFXSAVE)
+ return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+ if (GetFPRType() == eXSAVE)
+ return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const unsigned reg,
+ RegisterValue &value)
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg),
+ GetRegisterName(reg),
+ GetRegisterSize(reg),
+ value);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const unsigned reg,
+ const RegisterValue &value)
+{
+ unsigned reg_to_write = reg;
+ RegisterValue value_to_write = value;
+
+ // Check if this is a subregister of a full register.
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+ if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
+ {
+ RegisterValue full_value;
+ uint32_t full_reg = reg_info->invalidate_regs[0];
+ const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
+
+ // Read the full register.
+ if (ReadRegister(full_reg_info, full_value))
+ {
+ Error error;
+ ByteOrder byte_order = GetByteOrder();
+ uint8_t dst[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the full register.
+ const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
+ dst,
+ sizeof(dst),
+ byte_order,
+ error);
+ if (error.Success() && dest_size)
+ {
+ uint8_t src[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the source data.
+ const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
+ if (error.Success() && src_size && (src_size < dest_size))
+ {
+ // Copy the src bytes to the destination.
+ memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
+ // Set this full register as the value to write.
+ value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
+ value_to_write.SetType(full_reg_info);
+ reg_to_write = full_reg;
+ }
+ }
+ }
+ }
+
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg_to_write),
+ GetRegisterName(reg_to_write),
+ value_to_write);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+ if (!reg_info)
+ return false;
+
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ if (IsFPR(reg, GetFPRType()))
+ {
+ if (!ReadFPR())
+ return false;
+ }
+ else
+ {
+ uint32_t full_reg = reg;
+ bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
+
+ if (is_subreg)
+ {
+ // Read the full aligned 64-bit register.
+ full_reg = reg_info->invalidate_regs[0];
+ }
+
+ bool success = ReadRegister(full_reg, value);
+
+ if (success)
+ {
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
+ if (is_subreg && (reg_info->byte_offset & 0x1))
+ value.SetUInt64(value.GetAsUInt64() >> 8);
+
+ // If our return byte size was greater than the return value reg size, then
+ // use the type specified by reg_info rather than the uint64_t default
+ if (value.GetByteSize() > reg_info->byte_size)
+ value.SetType(reg_info);
+ }
+ return success;
+ }
+
+ if (reg_info->encoding == eEncodingVector)
+ {
+ ByteOrder byte_order = GetByteOrder();
+
+ if (byte_order != ByteOrder::eByteOrderInvalid)
+ {
+ if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
+ value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, reg_info->byte_size, byte_order);
+ if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
+ value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, reg_info->byte_size, byte_order);
+ if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
+ value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, reg_info->byte_size, byte_order);
+ if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm)
+ {
+ // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
+ if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
+ value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, reg_info->byte_size, byte_order);
+ else
+ return false;
+ }
+ return value.GetType() == RegisterValue::eTypeBytes;
+ }
+ return false;
+ }
+
+ // Get pointer to m_fpr.xstate.fxsave variable and set the data from it.
+ assert (reg_info->byte_offset < sizeof(m_fpr));
+ uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
+ switch (reg_info->byte_size)
+ {
+ case 2:
+ value.SetUInt16(*(uint16_t *)src);
+ return true;
+ case 4:
+ value.SetUInt32(*(uint32_t *)src);
+ return true;
+ case 8:
+ value.SetUInt64(*(uint64_t *)src);
+ return true;
+ default:
+ assert(false && "Unhandled data size.");
+ return false;
+ }
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ if (IsGPR(reg))
+ return WriteRegister(reg, value);
+
+ if (IsFPR(reg, GetFPRType()))
+ {
+ if (reg_info->encoding == eEncodingVector)
+ {
+ if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
+ ::memcpy (m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, value.GetBytes(), value.GetByteSize());
+
+ if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
+ ::memcpy (m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, value.GetBytes(), value.GetByteSize());
+
+ if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
+ ::memcpy (m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, value.GetBytes(), value.GetByteSize());
+
+ if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm)
+ {
+ if (GetFPRType() != eXSAVE)
+ return false; // the target processor does not support AVX
+
+ // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes
+ ::memcpy (m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, value.GetBytes(), value.GetByteSize());
+ if (false == CopyYMMtoXSTATE(reg, GetByteOrder()))
+ return false;
+ }
+ }
+ else
+ {
+ // Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
+ assert (reg_info->byte_offset < sizeof(m_fpr));
+ uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset;
+ switch (reg_info->byte_size)
+ {
+ case 2:
+ *(uint16_t *)dst = value.GetAsUInt16();
+ break;
+ case 4:
+ *(uint32_t *)dst = value.GetAsUInt32();
+ break;
+ case 8:
+ *(uint64_t *)dst = value.GetAsUInt64();
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ return false;
+ }
+ }
+
+ if (WriteFPR())
+ {
+ if (IsAVX(reg))
+ return CopyYMMtoXSTATE(reg, GetByteOrder());
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)
+{
+ bool success = false;
+ data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+ if (data_sp && ReadGPR () && ReadFPR ())
+ {
+ uint8_t *dst = data_sp->GetBytes();
+ success = dst != 0;
+
+ if (success)
+ {
+ ::memcpy (dst, &m_gpr_x86_64, GetGPRSize());
+ dst += GetGPRSize();
+ }
+ if (GetFPRType() == eFXSAVE)
+ ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+ if (GetFPRType() == eXSAVE)
+ {
+ ByteOrder byte_order = GetByteOrder();
+
+ // Assemble the YMM register content from the register halves.
+ for (uint32_t reg = m_reg_info.first_ymm; success && reg <= m_reg_info.last_ymm; ++reg)
+ success = CopyXSTATEtoYMM(reg, byte_order);
+
+ if (success)
+ {
+ // Copy the extended register state including the assembled ymm registers.
+ ::memcpy (dst, &m_fpr, sizeof(m_fpr));
+ }
+ }
+ }
+ return success;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)
+{
+ bool success = false;
+ if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+ {
+ uint8_t *src = data_sp->GetBytes();
+ if (src)
+ {
+ ::memcpy (&m_gpr_x86_64, src, GetGPRSize());
+
+ if (WriteGPR())
+ {
+ src += GetGPRSize();
+ if (GetFPRType() == eFXSAVE)
+ ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
+ if (GetFPRType() == eXSAVE)
+ ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
+
+ success = WriteFPR();
+ if (success)
+ {
+ success = true;
+
+ if (GetFPRType() == eXSAVE)
+ {
+ ByteOrder byte_order = GetByteOrder();
+
+ // Parse the YMM register content from the register halves.
+ for (uint32_t reg = m_reg_info.first_ymm; success && reg <= m_reg_info.last_ymm; ++reg)
+ success = CopyYMMtoXSTATE(reg, byte_order);
+ }
+ }
+ }
+ }
+ }
+ return success;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size,
+ bool read, bool write)
+{
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+ uint32_t hw_index;
+
+ for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+ {
+ if (IsWatchpointVacant(hw_index))
+ return SetHardwareWatchpointWithIndex(addr, size,
+ read, write,
+ hw_index);
+ }
+
+ return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+ if (hw_index < NumSupportedHardwareWatchpoints())
+ {
+ RegisterValue current_dr7_bits;
+
+ if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits))
+ {
+ uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index));
+
+ if (WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits)))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::HardwareSingleStep(bool enable)
+{
+ enum { TRACE_BIT = 0x100 };
+ uint64_t rflags;
+
+ if ((rflags = ReadRegisterAsUnsigned(m_reg_info.gpr_flags, -1UL)) == -1UL)
+ return false;
+
+ if (enable)
+ {
+ if (rflags & TRACE_BIT)
+ return true;
+
+ rflags |= TRACE_BIT;
+ }
+ else
+ {
+ if (!(rflags & TRACE_BIT))
+ return false;
+
+ rflags &= ~TRACE_BIT;
+ }
+
+ return WriteRegisterFromUnsigned(m_reg_info.gpr_flags, rflags);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::UpdateAfterBreakpoint()
+{
+ // PC points one byte past the int3 responsible for the breakpoint.
+ lldb::addr_t pc;
+
+ if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+ return false;
+
+ SetPC(pc - 1);
+ return true;
+}
+
+unsigned
+RegisterContextPOSIXProcessMonitor_x86_64::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg;
+ for (reg = 0; reg < m_reg_info.num_registers; reg++)
+ {
+ if (GetRegisterInfo()[reg].byte_offset == offset)
+ break;
+ }
+ assert(reg < m_reg_info.num_registers && "Invalid register offset.");
+ return reg;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointHit(uint32_t hw_index)
+{
+ bool is_hit = false;
+
+ if (m_watchpoints_initialized == false)
+ {
+ // Reset the debug status and debug control registers
+ RegisterValue zero_bits = RegisterValue(uint64_t(0));
+ if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || !WriteRegister(m_reg_info.first_dr + 7, zero_bits))
+ assert(false && "Could not initialize watchpoint registers");
+ m_watchpoints_initialized = true;
+ }
+
+ if (hw_index < NumSupportedHardwareWatchpoints())
+ {
+ RegisterValue value;
+
+ if (ReadRegister(m_reg_info.first_dr + 6, value))
+ {
+ uint64_t val = value.GetAsUInt64();
+ is_hit = val & (1 << hw_index);
+ }
+ }
+
+ return is_hit;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::ClearWatchpointHits()
+{
+ return WriteRegister(m_reg_info.first_dr + 6, RegisterValue((uint64_t)0));
+}
+
+addr_t
+RegisterContextPOSIXProcessMonitor_x86_64::GetWatchpointAddress(uint32_t hw_index)
+{
+ addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS;
+
+ if (hw_index < NumSupportedHardwareWatchpoints())
+ {
+ if (!IsWatchpointVacant(hw_index))
+ {
+ RegisterValue value;
+
+ if (ReadRegister(m_reg_info.first_dr + hw_index, value))
+ wp_monitor_addr = value.GetAsUInt64();
+ }
+ }
+
+ return wp_monitor_addr;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointVacant(uint32_t hw_index)
+{
+ bool is_vacant = false;
+ RegisterValue value;
+
+ assert(hw_index < NumSupportedHardwareWatchpoints());
+
+ if (m_watchpoints_initialized == false)
+ {
+ // Reset the debug status and debug control registers
+ RegisterValue zero_bits = RegisterValue(uint64_t(0));
+ if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || !WriteRegister(m_reg_info.first_dr + 7, zero_bits))
+ assert(false && "Could not initialize watchpoint registers");
+ m_watchpoints_initialized = true;
+ }
+
+ if (ReadRegister(m_reg_info.first_dr + 7, value))
+ {
+ uint64_t val = value.GetAsUInt64();
+ is_vacant = (val & (3 << 2*hw_index)) == 0;
+ }
+
+ return is_vacant;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
+ bool read, bool write,
+ uint32_t hw_index)
+{
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+
+ if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
+ return false;
+
+ if (!(size == 1 || size == 2 || size == 4 || size == 8))
+ return false;
+
+ if (read == false && write == false)
+ return false;
+
+ if (!IsWatchpointVacant(hw_index))
+ return false;
+
+ // Set both dr7 (debug control register) and dri (debug address register).
+
+ // dr7{7-0} encodes the local/global enable bits:
+ // global enable --. .-- local enable
+ // | |
+ // v v
+ // dr0 -> bits{1-0}
+ // dr1 -> bits{3-2}
+ // dr2 -> bits{5-4}
+ // dr3 -> bits{7-6}
+ //
+ // dr7{31-16} encodes the rw/len bits:
+ // b_x+3, b_x+2, b_x+1, b_x
+ // where bits{x+1, x} => rw
+ // 0b00: execute, 0b01: write, 0b11: read-or-write,
+ // 0b10: io read-or-write (unused)
+ // and bits{x+3, x+2} => len
+ // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
+ //
+ // dr0 -> bits{19-16}
+ // dr1 -> bits{23-20}
+ // dr2 -> bits{27-24}
+ // dr3 -> bits{31-28}
+ if (hw_index < num_hw_watchpoints)
+ {
+ RegisterValue current_dr7_bits;
+
+ if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits))
+ {
+ uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() |
+ (1 << (2*hw_index) |
+ size_and_rw_bits(size, read, write) <<
+ (16+4*hw_index));
+
+ if (WriteRegister(m_reg_info.first_dr + hw_index, RegisterValue(addr)) &&
+ WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits)))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_x86_64::NumSupportedHardwareWatchpoints()
+{
+ // Available debug address registers: dr0, dr1, dr2, dr3
+ return 4;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h
new file mode 100644
index 000000000000..2b64fa8003a2
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h
@@ -0,0 +1,95 @@
+//===-- RegisterContextPOSIXProcessMonitor_x86.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_RegisterContextPOSIXProcessMonitor_x86_H_
+#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
+
+#include "Plugins/Process/POSIX/RegisterContextPOSIX_x86.h"
+
+class RegisterContextPOSIXProcessMonitor_x86_64:
+ public RegisterContextPOSIX_x86,
+ public POSIXBreakpointProtocol
+{
+public:
+ RegisterContextPOSIXProcessMonitor_x86_64(lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info);
+
+protected:
+ bool
+ ReadGPR();
+
+ bool
+ ReadFPR();
+
+ bool
+ WriteGPR();
+
+ bool
+ WriteFPR();
+
+ // lldb_private::RegisterContext
+ bool
+ ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
+
+ bool
+ WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
+
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+ uint32_t
+ SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write);
+
+ bool
+ ClearHardwareWatchpoint(uint32_t hw_index);
+
+ bool
+ HardwareSingleStep(bool enable);
+
+ // POSIXBreakpointProtocol
+ bool
+ UpdateAfterBreakpoint();
+
+ unsigned
+ GetRegisterIndexFromOffset(unsigned offset);
+
+ bool
+ IsWatchpointHit(uint32_t hw_index);
+
+ bool
+ ClearWatchpointHits();
+
+ lldb::addr_t
+ GetWatchpointAddress(uint32_t hw_index);
+
+ bool
+ IsWatchpointVacant(uint32_t hw_index);
+
+ bool
+ SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index);
+
+ uint32_t
+ NumSupportedHardwareWatchpoints();
+
+private:
+ ProcessMonitor &
+ GetMonitor();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp
new file mode 100644
index 000000000000..45c99aec1657
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp
@@ -0,0 +1,238 @@
+//===-- RegisterContextPOSIX_mips64.cpp -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstring>
+#include <errno.h>
+#include <stdint.h>
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Host/Endian.h"
+#include "llvm/Support/Compiler.h"
+
+#include "ProcessPOSIX.h"
+#include "RegisterContextPOSIX_mips64.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+static const
+uint32_t g_gpr_regnums[] =
+{
+ gpr_zero_mips64,
+ gpr_r1_mips64,
+ gpr_r2_mips64,
+ gpr_r3_mips64,
+ gpr_r4_mips64,
+ gpr_r5_mips64,
+ gpr_r6_mips64,
+ gpr_r7_mips64,
+ gpr_r8_mips64,
+ gpr_r9_mips64,
+ gpr_r10_mips64,
+ gpr_r11_mips64,
+ gpr_r12_mips64,
+ gpr_r13_mips64,
+ gpr_r14_mips64,
+ gpr_r15_mips64,
+ gpr_r16_mips64,
+ gpr_r17_mips64,
+ gpr_r18_mips64,
+ gpr_r19_mips64,
+ gpr_r20_mips64,
+ gpr_r21_mips64,
+ gpr_r22_mips64,
+ gpr_r23_mips64,
+ gpr_r24_mips64,
+ gpr_r25_mips64,
+ gpr_r26_mips64,
+ gpr_r27_mips64,
+ gpr_gp_mips64,
+ gpr_sp_mips64,
+ gpr_r30_mips64,
+ gpr_ra_mips64,
+ gpr_sr_mips64,
+ gpr_mullo_mips64,
+ gpr_mulhi_mips64,
+ gpr_badvaddr_mips64,
+ gpr_cause_mips64,
+ gpr_pc_mips64,
+ gpr_ic_mips64,
+ gpr_dummy_mips64
+};
+
+// Number of register sets provided by this context.
+enum
+{
+ k_num_register_sets = 1
+};
+
+static const RegisterSet
+g_reg_sets_mips64[k_num_register_sets] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers_mips64, g_gpr_regnums },
+};
+
+bool RegisterContextPOSIX_mips64::IsGPR(unsigned reg)
+{
+ return reg <= k_num_gpr_registers_mips64; // GPR's come first.
+}
+
+bool
+RegisterContextPOSIX_mips64::IsFPR(unsigned reg)
+{
+ // XXX
+ return false;
+}
+
+RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64(Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info)
+ : RegisterContext(thread, concrete_frame_idx)
+{
+ m_register_info_ap.reset(register_info);
+
+ // elf-core yet to support ReadFPR()
+ ProcessSP base = CalculateProcess();
+ if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
+ return;
+}
+
+RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64()
+{
+}
+
+void
+RegisterContextPOSIX_mips64::Invalidate()
+{
+}
+
+void
+RegisterContextPOSIX_mips64::InvalidateAllRegisters()
+{
+}
+
+unsigned
+RegisterContextPOSIX_mips64::GetRegisterOffset(unsigned reg)
+{
+ assert(reg < k_num_registers_mips64 && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContextPOSIX_mips64::GetRegisterSize(unsigned reg)
+{
+ assert(reg < k_num_registers_mips64 && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_size;
+}
+
+size_t
+RegisterContextPOSIX_mips64::GetRegisterCount()
+{
+ size_t num_registers = k_num_registers_mips64;
+ return num_registers;
+}
+
+size_t
+RegisterContextPOSIX_mips64::GetGPRSize()
+{
+ return m_register_info_ap->GetGPRSize();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_mips64::GetRegisterInfo()
+{
+ // Commonly, this method is overridden and g_register_infos is copied and specialized.
+ // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ return m_register_info_ap->GetRegisterInfo ();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_mips64::GetRegisterInfoAtIndex(size_t reg)
+{
+ if (reg < k_num_registers_mips64)
+ return &GetRegisterInfo()[reg];
+ else
+ return NULL;
+}
+
+size_t
+RegisterContextPOSIX_mips64::GetRegisterSetCount()
+{
+ size_t sets = 0;
+ for (size_t set = 0; set < k_num_register_sets; ++set)
+ {
+ if (IsRegisterSetAvailable(set))
+ ++sets;
+ }
+
+ return sets;
+}
+
+const RegisterSet *
+RegisterContextPOSIX_mips64::GetRegisterSet(size_t set)
+{
+ if (IsRegisterSetAvailable(set))
+ return &g_reg_sets_mips64[set];
+ else
+ return NULL;
+}
+
+const char *
+RegisterContextPOSIX_mips64::GetRegisterName(unsigned reg)
+{
+ assert(reg < k_num_registers_mips64 && "Invalid register offset.");
+ return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContextPOSIX_mips64::GetByteOrder()
+{
+ // Get the target process whose privileged thread was used for the register read.
+ lldb::ByteOrder byte_order = eByteOrderInvalid;
+ Process *process = CalculateProcess().get();
+
+ if (process)
+ byte_order = process->GetByteOrder();
+ return byte_order;
+}
+
+bool
+RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index)
+{
+ size_t num_sets = k_num_register_sets;
+
+ return (set_index < num_sets);
+}
+
+// Used when parsing DWARF and EH frame information and any other
+// object file sections that contain register numbers in them.
+uint32_t
+RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
+ uint32_t num)
+{
+ const uint32_t num_regs = GetRegisterCount();
+
+ assert (kind < kNumRegisterKinds);
+ for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
+ {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx);
+
+ if (reg_info->kinds[kind] == num)
+ return reg_idx;
+ }
+
+ return LLDB_INVALID_REGNUM;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h
new file mode 100644
index 000000000000..a2a7d1f45271
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h
@@ -0,0 +1,138 @@
+//===-- RegisterContextPOSIX_mips64.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_RegisterContextPOSIX_mips64_H_
+#define liblldb_RegisterContextPOSIX_mips64_H_
+
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContext_mips64.h"
+
+class ProcessMonitor;
+
+// ---------------------------------------------------------------------------
+// Internal codes for all mips64 registers.
+// ---------------------------------------------------------------------------
+enum
+{
+ k_first_gpr_mips64,
+ gpr_zero_mips64 = k_first_gpr_mips64,
+ gpr_r1_mips64,
+ gpr_r2_mips64,
+ gpr_r3_mips64,
+ gpr_r4_mips64,
+ gpr_r5_mips64,
+ gpr_r6_mips64,
+ gpr_r7_mips64,
+ gpr_r8_mips64,
+ gpr_r9_mips64,
+ gpr_r10_mips64,
+ gpr_r11_mips64,
+ gpr_r12_mips64,
+ gpr_r13_mips64,
+ gpr_r14_mips64,
+ gpr_r15_mips64,
+ gpr_r16_mips64,
+ gpr_r17_mips64,
+ gpr_r18_mips64,
+ gpr_r19_mips64,
+ gpr_r20_mips64,
+ gpr_r21_mips64,
+ gpr_r22_mips64,
+ gpr_r23_mips64,
+ gpr_r24_mips64,
+ gpr_r25_mips64,
+ gpr_r26_mips64,
+ gpr_r27_mips64,
+ gpr_gp_mips64,
+ gpr_sp_mips64,
+ gpr_r30_mips64,
+ gpr_ra_mips64,
+ gpr_sr_mips64,
+ gpr_mullo_mips64,
+ gpr_mulhi_mips64,
+ gpr_badvaddr_mips64,
+ gpr_cause_mips64,
+ gpr_pc_mips64,
+ gpr_ic_mips64,
+ gpr_dummy_mips64,
+
+ k_num_registers_mips64,
+ k_num_gpr_registers_mips64 = k_num_registers_mips64
+};
+
+class RegisterContextPOSIX_mips64
+ : public lldb_private::RegisterContext
+{
+public:
+ RegisterContextPOSIX_mips64 (lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info);
+
+ ~RegisterContextPOSIX_mips64();
+
+ void
+ Invalidate();
+
+ void
+ InvalidateAllRegisters();
+
+ size_t
+ GetRegisterCount();
+
+ virtual size_t
+ GetGPRSize();
+
+ virtual unsigned
+ GetRegisterSize(unsigned reg);
+
+ virtual unsigned
+ GetRegisterOffset(unsigned reg);
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg);
+
+ size_t
+ GetRegisterSetCount();
+
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t set);
+
+ const char *
+ GetRegisterName(unsigned reg);
+
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
+
+protected:
+ uint64_t m_gpr_mips64[k_num_gpr_registers_mips64]; // general purpose registers.
+ std::unique_ptr<RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux)
+
+ // Determines if an extended register set is supported on the processor running the inferior process.
+ virtual bool
+ IsRegisterSetAvailable(size_t set_index);
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfo();
+
+ bool
+ IsGPR(unsigned reg);
+
+ bool
+ IsFPR(unsigned reg);
+
+ lldb::ByteOrder GetByteOrder();
+
+ virtual bool ReadGPR() = 0;
+ virtual bool ReadFPR() = 0;
+ virtual bool WriteGPR() = 0;
+ virtual bool WriteFPR() = 0;
+};
+
+#endif // #ifndef liblldb_RegisterContextPOSIX_mips64_H_
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp
new file mode 100644
index 000000000000..9ae541a6309b
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp
@@ -0,0 +1,666 @@
+//===-- RegisterContextPOSIX_x86.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstring>
+#include <errno.h>
+#include <stdint.h>
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Host/Endian.h"
+#include "llvm/Support/Compiler.h"
+
+#include "ProcessPOSIX.h"
+#include "RegisterContext_x86.h"
+#include "RegisterContextPOSIX_x86.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+const uint32_t
+g_gpr_regnums_i386[] =
+{
+ gpr_eax_i386,
+ gpr_ebx_i386,
+ gpr_ecx_i386,
+ gpr_edx_i386,
+ gpr_edi_i386,
+ gpr_esi_i386,
+ gpr_ebp_i386,
+ gpr_esp_i386,
+ gpr_eip_i386,
+ gpr_eflags_i386,
+ gpr_cs_i386,
+ gpr_fs_i386,
+ gpr_gs_i386,
+ gpr_ss_i386,
+ gpr_ds_i386,
+ gpr_es_i386,
+ gpr_ax_i386,
+ gpr_bx_i386,
+ gpr_cx_i386,
+ gpr_dx_i386,
+ gpr_di_i386,
+ gpr_si_i386,
+ gpr_bp_i386,
+ gpr_sp_i386,
+ gpr_ah_i386,
+ gpr_bh_i386,
+ gpr_ch_i386,
+ gpr_dh_i386,
+ gpr_al_i386,
+ gpr_bl_i386,
+ gpr_cl_i386,
+ gpr_dl_i386
+};
+static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) == k_num_gpr_registers_i386,
+ "g_gpr_regnums_i386 has wrong number of register infos");
+
+const uint32_t
+g_fpu_regnums_i386[] =
+{
+ fpu_fctrl_i386,
+ fpu_fstat_i386,
+ fpu_ftag_i386,
+ fpu_fop_i386,
+ fpu_fiseg_i386,
+ fpu_fioff_i386,
+ fpu_foseg_i386,
+ fpu_fooff_i386,
+ fpu_mxcsr_i386,
+ fpu_mxcsrmask_i386,
+ fpu_st0_i386,
+ fpu_st1_i386,
+ fpu_st2_i386,
+ fpu_st3_i386,
+ fpu_st4_i386,
+ fpu_st5_i386,
+ fpu_st6_i386,
+ fpu_st7_i386,
+ fpu_mm0_i386,
+ fpu_mm1_i386,
+ fpu_mm2_i386,
+ fpu_mm3_i386,
+ fpu_mm4_i386,
+ fpu_mm5_i386,
+ fpu_mm6_i386,
+ fpu_mm7_i386,
+ fpu_xmm0_i386,
+ fpu_xmm1_i386,
+ fpu_xmm2_i386,
+ fpu_xmm3_i386,
+ fpu_xmm4_i386,
+ fpu_xmm5_i386,
+ fpu_xmm6_i386,
+ fpu_xmm7_i386
+};
+static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) == k_num_fpr_registers_i386,
+ "g_fpu_regnums_i386 has wrong number of register infos");
+
+const uint32_t
+g_avx_regnums_i386[] =
+{
+ fpu_ymm0_i386,
+ fpu_ymm1_i386,
+ fpu_ymm2_i386,
+ fpu_ymm3_i386,
+ fpu_ymm4_i386,
+ fpu_ymm5_i386,
+ fpu_ymm6_i386,
+ fpu_ymm7_i386
+};
+static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) == k_num_avx_registers_i386,
+ " g_avx_regnums_i386 has wrong number of register infos");
+
+static const
+uint32_t g_gpr_regnums_x86_64[] =
+{
+ gpr_rax_x86_64,
+ gpr_rbx_x86_64,
+ gpr_rcx_x86_64,
+ gpr_rdx_x86_64,
+ gpr_rdi_x86_64,
+ gpr_rsi_x86_64,
+ gpr_rbp_x86_64,
+ gpr_rsp_x86_64,
+ gpr_r8_x86_64,
+ gpr_r9_x86_64,
+ gpr_r10_x86_64,
+ gpr_r11_x86_64,
+ gpr_r12_x86_64,
+ gpr_r13_x86_64,
+ gpr_r14_x86_64,
+ gpr_r15_x86_64,
+ gpr_rip_x86_64,
+ gpr_rflags_x86_64,
+ gpr_cs_x86_64,
+ gpr_fs_x86_64,
+ gpr_gs_x86_64,
+ gpr_ss_x86_64,
+ gpr_ds_x86_64,
+ gpr_es_x86_64,
+ gpr_eax_x86_64,
+ gpr_ebx_x86_64,
+ gpr_ecx_x86_64,
+ gpr_edx_x86_64,
+ gpr_edi_x86_64,
+ gpr_esi_x86_64,
+ gpr_ebp_x86_64,
+ gpr_esp_x86_64,
+ gpr_r8d_x86_64, // Low 32 bits or r8
+ gpr_r9d_x86_64, // Low 32 bits or r9
+ gpr_r10d_x86_64, // Low 32 bits or r10
+ gpr_r11d_x86_64, // Low 32 bits or r11
+ gpr_r12d_x86_64, // Low 32 bits or r12
+ gpr_r13d_x86_64, // Low 32 bits or r13
+ gpr_r14d_x86_64, // Low 32 bits or r14
+ gpr_r15d_x86_64, // Low 32 bits or r15
+ gpr_ax_x86_64,
+ gpr_bx_x86_64,
+ gpr_cx_x86_64,
+ gpr_dx_x86_64,
+ gpr_di_x86_64,
+ gpr_si_x86_64,
+ gpr_bp_x86_64,
+ gpr_sp_x86_64,
+ gpr_r8w_x86_64, // Low 16 bits or r8
+ gpr_r9w_x86_64, // Low 16 bits or r9
+ gpr_r10w_x86_64, // Low 16 bits or r10
+ gpr_r11w_x86_64, // Low 16 bits or r11
+ gpr_r12w_x86_64, // Low 16 bits or r12
+ gpr_r13w_x86_64, // Low 16 bits or r13
+ gpr_r14w_x86_64, // Low 16 bits or r14
+ gpr_r15w_x86_64, // Low 16 bits or r15
+ gpr_ah_x86_64,
+ gpr_bh_x86_64,
+ gpr_ch_x86_64,
+ gpr_dh_x86_64,
+ gpr_al_x86_64,
+ gpr_bl_x86_64,
+ gpr_cl_x86_64,
+ gpr_dl_x86_64,
+ gpr_dil_x86_64,
+ gpr_sil_x86_64,
+ gpr_bpl_x86_64,
+ gpr_spl_x86_64,
+ gpr_r8l_x86_64, // Low 8 bits or r8
+ gpr_r9l_x86_64, // Low 8 bits or r9
+ gpr_r10l_x86_64, // Low 8 bits or r10
+ gpr_r11l_x86_64, // Low 8 bits or r11
+ gpr_r12l_x86_64, // Low 8 bits or r12
+ gpr_r13l_x86_64, // Low 8 bits or r13
+ gpr_r14l_x86_64, // Low 8 bits or r14
+ gpr_r15l_x86_64, // Low 8 bits or r15
+};
+static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) == k_num_gpr_registers_x86_64,
+ "g_gpr_regnums_x86_64 has wrong number of register infos");
+
+static const uint32_t
+g_fpu_regnums_x86_64[] =
+{
+ fpu_fctrl_x86_64,
+ fpu_fstat_x86_64,
+ fpu_ftag_x86_64,
+ fpu_fop_x86_64,
+ fpu_fiseg_x86_64,
+ fpu_fioff_x86_64,
+ fpu_foseg_x86_64,
+ fpu_fooff_x86_64,
+ fpu_mxcsr_x86_64,
+ fpu_mxcsrmask_x86_64,
+ fpu_st0_x86_64,
+ fpu_st1_x86_64,
+ fpu_st2_x86_64,
+ fpu_st3_x86_64,
+ fpu_st4_x86_64,
+ fpu_st5_x86_64,
+ fpu_st6_x86_64,
+ fpu_st7_x86_64,
+ fpu_mm0_x86_64,
+ fpu_mm1_x86_64,
+ fpu_mm2_x86_64,
+ fpu_mm3_x86_64,
+ fpu_mm4_x86_64,
+ fpu_mm5_x86_64,
+ fpu_mm6_x86_64,
+ fpu_mm7_x86_64,
+ fpu_xmm0_x86_64,
+ fpu_xmm1_x86_64,
+ fpu_xmm2_x86_64,
+ fpu_xmm3_x86_64,
+ fpu_xmm4_x86_64,
+ fpu_xmm5_x86_64,
+ fpu_xmm6_x86_64,
+ fpu_xmm7_x86_64,
+ fpu_xmm8_x86_64,
+ fpu_xmm9_x86_64,
+ fpu_xmm10_x86_64,
+ fpu_xmm11_x86_64,
+ fpu_xmm12_x86_64,
+ fpu_xmm13_x86_64,
+ fpu_xmm14_x86_64,
+ fpu_xmm15_x86_64
+};
+static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) == k_num_fpr_registers_x86_64,
+ "g_fpu_regnums_x86_64 has wrong number of register infos");
+
+static const uint32_t
+g_avx_regnums_x86_64[] =
+{
+ fpu_ymm0_x86_64,
+ fpu_ymm1_x86_64,
+ fpu_ymm2_x86_64,
+ fpu_ymm3_x86_64,
+ fpu_ymm4_x86_64,
+ fpu_ymm5_x86_64,
+ fpu_ymm6_x86_64,
+ fpu_ymm7_x86_64,
+ fpu_ymm8_x86_64,
+ fpu_ymm9_x86_64,
+ fpu_ymm10_x86_64,
+ fpu_ymm11_x86_64,
+ fpu_ymm12_x86_64,
+ fpu_ymm13_x86_64,
+ fpu_ymm14_x86_64,
+ fpu_ymm15_x86_64
+};
+static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) == k_num_avx_registers_x86_64,
+ "g_avx_regnums_x86_64 has wrong number of register infos");
+
+uint32_t RegisterContextPOSIX_x86::g_contained_eax[] = { gpr_eax_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_ebx[] = { gpr_ebx_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_ecx[] = { gpr_ecx_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_edx[] = { gpr_edx_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_edi[] = { gpr_edi_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_esi[] = { gpr_esi_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_ebp[] = { gpr_ebp_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_esp[] = { gpr_esp_i386, LLDB_INVALID_REGNUM };
+
+uint32_t RegisterContextPOSIX_x86::g_invalidate_eax[] = { gpr_eax_i386, gpr_ax_i386, gpr_ah_i386, gpr_al_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_ebx[] = { gpr_ebx_i386, gpr_bx_i386, gpr_bh_i386, gpr_bl_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_ecx[] = { gpr_ecx_i386, gpr_cx_i386, gpr_ch_i386, gpr_cl_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_edx[] = { gpr_edx_i386, gpr_dx_i386, gpr_dh_i386, gpr_dl_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_edi[] = { gpr_edi_i386, gpr_di_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_esi[] = { gpr_esi_i386, gpr_si_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_ebp[] = { gpr_ebp_i386, gpr_bp_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_esp[] = { gpr_esp_i386, gpr_sp_i386, LLDB_INVALID_REGNUM };
+
+uint32_t RegisterContextPOSIX_x86::g_contained_rax[] = { gpr_rax_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rbx[] = { gpr_rbx_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rcx[] = { gpr_rcx_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rdx[] = { gpr_rdx_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rdi[] = { gpr_rdi_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rsi[] = { gpr_rsi_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rbp[] = { gpr_rbp_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rsp[] = { gpr_rsp_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r8[] = { gpr_r8_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r9[] = { gpr_r9_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r10[] = { gpr_r10_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r11[] = { gpr_r11_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r12[] = { gpr_r12_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r13[] = { gpr_r13_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r14[] = { gpr_r14_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r15[] = { gpr_r15_x86_64, LLDB_INVALID_REGNUM };
+
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rax[] = { gpr_rax_x86_64, gpr_eax_x86_64, gpr_ax_x86_64, gpr_ah_x86_64, gpr_al_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rbx[] = { gpr_rbx_x86_64, gpr_ebx_x86_64, gpr_bx_x86_64, gpr_bh_x86_64, gpr_bl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rcx[] = { gpr_rcx_x86_64, gpr_ecx_x86_64, gpr_cx_x86_64, gpr_ch_x86_64, gpr_cl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rdx[] = { gpr_rdx_x86_64, gpr_edx_x86_64, gpr_dx_x86_64, gpr_dh_x86_64, gpr_dl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rdi[] = { gpr_rdi_x86_64, gpr_edi_x86_64, gpr_di_x86_64, gpr_dil_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rsi[] = { gpr_rsi_x86_64, gpr_esi_x86_64, gpr_si_x86_64, gpr_sil_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rbp[] = { gpr_rbp_x86_64, gpr_ebp_x86_64, gpr_bp_x86_64, gpr_bpl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rsp[] = { gpr_rsp_x86_64, gpr_esp_x86_64, gpr_sp_x86_64, gpr_spl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r8[] = { gpr_r8_x86_64, gpr_r8d_x86_64, gpr_r8w_x86_64, gpr_r8l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r9[] = { gpr_r9_x86_64, gpr_r9d_x86_64, gpr_r9w_x86_64, gpr_r9l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r10[] = { gpr_r10_x86_64, gpr_r10d_x86_64, gpr_r10w_x86_64, gpr_r10l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r11[] = { gpr_r11_x86_64, gpr_r11d_x86_64, gpr_r11w_x86_64, gpr_r11l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r12[] = { gpr_r12_x86_64, gpr_r12d_x86_64, gpr_r12w_x86_64, gpr_r12l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r13[] = { gpr_r13_x86_64, gpr_r13d_x86_64, gpr_r13w_x86_64, gpr_r13l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r14[] = { gpr_r14_x86_64, gpr_r14d_x86_64, gpr_r14w_x86_64, gpr_r14l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r15[] = { gpr_r15_x86_64, gpr_r15d_x86_64, gpr_r15w_x86_64, gpr_r15l_x86_64, LLDB_INVALID_REGNUM };
+
+// Number of register sets provided by this context.
+enum
+{
+ k_num_extended_register_sets = 1,
+ k_num_register_sets = 3
+};
+
+static const RegisterSet
+g_reg_sets_i386[k_num_register_sets] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386 },
+ { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_fpu_regnums_i386 },
+ { "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 }
+};
+
+static const RegisterSet
+g_reg_sets_x86_64[k_num_register_sets] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64 },
+ { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_fpu_regnums_x86_64 },
+ { "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 }
+};
+
+bool RegisterContextPOSIX_x86::IsGPR(unsigned reg)
+{
+ return reg <= m_reg_info.last_gpr; // GPR's come first.
+}
+
+bool RegisterContextPOSIX_x86::IsFPR(unsigned reg)
+{
+ return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
+}
+
+bool RegisterContextPOSIX_x86::IsAVX(unsigned reg)
+{
+ return (m_reg_info.first_ymm <= reg && reg <= m_reg_info.last_ymm);
+}
+
+bool RegisterContextPOSIX_x86::IsFPR(unsigned reg, FPRType fpr_type)
+{
+ bool generic_fpr = IsFPR(reg);
+
+ if (fpr_type == eXSAVE)
+ return generic_fpr || IsAVX(reg);
+ return generic_fpr;
+}
+
+RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info)
+ : RegisterContext(thread, concrete_frame_idx)
+{
+ m_register_info_ap.reset(register_info);
+
+ switch (register_info->m_target_arch.GetCore())
+ {
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ m_reg_info.num_registers = k_num_registers_i386;
+ m_reg_info.num_gpr_registers = k_num_gpr_registers_i386;
+ m_reg_info.num_fpr_registers = k_num_fpr_registers_i386;
+ m_reg_info.num_avx_registers = k_num_avx_registers_i386;
+ m_reg_info.last_gpr = k_last_gpr_i386;
+ m_reg_info.first_fpr = k_first_fpr_i386;
+ m_reg_info.last_fpr = k_last_fpr_i386;
+ m_reg_info.first_st = fpu_st0_i386;
+ m_reg_info.last_st = fpu_st7_i386;
+ m_reg_info.first_mm = fpu_mm0_i386;
+ m_reg_info.last_mm = fpu_mm7_i386;
+ m_reg_info.first_xmm = fpu_xmm0_i386;
+ m_reg_info.last_xmm = fpu_xmm7_i386;
+ m_reg_info.first_ymm = fpu_ymm0_i386;
+ m_reg_info.last_ymm = fpu_ymm7_i386;
+ m_reg_info.first_dr = dr0_i386;
+ m_reg_info.gpr_flags = gpr_eflags_i386;
+ break;
+ case ArchSpec::eCore_x86_64_x86_64:
+ m_reg_info.num_registers = k_num_registers_x86_64;
+ m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64;
+ m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64;
+ m_reg_info.num_avx_registers = k_num_avx_registers_x86_64;
+ m_reg_info.last_gpr = k_last_gpr_x86_64;
+ m_reg_info.first_fpr = k_first_fpr_x86_64;
+ m_reg_info.last_fpr = k_last_fpr_x86_64;
+ m_reg_info.first_st = fpu_st0_x86_64;
+ m_reg_info.last_st = fpu_st7_x86_64;
+ m_reg_info.first_mm = fpu_mm0_x86_64;
+ m_reg_info.last_mm = fpu_mm7_x86_64;
+ m_reg_info.first_xmm = fpu_xmm0_x86_64;
+ m_reg_info.last_xmm = fpu_xmm15_x86_64;
+ m_reg_info.first_ymm = fpu_ymm0_x86_64;
+ m_reg_info.last_ymm = fpu_ymm15_x86_64;
+ m_reg_info.first_dr = dr0_x86_64;
+ m_reg_info.gpr_flags = gpr_rflags_x86_64;
+ break;
+ default:
+ assert(false && "Unhandled target architecture.");
+ break;
+ }
+
+ // Initialize m_iovec to point to the buffer and buffer size
+ // using the conventions of Berkeley style UIO structures, as required
+ // by PTRACE extensions.
+ m_iovec.iov_base = &m_fpr.xstate.xsave;
+ m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
+
+ ::memset(&m_fpr, 0, sizeof(FPR));
+
+ // elf-core yet to support ReadFPR()
+ ProcessSP base = CalculateProcess();
+ if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
+ return;
+
+ m_fpr_type = eNotValid;
+}
+
+RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86()
+{
+}
+
+RegisterContextPOSIX_x86::FPRType RegisterContextPOSIX_x86::GetFPRType()
+{
+ if (m_fpr_type == eNotValid)
+ {
+ // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx
+ m_fpr_type = eXSAVE; // extended floating-point registers, if available
+ if (false == ReadFPR())
+ m_fpr_type = eFXSAVE; // assume generic floating-point registers
+ }
+ return m_fpr_type;
+}
+
+void
+RegisterContextPOSIX_x86::Invalidate()
+{
+}
+
+void
+RegisterContextPOSIX_x86::InvalidateAllRegisters()
+{
+}
+
+unsigned
+RegisterContextPOSIX_x86::GetRegisterOffset(unsigned reg)
+{
+ assert(reg < m_reg_info.num_registers && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContextPOSIX_x86::GetRegisterSize(unsigned reg)
+{
+ assert(reg < m_reg_info.num_registers && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_size;
+}
+
+size_t
+RegisterContextPOSIX_x86::GetRegisterCount()
+{
+ size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers;
+ if (GetFPRType() == eXSAVE)
+ return num_registers + m_reg_info.num_avx_registers;
+ return num_registers;
+}
+
+size_t
+RegisterContextPOSIX_x86::GetGPRSize()
+{
+ return m_register_info_ap->GetGPRSize ();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_x86::GetRegisterInfo()
+{
+ // Commonly, this method is overridden and g_register_infos is copied and specialized.
+ // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ return m_register_info_ap->GetRegisterInfo ();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_x86::GetRegisterInfoAtIndex(size_t reg)
+{
+ if (reg < m_reg_info.num_registers)
+ return &GetRegisterInfo()[reg];
+ else
+ return NULL;
+}
+
+size_t
+RegisterContextPOSIX_x86::GetRegisterSetCount()
+{
+ size_t sets = 0;
+ for (size_t set = 0; set < k_num_register_sets; ++set)
+ {
+ if (IsRegisterSetAvailable(set))
+ ++sets;
+ }
+
+ return sets;
+}
+
+const RegisterSet *
+RegisterContextPOSIX_x86::GetRegisterSet(size_t set)
+{
+ if (IsRegisterSetAvailable(set))
+ {
+ switch (m_register_info_ap->m_target_arch.GetCore())
+ {
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ return &g_reg_sets_i386[set];
+ case ArchSpec::eCore_x86_64_x86_64:
+ return &g_reg_sets_x86_64[set];
+ default:
+ assert(false && "Unhandled target architecture.");
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+const char *
+RegisterContextPOSIX_x86::GetRegisterName(unsigned reg)
+{
+ assert(reg < m_reg_info.num_registers && "Invalid register offset.");
+ return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContextPOSIX_x86::GetByteOrder()
+{
+ // Get the target process whose privileged thread was used for the register read.
+ lldb::ByteOrder byte_order = eByteOrderInvalid;
+ Process *process = CalculateProcess().get();
+
+ if (process)
+ byte_order = process->GetByteOrder();
+ return byte_order;
+}
+
+// Parse ymm registers and into xmm.bytes and ymmh.bytes.
+bool RegisterContextPOSIX_x86::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
+{
+ if (!IsAVX(reg))
+ return false;
+
+ if (byte_order == eByteOrderLittle)
+ {
+ ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
+ sizeof(XMMReg));
+ ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
+ sizeof(YMMHReg));
+ return true;
+ }
+
+ if (byte_order == eByteOrderBig)
+ {
+ ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
+ sizeof(XMMReg));
+ ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
+ sizeof(YMMHReg));
+ return true;
+ }
+ return false; // unsupported or invalid byte order
+}
+
+// Concatenate xmm.bytes with ymmh.bytes
+bool RegisterContextPOSIX_x86::CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order)
+{
+ if (!IsAVX(reg))
+ return false;
+
+ if (byte_order == eByteOrderLittle)
+ {
+ ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
+ m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
+ sizeof(XMMReg));
+ ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
+ m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
+ sizeof(YMMHReg));
+ return true;
+ }
+
+ if (byte_order == eByteOrderBig)
+ {
+ ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
+ m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
+ sizeof(XMMReg));
+ ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
+ m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
+ sizeof(YMMHReg));
+ return true;
+ }
+ return false; // unsupported or invalid byte order
+}
+
+bool
+RegisterContextPOSIX_x86::IsRegisterSetAvailable(size_t set_index)
+{
+ // Note: Extended register sets are assumed to be at the end of g_reg_sets...
+ size_t num_sets = k_num_register_sets - k_num_extended_register_sets;
+
+ if (GetFPRType() == eXSAVE) // ...and to start with AVX registers.
+ ++num_sets;
+ return (set_index < num_sets);
+}
+
+
+// Used when parsing DWARF and EH frame information and any other
+// object file sections that contain register numbers in them.
+uint32_t
+RegisterContextPOSIX_x86::ConvertRegisterKindToRegisterNumber(uint32_t kind,
+ uint32_t num)
+{
+ const uint32_t num_regs = GetRegisterCount();
+
+ assert (kind < kNumRegisterKinds);
+ for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
+ {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx);
+
+ if (reg_info->kinds[kind] == num)
+ return reg_idx;
+ }
+
+ return LLDB_INVALID_REGNUM;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h
new file mode 100644
index 000000000000..5e922025b830
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h
@@ -0,0 +1,462 @@
+//===-- RegisterContextPOSIX_x86.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_RegisterContextPOSIX_x86_H_
+#define liblldb_RegisterContextPOSIX_x86_H_
+
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContext_x86.h"
+
+class ProcessMonitor;
+
+//---------------------------------------------------------------------------
+// Internal codes for all i386 registers.
+//---------------------------------------------------------------------------
+enum
+{
+ k_first_gpr_i386,
+ gpr_eax_i386 = k_first_gpr_i386,
+ gpr_ebx_i386,
+ gpr_ecx_i386,
+ gpr_edx_i386,
+ gpr_edi_i386,
+ gpr_esi_i386,
+ gpr_ebp_i386,
+ gpr_esp_i386,
+ gpr_eip_i386,
+ gpr_eflags_i386,
+ gpr_cs_i386,
+ gpr_fs_i386,
+ gpr_gs_i386,
+ gpr_ss_i386,
+ gpr_ds_i386,
+ gpr_es_i386,
+
+ k_first_alias_i386,
+ gpr_ax_i386 = k_first_alias_i386,
+ gpr_bx_i386,
+ gpr_cx_i386,
+ gpr_dx_i386,
+ gpr_di_i386,
+ gpr_si_i386,
+ gpr_bp_i386,
+ gpr_sp_i386,
+ gpr_ah_i386,
+ gpr_bh_i386,
+ gpr_ch_i386,
+ gpr_dh_i386,
+ gpr_al_i386,
+ gpr_bl_i386,
+ gpr_cl_i386,
+ gpr_dl_i386,
+ k_last_alias_i386 = gpr_dl_i386,
+
+ k_last_gpr_i386 = k_last_alias_i386,
+
+ k_first_fpr_i386,
+ fpu_fctrl_i386 = k_first_fpr_i386,
+ fpu_fstat_i386,
+ fpu_ftag_i386,
+ fpu_fop_i386,
+ fpu_fiseg_i386,
+ fpu_fioff_i386,
+ fpu_foseg_i386,
+ fpu_fooff_i386,
+ fpu_mxcsr_i386,
+ fpu_mxcsrmask_i386,
+ fpu_st0_i386,
+ fpu_st1_i386,
+ fpu_st2_i386,
+ fpu_st3_i386,
+ fpu_st4_i386,
+ fpu_st5_i386,
+ fpu_st6_i386,
+ fpu_st7_i386,
+ fpu_mm0_i386,
+ fpu_mm1_i386,
+ fpu_mm2_i386,
+ fpu_mm3_i386,
+ fpu_mm4_i386,
+ fpu_mm5_i386,
+ fpu_mm6_i386,
+ fpu_mm7_i386,
+ fpu_xmm0_i386,
+ fpu_xmm1_i386,
+ fpu_xmm2_i386,
+ fpu_xmm3_i386,
+ fpu_xmm4_i386,
+ fpu_xmm5_i386,
+ fpu_xmm6_i386,
+ fpu_xmm7_i386,
+ k_last_fpr_i386 = fpu_xmm7_i386,
+
+ k_first_avx_i386,
+ fpu_ymm0_i386 = k_first_avx_i386,
+ fpu_ymm1_i386,
+ fpu_ymm2_i386,
+ fpu_ymm3_i386,
+ fpu_ymm4_i386,
+ fpu_ymm5_i386,
+ fpu_ymm6_i386,
+ fpu_ymm7_i386,
+ k_last_avx_i386 = fpu_ymm7_i386,
+
+ dr0_i386,
+ dr1_i386,
+ dr2_i386,
+ dr3_i386,
+ dr4_i386,
+ dr5_i386,
+ dr6_i386,
+ dr7_i386,
+
+ k_num_registers_i386,
+ k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1,
+ k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1,
+ k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1
+};
+
+//---------------------------------------------------------------------------
+// Internal codes for all x86_64 registers.
+//---------------------------------------------------------------------------
+enum
+{
+ k_first_gpr_x86_64,
+ gpr_rax_x86_64 = k_first_gpr_x86_64,
+ gpr_rbx_x86_64,
+ gpr_rcx_x86_64,
+ gpr_rdx_x86_64,
+ gpr_rdi_x86_64,
+ gpr_rsi_x86_64,
+ gpr_rbp_x86_64,
+ gpr_rsp_x86_64,
+ gpr_r8_x86_64,
+ gpr_r9_x86_64,
+ gpr_r10_x86_64,
+ gpr_r11_x86_64,
+ gpr_r12_x86_64,
+ gpr_r13_x86_64,
+ gpr_r14_x86_64,
+ gpr_r15_x86_64,
+ gpr_rip_x86_64,
+ gpr_rflags_x86_64,
+ gpr_cs_x86_64,
+ gpr_fs_x86_64,
+ gpr_gs_x86_64,
+ gpr_ss_x86_64,
+ gpr_ds_x86_64,
+ gpr_es_x86_64,
+
+ k_first_alias_x86_64,
+ gpr_eax_x86_64 = k_first_alias_x86_64,
+ gpr_ebx_x86_64,
+ gpr_ecx_x86_64,
+ gpr_edx_x86_64,
+ gpr_edi_x86_64,
+ gpr_esi_x86_64,
+ gpr_ebp_x86_64,
+ gpr_esp_x86_64,
+ gpr_r8d_x86_64, // Low 32 bits of r8
+ gpr_r9d_x86_64, // Low 32 bits of r9
+ gpr_r10d_x86_64, // Low 32 bits of r10
+ gpr_r11d_x86_64, // Low 32 bits of r11
+ gpr_r12d_x86_64, // Low 32 bits of r12
+ gpr_r13d_x86_64, // Low 32 bits of r13
+ gpr_r14d_x86_64, // Low 32 bits of r14
+ gpr_r15d_x86_64, // Low 32 bits of r15
+ gpr_ax_x86_64,
+ gpr_bx_x86_64,
+ gpr_cx_x86_64,
+ gpr_dx_x86_64,
+ gpr_di_x86_64,
+ gpr_si_x86_64,
+ gpr_bp_x86_64,
+ gpr_sp_x86_64,
+ gpr_r8w_x86_64, // Low 16 bits of r8
+ gpr_r9w_x86_64, // Low 16 bits of r9
+ gpr_r10w_x86_64, // Low 16 bits of r10
+ gpr_r11w_x86_64, // Low 16 bits of r11
+ gpr_r12w_x86_64, // Low 16 bits of r12
+ gpr_r13w_x86_64, // Low 16 bits of r13
+ gpr_r14w_x86_64, // Low 16 bits of r14
+ gpr_r15w_x86_64, // Low 16 bits of r15
+ gpr_ah_x86_64,
+ gpr_bh_x86_64,
+ gpr_ch_x86_64,
+ gpr_dh_x86_64,
+ gpr_al_x86_64,
+ gpr_bl_x86_64,
+ gpr_cl_x86_64,
+ gpr_dl_x86_64,
+ gpr_dil_x86_64,
+ gpr_sil_x86_64,
+ gpr_bpl_x86_64,
+ gpr_spl_x86_64,
+ gpr_r8l_x86_64, // Low 8 bits of r8
+ gpr_r9l_x86_64, // Low 8 bits of r9
+ gpr_r10l_x86_64, // Low 8 bits of r10
+ gpr_r11l_x86_64, // Low 8 bits of r11
+ gpr_r12l_x86_64, // Low 8 bits of r12
+ gpr_r13l_x86_64, // Low 8 bits of r13
+ gpr_r14l_x86_64, // Low 8 bits of r14
+ gpr_r15l_x86_64, // Low 8 bits of r15
+ k_last_alias_x86_64 = gpr_r15l_x86_64,
+
+ k_last_gpr_x86_64 = k_last_alias_x86_64,
+
+ k_first_fpr_x86_64,
+ fpu_fctrl_x86_64 = k_first_fpr_x86_64,
+ fpu_fstat_x86_64,
+ fpu_ftag_x86_64,
+ fpu_fop_x86_64,
+ fpu_fiseg_x86_64,
+ fpu_fioff_x86_64,
+ fpu_foseg_x86_64,
+ fpu_fooff_x86_64,
+ fpu_mxcsr_x86_64,
+ fpu_mxcsrmask_x86_64,
+ fpu_st0_x86_64,
+ fpu_st1_x86_64,
+ fpu_st2_x86_64,
+ fpu_st3_x86_64,
+ fpu_st4_x86_64,
+ fpu_st5_x86_64,
+ fpu_st6_x86_64,
+ fpu_st7_x86_64,
+ fpu_mm0_x86_64,
+ fpu_mm1_x86_64,
+ fpu_mm2_x86_64,
+ fpu_mm3_x86_64,
+ fpu_mm4_x86_64,
+ fpu_mm5_x86_64,
+ fpu_mm6_x86_64,
+ fpu_mm7_x86_64,
+ fpu_xmm0_x86_64,
+ fpu_xmm1_x86_64,
+ fpu_xmm2_x86_64,
+ fpu_xmm3_x86_64,
+ fpu_xmm4_x86_64,
+ fpu_xmm5_x86_64,
+ fpu_xmm6_x86_64,
+ fpu_xmm7_x86_64,
+ fpu_xmm8_x86_64,
+ fpu_xmm9_x86_64,
+ fpu_xmm10_x86_64,
+ fpu_xmm11_x86_64,
+ fpu_xmm12_x86_64,
+ fpu_xmm13_x86_64,
+ fpu_xmm14_x86_64,
+ fpu_xmm15_x86_64,
+ k_last_fpr_x86_64 = fpu_xmm15_x86_64,
+
+ k_first_avx_x86_64,
+ fpu_ymm0_x86_64 = k_first_avx_x86_64,
+ fpu_ymm1_x86_64,
+ fpu_ymm2_x86_64,
+ fpu_ymm3_x86_64,
+ fpu_ymm4_x86_64,
+ fpu_ymm5_x86_64,
+ fpu_ymm6_x86_64,
+ fpu_ymm7_x86_64,
+ fpu_ymm8_x86_64,
+ fpu_ymm9_x86_64,
+ fpu_ymm10_x86_64,
+ fpu_ymm11_x86_64,
+ fpu_ymm12_x86_64,
+ fpu_ymm13_x86_64,
+ fpu_ymm14_x86_64,
+ fpu_ymm15_x86_64,
+ k_last_avx_x86_64 = fpu_ymm15_x86_64,
+
+ dr0_x86_64,
+ dr1_x86_64,
+ dr2_x86_64,
+ dr3_x86_64,
+ dr4_x86_64,
+ dr5_x86_64,
+ dr6_x86_64,
+ dr7_x86_64,
+
+ k_num_registers_x86_64,
+ k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1,
+ k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1,
+ k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1
+};
+
+class RegisterContextPOSIX_x86
+ : public lldb_private::RegisterContext
+{
+public:
+ RegisterContextPOSIX_x86 (lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *register_info);
+
+ ~RegisterContextPOSIX_x86();
+
+ void
+ Invalidate();
+
+ void
+ InvalidateAllRegisters();
+
+ size_t
+ GetRegisterCount();
+
+ virtual size_t
+ GetGPRSize();
+
+ virtual unsigned
+ GetRegisterSize(unsigned reg);
+
+ virtual unsigned
+ GetRegisterOffset(unsigned reg);
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg);
+
+ size_t
+ GetRegisterSetCount();
+
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t set);
+
+ const char *
+ GetRegisterName(unsigned reg);
+
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
+
+ //---------------------------------------------------------------------------
+ // Note: prefer kernel definitions over user-land
+ //---------------------------------------------------------------------------
+ enum FPRType
+ {
+ eNotValid = 0,
+ eFSAVE, // TODO
+ eFXSAVE,
+ eSOFT, // TODO
+ eXSAVE
+ };
+
+ static uint32_t g_contained_eax[];
+ static uint32_t g_contained_ebx[];
+ static uint32_t g_contained_ecx[];
+ static uint32_t g_contained_edx[];
+ static uint32_t g_contained_edi[];
+ static uint32_t g_contained_esi[];
+ static uint32_t g_contained_ebp[];
+ static uint32_t g_contained_esp[];
+
+ static uint32_t g_invalidate_eax[];
+ static uint32_t g_invalidate_ebx[];
+ static uint32_t g_invalidate_ecx[];
+ static uint32_t g_invalidate_edx[];
+ static uint32_t g_invalidate_edi[];
+ static uint32_t g_invalidate_esi[];
+ static uint32_t g_invalidate_ebp[];
+ static uint32_t g_invalidate_esp[];
+
+ static uint32_t g_contained_rax[];
+ static uint32_t g_contained_rbx[];
+ static uint32_t g_contained_rcx[];
+ static uint32_t g_contained_rdx[];
+ static uint32_t g_contained_rdi[];
+ static uint32_t g_contained_rsi[];
+ static uint32_t g_contained_rbp[];
+ static uint32_t g_contained_rsp[];
+ static uint32_t g_contained_r8[];
+ static uint32_t g_contained_r9[];
+ static uint32_t g_contained_r10[];
+ static uint32_t g_contained_r11[];
+ static uint32_t g_contained_r12[];
+ static uint32_t g_contained_r13[];
+ static uint32_t g_contained_r14[];
+ static uint32_t g_contained_r15[];
+
+ static uint32_t g_invalidate_rax[];
+ static uint32_t g_invalidate_rbx[];
+ static uint32_t g_invalidate_rcx[];
+ static uint32_t g_invalidate_rdx[];
+ static uint32_t g_invalidate_rdi[];
+ static uint32_t g_invalidate_rsi[];
+ static uint32_t g_invalidate_rbp[];
+ static uint32_t g_invalidate_rsp[];
+ static uint32_t g_invalidate_r8[];
+ static uint32_t g_invalidate_r9[];
+ static uint32_t g_invalidate_r10[];
+ static uint32_t g_invalidate_r11[];
+ static uint32_t g_invalidate_r12[];
+ static uint32_t g_invalidate_r13[];
+ static uint32_t g_invalidate_r14[];
+ static uint32_t g_invalidate_r15[];
+
+protected:
+ struct RegInfo
+ {
+ uint32_t num_registers;
+ uint32_t num_gpr_registers;
+ uint32_t num_fpr_registers;
+ uint32_t num_avx_registers;
+
+ uint32_t last_gpr;
+ uint32_t first_fpr;
+ uint32_t last_fpr;
+
+ uint32_t first_st;
+ uint32_t last_st;
+ uint32_t first_mm;
+ uint32_t last_mm;
+ uint32_t first_xmm;
+ uint32_t last_xmm;
+ uint32_t first_ymm;
+ uint32_t last_ymm;
+
+ uint32_t first_dr;
+ uint32_t gpr_flags;
+ };
+
+ uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; // 64-bit general purpose registers.
+ RegInfo m_reg_info;
+ FPRType m_fpr_type; // determines the type of data stored by union FPR, if any.
+ FPR m_fpr; // floating-point registers including extended register sets.
+ IOVEC m_iovec; // wrapper for xsave.
+ YMM m_ymm_set; // copy of ymmh and xmm register halves.
+ std::unique_ptr<RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux)
+
+ // Determines if an extended register set is supported on the processor running the inferior process.
+ virtual bool
+ IsRegisterSetAvailable(size_t set_index);
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfo();
+
+ bool
+ IsGPR(unsigned reg);
+
+ bool
+ IsFPR(unsigned reg);
+
+ bool
+ IsAVX(unsigned reg);
+
+ lldb::ByteOrder GetByteOrder();
+
+ bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order);
+ bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
+ bool IsFPR(unsigned reg, FPRType fpr_type);
+ FPRType GetFPRType();
+
+ virtual bool ReadGPR() = 0;
+ virtual bool ReadFPR() = 0;
+ virtual bool WriteGPR() = 0;
+ virtual bool WriteFPR() = 0;
+};
+
+#endif // #ifndef liblldb_RegisterContextPOSIX_x86_H_
diff --git a/source/Plugins/Process/POSIX/RegisterContext_i386.cpp b/source/Plugins/Process/POSIX/RegisterContext_i386.cpp
deleted file mode 100644
index 49676bd3fc73..000000000000
--- a/source/Plugins/Process/POSIX/RegisterContext_i386.cpp
+++ /dev/null
@@ -1,551 +0,0 @@
-//===-- RegisterContextPOSIX_i386.cpp ---------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Host/Endian.h"
-#include "llvm/Support/Compiler.h"
-
-#include "ProcessPOSIX.h"
-#include "ProcessPOSIXLog.h"
-#include "ProcessMonitor.h"
-#include "RegisterContext_i386.h"
-#include "RegisterContext_x86.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-enum
-{
- k_first_gpr,
- gpr_eax = k_first_gpr,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_ss,
- gpr_eflags,
-#ifdef __FreeBSD__
- gpr_orig_ax,
-#endif
- gpr_eip,
- gpr_cs,
- gpr_ds,
- gpr_es,
- gpr_fs,
- gpr_gs,
- k_last_gpr = gpr_gs,
-
- k_first_fpr,
- fpu_fcw = k_first_fpr,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_foo,
- fpu_fos,
- fpu_mxcsr,
- 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,
- k_last_fpr = fpu_xmm7,
-
- k_num_registers,
- k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
- k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
-};
-
-// Number of register sets provided by this context.
-enum
-{
- k_num_register_sets = 2
-};
-
-static const
-uint32_t g_gpr_regnums[k_num_gpr_registers] =
-{
- gpr_eax,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_ss,
- gpr_eflags,
-#ifdef __FreeBSD__
- gpr_orig_ax,
-#endif
- gpr_eip,
- gpr_cs,
- gpr_ds,
- gpr_es,
- gpr_fs,
- gpr_gs,
-};
-
-static const uint32_t
-g_fpu_regnums[k_num_fpu_registers] =
-{
- fpu_fcw,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_foo,
- fpu_fos,
- fpu_mxcsr,
- 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,
-};
-
-static const RegisterSet
-g_reg_sets[k_num_register_sets] =
-{
- { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
- { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }
-};
-
-// Computes the offset of the given GPR in the user data area.
-#define GPR_OFFSET(regname) \
- (offsetof(RegisterContext_i386::UserArea, regs) + \
- offsetof(RegisterContext_i386::GPR, regname))
-
-// Computes the offset of the given FPR in the user data area.
-#define FPR_OFFSET(regname) \
- (offsetof(RegisterContext_i386::UserArea, i387) + \
- offsetof(RegisterContext_i386::FPU, regname))
-
-// Number of bytes needed to represent a GPR.
-#define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)
-
-// Number of bytes needed to represent a FPR.
-#define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg)
-
-// Number of bytes needed to represent the i'th FP register.
-#define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes)
-
-// Number of bytes needed to represent an XMM register.
-#define XMM_SIZE sizeof(RegisterContext_i386::XMMReg)
-
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
- { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL }
-
-#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
- { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL }
-
-#define DEFINE_FP(reg, i) \
- { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
- eEncodingVector, eFormatVectorOfUInt8, \
- { dwarf_##reg##i, dwarf_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL }
-
-#define DEFINE_XMM(reg, i) \
- { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
- eEncodingVector, eFormatVectorOfUInt8, \
- { dwarf_##reg##i, dwarf_##reg##i, \
- LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL }
-
-static RegisterInfo
-g_register_infos[k_num_registers] =
-{
- // General purpose registers.
- DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax),
- DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx),
- DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx),
- DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx),
- DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi),
- DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi),
- DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp),
- DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp),
- DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss),
- DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags),
- DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip),
- DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs),
- DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds),
- DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es),
- DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs),
- DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs),
-
- // Floating point registers.
- DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw),
- DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw),
- DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw),
- DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop),
- DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip),
- DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),
- DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp),
- DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),
- DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr),
-
- DEFINE_FP(stmm, 0),
- DEFINE_FP(stmm, 1),
- DEFINE_FP(stmm, 2),
- DEFINE_FP(stmm, 3),
- DEFINE_FP(stmm, 4),
- DEFINE_FP(stmm, 5),
- DEFINE_FP(stmm, 6),
- DEFINE_FP(stmm, 7),
-
- // XMM registers
- DEFINE_XMM(xmm, 0),
- DEFINE_XMM(xmm, 1),
- DEFINE_XMM(xmm, 2),
- DEFINE_XMM(xmm, 3),
- DEFINE_XMM(xmm, 4),
- DEFINE_XMM(xmm, 5),
- DEFINE_XMM(xmm, 6),
- DEFINE_XMM(xmm, 7),
-
-};
-
-#ifndef NDEBUG
-static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
-#endif
-
-static unsigned GetRegOffset(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return g_register_infos[reg].byte_offset;
-}
-
-static unsigned GetRegSize(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return g_register_infos[reg].byte_size;
-}
-
-RegisterContext_i386::RegisterContext_i386(Thread &thread,
- uint32_t concrete_frame_idx)
- : RegisterContextPOSIX(thread, concrete_frame_idx)
-{
-}
-
-RegisterContext_i386::~RegisterContext_i386()
-{
-}
-
-ProcessMonitor &
-RegisterContext_i386::GetMonitor()
-{
- ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
- return process->GetMonitor();
-}
-
-void
-RegisterContext_i386::Invalidate()
-{
-}
-
-void
-RegisterContext_i386::InvalidateAllRegisters()
-{
-}
-
-size_t
-RegisterContext_i386::GetRegisterCount()
-{
- assert(k_num_register_infos == k_num_registers);
- return k_num_registers;
-}
-
-const RegisterInfo *
-RegisterContext_i386::GetRegisterInfoAtIndex(size_t reg)
-{
- assert(k_num_register_infos == k_num_registers);
- if (reg < k_num_registers)
- return &g_register_infos[reg];
- else
- return NULL;
-}
-
-size_t
-RegisterContext_i386::GetRegisterSetCount()
-{
- return k_num_register_sets;
-}
-
-const RegisterSet *
-RegisterContext_i386::GetRegisterSet(size_t set)
-{
- if (set < k_num_register_sets)
- return &g_reg_sets[set];
- else
- return NULL;
-}
-
-unsigned
-RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset)
-{
- unsigned reg;
- for (reg = 0; reg < k_num_registers; reg++)
- {
- if (g_register_infos[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers && "Invalid register offset.");
- return reg;
-}
-
-const char *
-RegisterContext_i386::GetRegisterName(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register offset.");
- return g_register_infos[reg].name;
-}
-
-bool
-RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info,
- RegisterValue &value)
-{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegOffset(reg),
- GetRegisterName(reg), GetRegSize(reg), value);
-}
-
-bool
-RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info,
- const RegisterValue &value)
-{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(m_thread.GetID(), GetRegOffset(reg),
- GetRegisterName(reg), value);
-}
-
-bool
-RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data)
-{
- return false;
-}
-
-bool
-RegisterContext_i386::UpdateAfterBreakpoint()
-{
- // PC points one byte past the int3 responsible for the breakpoint.
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- SetPC(pc - 1);
- return true;
-}
-
-uint32_t
-RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind,
- uint32_t num)
-{
- if (kind == eRegisterKindGeneric)
- {
- switch (num)
- {
- 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:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
- {
- switch (num)
- {
- case dwarf_eax: return gpr_eax;
- case dwarf_edx: return gpr_edx;
- case dwarf_ecx: return gpr_ecx;
- case dwarf_ebx: return gpr_ebx;
- case dwarf_esi: return gpr_esi;
- case dwarf_edi: return gpr_edi;
- case dwarf_ebp: return gpr_ebp;
- case dwarf_esp: return gpr_esp;
- case dwarf_eip: return gpr_eip;
- 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;
- 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;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGDB)
- {
- switch (num)
- {
- 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_fcw : return fpu_fcw;
- case gdb_fsw : return fpu_fsw;
- case gdb_ftw : return fpu_ftw;
- case gdb_fpu_cs : return fpu_cs;
- case gdb_ip : return fpu_ip;
- case gdb_fpu_ds : return fpu_fos;
- case gdb_dp : return fpu_foo;
- 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:
- return LLDB_INVALID_REGNUM;
- }
- }
- else if (kind == eRegisterKindLLDB)
- {
- return num;
- }
-
- return LLDB_INVALID_REGNUM;
-}
-
-bool
-RegisterContext_i386::HardwareSingleStep(bool enable)
-{
- enum { TRACE_BIT = 0x100 };
- uint64_t eflags;
-
- if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL)
- return false;
-
- if (enable)
- {
- if (eflags & TRACE_BIT)
- return true;
-
- eflags |= TRACE_BIT;
- }
- else
- {
- if (!(eflags & TRACE_BIT))
- return false;
-
- eflags &= ~TRACE_BIT;
- }
-
- return WriteRegisterFromUnsigned(gpr_eflags, eflags);
-}
-
-void
-RegisterContext_i386::LogGPR(const char *title)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
- 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.8" PRIx64, g_register_infos[reg].name, ((uint64_t*)&user.regs)[reg]);
- }
- }
-}
-
-bool
-RegisterContext_i386::ReadGPR()
-{
- bool result;
-
- ProcessMonitor &monitor = GetMonitor();
- result = monitor.ReadGPR(m_thread.GetID(), &user.regs, sizeof(user.regs));
- LogGPR("RegisterContext_i386::ReadGPR()");
- return result;
-}
-
-bool
-RegisterContext_i386::ReadFPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(m_thread.GetID(), &user.i387, sizeof(user.i387));
-}
diff --git a/source/Plugins/Process/POSIX/RegisterContext_i386.h b/source/Plugins/Process/POSIX/RegisterContext_i386.h
deleted file mode 100644
index 96066c47b815..000000000000
--- a/source/Plugins/Process/POSIX/RegisterContext_i386.h
+++ /dev/null
@@ -1,169 +0,0 @@
-//===-- RegisterContext_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_RegisterContext_i386_h_
-#define liblldb_RegisterContext_i386_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Log.h"
-#include "RegisterContextPOSIX.h"
-
-class RegisterContext_i386 : public RegisterContextPOSIX
-{
-public:
- RegisterContext_i386(lldb_private::Thread &thread,
- uint32_t concreate_frame_idx);
-
- ~RegisterContext_i386();
-
- void
- Invalidate();
-
- void
- InvalidateAllRegisters();
-
- size_t
- GetRegisterCount();
-
- const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
-
- size_t
- GetRegisterSetCount();
-
- const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
-
- unsigned
- GetRegisterIndexFromOffset(unsigned offset);
-
- const char *
- GetRegisterName(unsigned reg);
-
- bool
- ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value);
-
- bool
- ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data);
-
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value);
-
- bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
-
- bool
- WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value);
-
- bool
- WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data,
- uint32_t data_offset = 0);
-
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value);
-
- bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
-
- uint32_t
- ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
-
- bool
- HardwareSingleStep(bool enable);
-
- bool
- UpdateAfterBreakpoint();
-
- struct GPR
- {
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
- uint32_t esi;
- uint32_t edi;
- uint32_t ebp;
- uint32_t eax;
- uint32_t ds;
- uint32_t es;
- uint32_t fs;
- uint32_t gs;
- uint32_t orig_ax;
- uint32_t eip;
- uint32_t cs;
- uint32_t eflags;
- uint32_t esp;
- uint32_t ss;
- };
-
- struct MMSReg
- {
- uint8_t bytes[8];
- };
-
- struct XMMReg
- {
- uint8_t bytes[16];
- };
-
- struct FPU
- {
- uint16_t fcw;
- uint16_t fsw;
- uint16_t ftw;
- uint16_t fop;
- uint32_t ip;
- uint32_t cs;
- uint32_t foo;
- uint32_t fos;
- uint32_t mxcsr;
- uint32_t reserved;
- MMSReg stmm[8];
- XMMReg xmm[8];
- uint32_t pad[56];
- };
-
- // A user area like this no longer exists on FreeBSD
- // making this a Linux artifact. Nonetheless, it is safe
- // leaving it here while the code is being cleaned up and generalized.
-
- struct UserArea
- {
- GPR regs; // General purpose registers.
- int32_t fpvalid; // True if FPU is being used.
- FPU i387; // FPU registers.
- uint32_t tsize; // Text segment size.
- uint32_t dsize; // Data segment size.
- uint32_t ssize; // Stack segment size.
- uint32_t start_code; // VM address of text.
- uint32_t start_stack; // VM address of stack bottom (top in rsp).
- int32_t signal; // Signal causing core dump.
- int32_t reserved; // Unused.
- uint32_t ar0; // Location of GPR's.
- FPU* fpstate; // Location of FPR's.
- uint32_t magic; // Identifier for core dumps.
- char u_comm[32]; // Command causing core dump.
- uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).
- };
-private:
- UserArea user;
-
- ProcessMonitor &GetMonitor();
-
- void LogGPR(const char *title);
-
- bool ReadGPR();
- bool ReadFPR();
-};
-
-#endif // #ifndef liblldb_RegisterContext_i386_h_
diff --git a/source/Plugins/Process/POSIX/RegisterContext_mips64.h b/source/Plugins/Process/POSIX/RegisterContext_mips64.h
new file mode 100644
index 000000000000..dfd473d7cbec
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContext_mips64.h
@@ -0,0 +1,104 @@
+//===-- RegisterContext_mips64.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_RegisterContext_mips64_H_
+#define liblldb_RegisterContext_mips64_H_
+
+// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
+enum
+{
+ // GP Registers
+ gcc_dwarf_zero_mips64 = 0,
+ gcc_dwarf_r1_mips64,
+ gcc_dwarf_r2_mips64,
+ gcc_dwarf_r3_mips64,
+ gcc_dwarf_r4_mips64,
+ gcc_dwarf_r5_mips64,
+ gcc_dwarf_r6_mips64,
+ gcc_dwarf_r7_mips64,
+ gcc_dwarf_r8_mips64,
+ gcc_dwarf_r9_mips64,
+ gcc_dwarf_r10_mips64,
+ gcc_dwarf_r11_mips64,
+ gcc_dwarf_r12_mips64,
+ gcc_dwarf_r13_mips64,
+ gcc_dwarf_r14_mips64,
+ gcc_dwarf_r15_mips64,
+ gcc_dwarf_r16_mips64,
+ gcc_dwarf_r17_mips64,
+ gcc_dwarf_r18_mips64,
+ gcc_dwarf_r19_mips64,
+ gcc_dwarf_r20_mips64,
+ gcc_dwarf_r21_mips64,
+ gcc_dwarf_r22_mips64,
+ gcc_dwarf_r23_mips64,
+ gcc_dwarf_r24_mips64,
+ gcc_dwarf_r25_mips64,
+ gcc_dwarf_r26_mips64,
+ gcc_dwarf_r27_mips64,
+ gcc_dwarf_gp_mips64,
+ gcc_dwarf_sp_mips64,
+ gcc_dwarf_r30_mips64,
+ gcc_dwarf_ra_mips64,
+ gcc_dwarf_sr_mips64,
+ gcc_dwarf_lo_mips64,
+ gcc_dwarf_hi_mips64,
+ gcc_dwarf_bad_mips64,
+ gcc_dwarf_cause_mips64,
+ gcc_dwarf_pc_mips64,
+ gcc_dwarf_ic_mips64,
+ gcc_dwarf_dummy_mips64
+};
+
+// GDB Register numbers (eRegisterKindGDB)
+enum
+{
+ gdb_zero_mips64 = 0,
+ gdb_r1_mips64,
+ gdb_r2_mips64,
+ gdb_r3_mips64,
+ gdb_r4_mips64,
+ gdb_r5_mips64,
+ gdb_r6_mips64,
+ gdb_r7_mips64,
+ gdb_r8_mips64,
+ gdb_r9_mips64,
+ gdb_r10_mips64,
+ gdb_r11_mips64,
+ gdb_r12_mips64,
+ gdb_r13_mips64,
+ gdb_r14_mips64,
+ gdb_r15_mips64,
+ gdb_r16_mips64,
+ gdb_r17_mips64,
+ gdb_r18_mips64,
+ gdb_r19_mips64,
+ gdb_r20_mips64,
+ gdb_r21_mips64,
+ gdb_r22_mips64,
+ gdb_r23_mips64,
+ gdb_r24_mips64,
+ gdb_r25_mips64,
+ gdb_r26_mips64,
+ gdb_r27_mips64,
+ gdb_gp_mips64,
+ gdb_sp_mips64,
+ gdb_r30_mips64,
+ gdb_ra_mips64,
+ gdb_sr_mips64,
+ gdb_lo_mips64,
+ gdb_hi_mips64,
+ gdb_bad_mips64,
+ gdb_cause_mips64,
+ gdb_pc_mips64,
+ gdb_ic_mips64,
+ gdb_dummy_mips64
+};
+
+#endif // liblldb_RegisterContext_mips64_H_
diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86.h b/source/Plugins/Process/POSIX/RegisterContext_x86.h
index 61a25c407758..df3e1e5a84bf 100644
--- a/source/Plugins/Process/POSIX/RegisterContext_x86.h
+++ b/source/Plugins/Process/POSIX/RegisterContext_x86.h
@@ -1,4 +1,4 @@
-//===-- RegisterContext_x86.h ---------------------------*- C++ -*-===//
+//===-- RegisterContext_x86.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,101 +10,470 @@
#ifndef liblldb_RegisterContext_x86_H_
#define liblldb_RegisterContext_x86_H_
+//---------------------------------------------------------------------------
+// i386 gcc, dwarf, gdb enums
+//---------------------------------------------------------------------------
+
+// Register numbers seen in eh_frame (eRegisterKindGCC)
+//
+// From Jason Molenda: "gcc registers" is the register numbering used in the eh_frame
+// CFI. The only registers that are described in eh_frame CFI are those that are
+// preserved across function calls aka callee-saved aka non-volatile. And none
+// of the floating point registers on x86 are preserved across function calls.
+//
+// The only reason there is a "gcc register" and a "dwarf register" is because of a
+// mistake years and years ago with i386 where they got esp and ebp
+// backwards when they emitted the eh_frame instructions. Once there were
+// binaries In The Wild using the reversed numbering, we had to stick with it
+// forever.
+enum
+{
+ // 2nd parameter in DwarfRegNum() is regnum for exception handling on x86-32.
+ // See http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register
+ gcc_eax_i386 = 0,
+ gcc_ecx_i386,
+ gcc_edx_i386,
+ gcc_ebx_i386,
+ gcc_ebp_i386, // Warning: these are switched from dwarf values
+ gcc_esp_i386, //
+ gcc_esi_i386,
+ gcc_edi_i386,
+ gcc_eip_i386,
+ gcc_eflags_i386,
+ gcc_st0_i386 = 12,
+ gcc_st1_i386,
+ gcc_st2_i386,
+ gcc_st3_i386,
+ gcc_st4_i386,
+ gcc_st5_i386,
+ gcc_st6_i386,
+ gcc_st7_i386,
+ gcc_xmm0_i386 = 21,
+ gcc_xmm1_i386,
+ gcc_xmm2_i386,
+ gcc_xmm3_i386,
+ gcc_xmm4_i386,
+ gcc_xmm5_i386,
+ gcc_xmm6_i386,
+ gcc_xmm7_i386,
+ gcc_mm0_i386 = 29,
+ gcc_mm1_i386,
+ gcc_mm2_i386,
+ gcc_mm3_i386,
+ gcc_mm4_i386,
+ gcc_mm5_i386,
+ gcc_mm6_i386,
+ gcc_mm7_i386,
+};
+
+// DWARF register numbers (eRegisterKindDWARF)
+// Intel's x86 or IA-32
enum
{
- gcc_eax = 0,
- gcc_ecx,
- gcc_edx,
- gcc_ebx,
- gcc_ebp,
- gcc_esp,
- gcc_esi,
- gcc_edi,
- gcc_eip,
- gcc_eflags
+ // General Purpose Registers.
+ dwarf_eax_i386 = 0,
+ dwarf_ecx_i386,
+ dwarf_edx_i386,
+ dwarf_ebx_i386,
+ dwarf_esp_i386,
+ dwarf_ebp_i386,
+ dwarf_esi_i386,
+ dwarf_edi_i386,
+ dwarf_eip_i386,
+ dwarf_eflags_i386,
+ // Floating Point Registers
+ dwarf_st0_i386 = 11,
+ dwarf_st1_i386,
+ dwarf_st2_i386,
+ dwarf_st3_i386,
+ dwarf_st4_i386,
+ dwarf_st5_i386,
+ dwarf_st6_i386,
+ dwarf_st7_i386,
+ // SSE Registers
+ dwarf_xmm0_i386 = 21,
+ dwarf_xmm1_i386,
+ dwarf_xmm2_i386,
+ dwarf_xmm3_i386,
+ dwarf_xmm4_i386,
+ dwarf_xmm5_i386,
+ dwarf_xmm6_i386,
+ dwarf_xmm7_i386,
+ // MMX Registers
+ dwarf_mm0_i386 = 29,
+ dwarf_mm1_i386,
+ dwarf_mm2_i386,
+ dwarf_mm3_i386,
+ dwarf_mm4_i386,
+ dwarf_mm5_i386,
+ dwarf_mm6_i386,
+ dwarf_mm7_i386,
+ dwarf_fctrl_i386 = 37, // x87 control word
+ dwarf_fstat_i386 = 38, // x87 status word
+ dwarf_mxcsr_i386 = 39,
+ dwarf_es_i386 = 40,
+ dwarf_cs_i386 = 41,
+ dwarf_ss_i386 = 42,
+ dwarf_ds_i386 = 43,
+ dwarf_fs_i386 = 44,
+ dwarf_gs_i386 = 45
+
+ // I believe the ymm registers use the dwarf_xmm%_i386 register numbers and
+ // then differentiate based on size of the register.
};
+// Register numbers GDB uses (eRegisterKindGDB)
+//
+// From Jason Molenda: The "gdb numbers" are what you would see in the stabs debug format.
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
+ gdb_eax_i386,
+ gdb_ecx_i386,
+ gdb_edx_i386,
+ gdb_ebx_i386,
+ gdb_esp_i386,
+ gdb_ebp_i386,
+ gdb_esi_i386,
+ gdb_edi_i386,
+ gdb_eip_i386,
+ gdb_eflags_i386,
+ gdb_cs_i386,
+ gdb_ss_i386,
+ gdb_ds_i386,
+ gdb_es_i386,
+ gdb_fs_i386,
+ gdb_gs_i386,
+ gdb_st0_i386 = 16,
+ gdb_st1_i386,
+ gdb_st2_i386,
+ gdb_st3_i386,
+ gdb_st4_i386,
+ gdb_st5_i386,
+ gdb_st6_i386,
+ gdb_st7_i386,
+ gdb_fctrl_i386, // FPU Control Word
+ gdb_fstat_i386, // FPU Status Word
+ gdb_ftag_i386, // FPU Tag Word
+ gdb_fiseg_i386, // FPU IP Selector
+ gdb_fioff_i386, // FPU IP Offset
+ gdb_foseg_i386, // FPU Operand Pointer Selector
+ gdb_fooff_i386, // FPU Operand Pointer Offset
+ gdb_fop_i386, // Last Instruction Opcode
+ gdb_xmm0_i386 = 32,
+ gdb_xmm1_i386,
+ gdb_xmm2_i386,
+ gdb_xmm3_i386,
+ gdb_xmm4_i386,
+ gdb_xmm5_i386,
+ gdb_xmm6_i386,
+ gdb_xmm7_i386,
+ gdb_mxcsr_i386 = 40,
+ gdb_ymm0h_i386,
+ gdb_ymm1h_i386,
+ gdb_ymm2h_i386,
+ gdb_ymm3h_i386,
+ gdb_ymm4h_i386,
+ gdb_ymm5h_i386,
+ gdb_ymm6h_i386,
+ gdb_ymm7h_i386,
+ gdb_mm0_i386,
+ gdb_mm1_i386,
+ gdb_mm2_i386,
+ gdb_mm3_i386,
+ gdb_mm4_i386,
+ gdb_mm5_i386,
+ gdb_mm6_i386,
+ gdb_mm7_i386,
};
+//---------------------------------------------------------------------------
+// AMD x86_64, AMD64, Intel EM64T, or Intel 64 gcc, dwarf, gdb enums
+//---------------------------------------------------------------------------
+
+// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
+// This is the spec I used (as opposed to x86-64-abi-0.99.pdf):
+// http://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
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_fcw = 24,
- gdb_fsw = 25,
- gdb_ftw = 26,
- gdb_fpu_cs = 27,
- gdb_ip = 28,
- gdb_fpu_ds = 29,
- gdb_dp = 30,
- 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
+ // GP Registers
+ gcc_dwarf_rax_x86_64 = 0,
+ gcc_dwarf_rdx_x86_64,
+ gcc_dwarf_rcx_x86_64,
+ gcc_dwarf_rbx_x86_64,
+ gcc_dwarf_rsi_x86_64,
+ gcc_dwarf_rdi_x86_64,
+ gcc_dwarf_rbp_x86_64,
+ gcc_dwarf_rsp_x86_64,
+ // Extended GP Registers
+ gcc_dwarf_r8_x86_64 = 8,
+ gcc_dwarf_r9_x86_64,
+ gcc_dwarf_r10_x86_64,
+ gcc_dwarf_r11_x86_64,
+ gcc_dwarf_r12_x86_64,
+ gcc_dwarf_r13_x86_64,
+ gcc_dwarf_r14_x86_64,
+ gcc_dwarf_r15_x86_64,
+ // Return Address (RA) mapped to RIP
+ gcc_dwarf_rip_x86_64 = 16,
+ // SSE Vector Registers
+ gcc_dwarf_xmm0_x86_64 = 17,
+ gcc_dwarf_xmm1_x86_64,
+ gcc_dwarf_xmm2_x86_64,
+ gcc_dwarf_xmm3_x86_64,
+ gcc_dwarf_xmm4_x86_64,
+ gcc_dwarf_xmm5_x86_64,
+ gcc_dwarf_xmm6_x86_64,
+ gcc_dwarf_xmm7_x86_64,
+ gcc_dwarf_xmm8_x86_64,
+ gcc_dwarf_xmm9_x86_64,
+ gcc_dwarf_xmm10_x86_64,
+ gcc_dwarf_xmm11_x86_64,
+ gcc_dwarf_xmm12_x86_64,
+ gcc_dwarf_xmm13_x86_64,
+ gcc_dwarf_xmm14_x86_64,
+ gcc_dwarf_xmm15_x86_64,
+ // Floating Point Registers
+ gcc_dwarf_st0_x86_64 = 33,
+ gcc_dwarf_st1_x86_64,
+ gcc_dwarf_st2_x86_64,
+ gcc_dwarf_st3_x86_64,
+ gcc_dwarf_st4_x86_64,
+ gcc_dwarf_st5_x86_64,
+ gcc_dwarf_st6_x86_64,
+ gcc_dwarf_st7_x86_64,
+ // MMX Registers
+ gcc_dwarf_mm0_x86_64 = 41,
+ gcc_dwarf_mm1_x86_64,
+ gcc_dwarf_mm2_x86_64,
+ gcc_dwarf_mm3_x86_64,
+ gcc_dwarf_mm4_x86_64,
+ gcc_dwarf_mm5_x86_64,
+ gcc_dwarf_mm6_x86_64,
+ gcc_dwarf_mm7_x86_64,
+ // Control and Status Flags Register
+ gcc_dwarf_rflags_x86_64 = 49,
+ // selector registers
+ gcc_dwarf_es_x86_64 = 50,
+ gcc_dwarf_cs_x86_64,
+ gcc_dwarf_ss_x86_64,
+ gcc_dwarf_ds_x86_64,
+ gcc_dwarf_fs_x86_64,
+ gcc_dwarf_gs_x86_64,
+ // Floating point control registers
+ gcc_dwarf_mxcsr_x86_64 = 64, // Media Control and Status
+ gcc_dwarf_fctrl_x86_64, // x87 control word
+ gcc_dwarf_fstat_x86_64, // x87 status word
+ // Upper Vector Registers
+ gcc_dwarf_ymm0h_x86_64 = 67,
+ gcc_dwarf_ymm1h_x86_64,
+ gcc_dwarf_ymm2h_x86_64,
+ gcc_dwarf_ymm3h_x86_64,
+ gcc_dwarf_ymm4h_x86_64,
+ gcc_dwarf_ymm5h_x86_64,
+ gcc_dwarf_ymm6h_x86_64,
+ gcc_dwarf_ymm7h_x86_64,
+ gcc_dwarf_ymm8h_x86_64,
+ gcc_dwarf_ymm9h_x86_64,
+ gcc_dwarf_ymm10h_x86_64,
+ gcc_dwarf_ymm11h_x86_64,
+ gcc_dwarf_ymm12h_x86_64,
+ gcc_dwarf_ymm13h_x86_64,
+ gcc_dwarf_ymm14h_x86_64,
+ gcc_dwarf_ymm15h_x86_64,
+ // AVX2 Vector Mask Registers
+ // gcc_dwarf_k0_x86_64 = 118,
+ // gcc_dwarf_k1_x86_64,
+ // gcc_dwarf_k2_x86_64,
+ // gcc_dwarf_k3_x86_64,
+ // gcc_dwarf_k4_x86_64,
+ // gcc_dwarf_k5_x86_64,
+ // gcc_dwarf_k6_x86_64,
+ // gcc_dwarf_k7_x86_64,
+};
+
+// GDB Register numbers (eRegisterKindGDB)
+enum
+{
+ // GP Registers
+ gdb_rax_x86_64 = 0,
+ gdb_rbx_x86_64,
+ gdb_rcx_x86_64,
+ gdb_rdx_x86_64,
+ gdb_rsi_x86_64,
+ gdb_rdi_x86_64,
+ gdb_rbp_x86_64,
+ gdb_rsp_x86_64,
+ // Extended GP Registers
+ gdb_r8_x86_64,
+ gdb_r9_x86_64,
+ gdb_r10_x86_64,
+ gdb_r11_x86_64,
+ gdb_r12_x86_64,
+ gdb_r13_x86_64,
+ gdb_r14_x86_64,
+ gdb_r15_x86_64,
+ // Return Address (RA) mapped to RIP
+ gdb_rip_x86_64,
+ // Control and Status Flags Register
+ gdb_rflags_x86_64,
+ gdb_cs_x86_64,
+ gdb_ss_x86_64,
+ gdb_ds_x86_64,
+ gdb_es_x86_64,
+ gdb_fs_x86_64,
+ gdb_gs_x86_64,
+ // Floating Point Registers
+ gdb_st0_x86_64,
+ gdb_st1_x86_64,
+ gdb_st2_x86_64,
+ gdb_st3_x86_64,
+ gdb_st4_x86_64,
+ gdb_st5_x86_64,
+ gdb_st6_x86_64,
+ gdb_st7_x86_64,
+ gdb_fctrl_x86_64,
+ gdb_fstat_x86_64,
+ gdb_ftag_x86_64,
+ gdb_fiseg_x86_64,
+ gdb_fioff_x86_64,
+ gdb_foseg_x86_64,
+ gdb_fooff_x86_64,
+ gdb_fop_x86_64,
+ // SSE Vector Registers
+ gdb_xmm0_x86_64 = 40,
+ gdb_xmm1_x86_64,
+ gdb_xmm2_x86_64,
+ gdb_xmm3_x86_64,
+ gdb_xmm4_x86_64,
+ gdb_xmm5_x86_64,
+ gdb_xmm6_x86_64,
+ gdb_xmm7_x86_64,
+ gdb_xmm8_x86_64,
+ gdb_xmm9_x86_64,
+ gdb_xmm10_x86_64,
+ gdb_xmm11_x86_64,
+ gdb_xmm12_x86_64,
+ gdb_xmm13_x86_64,
+ gdb_xmm14_x86_64,
+ gdb_xmm15_x86_64,
+ // Floating point control registers
+ gdb_mxcsr_x86_64 = 56,
+ gdb_ymm0h_x86_64,
+ gdb_ymm1h_x86_64,
+ gdb_ymm2h_x86_64,
+ gdb_ymm3h_x86_64,
+ gdb_ymm4h_x86_64,
+ gdb_ymm5h_x86_64,
+ gdb_ymm6h_x86_64,
+ gdb_ymm7h_x86_64,
+ gdb_ymm8h_x86_64,
+ gdb_ymm9h_x86_64,
+ gdb_ymm10h_x86_64,
+ gdb_ymm11h_x86_64,
+ gdb_ymm12h_x86_64,
+ gdb_ymm13h_x86_64,
+ gdb_ymm14h_x86_64,
+ gdb_ymm15h_x86_64
+};
+
+//---------------------------------------------------------------------------
+// Generic floating-point registers
+//---------------------------------------------------------------------------
+
+struct MMSReg
+{
+ uint8_t bytes[10];
+ uint8_t pad[6];
+};
+
+struct XMMReg
+{
+ uint8_t bytes[16]; // 128-bits for each XMM register
+};
+
+// i387_fxsave_struct
+struct FXSAVE
+{
+ uint16_t fctrl; // FPU Control Word (fcw)
+ uint16_t fstat; // FPU Status Word (fsw)
+ uint16_t ftag; // FPU Tag Word (ftw)
+ uint16_t fop; // Last Instruction Opcode (fop)
+ union
+ {
+ struct
+ {
+ uint64_t fip; // Instruction Pointer
+ uint64_t fdp; // Data Pointer
+ } x86_64;
+ struct
+ {
+ uint32_t fioff; // FPU IP Offset (fip)
+ uint32_t fiseg; // FPU IP Selector (fcs)
+ uint32_t fooff; // FPU Operand Pointer Offset (foo)
+ uint32_t foseg; // FPU Operand Pointer Selector (fos)
+ } i386;
+ } ptr;
+ uint32_t mxcsr; // MXCSR Register State
+ uint32_t mxcsrmask; // MXCSR Mask
+ MMSReg stmm[8]; // 8*16 bytes for each FP-reg = 128 bytes
+ XMMReg xmm[16]; // 16*16 bytes for each XMM-reg = 256 bytes
+ uint32_t padding[24];
+};
+
+//---------------------------------------------------------------------------
+// Extended floating-point registers
+//---------------------------------------------------------------------------
+
+struct YMMHReg
+{
+ uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register
+};
+
+struct YMMReg
+{
+ uint8_t bytes[32]; // 16 * 16 bits for each YMM register
+};
+
+struct YMM
+{
+ YMMReg ymm[16]; // assembled from ymmh and xmm registers
+};
+
+struct XSAVE_HDR
+{
+ uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states supported by the processor
+ uint64_t reserved1[2];
+ uint64_t reserved2[5];
+} __attribute__((packed));
+
+// x86 extensions to FXSAVE (i.e. for AVX processors)
+struct XSAVE
+{
+ FXSAVE i387; // floating point registers typical in i387_fxsave_struct
+ XSAVE_HDR header; // The xsave_hdr_struct can be used to determine if the following extensions are usable
+ YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes are in FXSAVE.xmm for compatibility with SSE)
+ // Slot any extensions to the register file here
+} __attribute__((packed, aligned (64)));
+
+// Floating-point registers
+struct FPR
+{
+ // Thread state for the floating-point unit of the processor read by ptrace.
+ union XSTATE
+ {
+ FXSAVE fxsave; // Generic floating-point registers.
+ XSAVE xsave; // x86 extended processor state.
+ } xstate;
+};
+
+//---------------------------------------------------------------------------
+// ptrace PTRACE_GETREGSET, PTRACE_SETREGSET structure
+//---------------------------------------------------------------------------
+
+struct IOVEC
+{
+ void *iov_base; // pointer to XSAVE
+ size_t iov_len; // sizeof(XSAVE)
};
#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
deleted file mode 100644
index 617b18484e5a..000000000000
--- a/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
+++ /dev/null
@@ -1,1563 +0,0 @@
-//===-- RegisterContext_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.
-//
-//===----------------------------------------------------------------------===//
-
-#include <cstring>
-#include <errno.h>
-#include <stdint.h>
-
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Host/Endian.h"
-#include "llvm/Support/Compiler.h"
-
-#include "ProcessPOSIX.h"
-#if defined(__linux__) or defined(__FreeBSD__)
-#include "ProcessMonitor.h"
-#endif
-#include "RegisterContext_i386.h"
-#include "RegisterContext_x86.h"
-#include "RegisterContext_x86_64.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-// Support ptrace extensions even when compiled without required kernel support
-#ifndef NT_X86_XSTATE
- #define NT_X86_XSTATE 0x202
-#endif
-
-enum
-{
- 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,
- gcc_dwarf_fpu_ymm0,
- gcc_dwarf_fpu_ymm1,
- gcc_dwarf_fpu_ymm2,
- gcc_dwarf_fpu_ymm3,
- gcc_dwarf_fpu_ymm4,
- gcc_dwarf_fpu_ymm5,
- gcc_dwarf_fpu_ymm6,
- gcc_dwarf_fpu_ymm7,
- gcc_dwarf_fpu_ymm8,
- gcc_dwarf_fpu_ymm9,
- gcc_dwarf_fpu_ymm10,
- gcc_dwarf_fpu_ymm11,
- gcc_dwarf_fpu_ymm12,
- gcc_dwarf_fpu_ymm13,
- gcc_dwarf_fpu_ymm14,
- gcc_dwarf_fpu_ymm15
-};
-
-enum
-{
- 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_fcw = 32,
- gdb_fpu_fsw = 33,
- gdb_fpu_ftw = 34,
- gdb_fpu_cs_64 = 35,
- gdb_fpu_ip = 36,
- gdb_fpu_ds_64 = 37,
- gdb_fpu_dp = 38,
- 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,
- gdb_fpu_ymm0 = 57,
- gdb_fpu_ymm1 = 58,
- gdb_fpu_ymm2 = 59,
- gdb_fpu_ymm3 = 60,
- gdb_fpu_ymm4 = 61,
- gdb_fpu_ymm5 = 62,
- gdb_fpu_ymm6 = 63,
- gdb_fpu_ymm7 = 64,
- gdb_fpu_ymm8 = 65,
- gdb_fpu_ymm9 = 66,
- gdb_fpu_ymm10 = 67,
- gdb_fpu_ymm11 = 68,
- gdb_fpu_ymm12 = 69,
- gdb_fpu_ymm13 = 70,
- gdb_fpu_ymm14 = 71,
- gdb_fpu_ymm15 = 72
-};
-
-static const
-uint32_t g_gpr_regnums[k_num_gpr_registers] =
-{
- 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,
- gpr_ss,
- gpr_ds,
- gpr_es,
- gpr_eax,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_eip,
- gpr_eflags
-};
-
-static const uint32_t
-g_fpu_regnums[k_num_fpr_registers] =
-{
- 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 const uint32_t
-g_avx_regnums[k_num_avx_registers] =
-{
- fpu_ymm0,
- fpu_ymm1,
- fpu_ymm2,
- fpu_ymm3,
- fpu_ymm4,
- fpu_ymm5,
- fpu_ymm6,
- fpu_ymm7,
- fpu_ymm8,
- fpu_ymm9,
- fpu_ymm10,
- fpu_ymm11,
- fpu_ymm12,
- fpu_ymm13,
- fpu_ymm14,
- fpu_ymm15
-};
-
-// Number of register sets provided by this context.
-enum
-{
- k_num_extended_register_sets = 1,
- k_num_register_sets = 3
-};
-
-static const RegisterSet
-g_reg_sets[k_num_register_sets] =
-{
- { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
- { "Floating Point Registers", "fpu", k_num_fpr_registers, g_fpu_regnums },
- { "Advanced Vector Extensions", "avx", k_num_avx_registers, g_avx_regnums }
-};
-
-// Computes the offset of the given FPR in the extended data area.
-#define FPR_OFFSET(regname) \
- (offsetof(RegisterContext_x86_64::FPR, xstate) + \
- offsetof(RegisterContext_x86_64::FXSAVE, regname))
-
-// Computes the offset of the YMM register assembled from register halves.
-#define YMM_OFFSET(regname) \
- (offsetof(RegisterContext_x86_64::YMM, regname))
-
-// Number of bytes needed to represent a i386 GPR
-#define GPR_i386_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)
-
-// Number of bytes needed to represent a FPR.
-#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FXSAVE*)NULL)->reg)
-
-// Number of bytes needed to represent the i'th FP register.
-#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes)
-
-// Number of bytes needed to represent an XMM register.
-#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg)
-
-// Number of bytes needed to represent a YMM register.
-#define YMM_SIZE sizeof(RegisterContext_x86_64::YMMReg)
-
-// Note that the size and offset will be updated by platform-specific classes.
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
- { #reg, alt, 0, 0, eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL }
-
-// Dummy data for RegisterInfo::value_regs as expected by DumpRegisterSet.
-static uint32_t value_regs = LLDB_INVALID_REGNUM;
-
-#define DEFINE_GPR_i386(reg_i386, reg_x86_64, alt, kind1, kind2, kind3, kind4) \
- { #reg_i386, alt, GPR_i386_SIZE(reg_i386), 0, eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg_i386 }, &value_regs, NULL }
-
-#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
- { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL }
-
-#define DEFINE_FP(reg, i) \
- { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_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 }, NULL, NULL }
-
-#define DEFINE_XMM(reg, i) \
- { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_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 }, NULL, NULL }
-
-#define DEFINE_YMM(reg, i) \
- { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_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 }, NULL, NULL }
-
-#define DEFINE_DR(reg, i) \
- { #reg#i, NULL, 0, 0, eEncodingUint, eFormatHex, \
- { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
-
-#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(RegisterContext_x86_64::FPR))
-
-static RegisterInfo
-g_register_infos[k_num_registers] =
-{
- // General purpose registers.
- DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax),
- DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx),
- DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx),
- DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx),
- DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi),
- DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi),
- DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp),
- DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp),
- DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8),
- DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9),
- DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10),
- DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11),
- DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12),
- DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13),
- DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14),
- DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15),
- DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip),
- DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags),
- DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs),
- DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs),
- DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs),
- DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss),
- DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds),
- DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es),
- // i386 registers
- DEFINE_GPR_i386(eax, rax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax),
- DEFINE_GPR_i386(ebx, rbx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx),
- DEFINE_GPR_i386(ecx, rcx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx),
- DEFINE_GPR_i386(edx, rdx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx),
- DEFINE_GPR_i386(edi, rdi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi),
- DEFINE_GPR_i386(esi, rsi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi),
- DEFINE_GPR_i386(ebp, rbp, "fp", gcc_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, gdb_ebp),
- DEFINE_GPR_i386(esp, rsp, "sp", gcc_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, gdb_esp),
- DEFINE_GPR_i386(eip, rip, "pc", gcc_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, gdb_eip),
- DEFINE_GPR_i386(eflags, rflags, "flags", gcc_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags),
- // i387 Floating point registers.
- DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw),
- DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw),
- DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw),
- DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop),
- DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip),
- // FIXME: Extract segment from ip.
- DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs_64),
- DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp),
- // FIXME: Extract segment from dp.
- DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds_64),
- DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr),
- DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
-
- // FP registers.
- DEFINE_FP(stmm, 0),
- DEFINE_FP(stmm, 1),
- DEFINE_FP(stmm, 2),
- DEFINE_FP(stmm, 3),
- DEFINE_FP(stmm, 4),
- DEFINE_FP(stmm, 5),
- DEFINE_FP(stmm, 6),
- DEFINE_FP(stmm, 7),
-
- // XMM registers
- DEFINE_XMM(xmm, 0),
- DEFINE_XMM(xmm, 1),
- DEFINE_XMM(xmm, 2),
- DEFINE_XMM(xmm, 3),
- DEFINE_XMM(xmm, 4),
- DEFINE_XMM(xmm, 5),
- DEFINE_XMM(xmm, 6),
- DEFINE_XMM(xmm, 7),
- DEFINE_XMM(xmm, 8),
- DEFINE_XMM(xmm, 9),
- DEFINE_XMM(xmm, 10),
- DEFINE_XMM(xmm, 11),
- DEFINE_XMM(xmm, 12),
- DEFINE_XMM(xmm, 13),
- DEFINE_XMM(xmm, 14),
- DEFINE_XMM(xmm, 15),
-
- // Copy of YMM registers assembled from xmm and ymmh
- DEFINE_YMM(ymm, 0),
- DEFINE_YMM(ymm, 1),
- DEFINE_YMM(ymm, 2),
- DEFINE_YMM(ymm, 3),
- DEFINE_YMM(ymm, 4),
- DEFINE_YMM(ymm, 5),
- DEFINE_YMM(ymm, 6),
- DEFINE_YMM(ymm, 7),
- DEFINE_YMM(ymm, 8),
- DEFINE_YMM(ymm, 9),
- DEFINE_YMM(ymm, 10),
- DEFINE_YMM(ymm, 11),
- DEFINE_YMM(ymm, 12),
- DEFINE_YMM(ymm, 13),
- DEFINE_YMM(ymm, 14),
- DEFINE_YMM(ymm, 15),
-
- // Debug registers for lldb internal use
- DEFINE_DR(dr, 0),
- DEFINE_DR(dr, 1),
- DEFINE_DR(dr, 2),
- DEFINE_DR(dr, 3),
- DEFINE_DR(dr, 4),
- DEFINE_DR(dr, 5),
- DEFINE_DR(dr, 6),
- DEFINE_DR(dr, 7)
-};
-
-static bool IsGPR(unsigned reg)
-{
- return reg <= k_last_gpr; // GPR's come first.
-}
-
-static bool IsAVX(unsigned reg)
-{
- return (k_first_avx <= reg && reg <= k_last_avx);
-}
-static bool IsFPR(unsigned reg)
-{
- return (k_first_fpr <= reg && reg <= k_last_fpr);
-}
-
-
-bool RegisterContext_x86_64::IsFPR(unsigned reg, FPRType fpr_type)
-{
- bool generic_fpr = ::IsFPR(reg);
- if (fpr_type == eXSAVE)
- return generic_fpr || IsAVX(reg);
-
- return generic_fpr;
-}
-
-RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread,
- uint32_t concrete_frame_idx)
- : RegisterContextPOSIX(thread, concrete_frame_idx)
-{
- // Initialize m_iovec to point to the buffer and buffer size
- // using the conventions of Berkeley style UIO structures, as required
- // by PTRACE extensions.
- m_iovec.iov_base = &m_fpr.xstate.xsave;
- m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
-
- ::memset(&m_fpr, 0, sizeof(RegisterContext_x86_64::FPR));
-
- // elf-core yet to support ReadFPR()
- ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
-
- // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx
- m_fpr_type = eXSAVE; // extended floating-point registers, if available
- if (false == ReadFPR())
- m_fpr_type = eFXSAVE; // assume generic floating-point registers
-}
-
-RegisterContext_x86_64::~RegisterContext_x86_64()
-{
-}
-
-void
-RegisterContext_x86_64::Invalidate()
-{
-}
-
-void
-RegisterContext_x86_64::InvalidateAllRegisters()
-{
-}
-
-unsigned
-RegisterContext_x86_64::GetRegisterOffset(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return GetRegisterInfo()[reg].byte_offset;
-}
-
-unsigned
-RegisterContext_x86_64::GetRegisterSize(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register number.");
- return GetRegisterInfo()[reg].byte_size;
-}
-
-size_t
-RegisterContext_x86_64::GetRegisterCount()
-{
- size_t num_registers = k_num_gpr_registers + k_num_fpr_registers;
- if (m_fpr_type == eXSAVE)
- return num_registers + k_num_avx_registers;
- return num_registers;
-}
-
-const RegisterInfo *
-RegisterContext_x86_64::GetRegisterInfo()
-{
- // Commonly, this method is overridden and g_register_infos is copied and specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
- return g_register_infos;
-}
-
-const RegisterInfo *
-RegisterContext_x86_64::GetRegisterInfoAtIndex(size_t reg)
-{
- if (reg < k_num_registers)
- return &GetRegisterInfo()[reg];
- else
- return NULL;
-}
-
-size_t
-RegisterContext_x86_64::GetRegisterSetCount()
-{
- size_t sets = 0;
- for (size_t set = 0; set < k_num_register_sets; ++set)
- if (IsRegisterSetAvailable(set))
- ++sets;
-
- return sets;
-}
-
-const RegisterSet *
-RegisterContext_x86_64::GetRegisterSet(size_t set)
-{
- if (IsRegisterSetAvailable(set))
- return &g_reg_sets[set];
- else
- return NULL;
-}
-
-unsigned
-RegisterContext_x86_64::GetRegisterIndexFromOffset(unsigned offset)
-{
- unsigned reg;
- for (reg = 0; reg < k_num_registers; reg++)
- {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers && "Invalid register offset.");
- return reg;
-}
-
-const char *
-RegisterContext_x86_64::GetRegisterName(unsigned reg)
-{
- assert(reg < k_num_registers && "Invalid register offset.");
- return GetRegisterInfo()[reg].name;
-}
-
-lldb::ByteOrder
-RegisterContext_x86_64::GetByteOrder()
-{
- // Get the target process whose privileged thread was used for the register read.
- lldb::ByteOrder byte_order = eByteOrderInvalid;
- Process *process = CalculateProcess().get();
-
- if (process)
- byte_order = process->GetByteOrder();
- return byte_order;
-}
-
-// Parse ymm registers and into xmm.bytes and ymmh.bytes.
-bool RegisterContext_x86_64::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
-{
- if (!IsAVX(reg))
- return false;
-
- if (byte_order == eByteOrderLittle) {
- ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
- m_ymm_set.ymm[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::XMMReg));
- ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
- m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
- sizeof(RegisterContext_x86_64::YMMHReg));
- return true;
- }
-
- if (byte_order == eByteOrderBig) {
- ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
- m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
- sizeof(RegisterContext_x86_64::XMMReg));
- ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
- m_ymm_set.ymm[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::YMMHReg));
- return true;
- }
- return false; // unsupported or invalid byte order
-}
-
-// Concatenate xmm.bytes with ymmh.bytes
-bool RegisterContext_x86_64::CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order)
-{
- if (!IsAVX(reg))
- return false;
-
- if (byte_order == eByteOrderLittle) {
- ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes,
- m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::XMMReg));
- ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
- m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::YMMHReg));
- return true;
- }
- if (byte_order == eByteOrderBig) {
- ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
- m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::XMMReg));
- ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes,
- m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
- sizeof(RegisterContext_x86_64::YMMHReg));
- return true;
- }
- return false; // unsupported or invalid byte order
-}
-
-bool
-RegisterContext_x86_64::IsRegisterSetAvailable(size_t set_index)
-{
- // Note: Extended register sets are assumed to be at the end of g_reg_sets...
- size_t num_sets = k_num_register_sets - k_num_extended_register_sets;
- if (m_fpr_type == eXSAVE) // ...and to start with AVX registers.
- ++num_sets;
-
- return (set_index < num_sets);
-}
-
-bool
-RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
-{
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsFPR(reg, m_fpr_type)) {
- if (!ReadFPR())
- return false;
- }
- else {
- bool success = ReadRegister(reg, value);
-
- // If an i386 register should be parsed from an x86_64 register...
- if (success && reg >= k_first_i386 && reg <= k_last_i386)
- if (value.GetByteSize() > reg_info->byte_size)
- value.SetType(reg_info); // ...use the type specified by reg_info rather than the uint64_t default
- return success;
- }
-
- if (reg_info->encoding == eEncodingVector) {
- ByteOrder byte_order = GetByteOrder();
-
- if (byte_order != ByteOrder::eByteOrderInvalid) {
- if (reg >= fpu_stmm0 && reg <= fpu_stmm7) {
- value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, byte_order);
- }
- if (reg >= fpu_xmm0 && reg <= fpu_xmm15) {
- value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, byte_order);
- }
- if (reg >= fpu_ymm0 && reg <= fpu_ymm15) {
- // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
- if (m_fpr_type == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
- value.SetBytes(m_ymm_set.ymm[reg - fpu_ymm0].bytes, reg_info->byte_size, byte_order);
- else
- return false;
- }
- return value.GetType() == RegisterValue::eTypeBytes;
- }
- return false;
- }
-
- // Note that lldb uses slightly different naming conventions from sys/user.h
- switch (reg)
- {
- default:
- return false;
- case fpu_dp:
- value = m_fpr.xstate.fxsave.dp;
- break;
- case fpu_fcw:
- value = m_fpr.xstate.fxsave.fcw;
- break;
- case fpu_fsw:
- value = m_fpr.xstate.fxsave.fsw;
- break;
- case fpu_ip:
- value = m_fpr.xstate.fxsave.ip;
- break;
- case fpu_fop:
- value = m_fpr.xstate.fxsave.fop;
- break;
- case fpu_ftw:
- value = m_fpr.xstate.fxsave.ftw;
- break;
- case fpu_mxcsr:
- value = m_fpr.xstate.fxsave.mxcsr;
- break;
- case fpu_mxcsrmask:
- value = m_fpr.xstate.fxsave.mxcsrmask;
- break;
- }
- return true;
-}
-
-bool
-RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)
-{
- bool success = false;
- data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
- if (data_sp && ReadGPR () && ReadFPR ())
- {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy (dst, &m_gpr, GetGPRSize());
- dst += GetGPRSize();
- }
- if (m_fpr_type == eFXSAVE)
- ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
-
- if (m_fpr_type == eXSAVE) {
- ByteOrder byte_order = GetByteOrder();
-
- // Assemble the YMM register content from the register halves.
- for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg)
- success = CopyXSTATEtoYMM(reg, byte_order);
-
- if (success) {
- // Copy the extended register state including the assembled ymm registers.
- ::memcpy (dst, &m_fpr, sizeof(m_fpr));
- }
- }
- }
- return success;
-}
-
-bool
-RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value)
-{
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- if (IsGPR(reg)) {
- return WriteRegister(reg, value);
- }
-
- if (IsFPR(reg, m_fpr_type)) {
- switch (reg)
- {
- default:
- if (reg_info->encoding != eEncodingVector)
- return false;
-
- if (reg >= fpu_stmm0 && reg <= fpu_stmm7)
- ::memcpy (m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize());
-
- if (reg >= fpu_xmm0 && reg <= fpu_xmm15)
- ::memcpy (m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize());
-
- if (reg >= fpu_ymm0 && reg <= fpu_ymm15) {
- if (m_fpr_type != eXSAVE)
- return false; // the target processor does not support AVX
-
- // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes
- ::memcpy (m_ymm_set.ymm[reg - fpu_ymm0].bytes, value.GetBytes(), value.GetByteSize());
- if (false == CopyYMMtoXSTATE(reg, GetByteOrder()))
- return false;
- }
- break;
- case fpu_dp:
- m_fpr.xstate.fxsave.dp = value.GetAsUInt64();
- break;
- case fpu_fcw:
- m_fpr.xstate.fxsave.fcw = value.GetAsUInt16();
- break;
- case fpu_fsw:
- m_fpr.xstate.fxsave.fsw = value.GetAsUInt16();
- break;
- case fpu_ip:
- m_fpr.xstate.fxsave.ip = value.GetAsUInt64();
- break;
- case fpu_fop:
- m_fpr.xstate.fxsave.fop = value.GetAsUInt16();
- break;
- case fpu_ftw:
- m_fpr.xstate.fxsave.ftw = value.GetAsUInt16();
- break;
- case fpu_mxcsr:
- m_fpr.xstate.fxsave.mxcsr = value.GetAsUInt32();
- break;
- case fpu_mxcsrmask:
- m_fpr.xstate.fxsave.mxcsrmask = value.GetAsUInt32();
- break;
- }
- if (WriteFPR()) {
- if (IsAVX(reg))
- return CopyYMMtoXSTATE(reg, GetByteOrder());
- return true;
- }
- }
- return false;
-}
-
-bool
-RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)
-{
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
- {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy (&m_gpr, src, GetGPRSize());
-
- if (WriteGPR()) {
- src += GetGPRSize();
- if (m_fpr_type == eFXSAVE)
- ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
- if (m_fpr_type == eXSAVE)
- ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
-
- success = WriteFPR();
- if (success) {
- success = true;
-
- if (m_fpr_type == eXSAVE) {
- ByteOrder byte_order = GetByteOrder();
-
- // Parse the YMM register content from the register halves.
- for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg)
- success = CopyYMMtoXSTATE(reg, byte_order);
- }
- }
- }
- }
- }
- return success;
-}
-
-bool
-RegisterContext_x86_64::UpdateAfterBreakpoint()
-{
- // PC points one byte past the int3 responsible for the breakpoint.
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- SetPC(pc - 1);
- return true;
-}
-
-uint32_t
-RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
- uint32_t num)
-{
- const Process *process = CalculateProcess().get();
- if (process)
- {
- const ArchSpec arch = process->GetTarget().GetArchitecture();;
- switch (arch.GetCore())
- {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case ArchSpec::eCore_x86_32_i386:
- case ArchSpec::eCore_x86_32_i486:
- case ArchSpec::eCore_x86_32_i486sx:
- {
- if (kind == eRegisterKindGeneric)
- {
- switch (num)
- {
- 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:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
- {
- switch (num)
- {
- case dwarf_eax: return gpr_eax;
- case dwarf_edx: return gpr_edx;
- case dwarf_ecx: return gpr_ecx;
- case dwarf_ebx: return gpr_ebx;
- case dwarf_esi: return gpr_esi;
- case dwarf_edi: return gpr_edi;
- case dwarf_ebp: return gpr_ebp;
- case dwarf_esp: return gpr_esp;
- case dwarf_eip: return gpr_eip;
- 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;
- 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;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGDB)
- {
- switch (num)
- {
- 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_fcw : return fpu_fcw;
- case gdb_fsw : return fpu_fsw;
- case gdb_ftw : return fpu_ftw;
- case gdb_fpu_cs : return fpu_cs;
- case gdb_ip : return fpu_ip;
- case gdb_fpu_ds : return fpu_ds; //fpu_fos
- case gdb_dp : return fpu_dp; //fpu_foo
- 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:
- return LLDB_INVALID_REGNUM;
- }
- }
- else if (kind == eRegisterKindLLDB)
- {
- return num;
- }
-
- break;
- }
-
- case ArchSpec::eCore_x86_64_x86_64:
- {
- if (kind == eRegisterKindGeneric)
- {
- switch (num)
- {
- 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:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
- {
- switch (num)
- {
- 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;
- case gcc_dwarf_fpu_ymm0: return fpu_ymm0;
- case gcc_dwarf_fpu_ymm1: return fpu_ymm1;
- case gcc_dwarf_fpu_ymm2: return fpu_ymm2;
- case gcc_dwarf_fpu_ymm3: return fpu_ymm3;
- case gcc_dwarf_fpu_ymm4: return fpu_ymm4;
- case gcc_dwarf_fpu_ymm5: return fpu_ymm5;
- case gcc_dwarf_fpu_ymm6: return fpu_ymm6;
- case gcc_dwarf_fpu_ymm7: return fpu_ymm7;
- case gcc_dwarf_fpu_ymm8: return fpu_ymm8;
- case gcc_dwarf_fpu_ymm9: return fpu_ymm9;
- case gcc_dwarf_fpu_ymm10: return fpu_ymm10;
- case gcc_dwarf_fpu_ymm11: return fpu_ymm11;
- case gcc_dwarf_fpu_ymm12: return fpu_ymm12;
- case gcc_dwarf_fpu_ymm13: return fpu_ymm13;
- case gcc_dwarf_fpu_ymm14: return fpu_ymm14;
- case gcc_dwarf_fpu_ymm15: return fpu_ymm15;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
-
- if (kind == eRegisterKindGDB)
- {
- switch (num)
- {
- 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_ss;
- case gdb_gpr_ds : return gpr_ds;
- case gdb_gpr_es : return gpr_es;
- 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_fcw : return fpu_fcw;
- case gdb_fpu_fsw : return fpu_fsw;
- case gdb_fpu_ftw : return fpu_ftw;
- case gdb_fpu_cs_64 : return fpu_cs;
- case gdb_fpu_ip : return fpu_ip;
- case gdb_fpu_ds_64 : return fpu_ds;
- case gdb_fpu_dp : return fpu_dp;
- 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;
- case gdb_fpu_ymm0 : return fpu_ymm0;
- case gdb_fpu_ymm1 : return fpu_ymm1;
- case gdb_fpu_ymm2 : return fpu_ymm2;
- case gdb_fpu_ymm3 : return fpu_ymm3;
- case gdb_fpu_ymm4 : return fpu_ymm4;
- case gdb_fpu_ymm5 : return fpu_ymm5;
- case gdb_fpu_ymm6 : return fpu_ymm6;
- case gdb_fpu_ymm7 : return fpu_ymm7;
- case gdb_fpu_ymm8 : return fpu_ymm8;
- case gdb_fpu_ymm9 : return fpu_ymm9;
- case gdb_fpu_ymm10 : return fpu_ymm10;
- case gdb_fpu_ymm11 : return fpu_ymm11;
- case gdb_fpu_ymm12 : return fpu_ymm12;
- case gdb_fpu_ymm13 : return fpu_ymm13;
- case gdb_fpu_ymm14 : return fpu_ymm14;
- case gdb_fpu_ymm15 : return fpu_ymm15;
- default:
- return LLDB_INVALID_REGNUM;
- }
- }
- else if (kind == eRegisterKindLLDB)
- {
- return num;
- }
- }
- }
- }
-
- return LLDB_INVALID_REGNUM;
-}
-
-uint32_t
-RegisterContext_x86_64::NumSupportedHardwareWatchpoints()
-{
- // Available debug address registers: dr0, dr1, dr2, dr3
- return 4;
-}
-
-bool
-RegisterContext_x86_64::IsWatchpointVacant(uint32_t hw_index)
-{
- bool is_vacant = false;
- RegisterValue value;
-
- assert(hw_index < NumSupportedHardwareWatchpoints());
-
- if (m_watchpoints_initialized == false)
- {
- // Reset the debug status and debug control registers
- RegisterValue zero_bits = RegisterValue(uint64_t(0));
- if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits))
- assert(false && "Could not initialize watchpoint registers");
- m_watchpoints_initialized = true;
- }
-
- if (ReadRegister(dr7, value))
- {
- uint64_t val = value.GetAsUInt64();
- is_vacant = (val & (3 << 2*hw_index)) == 0;
- }
-
- return is_vacant;
-}
-
-static uint32_t
-size_and_rw_bits(size_t size, bool read, bool write)
-{
- uint32_t rw;
- if (read) {
- rw = 0x3; // READ or READ/WRITE
- } else if (write) {
- rw = 0x1; // WRITE
- } else {
- assert(0 && "read and write cannot both be false");
- }
-
- switch (size) {
- case 1:
- return rw;
- case 2:
- return (0x1 << 2) | rw;
- case 4:
- return (0x3 << 2) | rw;
- case 8:
- return (0x2 << 2) | rw;
- default:
- assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
- }
-}
-
-uint32_t
-RegisterContext_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size,
- bool read, bool write)
-{
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
- {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size,
- read, write,
- hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool
-RegisterContext_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
- bool read, bool write,
- uint32_t hw_index)
-{
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
-
- if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
- return false;
-
- if (!(size == 1 || size == 2 || size == 4 || size == 8))
- return false;
-
- if (read == false && write == false)
- return false;
-
- if (!IsWatchpointVacant(hw_index))
- return false;
-
- // Set both dr7 (debug control register) and dri (debug address register).
-
- // dr7{7-0} encodes the local/gloabl enable bits:
- // global enable --. .-- local enable
- // | |
- // v v
- // dr0 -> bits{1-0}
- // dr1 -> bits{3-2}
- // dr2 -> bits{5-4}
- // dr3 -> bits{7-6}
- //
- // dr7{31-16} encodes the rw/len bits:
- // b_x+3, b_x+2, b_x+1, b_x
- // where bits{x+1, x} => rw
- // 0b00: execute, 0b01: write, 0b11: read-or-write,
- // 0b10: io read-or-write (unused)
- // and bits{x+3, x+2} => len
- // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
- //
- // dr0 -> bits{19-16}
- // dr1 -> bits{23-20}
- // dr2 -> bits{27-24}
- // dr3 -> bits{31-28}
- if (hw_index < num_hw_watchpoints)
- {
- RegisterValue current_dr7_bits;
-
- if (ReadRegister(dr7, current_dr7_bits))
- {
- uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() |
- (1 << (2*hw_index) |
- size_and_rw_bits(size, read, write) <<
- (16+4*hw_index));
-
- if (WriteRegister(dr0 + hw_index, RegisterValue(addr)) &&
- WriteRegister(dr7, RegisterValue(new_dr7_bits)))
- return true;
- }
- }
-
- return false;
-}
-
-bool
-RegisterContext_x86_64::ClearHardwareWatchpoint(uint32_t hw_index)
-{
- if (hw_index < NumSupportedHardwareWatchpoints())
- {
- RegisterValue current_dr7_bits;
-
- if (ReadRegister(dr7, current_dr7_bits))
- {
- uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index));
-
- if (WriteRegister(dr7, RegisterValue(new_dr7_bits)))
- return true;
- }
- }
-
- return false;
-}
-
-bool
-RegisterContext_x86_64::IsWatchpointHit(uint32_t hw_index)
-{
- bool is_hit = false;
-
- if (m_watchpoints_initialized == false)
- {
- // Reset the debug status and debug control registers
- RegisterValue zero_bits = RegisterValue(uint64_t(0));
- if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits))
- assert(false && "Could not initialize watchpoint registers");
- m_watchpoints_initialized = true;
- }
-
- if (hw_index < NumSupportedHardwareWatchpoints())
- {
- RegisterValue value;
-
- if (ReadRegister(dr6, value))
- {
- uint64_t val = value.GetAsUInt64();
- is_hit = val & (1 << hw_index);
- }
- }
-
- return is_hit;
-}
-
-addr_t
-RegisterContext_x86_64::GetWatchpointAddress(uint32_t hw_index)
-{
- addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS;
-
- if (hw_index < NumSupportedHardwareWatchpoints())
- {
- if (!IsWatchpointVacant(hw_index))
- {
- RegisterValue value;
-
- if (ReadRegister(dr0 + hw_index, value))
- wp_monitor_addr = value.GetAsUInt64();
- }
- }
-
- return wp_monitor_addr;
-}
-
-
-bool
-RegisterContext_x86_64::ClearWatchpointHits()
-{
- return WriteRegister(dr6, RegisterValue((uint64_t)0));
-}
-
-bool
-RegisterContext_x86_64::HardwareSingleStep(bool enable)
-{
- enum { TRACE_BIT = 0x100 };
- uint64_t rflags;
-
- if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL)
- return false;
-
- if (enable)
- {
- if (rflags & TRACE_BIT)
- return true;
-
- rflags |= TRACE_BIT;
- }
- else
- {
- if (!(rflags & TRACE_BIT))
- return false;
-
- rflags &= ~TRACE_BIT;
- }
-
- return WriteRegisterFromUnsigned(gpr_rflags, rflags);
-}
-
-#if defined(__linux__) or defined(__FreeBSD__)
-
-ProcessMonitor &
-RegisterContext_x86_64::GetMonitor()
-{
- ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
- return process->GetMonitor();
-}
-
-bool
-RegisterContext_x86_64::ReadGPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr, GetGPRSize());
-}
-
-bool
-RegisterContext_x86_64::ReadFPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- if (m_fpr_type == eFXSAVE)
- return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
-
- if (m_fpr_type == eXSAVE)
- return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
- return false;
-}
-
-bool
-RegisterContext_x86_64::WriteGPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr, GetGPRSize());
-}
-
-bool
-RegisterContext_x86_64::WriteFPR()
-{
- ProcessMonitor &monitor = GetMonitor();
- if (m_fpr_type == eFXSAVE)
- return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
-
- if (m_fpr_type == eXSAVE)
- return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
- return false;
-}
-
-bool
-RegisterContext_x86_64::ReadRegister(const unsigned reg,
- RegisterValue &value)
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(),
- GetRegisterOffset(reg),
- GetRegisterName(reg),
- GetRegisterSize(reg),
- value);
-}
-
-bool
-RegisterContext_x86_64::WriteRegister(const unsigned reg,
- const RegisterValue &value)
-{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(m_thread.GetID(),
- GetRegisterOffset(reg),
- GetRegisterName(reg),
- value);
-}
-
-#else
-
-bool
-RegisterContext_x86_64::ReadGPR()
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-bool
-RegisterContext_x86_64::ReadFPR()
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-bool
-RegisterContext_x86_64::WriteGPR()
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-bool
-RegisterContext_x86_64::WriteFPR()
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-bool
-RegisterContext_x86_64::ReadRegister(const unsigned reg,
- RegisterValue &value)
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-bool
-RegisterContext_x86_64::WriteRegister(const unsigned reg,
- const RegisterValue &value)
-{
- llvm_unreachable("not implemented");
- return false;
-}
-
-#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86_64.h b/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
deleted file mode 100644
index 9d59bd78e547..000000000000
--- a/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
+++ /dev/null
@@ -1,347 +0,0 @@
-//===-- RegisterContext_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_RegisterContext_x86_64_H_
-#define liblldb_RegisterContext_x86_64_H_
-
-#include "lldb/Core/Log.h"
-#include "RegisterContextPOSIX.h"
-
-class ProcessMonitor;
-
-// Internal codes for all x86_64 registers.
-enum
-{
- k_first_gpr,
- gpr_rax = k_first_gpr,
- 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,
- gpr_ss,
- gpr_ds,
- gpr_es,
- k_first_i386,
- gpr_eax = k_first_i386,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_eip,
- gpr_eflags, // eRegisterKindLLDB == 33
- k_last_i386 = gpr_eflags,
- k_last_gpr = gpr_eflags,
-
- k_first_fpr,
- fpu_fcw = k_first_fpr,
- 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,
- k_last_fpr = fpu_xmm15,
- k_first_avx,
- fpu_ymm0 = k_first_avx,
- fpu_ymm1,
- fpu_ymm2,
- fpu_ymm3,
- fpu_ymm4,
- fpu_ymm5,
- fpu_ymm6,
- fpu_ymm7,
- fpu_ymm8,
- fpu_ymm9,
- fpu_ymm10,
- fpu_ymm11,
- fpu_ymm12,
- fpu_ymm13,
- fpu_ymm14,
- fpu_ymm15,
- k_last_avx = fpu_ymm15,
-
- dr0,
- dr1,
- dr2,
- dr3,
- dr4,
- dr5,
- dr6,
- dr7,
-
- k_num_registers,
- k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
- k_num_fpr_registers = k_last_fpr - k_first_fpr + 1,
- k_num_avx_registers = k_last_avx - k_first_avx + 1
-};
-
-class RegisterContext_x86_64
- : public RegisterContextPOSIX
-{
-public:
- RegisterContext_x86_64 (lldb_private::Thread &thread,
- uint32_t concrete_frame_idx);
-
- ~RegisterContext_x86_64();
-
- void
- Invalidate();
-
- void
- InvalidateAllRegisters();
-
- size_t
- GetRegisterCount();
-
- virtual size_t
- GetGPRSize() = 0;
-
- virtual unsigned
- GetRegisterSize(unsigned reg);
-
- virtual unsigned
- GetRegisterOffset(unsigned reg);
-
- const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
-
- size_t
- GetRegisterSetCount();
-
- const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
-
- unsigned
- GetRegisterIndexFromOffset(unsigned offset);
-
- const char *
- GetRegisterName(unsigned reg);
-
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value);
-
- bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
-
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value);
-
- bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
-
- uint32_t
- ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
-
- uint32_t
- NumSupportedHardwareWatchpoints();
-
- uint32_t
- SetHardwareWatchpoint(lldb::addr_t, size_t size, bool read, bool write);
-
- bool
- SetHardwareWatchpointWithIndex(lldb::addr_t, size_t size, bool read,
- bool write, uint32_t hw_index);
-
- bool
- ClearHardwareWatchpoint(uint32_t hw_index);
-
- bool
- HardwareSingleStep(bool enable);
-
- bool
- UpdateAfterBreakpoint();
-
- bool
- IsWatchpointVacant(uint32_t hw_index);
-
- bool
- IsWatchpointHit (uint32_t hw_index);
-
- lldb::addr_t
- GetWatchpointAddress (uint32_t hw_index);
-
- bool
- ClearWatchpointHits();
-
- //---------------------------------------------------------------------------
- // Generic floating-point registers
- //---------------------------------------------------------------------------
-
- struct MMSReg
- {
- uint8_t bytes[10];
- uint8_t pad[6];
- };
-
- struct XMMReg
- {
- uint8_t bytes[16]; // 128-bits for each XMM register
- };
-
- struct FXSAVE
- {
- uint16_t fcw;
- uint16_t fsw;
- uint16_t ftw;
- uint16_t fop;
- uint64_t ip;
- uint64_t dp;
- uint32_t mxcsr;
- uint32_t mxcsrmask;
- MMSReg stmm[8];
- XMMReg xmm[16];
- uint32_t padding[24];
- };
-
- //---------------------------------------------------------------------------
- // Extended floating-point registers
- //---------------------------------------------------------------------------
- struct YMMHReg
- {
- uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register
- };
-
- struct YMMReg
- {
- uint8_t bytes[32]; // 16 * 16 bits for each YMM register
- };
-
- struct YMM
- {
- YMMReg ymm[16]; // assembled from ymmh and xmm registers
- };
-
- struct XSAVE_HDR
- {
- uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states supported by the processor
- uint64_t reserved1[2];
- uint64_t reserved2[5];
- } __attribute__((packed));
-
- // x86 extensions to FXSAVE (i.e. for AVX processors)
- struct XSAVE
- {
- FXSAVE i387; // floating point registers typical in i387_fxsave_struct
- XSAVE_HDR header; // The xsave_hdr_struct can be used to determine if the following extensions are usable
- YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes are in FXSAVE.xmm for compatibility with SSE)
- // Slot any extensions to the register file here
- } __attribute__((packed, aligned (64)));
-
- struct IOVEC
- {
- void *iov_base; // pointer to XSAVE
- size_t iov_len; // sizeof(XSAVE)
- };
-
- //---------------------------------------------------------------------------
- // Note: prefer kernel definitions over user-land
- //---------------------------------------------------------------------------
- enum FPRType
- {
- eNotValid = 0,
- eFSAVE, // TODO
- eFXSAVE,
- eSOFT, // TODO
- eXSAVE
- };
-
- // Floating-point registers
- struct FPR
- {
- // Thread state for the floating-point unit of the processor read by ptrace.
- union XSTATE {
- FXSAVE fxsave; // Generic floating-point registers.
- XSAVE xsave; // x86 extended processor state.
- } xstate;
- };
-
-protected:
- // Determines if an extended register set is supported on the processor running the inferior process.
- virtual bool
- IsRegisterSetAvailable(size_t set_index);
-
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfo();
-
- virtual bool
- ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- virtual bool
- WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
-
-private:
- uint64_t m_gpr[k_num_gpr_registers]; // general purpose registers.
- FPRType m_fpr_type; // determines the type of data stored by union FPR, if any.
- FPR m_fpr; // floating-point registers including extended register sets.
- IOVEC m_iovec; // wrapper for xsave.
- YMM m_ymm_set; // copy of ymmh and xmm register halves.
-
- ProcessMonitor &GetMonitor();
- lldb::ByteOrder GetByteOrder();
-
- bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order);
- bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
- bool IsFPR(unsigned reg, FPRType fpr_type);
-
- bool ReadGPR();
- bool ReadFPR();
-
- bool WriteGPR();
- bool WriteFPR();
-};
-
-#endif // #ifndef liblldb_RegisterContext_x86_64_H_
diff --git a/source/Plugins/Process/POSIX/RegisterInfos_i386.h b/source/Plugins/Process/POSIX/RegisterInfos_i386.h
new file mode 100644
index 000000000000..7c516568cd62
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterInfos_i386.h
@@ -0,0 +1,207 @@
+//===-- RegisterInfos_i386.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "llvm/Support/Compiler.h"
+
+#ifdef DECLARE_REGISTER_INFOS_I386_STRUCT
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(GPR, regname))
+
+// Computes the offset of the given FPR in the extended data area.
+#define FPR_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(FPR, xstate) + \
+ LLVM_EXTENSION offsetof(FXSAVE, regname))
+
+// Computes the offset of the YMM register assembled from register halves.
+#define YMM_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(YMM, regname))
+
+// Number of bytes needed to represent a FPR.
+#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg)
+
+// Number of bytes needed to represent the i'th FP register.
+#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes)
+
+// Number of bytes needed to represent an XMM register.
+#define XMM_SIZE sizeof(XMMReg)
+
+// Number of bytes needed to represent a YMM register.
+#define YMM_SIZE sizeof(YMMReg)
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
+ { #reg, alt, sizeof(GPR::reg), GPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_i386 }, NULL, NULL }
+
+#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \
+ { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, fpu_##name##_i386 }, NULL, NULL }
+
+// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+
+#define DEFINE_FP_ST(reg, i) \
+ { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { gcc_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, gdb_st##i##_i386, fpu_st##i##_i386 }, \
+ NULL, NULL }
+
+#define DEFINE_FP_MM(reg, i) \
+ { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
+ eEncodingUint, eFormatHex, \
+ { gcc_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, gdb_mm##i##_i386, fpu_mm##i##_i386 }, \
+ NULL, NULL }
+
+#define DEFINE_XMM(reg, i) \
+ { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { gcc_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##_i386, fpu_##reg##i##_i386}, \
+ NULL, NULL }
+
+// I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then differentiate based on register size.
+#define DEFINE_YMM(reg, i) \
+ { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##h_i386, fpu_##reg##i##_i386 }, \
+ NULL, NULL }
+
+#define DEFINE_DR(reg, i) \
+ { #reg#i, NULL, DR_SIZE, DR_OFFSET(i), eEncodingUint, eFormatHex, \
+ { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+
+#define DEFINE_GPR_PSEUDO_16(reg16, reg32) \
+ { #reg16, NULL, 2, GPR_OFFSET(reg32), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg16##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 }
+#define DEFINE_GPR_PSEUDO_8H(reg8, reg32) \
+ { #reg8, NULL, 1, GPR_OFFSET(reg32)+1, eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 }
+#define DEFINE_GPR_PSEUDO_8L(reg8, reg32) \
+ { #reg8, NULL, 1, GPR_OFFSET(reg32), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 }
+
+static RegisterInfo
+g_register_infos_i386[] =
+{
+ // General purpose registers.
+ DEFINE_GPR(eax, NULL, gcc_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, gdb_eax_i386),
+ DEFINE_GPR(ebx, NULL, gcc_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, gdb_ebx_i386),
+ DEFINE_GPR(ecx, NULL, gcc_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, gdb_ecx_i386),
+ DEFINE_GPR(edx, NULL, gcc_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, gdb_edx_i386),
+ DEFINE_GPR(edi, NULL, gcc_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, gdb_edi_i386),
+ DEFINE_GPR(esi, NULL, gcc_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, gdb_esi_i386),
+ DEFINE_GPR(ebp, "fp", gcc_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, gdb_ebp_i386),
+ DEFINE_GPR(esp, "sp", gcc_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, gdb_esp_i386),
+ DEFINE_GPR(eip, "pc", gcc_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, gdb_eip_i386),
+ DEFINE_GPR(eflags, "flags", gcc_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags_i386),
+ DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, gdb_cs_i386),
+ DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, gdb_fs_i386),
+ DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, gdb_gs_i386),
+ DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, gdb_ss_i386),
+ DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, gdb_ds_i386),
+ DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, gdb_es_i386),
+
+ DEFINE_GPR_PSEUDO_16(ax, eax),
+ DEFINE_GPR_PSEUDO_16(bx, ebx),
+ DEFINE_GPR_PSEUDO_16(cx, ecx),
+ DEFINE_GPR_PSEUDO_16(dx, edx),
+ DEFINE_GPR_PSEUDO_16(di, edi),
+ DEFINE_GPR_PSEUDO_16(si, esi),
+ DEFINE_GPR_PSEUDO_16(bp, ebp),
+ DEFINE_GPR_PSEUDO_16(sp, esp),
+ DEFINE_GPR_PSEUDO_8H(ah, eax),
+ DEFINE_GPR_PSEUDO_8H(bh, ebx),
+ DEFINE_GPR_PSEUDO_8H(ch, ecx),
+ DEFINE_GPR_PSEUDO_8H(dh, edx),
+ DEFINE_GPR_PSEUDO_8L(al, eax),
+ DEFINE_GPR_PSEUDO_8L(bl, ebx),
+ DEFINE_GPR_PSEUDO_8L(cl, ecx),
+ DEFINE_GPR_PSEUDO_8L(dl, edx),
+
+ // i387 Floating point registers.
+ DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386, LLDB_INVALID_REGNUM, gdb_fctrl_i386),
+ DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386, LLDB_INVALID_REGNUM, gdb_fstat_i386),
+ DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_i386),
+ DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_i386),
+ DEFINE_FPR(fiseg, ptr.i386.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_i386),
+ DEFINE_FPR(fioff, ptr.i386.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_i386),
+ DEFINE_FPR(foseg, ptr.i386.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_i386),
+ DEFINE_FPR(fooff, ptr.i386.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_i386),
+ DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386, LLDB_INVALID_REGNUM, gdb_mxcsr_i386),
+ DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+
+ // FP registers.
+ DEFINE_FP_ST(st, 0),
+ DEFINE_FP_ST(st, 1),
+ DEFINE_FP_ST(st, 2),
+ DEFINE_FP_ST(st, 3),
+ DEFINE_FP_ST(st, 4),
+ DEFINE_FP_ST(st, 5),
+ DEFINE_FP_ST(st, 6),
+ DEFINE_FP_ST(st, 7),
+ DEFINE_FP_MM(mm, 0),
+ DEFINE_FP_MM(mm, 1),
+ DEFINE_FP_MM(mm, 2),
+ DEFINE_FP_MM(mm, 3),
+ DEFINE_FP_MM(mm, 4),
+ DEFINE_FP_MM(mm, 5),
+ DEFINE_FP_MM(mm, 6),
+ DEFINE_FP_MM(mm, 7),
+
+ // XMM registers
+ DEFINE_XMM(xmm, 0),
+ DEFINE_XMM(xmm, 1),
+ DEFINE_XMM(xmm, 2),
+ DEFINE_XMM(xmm, 3),
+ DEFINE_XMM(xmm, 4),
+ DEFINE_XMM(xmm, 5),
+ DEFINE_XMM(xmm, 6),
+ DEFINE_XMM(xmm, 7),
+
+ // Copy of YMM registers assembled from xmm and ymmh
+ DEFINE_YMM(ymm, 0),
+ DEFINE_YMM(ymm, 1),
+ DEFINE_YMM(ymm, 2),
+ DEFINE_YMM(ymm, 3),
+ DEFINE_YMM(ymm, 4),
+ DEFINE_YMM(ymm, 5),
+ DEFINE_YMM(ymm, 6),
+ DEFINE_YMM(ymm, 7),
+
+ // Debug registers for lldb internal use
+ DEFINE_DR(dr, 0),
+ DEFINE_DR(dr, 1),
+ DEFINE_DR(dr, 2),
+ DEFINE_DR(dr, 3),
+ DEFINE_DR(dr, 4),
+ DEFINE_DR(dr, 5),
+ DEFINE_DR(dr, 6),
+ DEFINE_DR(dr, 7)
+};
+static_assert((sizeof(g_register_infos_i386) / sizeof(g_register_infos_i386[0])) == k_num_registers_i386,
+ "g_register_infos_x86_64 has wrong number of register infos");
+
+#undef GPR_OFFSET
+#undef FPR_OFFSET
+#undef YMM_OFFSET
+#undef FPR_SIZE
+#undef FP_SIZE
+#undef XMM_SIZE
+#undef YMM_SIZE
+#undef DEFINE_GPR
+#undef DEFINE_FPR
+#undef DEFINE_FP
+#undef DEFINE_XMM
+#undef DEFINE_YMM
+#undef DEFINE_DR
+#undef DEFINE_GPR_PSEUDO_16
+#undef DEFINE_GPR_PSEUDO_8H
+#undef DEFINE_GPR_PSEUDO_8L
+
+#endif // DECLARE_REGISTER_INFOS_I386_STRUCT
diff --git a/source/Plugins/Process/POSIX/RegisterInfos_mips64.h b/source/Plugins/Process/POSIX/RegisterInfos_mips64.h
new file mode 100644
index 000000000000..13526e3680b7
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterInfos_mips64.h
@@ -0,0 +1,74 @@
+//===-- RegisterInfos_mips64.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+ (offsetof(GPR, regname))
+
+#ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
+ { #reg, alt, sizeof(GPR::reg), GPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL }
+
+static RegisterInfo
+g_register_infos_mips64[] =
+{
+ // General purpose registers. GCC, DWARF, Generic, GDB
+ DEFINE_GPR(zero, "r0", gcc_dwarf_zero_mips64, gcc_dwarf_zero_mips64, LLDB_INVALID_REGNUM, gdb_zero_mips64),
+ DEFINE_GPR(r1, NULL, gcc_dwarf_r1_mips64, gcc_dwarf_r1_mips64, LLDB_INVALID_REGNUM, gdb_r1_mips64),
+ DEFINE_GPR(r2, NULL, gcc_dwarf_r2_mips64, gcc_dwarf_r2_mips64, LLDB_INVALID_REGNUM, gdb_r2_mips64),
+ DEFINE_GPR(r3, NULL, gcc_dwarf_r3_mips64, gcc_dwarf_r3_mips64, LLDB_INVALID_REGNUM, gdb_r3_mips64),
+ DEFINE_GPR(r4, NULL, gcc_dwarf_r4_mips64, gcc_dwarf_r4_mips64, LLDB_INVALID_REGNUM, gdb_r4_mips64),
+ DEFINE_GPR(r5, NULL, gcc_dwarf_r5_mips64, gcc_dwarf_r5_mips64, LLDB_INVALID_REGNUM, gdb_r5_mips64),
+ DEFINE_GPR(r6, NULL, gcc_dwarf_r6_mips64, gcc_dwarf_r6_mips64, LLDB_INVALID_REGNUM, gdb_r6_mips64),
+ DEFINE_GPR(r7, NULL, gcc_dwarf_r7_mips64, gcc_dwarf_r7_mips64, LLDB_INVALID_REGNUM, gdb_r7_mips64),
+ DEFINE_GPR(r8, NULL, gcc_dwarf_r8_mips64, gcc_dwarf_r8_mips64, LLDB_INVALID_REGNUM, gdb_r8_mips64),
+ DEFINE_GPR(r9, NULL, gcc_dwarf_r9_mips64, gcc_dwarf_r9_mips64, LLDB_INVALID_REGNUM, gdb_r9_mips64),
+ DEFINE_GPR(r10, NULL, gcc_dwarf_r10_mips64, gcc_dwarf_r10_mips64, LLDB_INVALID_REGNUM, gdb_r10_mips64),
+ DEFINE_GPR(r11, NULL, gcc_dwarf_r11_mips64, gcc_dwarf_r11_mips64, LLDB_INVALID_REGNUM, gdb_r11_mips64),
+ DEFINE_GPR(r12, NULL, gcc_dwarf_r12_mips64, gcc_dwarf_r12_mips64, LLDB_INVALID_REGNUM, gdb_r12_mips64),
+ DEFINE_GPR(r13, NULL, gcc_dwarf_r13_mips64, gcc_dwarf_r13_mips64, LLDB_INVALID_REGNUM, gdb_r13_mips64),
+ DEFINE_GPR(r14, NULL, gcc_dwarf_r14_mips64, gcc_dwarf_r14_mips64, LLDB_INVALID_REGNUM, gdb_r14_mips64),
+ DEFINE_GPR(r15, NULL, gcc_dwarf_r15_mips64, gcc_dwarf_r15_mips64, LLDB_INVALID_REGNUM, gdb_r15_mips64),
+ DEFINE_GPR(r16, NULL, gcc_dwarf_r16_mips64, gcc_dwarf_r16_mips64, LLDB_INVALID_REGNUM, gdb_r16_mips64),
+ DEFINE_GPR(r17, NULL, gcc_dwarf_r17_mips64, gcc_dwarf_r17_mips64, LLDB_INVALID_REGNUM, gdb_r17_mips64),
+ DEFINE_GPR(r18, NULL, gcc_dwarf_r18_mips64, gcc_dwarf_r18_mips64, LLDB_INVALID_REGNUM, gdb_r18_mips64),
+ DEFINE_GPR(r19, NULL, gcc_dwarf_r19_mips64, gcc_dwarf_r19_mips64, LLDB_INVALID_REGNUM, gdb_r19_mips64),
+ DEFINE_GPR(r20, NULL, gcc_dwarf_r20_mips64, gcc_dwarf_r20_mips64, LLDB_INVALID_REGNUM, gdb_r20_mips64),
+ DEFINE_GPR(r21, NULL, gcc_dwarf_r21_mips64, gcc_dwarf_r21_mips64, LLDB_INVALID_REGNUM, gdb_r21_mips64),
+ DEFINE_GPR(r22, NULL, gcc_dwarf_r22_mips64, gcc_dwarf_r22_mips64, LLDB_INVALID_REGNUM, gdb_r22_mips64),
+ DEFINE_GPR(r23, NULL, gcc_dwarf_r23_mips64, gcc_dwarf_r23_mips64, LLDB_INVALID_REGNUM, gdb_r23_mips64),
+ DEFINE_GPR(r24, NULL, gcc_dwarf_r24_mips64, gcc_dwarf_r24_mips64, LLDB_INVALID_REGNUM, gdb_r24_mips64),
+ DEFINE_GPR(r25, NULL, gcc_dwarf_r25_mips64, gcc_dwarf_r25_mips64, LLDB_INVALID_REGNUM, gdb_r25_mips64),
+ DEFINE_GPR(r26, NULL, gcc_dwarf_r26_mips64, gcc_dwarf_r26_mips64, LLDB_INVALID_REGNUM, gdb_r26_mips64),
+ DEFINE_GPR(r27, NULL, gcc_dwarf_r27_mips64, gcc_dwarf_r27_mips64, LLDB_INVALID_REGNUM, gdb_r27_mips64),
+ DEFINE_GPR(gp, "r28", gcc_dwarf_gp_mips64, gcc_dwarf_gp_mips64, LLDB_INVALID_REGNUM, gdb_gp_mips64),
+ DEFINE_GPR(sp, "r29", gcc_dwarf_sp_mips64, gcc_dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, gdb_sp_mips64),
+ DEFINE_GPR(r30, NULL, gcc_dwarf_r30_mips64, gcc_dwarf_r30_mips64, LLDB_INVALID_REGNUM, gdb_r30_mips64),
+ DEFINE_GPR(ra, "r31", gcc_dwarf_ra_mips64, gcc_dwarf_ra_mips64, LLDB_INVALID_REGNUM, gdb_ra_mips64),
+ DEFINE_GPR(sr, NULL, gcc_dwarf_sr_mips64, gcc_dwarf_sr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mullo, NULL, gcc_dwarf_lo_mips64, gcc_dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mulhi, NULL, gcc_dwarf_hi_mips64, gcc_dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(badvaddr, NULL, gcc_dwarf_bad_mips64, gcc_dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cause, NULL, gcc_dwarf_cause_mips64, gcc_dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", gcc_dwarf_pc_mips64, gcc_dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ic, NULL, gcc_dwarf_ic_mips64, gcc_dwarf_ic_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(dummy, NULL, gcc_dwarf_dummy_mips64, gcc_dwarf_dummy_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+};
+static_assert((sizeof(g_register_infos_mips64) / sizeof(g_register_infos_mips64[0])) == k_num_registers_mips64,
+ "g_register_infos_mips64 has wrong number of register infos");
+
+#undef DEFINE_GPR
+
+#endif // DECLARE_REGISTER_INFOS_MIPS64_STRUCT
+
+#undef GPR_OFFSET
+
diff --git a/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h b/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h
new file mode 100644
index 000000000000..1bab88cd5727
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h
@@ -0,0 +1,409 @@
+//===-- RegisterInfos_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.
+//
+//===---------------------------------------------------------------------===//
+#include "llvm/Support/Compiler.h"
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(GPR, regname))
+
+// Computes the offset of the given FPR in the extended data area.
+#define FPR_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(FPR, xstate) + \
+ LLVM_EXTENSION offsetof(FXSAVE, regname))
+
+// Computes the offset of the YMM register assembled from register halves.
+#define YMM_OFFSET(regname) \
+ (LLVM_EXTENSION offsetof(YMM, regname))
+
+#ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT
+
+// Number of bytes needed to represent a FPR.
+#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg)
+
+// Number of bytes needed to represent the i'th FP register.
+#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes)
+
+// Number of bytes needed to represent an XMM register.
+#define XMM_SIZE sizeof(XMMReg)
+
+// Number of bytes needed to represent a YMM register.
+#define YMM_SIZE sizeof(YMMReg)
+
+// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
+ { #reg, alt, sizeof(GPR::reg), GPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_x86_64 }, NULL, NULL }
+
+#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \
+ { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, fpu_##name##_x86_64 }, NULL, NULL }
+
+#define DEFINE_FP_ST(reg, i) \
+ { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { gcc_dwarf_st##i##_x86_64, gcc_dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, fpu_st##i##_x86_64 }, \
+ NULL, NULL }
+
+#define DEFINE_FP_MM(reg, i) \
+ { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
+ eEncodingUint, eFormatHex, \
+ { gcc_dwarf_mm##i##_x86_64, gcc_dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, fpu_mm##i##_x86_64 }, \
+ NULL, NULL }
+
+#define DEFINE_XMM(reg, i) \
+ { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { gcc_dwarf_##reg##i##_x86_64, gcc_dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##_x86_64, fpu_##reg##i##_x86_64}, \
+ NULL, NULL }
+
+#define DEFINE_YMM(reg, i) \
+ { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]), \
+ eEncodingVector, eFormatVectorOfUInt8, \
+ { gcc_dwarf_##reg##i##h_x86_64, gcc_dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##h_x86_64, fpu_##reg##i##_x86_64 }, \
+ NULL, NULL }
+
+#define DEFINE_DR(reg, i) \
+ { #reg#i, NULL, DR_SIZE, DR_OFFSET(i), eEncodingUint, eFormatHex, \
+ { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+
+#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \
+ { #reg32, NULL, 4, GPR_OFFSET(reg64), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg32##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 }
+#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \
+ { #reg16, NULL, 2, GPR_OFFSET(reg64), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg16##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 }
+#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \
+ { #reg8, NULL, 1, GPR_OFFSET(reg64)+1, eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 }
+#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \
+ { #reg8, NULL, 1, GPR_OFFSET(reg64), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 }
+
+static RegisterInfo
+g_register_infos_x86_64[] =
+{
+ // General purpose registers. GCC, DWARF, Generic, GDB
+ DEFINE_GPR(rax, NULL, gcc_dwarf_rax_x86_64, gcc_dwarf_rax_x86_64, LLDB_INVALID_REGNUM, gdb_rax_x86_64),
+ DEFINE_GPR(rbx, NULL, gcc_dwarf_rbx_x86_64, gcc_dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, gdb_rbx_x86_64),
+ DEFINE_GPR(rcx, "arg4", gcc_dwarf_rcx_x86_64, gcc_dwarf_rcx_x86_64, LLDB_INVALID_REGNUM, gdb_rcx_x86_64),
+ DEFINE_GPR(rdx, "arg3", gcc_dwarf_rdx_x86_64, gcc_dwarf_rdx_x86_64, LLDB_INVALID_REGNUM, gdb_rdx_x86_64),
+ DEFINE_GPR(rdi, "arg1", gcc_dwarf_rdi_x86_64, gcc_dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, gdb_rdi_x86_64),
+ DEFINE_GPR(rsi, "arg2", gcc_dwarf_rsi_x86_64, gcc_dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, gdb_rsi_x86_64),
+ DEFINE_GPR(rbp, "fp", gcc_dwarf_rbp_x86_64, gcc_dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, gdb_rbp_x86_64),
+ DEFINE_GPR(rsp, "sp", gcc_dwarf_rsp_x86_64, gcc_dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, gdb_rsp_x86_64),
+ DEFINE_GPR(r8, "arg5", gcc_dwarf_r8_x86_64, gcc_dwarf_r8_x86_64, LLDB_INVALID_REGNUM, gdb_r8_x86_64),
+ DEFINE_GPR(r9, "arg6", gcc_dwarf_r9_x86_64, gcc_dwarf_r9_x86_64, LLDB_INVALID_REGNUM, gdb_r9_x86_64),
+ DEFINE_GPR(r10, NULL, gcc_dwarf_r10_x86_64, gcc_dwarf_r10_x86_64, LLDB_INVALID_REGNUM, gdb_r10_x86_64),
+ DEFINE_GPR(r11, NULL, gcc_dwarf_r11_x86_64, gcc_dwarf_r11_x86_64, LLDB_INVALID_REGNUM, gdb_r11_x86_64),
+ DEFINE_GPR(r12, NULL, gcc_dwarf_r12_x86_64, gcc_dwarf_r12_x86_64, LLDB_INVALID_REGNUM, gdb_r12_x86_64),
+ DEFINE_GPR(r13, NULL, gcc_dwarf_r13_x86_64, gcc_dwarf_r13_x86_64, LLDB_INVALID_REGNUM, gdb_r13_x86_64),
+ DEFINE_GPR(r14, NULL, gcc_dwarf_r14_x86_64, gcc_dwarf_r14_x86_64, LLDB_INVALID_REGNUM, gdb_r14_x86_64),
+ DEFINE_GPR(r15, NULL, gcc_dwarf_r15_x86_64, gcc_dwarf_r15_x86_64, LLDB_INVALID_REGNUM, gdb_r15_x86_64),
+ DEFINE_GPR(rip, "pc", gcc_dwarf_rip_x86_64, gcc_dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, gdb_rip_x86_64),
+ DEFINE_GPR(rflags, "flags", gcc_dwarf_rflags_x86_64, gcc_dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, gdb_rflags_x86_64),
+ DEFINE_GPR(cs, NULL, gcc_dwarf_cs_x86_64, gcc_dwarf_cs_x86_64, LLDB_INVALID_REGNUM, gdb_cs_x86_64),
+ DEFINE_GPR(fs, NULL, gcc_dwarf_fs_x86_64, gcc_dwarf_fs_x86_64, LLDB_INVALID_REGNUM, gdb_fs_x86_64),
+ DEFINE_GPR(gs, NULL, gcc_dwarf_gs_x86_64, gcc_dwarf_gs_x86_64, LLDB_INVALID_REGNUM, gdb_gs_x86_64),
+ DEFINE_GPR(ss, NULL, gcc_dwarf_ss_x86_64, gcc_dwarf_ss_x86_64, LLDB_INVALID_REGNUM, gdb_ss_x86_64),
+ DEFINE_GPR(ds, NULL, gcc_dwarf_ds_x86_64, gcc_dwarf_ds_x86_64, LLDB_INVALID_REGNUM, gdb_ds_x86_64),
+ DEFINE_GPR(es, NULL, gcc_dwarf_es_x86_64, gcc_dwarf_es_x86_64, LLDB_INVALID_REGNUM, gdb_es_x86_64),
+
+ DEFINE_GPR_PSEUDO_32(eax, rax),
+ DEFINE_GPR_PSEUDO_32(ebx, rbx),
+ DEFINE_GPR_PSEUDO_32(ecx, rcx),
+ DEFINE_GPR_PSEUDO_32(edx, rdx),
+ DEFINE_GPR_PSEUDO_32(edi, rdi),
+ DEFINE_GPR_PSEUDO_32(esi, rsi),
+ DEFINE_GPR_PSEUDO_32(ebp, rbp),
+ DEFINE_GPR_PSEUDO_32(esp, rsp),
+ DEFINE_GPR_PSEUDO_32(r8d, r8),
+ DEFINE_GPR_PSEUDO_32(r9d, r9),
+ DEFINE_GPR_PSEUDO_32(r10d, r10),
+ DEFINE_GPR_PSEUDO_32(r11d, r11),
+ DEFINE_GPR_PSEUDO_32(r12d, r12),
+ DEFINE_GPR_PSEUDO_32(r13d, r13),
+ DEFINE_GPR_PSEUDO_32(r14d, r14),
+ DEFINE_GPR_PSEUDO_32(r15d, r15),
+ DEFINE_GPR_PSEUDO_16(ax, rax),
+ DEFINE_GPR_PSEUDO_16(bx, rbx),
+ DEFINE_GPR_PSEUDO_16(cx, rcx),
+ DEFINE_GPR_PSEUDO_16(dx, rdx),
+ DEFINE_GPR_PSEUDO_16(di, rdi),
+ DEFINE_GPR_PSEUDO_16(si, rsi),
+ DEFINE_GPR_PSEUDO_16(bp, rbp),
+ DEFINE_GPR_PSEUDO_16(sp, rsp),
+ DEFINE_GPR_PSEUDO_16(r8w, r8),
+ DEFINE_GPR_PSEUDO_16(r9w, r9),
+ DEFINE_GPR_PSEUDO_16(r10w, r10),
+ DEFINE_GPR_PSEUDO_16(r11w, r11),
+ DEFINE_GPR_PSEUDO_16(r12w, r12),
+ DEFINE_GPR_PSEUDO_16(r13w, r13),
+ DEFINE_GPR_PSEUDO_16(r14w, r14),
+ DEFINE_GPR_PSEUDO_16(r15w, r15),
+ DEFINE_GPR_PSEUDO_8H(ah, rax),
+ DEFINE_GPR_PSEUDO_8H(bh, rbx),
+ DEFINE_GPR_PSEUDO_8H(ch, rcx),
+ DEFINE_GPR_PSEUDO_8H(dh, rdx),
+ DEFINE_GPR_PSEUDO_8L(al, rax),
+ DEFINE_GPR_PSEUDO_8L(bl, rbx),
+ DEFINE_GPR_PSEUDO_8L(cl, rcx),
+ DEFINE_GPR_PSEUDO_8L(dl, rdx),
+ DEFINE_GPR_PSEUDO_8L(dil, rdi),
+ DEFINE_GPR_PSEUDO_8L(sil, rsi),
+ DEFINE_GPR_PSEUDO_8L(bpl, rbp),
+ DEFINE_GPR_PSEUDO_8L(spl, rsp),
+ DEFINE_GPR_PSEUDO_8L(r8l, r8),
+ DEFINE_GPR_PSEUDO_8L(r9l, r9),
+ DEFINE_GPR_PSEUDO_8L(r10l, r10),
+ DEFINE_GPR_PSEUDO_8L(r11l, r11),
+ DEFINE_GPR_PSEUDO_8L(r12l, r12),
+ DEFINE_GPR_PSEUDO_8L(r13l, r13),
+ DEFINE_GPR_PSEUDO_8L(r14l, r14),
+ DEFINE_GPR_PSEUDO_8L(r15l, r15),
+
+ // i387 Floating point registers. GCC, DWARF, Generic, GDB
+ DEFINE_FPR(fctrl, fctrl, gcc_dwarf_fctrl_x86_64, gcc_dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, gdb_fctrl_x86_64),
+ DEFINE_FPR(fstat, fstat, gcc_dwarf_fstat_x86_64, gcc_dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, gdb_fstat_x86_64),
+ DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_x86_64),
+ DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_x86_64),
+ DEFINE_FPR(fiseg, ptr.i386.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_x86_64),
+ DEFINE_FPR(fioff, ptr.i386.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_x86_64),
+ DEFINE_FPR(foseg, ptr.i386.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_x86_64),
+ DEFINE_FPR(fooff, ptr.i386.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_x86_64),
+ DEFINE_FPR(mxcsr, mxcsr, gcc_dwarf_mxcsr_x86_64, gcc_dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, gdb_mxcsr_x86_64),
+ DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+
+ // FP registers.
+ DEFINE_FP_ST(st, 0),
+ DEFINE_FP_ST(st, 1),
+ DEFINE_FP_ST(st, 2),
+ DEFINE_FP_ST(st, 3),
+ DEFINE_FP_ST(st, 4),
+ DEFINE_FP_ST(st, 5),
+ DEFINE_FP_ST(st, 6),
+ DEFINE_FP_ST(st, 7),
+ DEFINE_FP_MM(mm, 0),
+ DEFINE_FP_MM(mm, 1),
+ DEFINE_FP_MM(mm, 2),
+ DEFINE_FP_MM(mm, 3),
+ DEFINE_FP_MM(mm, 4),
+ DEFINE_FP_MM(mm, 5),
+ DEFINE_FP_MM(mm, 6),
+ DEFINE_FP_MM(mm, 7),
+
+ // XMM registers
+ DEFINE_XMM(xmm, 0),
+ DEFINE_XMM(xmm, 1),
+ DEFINE_XMM(xmm, 2),
+ DEFINE_XMM(xmm, 3),
+ DEFINE_XMM(xmm, 4),
+ DEFINE_XMM(xmm, 5),
+ DEFINE_XMM(xmm, 6),
+ DEFINE_XMM(xmm, 7),
+ DEFINE_XMM(xmm, 8),
+ DEFINE_XMM(xmm, 9),
+ DEFINE_XMM(xmm, 10),
+ DEFINE_XMM(xmm, 11),
+ DEFINE_XMM(xmm, 12),
+ DEFINE_XMM(xmm, 13),
+ DEFINE_XMM(xmm, 14),
+ DEFINE_XMM(xmm, 15),
+
+ // Copy of YMM registers assembled from xmm and ymmh
+ DEFINE_YMM(ymm, 0),
+ DEFINE_YMM(ymm, 1),
+ DEFINE_YMM(ymm, 2),
+ DEFINE_YMM(ymm, 3),
+ DEFINE_YMM(ymm, 4),
+ DEFINE_YMM(ymm, 5),
+ DEFINE_YMM(ymm, 6),
+ DEFINE_YMM(ymm, 7),
+ DEFINE_YMM(ymm, 8),
+ DEFINE_YMM(ymm, 9),
+ DEFINE_YMM(ymm, 10),
+ DEFINE_YMM(ymm, 11),
+ DEFINE_YMM(ymm, 12),
+ DEFINE_YMM(ymm, 13),
+ DEFINE_YMM(ymm, 14),
+ DEFINE_YMM(ymm, 15),
+
+ // Debug registers for lldb internal use
+ DEFINE_DR(dr, 0),
+ DEFINE_DR(dr, 1),
+ DEFINE_DR(dr, 2),
+ DEFINE_DR(dr, 3),
+ DEFINE_DR(dr, 4),
+ DEFINE_DR(dr, 5),
+ DEFINE_DR(dr, 6),
+ DEFINE_DR(dr, 7)
+};
+static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[0])) == k_num_registers_x86_64,
+ "g_register_infos_x86_64 has wrong number of register infos");
+
+#undef FPR_SIZE
+#undef FP_SIZE
+#undef XMM_SIZE
+#undef YMM_SIZE
+#undef DEFINE_GPR
+#undef DEFINE_FPR
+#undef DEFINE_FP
+#undef DEFINE_XMM
+#undef DEFINE_YMM
+#undef DEFINE_DR
+#undef DEFINE_GPR_PSEUDO_32
+#undef DEFINE_GPR_PSEUDO_16
+#undef DEFINE_GPR_PSEUDO_8H
+#undef DEFINE_GPR_PSEUDO_8L
+
+#endif // DECLARE_REGISTER_INFOS_X86_64_STRUCT
+
+
+#ifdef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+
+#define UPDATE_GPR_INFO(reg, reg64) \
+do { \
+ g_register_infos[gpr_##reg##_i386].byte_offset = GPR_OFFSET(reg64); \
+} while(false);
+
+#define UPDATE_GPR_INFO_8H(reg, reg64) \
+do { \
+ g_register_infos[gpr_##reg##_i386].byte_offset = GPR_OFFSET(reg64) + 1; \
+} while(false);
+
+#define UPDATE_FPR_INFO(reg, reg64) \
+do { \
+ g_register_infos[fpu_##reg##_i386].byte_offset = FPR_OFFSET(reg64); \
+} while(false);
+
+#define UPDATE_FP_INFO(reg, i) \
+do { \
+ g_register_infos[fpu_##reg##i##_i386].byte_offset = FPR_OFFSET(stmm[i]); \
+} while(false);
+
+#define UPDATE_XMM_INFO(reg, i) \
+do { \
+ g_register_infos[fpu_##reg##i##_i386].byte_offset = FPR_OFFSET(reg[i]); \
+} while(false);
+
+#define UPDATE_YMM_INFO(reg, i) \
+do { \
+ g_register_infos[fpu_##reg##i##_i386].byte_offset = YMM_OFFSET(reg[i]); \
+} while(false);
+
+#define UPDATE_DR_INFO(reg_index) \
+do { \
+ g_register_infos[dr##reg_index##_i386].byte_offset = DR_OFFSET(reg_index); \
+} while(false);
+
+ // Update the register offsets
+ UPDATE_GPR_INFO(eax, rax);
+ UPDATE_GPR_INFO(ebx, rbx);
+ UPDATE_GPR_INFO(ecx, rcx);
+ UPDATE_GPR_INFO(edx, rdx);
+ UPDATE_GPR_INFO(edi, rdi);
+ UPDATE_GPR_INFO(esi, rsi);
+ UPDATE_GPR_INFO(ebp, rbp);
+ UPDATE_GPR_INFO(esp, rsp);
+ UPDATE_GPR_INFO(eip, rip);
+ UPDATE_GPR_INFO(eflags, rflags);
+ UPDATE_GPR_INFO(cs, cs);
+ UPDATE_GPR_INFO(fs, fs);
+ UPDATE_GPR_INFO(gs, gs);
+ UPDATE_GPR_INFO(ss, ss);
+ UPDATE_GPR_INFO(ds, ds);
+ UPDATE_GPR_INFO(es, es);
+
+ UPDATE_GPR_INFO(ax, rax);
+ UPDATE_GPR_INFO(bx, rbx);
+ UPDATE_GPR_INFO(cx, rcx);
+ UPDATE_GPR_INFO(dx, rdx);
+ UPDATE_GPR_INFO(di, rdi);
+ UPDATE_GPR_INFO(si, rsi);
+ UPDATE_GPR_INFO(bp, rbp);
+ UPDATE_GPR_INFO(sp, rsp);
+ UPDATE_GPR_INFO_8H(ah, rax);
+ UPDATE_GPR_INFO_8H(bh, rbx);
+ UPDATE_GPR_INFO_8H(ch, rcx);
+ UPDATE_GPR_INFO_8H(dh, rdx);
+ UPDATE_GPR_INFO(al, rax);
+ UPDATE_GPR_INFO(bl, rbx);
+ UPDATE_GPR_INFO(cl, rcx);
+ UPDATE_GPR_INFO(dl, rdx);
+
+ UPDATE_FPR_INFO(fctrl, fctrl);
+ UPDATE_FPR_INFO(fstat, fstat);
+ UPDATE_FPR_INFO(ftag, ftag);
+ UPDATE_FPR_INFO(fop, fop);
+ UPDATE_FPR_INFO(fiseg, ptr.i386.fiseg);
+ UPDATE_FPR_INFO(fioff, ptr.i386.fioff);
+ UPDATE_FPR_INFO(fooff, ptr.i386.fooff);
+ UPDATE_FPR_INFO(foseg, ptr.i386.foseg);
+ UPDATE_FPR_INFO(mxcsr, mxcsr);
+ UPDATE_FPR_INFO(mxcsrmask, mxcsrmask);
+
+ UPDATE_FP_INFO(st, 0);
+ UPDATE_FP_INFO(st, 1);
+ UPDATE_FP_INFO(st, 2);
+ UPDATE_FP_INFO(st, 3);
+ UPDATE_FP_INFO(st, 4);
+ UPDATE_FP_INFO(st, 5);
+ UPDATE_FP_INFO(st, 6);
+ UPDATE_FP_INFO(st, 7);
+ UPDATE_FP_INFO(mm, 0);
+ UPDATE_FP_INFO(mm, 1);
+ UPDATE_FP_INFO(mm, 2);
+ UPDATE_FP_INFO(mm, 3);
+ UPDATE_FP_INFO(mm, 4);
+ UPDATE_FP_INFO(mm, 5);
+ UPDATE_FP_INFO(mm, 6);
+ UPDATE_FP_INFO(mm, 7);
+
+ UPDATE_XMM_INFO(xmm, 0);
+ UPDATE_XMM_INFO(xmm, 1);
+ UPDATE_XMM_INFO(xmm, 2);
+ UPDATE_XMM_INFO(xmm, 3);
+ UPDATE_XMM_INFO(xmm, 4);
+ UPDATE_XMM_INFO(xmm, 5);
+ UPDATE_XMM_INFO(xmm, 6);
+ UPDATE_XMM_INFO(xmm, 7);
+
+ UPDATE_YMM_INFO(ymm, 0);
+ UPDATE_YMM_INFO(ymm, 1);
+ UPDATE_YMM_INFO(ymm, 2);
+ UPDATE_YMM_INFO(ymm, 3);
+ UPDATE_YMM_INFO(ymm, 4);
+ UPDATE_YMM_INFO(ymm, 5);
+ UPDATE_YMM_INFO(ymm, 6);
+ UPDATE_YMM_INFO(ymm, 7);
+
+ UPDATE_DR_INFO(0);
+ UPDATE_DR_INFO(1);
+ UPDATE_DR_INFO(2);
+ UPDATE_DR_INFO(3);
+ UPDATE_DR_INFO(4);
+ UPDATE_DR_INFO(5);
+ UPDATE_DR_INFO(6);
+ UPDATE_DR_INFO(7);
+
+#undef UPDATE_GPR_INFO
+#undef UPDATE_GPR_INFO_8H
+#undef UPDATE_FPR_INFO
+#undef UPDATE_FP_INFO
+#undef UPDATE_XMM_INFO
+#undef UPDATE_YMM_INFO
+#undef UPDATE_DR_INFO
+
+#endif // UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+
+#undef GPR_OFFSET
+#undef FPR_OFFSET
+#undef YMM_OFFSET
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 0c95d66cef94..dc90b7ae02c3 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -16,6 +16,9 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/DataFormatters/FormatManager.h"
#ifndef LLDB_DISABLE_PYTHON
#include "lldb/Interpreter/PythonDataObjects.h"
@@ -29,18 +32,24 @@ DynamicRegisterInfo::DynamicRegisterInfo () :
m_sets (),
m_set_reg_nums (),
m_set_names (),
- m_reg_data_byte_size (0)
+ m_value_regs_map (),
+ m_invalidate_regs_map (),
+ m_reg_data_byte_size (0),
+ m_finalized (false)
{
}
-DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict) :
+DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict, ByteOrder byte_order) :
m_regs (),
m_sets (),
m_set_reg_nums (),
m_set_names (),
- m_reg_data_byte_size (0)
+ m_value_regs_map (),
+ m_invalidate_regs_map (),
+ m_reg_data_byte_size (0),
+ m_finalized (false)
{
- SetRegisterInfo (dict);
+ SetRegisterInfo (dict, byte_order);
}
DynamicRegisterInfo::~DynamicRegisterInfo ()
@@ -49,8 +58,10 @@ DynamicRegisterInfo::~DynamicRegisterInfo ()
size_t
-DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict)
+DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict,
+ ByteOrder byte_order)
{
+ assert(!m_finalized);
#ifndef LLDB_DISABLE_PYTHON
PythonList sets (dict.GetItemForKey("sets"));
if (sets)
@@ -89,6 +100,12 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
PythonString gcc_pystr("gcc");
PythonString dwarf_pystr("dwarf");
PythonString generic_pystr("generic");
+ PythonString slice_pystr("slice");
+ PythonString composite_pystr("composite");
+ PythonString invalidate_regs_pystr("invalidate-regs");
+
+// typedef std::map<std::string, std::vector<std::string> > InvalidateNameMap;
+// InvalidateNameMap invalidate_map;
for (uint32_t i=0; i<num_regs; ++i)
{
PythonDictionary reg_info_dict(regs.GetItemAtIndex(i));
@@ -96,6 +113,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
{
// { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
RegisterInfo reg_info;
+ std::vector<uint32_t> value_regs;
+ std::vector<uint32_t> invalidate_regs;
bzero (&reg_info, sizeof(reg_info));
reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
@@ -111,16 +130,177 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
if (reg_info.byte_offset == UINT32_MAX)
{
- Clear();
- return 0;
+ // No offset for this register, see if the register has a value expression
+ // which indicates this register is part of another register. Value expressions
+ // are things like "rax[31:0]" which state that the current register's value
+ // is in a concrete register "rax" in bits 31:0. If there is a value expression
+ // we can calculate the offset
+ bool success = false;
+ const char *slice_cstr = reg_info_dict.GetItemForKeyAsString(slice_pystr);
+ if (slice_cstr)
+ {
+ // Slices use the following format:
+ // REGNAME[MSBIT:LSBIT]
+ // REGNAME - name of the register to grab a slice of
+ // MSBIT - the most significant bit at which the current register value starts at
+ // LSBIT - the least significant bit at which the current register value ends at
+ static RegularExpression g_bitfield_regex("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]");
+ RegularExpression::Match regex_match(3);
+ if (g_bitfield_regex.Execute(slice_cstr, &regex_match))
+ {
+ llvm::StringRef reg_name_str;
+ std::string msbit_str;
+ std::string lsbit_str;
+ if (regex_match.GetMatchAtIndex(slice_cstr, 1, reg_name_str) &&
+ regex_match.GetMatchAtIndex(slice_cstr, 2, msbit_str) &&
+ regex_match.GetMatchAtIndex(slice_cstr, 3, lsbit_str))
+ {
+ const uint32_t msbit = Args::StringToUInt32(msbit_str.c_str(), UINT32_MAX);
+ const uint32_t lsbit = Args::StringToUInt32(lsbit_str.c_str(), UINT32_MAX);
+ if (msbit != UINT32_MAX && lsbit != UINT32_MAX)
+ {
+ if (msbit > lsbit)
+ {
+ const uint32_t msbyte = msbit / 8;
+ const uint32_t lsbyte = lsbit / 8;
+
+ ConstString containing_reg_name(reg_name_str);
+
+ RegisterInfo *containing_reg_info = GetRegisterInfo (containing_reg_name);
+ if (containing_reg_info)
+ {
+ const uint32_t max_bit = containing_reg_info->byte_size * 8;
+ if (msbit < max_bit && lsbit < max_bit)
+ {
+ m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]].push_back(i);
+ m_value_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]);
+ m_invalidate_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]);
+
+ if (byte_order == eByteOrderLittle)
+ {
+ success = true;
+ reg_info.byte_offset = containing_reg_info->byte_offset + lsbyte;
+ }
+ else if (byte_order == eByteOrderBig)
+ {
+ success = true;
+ reg_info.byte_offset = containing_reg_info->byte_offset + msbyte;
+ }
+ else
+ {
+ assert(!"Invalid byte order");
+ }
+ }
+ else
+ {
+ if (msbit > max_bit)
+ printf("error: msbit (%u) must be less than the bitsize of the register (%u)\n", msbit, max_bit);
+ else
+ printf("error: lsbit (%u) must be less than the bitsize of the register (%u)\n", lsbit, max_bit);
+ }
+ }
+ else
+ {
+ printf("error: invalid concrete register \"%s\"\n", containing_reg_name.GetCString());
+ }
+ }
+ else
+ {
+ printf("error: msbit (%u) must be greater than lsbit (%u)\n", msbit, lsbit);
+ }
+ }
+ else
+ {
+ printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, lsbit);
+ }
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to extract regex matches for parsing the register bitfield regex\n");
+
+ }
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to match against register bitfield regex\n");
+ }
+ }
+ else
+ {
+ PythonList composite_reg_list (reg_info_dict.GetItemForKey(composite_pystr));
+ if (composite_reg_list)
+ {
+ const size_t num_composite_regs = composite_reg_list.GetSize();
+ if (num_composite_regs > 0)
+ {
+ uint32_t composite_offset = UINT32_MAX;
+ for (uint32_t composite_idx=0; composite_idx<num_composite_regs; ++composite_idx)
+ {
+ PythonString composite_reg_name_pystr(composite_reg_list.GetItemAtIndex(composite_idx));
+ if (composite_reg_name_pystr)
+ {
+ ConstString composite_reg_name(composite_reg_name_pystr.GetString());
+ if (composite_reg_name)
+ {
+ RegisterInfo *composite_reg_info = GetRegisterInfo (composite_reg_name);
+ if (composite_reg_info)
+ {
+ if (composite_offset > composite_reg_info->byte_offset)
+ composite_offset = composite_reg_info->byte_offset;
+ m_value_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]);
+ m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]].push_back(i);
+ m_invalidate_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]);
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to find composite register by name: \"%s\"\n", composite_reg_name.GetCString());
+ }
+ }
+ else
+ {
+ printf("error: 'composite' key contained an empty string\n");
+ }
+ }
+ else
+ {
+ printf("error: 'composite' list value wasn't a python string\n");
+ }
+ }
+ if (composite_offset != UINT32_MAX)
+ {
+ reg_info.byte_offset = composite_offset;
+ success = m_value_regs_map.find(i) != m_value_regs_map.end();
+ }
+ else
+ {
+ printf("error: 'composite' registers must specify at least one real register\n");
+ }
+ }
+ else
+ {
+ printf("error: 'composite' list was empty\n");
+ }
+ }
+ }
+
+
+ if (!success)
+ {
+ Clear();
+ return 0;
+ }
}
- reg_info.byte_size = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0) / 8;
-
- if (reg_info.byte_size == 0)
+ const int64_t bitsize = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0);
+ if (bitsize == 0)
{
Clear();
return 0;
}
+
+ reg_info.byte_size = bitsize / 8;
const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr);
if (format_cstr)
@@ -132,13 +312,15 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
}
}
else
- reg_info.format = eFormatHex;
-
+ {
+ reg_info.format = (Format)reg_info_dict.GetItemForKeyAsInteger (format_pystr, eFormatHex);
+ }
+
const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr);
if (encoding_cstr)
reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint);
else
- reg_info.encoding = eEncodingUint;
+ reg_info.encoding = (Encoding)reg_info_dict.GetItemForKeyAsInteger (encoding_pystr, eEncodingUint);
const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1);
if (set >= m_sets.size())
@@ -147,11 +329,75 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
return 0;
}
+ // Fill in the register numbers
reg_info.kinds[lldb::eRegisterKindLLDB] = i;
reg_info.kinds[lldb::eRegisterKindGDB] = i;
reg_info.kinds[lldb::eRegisterKindGCC] = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr, LLDB_INVALID_REGNUM);
reg_info.kinds[lldb::eRegisterKindDWARF] = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr, LLDB_INVALID_REGNUM);
- reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (reg_info_dict.GetItemForKeyAsString(generic_pystr));
+ const char *generic_cstr = reg_info_dict.GetItemForKeyAsString(generic_pystr);
+ if (generic_cstr)
+ reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (generic_cstr);
+ else
+ reg_info.kinds[lldb::eRegisterKindGeneric] = reg_info_dict.GetItemForKeyAsInteger(generic_pystr, LLDB_INVALID_REGNUM);
+
+ // Check if this register invalidates any other register values when it is modified
+ PythonList invalidate_reg_list (reg_info_dict.GetItemForKey(invalidate_regs_pystr));
+ if (invalidate_reg_list)
+ {
+ const size_t num_regs = invalidate_reg_list.GetSize();
+ if (num_regs > 0)
+ {
+ for (uint32_t idx=0; idx<num_regs; ++idx)
+ {
+ PythonObject invalidate_reg_object (invalidate_reg_list.GetItemAtIndex(idx));
+ PythonString invalidate_reg_name_pystr(invalidate_reg_object);
+ if (invalidate_reg_name_pystr)
+ {
+ ConstString invalidate_reg_name(invalidate_reg_name_pystr.GetString());
+ if (invalidate_reg_name)
+ {
+ RegisterInfo *invalidate_reg_info = GetRegisterInfo (invalidate_reg_name);
+ if (invalidate_reg_info)
+ {
+ m_invalidate_regs_map[i].push_back(invalidate_reg_info->kinds[eRegisterKindLLDB]);
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to find a 'invalidate-regs' register for \"%s\" while parsing register \"%s\"\n", invalidate_reg_name.GetCString(), reg_info.name);
+ }
+ }
+ else
+ {
+ printf("error: 'invalidate-regs' list value was an empty string\n");
+ }
+ }
+ else
+ {
+ PythonInteger invalidate_reg_num(invalidate_reg_object);
+
+ if (invalidate_reg_num)
+ {
+ const int64_t r = invalidate_reg_num.GetInteger();
+ if (r != UINT64_MAX)
+ m_invalidate_regs_map[i].push_back(r);
+ else
+ printf("error: 'invalidate-regs' list value wasn't a valid integer\n");
+ }
+ else
+ {
+ printf("error: 'invalidate-regs' list value wasn't a python string or integer\n");
+ }
+ }
+ }
+ }
+ else
+ {
+ printf("error: 'invalidate-regs' contained an empty list\n");
+ }
+ }
+
+ // Calculate the register offset
const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
if (m_reg_data_byte_size < end_reg_offset)
m_reg_data_byte_size = end_reg_offset;
@@ -169,7 +415,7 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
Finalize ();
}
#endif
- return 0;
+ return m_regs.size();
}
@@ -179,10 +425,22 @@ DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
ConstString &reg_alt_name,
ConstString &set_name)
{
+ assert(!m_finalized);
const uint32_t reg_num = m_regs.size();
reg_info.name = reg_name.AsCString();
assert (reg_info.name);
reg_info.alt_name = reg_alt_name.AsCString(NULL);
+ uint32_t i;
+ if (reg_info.value_regs)
+ {
+ for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i)
+ m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]);
+ }
+ if (reg_info.invalidate_regs)
+ {
+ for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i)
+ m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]);
+ }
m_regs.push_back (reg_info);
uint32_t set = GetRegisterSetIndexByName (set_name, true);
assert (set < m_sets.size());
@@ -197,12 +455,99 @@ DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
void
DynamicRegisterInfo::Finalize ()
{
- for (uint32_t set = 0; set < m_sets.size(); ++set)
+ if (m_finalized)
+ return;
+
+ m_finalized = true;
+ const size_t num_sets = m_sets.size();
+ for (size_t set = 0; set < num_sets; ++set)
{
assert (m_sets.size() == m_set_reg_nums.size());
m_sets[set].num_registers = m_set_reg_nums[set].size();
m_sets[set].registers = &m_set_reg_nums[set][0];
}
+
+ // sort and unique all value registers and make sure each is terminated with
+ // LLDB_INVALID_REGNUM
+
+ for (reg_to_regs_map::iterator pos = m_value_regs_map.begin(), end = m_value_regs_map.end();
+ pos != end;
+ ++pos)
+ {
+ if (pos->second.size() > 1)
+ {
+ std::sort (pos->second.begin(), pos->second.end());
+ reg_num_collection::iterator unique_end = std::unique (pos->second.begin(), pos->second.end());
+ if (unique_end != pos->second.end())
+ pos->second.erase(unique_end, pos->second.end());
+ }
+ assert (!pos->second.empty());
+ if (pos->second.back() != LLDB_INVALID_REGNUM)
+ pos->second.push_back(LLDB_INVALID_REGNUM);
+ }
+
+ // Now update all value_regs with each register info as needed
+ const size_t num_regs = m_regs.size();
+ for (size_t i=0; i<num_regs; ++i)
+ {
+ if (m_value_regs_map.find(i) != m_value_regs_map.end())
+ m_regs[i].value_regs = m_value_regs_map[i].data();
+ else
+ m_regs[i].value_regs = NULL;
+ }
+
+ // Expand all invalidation dependencies
+ for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), end = m_invalidate_regs_map.end();
+ pos != end;
+ ++pos)
+ {
+ const uint32_t reg_num = pos->first;
+
+ if (m_regs[reg_num].value_regs)
+ {
+ reg_num_collection extra_invalid_regs;
+ for (const uint32_t invalidate_reg_num : pos->second)
+ {
+ reg_to_regs_map::iterator invalidate_pos = m_invalidate_regs_map.find(invalidate_reg_num);
+ if (invalidate_pos != m_invalidate_regs_map.end())
+ {
+ for (const uint32_t concrete_invalidate_reg_num : invalidate_pos->second)
+ {
+ if (concrete_invalidate_reg_num != reg_num)
+ extra_invalid_regs.push_back(concrete_invalidate_reg_num);
+ }
+ }
+ }
+ pos->second.insert(pos->second.end(), extra_invalid_regs.begin(), extra_invalid_regs.end());
+ }
+ }
+
+ // sort and unique all invalidate registers and make sure each is terminated with
+ // LLDB_INVALID_REGNUM
+ for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), end = m_invalidate_regs_map.end();
+ pos != end;
+ ++pos)
+ {
+ if (pos->second.size() > 1)
+ {
+ std::sort (pos->second.begin(), pos->second.end());
+ reg_num_collection::iterator unique_end = std::unique (pos->second.begin(), pos->second.end());
+ if (unique_end != pos->second.end())
+ pos->second.erase(unique_end, pos->second.end());
+ }
+ assert (!pos->second.empty());
+ if (pos->second.back() != LLDB_INVALID_REGNUM)
+ pos->second.push_back(LLDB_INVALID_REGNUM);
+ }
+
+ // Now update all invalidate_regs with each register info as needed
+ for (size_t i=0; i<num_regs; ++i)
+ {
+ if (m_invalidate_regs_map.find(i) != m_invalidate_regs_map.end())
+ m_regs[i].invalidate_regs = m_invalidate_regs_map[i].data();
+ else
+ m_regs[i].invalidate_regs = NULL;
+ }
}
size_t
@@ -276,4 +621,83 @@ DynamicRegisterInfo::Clear()
m_sets.clear();
m_set_reg_nums.clear();
m_set_names.clear();
+ m_value_regs_map.clear();
+ m_invalidate_regs_map.clear();
+ m_reg_data_byte_size = 0;
+ m_finalized = false;
+}
+
+void
+DynamicRegisterInfo::Dump () const
+{
+ StreamFile s(stdout, false);
+ const size_t num_regs = m_regs.size();
+ s.Printf("%p: DynamicRegisterInfo contains %zu registers:\n", this, num_regs);
+ for (size_t i=0; i<num_regs; ++i)
+ {
+ s.Printf("[%3zu] name = %-10s", i, m_regs[i].name);
+ s.Printf(", size = %2u, offset = %4u, encoding = %u, format = %-10s",
+ m_regs[i].byte_size,
+ m_regs[i].byte_offset,
+ m_regs[i].encoding,
+ FormatManager::GetFormatAsCString (m_regs[i].format));
+ if (m_regs[i].kinds[eRegisterKindGDB] != LLDB_INVALID_REGNUM)
+ s.Printf(", gdb = %3u", m_regs[i].kinds[eRegisterKindGDB]);
+ if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
+ s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]);
+ if (m_regs[i].kinds[eRegisterKindGCC] != LLDB_INVALID_REGNUM)
+ s.Printf(", gcc = %3u", m_regs[i].kinds[eRegisterKindGCC]);
+ if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
+ s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]);
+ if (m_regs[i].alt_name)
+ s.Printf(", alt-name = %s", m_regs[i].alt_name);
+ if (m_regs[i].value_regs)
+ {
+ s.Printf(", value_regs = [ ");
+ for (size_t j=0; m_regs[i].value_regs[j] != LLDB_INVALID_REGNUM; ++j)
+ {
+ s.Printf("%s ", m_regs[m_regs[i].value_regs[j]].name);
+ }
+ s.Printf("]");
+ }
+ if (m_regs[i].invalidate_regs)
+ {
+ s.Printf(", invalidate_regs = [ ");
+ for (size_t j=0; m_regs[i].invalidate_regs[j] != LLDB_INVALID_REGNUM; ++j)
+ {
+ s.Printf("%s ", m_regs[m_regs[i].invalidate_regs[j]].name);
+ }
+ s.Printf("]");
+ }
+ s.EOL();
+ }
+
+ const size_t num_sets = m_sets.size();
+ s.Printf("%p: DynamicRegisterInfo contains %zu register sets:\n", this, num_sets);
+ for (size_t i=0; i<num_sets; ++i)
+ {
+ s.Printf("set[%zu] name = %s, regs = [", i, m_sets[i].name);
+ for (size_t idx=0; idx<m_sets[i].num_registers; ++idx)
+ {
+ s.Printf("%s ", m_regs[m_sets[i].registers[idx]].name);
+ }
+ s.Printf("]\n");
+ }
+}
+
+
+
+lldb_private::RegisterInfo *
+DynamicRegisterInfo::GetRegisterInfo (const lldb_private::ConstString &reg_name)
+{
+ for (auto &reg_info : m_regs)
+ {
+ // We can use pointer comparison since we used a ConstString to set
+ // the "name" member in AddRegister()
+ if (reg_info.name == reg_name.GetCString())
+ {
+ return &reg_info;
+ }
+ }
+ return NULL;
}
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
index a11cd333545f..a41c77e49f9d 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -13,6 +13,7 @@
// C Includes
// C++ Includes
#include <vector>
+#include <map>
// Other libraries and framework includes
// Project includes
@@ -24,13 +25,15 @@ class DynamicRegisterInfo
public:
DynamicRegisterInfo ();
- DynamicRegisterInfo (const lldb_private::PythonDictionary &dict);
+ DynamicRegisterInfo (const lldb_private::PythonDictionary &dict,
+ lldb::ByteOrder byte_order);
virtual
~DynamicRegisterInfo ();
size_t
- SetRegisterInfo (const lldb_private::PythonDictionary &dict);
+ SetRegisterInfo (const lldb_private::PythonDictionary &dict,
+ lldb::ByteOrder byte_order);
void
AddRegister (lldb_private::RegisterInfo &reg_info,
@@ -63,6 +66,9 @@ public:
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const;
void
+ Dump () const;
+
+ void
Clear();
protected:
@@ -74,12 +80,19 @@ protected:
typedef std::vector <uint32_t> reg_num_collection;
typedef std::vector <reg_num_collection> set_reg_num_collection;
typedef std::vector <lldb_private::ConstString> name_collection;
+ typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map;
+
+ lldb_private::RegisterInfo *
+ GetRegisterInfo (const lldb_private::ConstString &reg_name);
reg_collection m_regs;
set_collection m_sets;
set_reg_num_collection m_set_reg_nums;
name_collection m_set_names;
+ reg_to_regs_map m_value_regs_map;
+ reg_to_regs_map m_invalidate_regs_map;
size_t m_reg_data_byte_size; // The number of bytes required to store all registers
+ bool m_finalized;
};
#endif // lldb_DynamicRegisterInfo_h_
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 499d6d766150..8b22d6457ada 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -17,8 +17,19 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Host/Config.h"
+#ifndef LLDB_DISABLE_POSIX
#include <sys/mman.h>
+#else
+// define them
+#define PROT_NONE 0
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define PROT_EXEC 4
+#define MAP_PRIVATE 2
+#define MAP_ANON 0x1000
+#endif
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 1ffc30da5762..c19aec3a02c7 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -369,8 +369,13 @@ RegisterContextLLDB::InitializeNonZerothFrame()
return;
}
+ bool resolve_tail_call_address = true; // m_current_pc can be one past the address range of the function...
+ uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress (m_current_pc,
+ eSymbolContextFunction | eSymbolContextSymbol,
+ m_sym_ctx, resolve_tail_call_address);
+
// We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
- if ((pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+ if ((resolved_scope & eSymbolContextSymbol) == eSymbolContextSymbol)
{
m_sym_ctx_valid = true;
}
@@ -387,35 +392,18 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (m_sym_ctx_valid == false)
decr_pc_and_recompute_addr_range = true;
- // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp),
- // and our "current" pc is the start of a function...
+ // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp), and
+ // our "current" pc is the start of a function or our "current" pc is one past the end of a function...
if (m_sym_ctx_valid
&& GetNextFrame()->m_frame_type != eSigtrampFrame
&& GetNextFrame()->m_frame_type != eDebuggerFrame
&& addr_range.GetBaseAddress().IsValid()
- && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection()
- && addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset())
+ && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection())
{
- decr_pc_and_recompute_addr_range = true;
- }
-
- // We need to back up the pc by 1 byte and re-search for the Symbol to handle the case where the "saved pc"
- // value is pointing to the next function, e.g. if a function ends with a CALL instruction.
- // FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function
- // to the ABI plugin and consult that.
- if (decr_pc_and_recompute_addr_range)
- {
- Address temporary_pc(m_current_pc);
- temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
- m_sym_ctx.Clear(false);
- m_sym_ctx_valid = false;
- if ((pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+ if (addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset() ||
+ addr_range.GetBaseAddress().GetOffset() + addr_range.GetByteSize() == m_current_pc.GetOffset())
{
- m_sym_ctx_valid = true;
- }
- if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
- {
- m_sym_ctx_valid = false;
+ decr_pc_and_recompute_addr_range = true;
}
}
@@ -632,6 +620,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
}
+ else
+ {
+ UnwindLogMsg ("unable to get architectural default UnwindPlan from ABI plugin");
+ }
bool behaves_like_zeroth_frame = false;
if (IsFrameZero ()
@@ -648,9 +640,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// in the zeroth frame, we need to use the "unwind at first instruction" arch default UnwindPlan
// Also, if this Process can report on memory region attributes, any non-executable region means
// we jumped through a bad function pointer - handle the same way as 0x0.
- // Note, if the symbol context has a function for the symbol, then we don't need to do this check.
+ // Note, if we have a symbol context & a symbol, we don't want to follow this code path. This is
+ // for jumping to memory regions without any information available.
- if ((!m_sym_ctx_valid || m_sym_ctx.function == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
+ if ((!m_sym_ctx_valid || m_sym_ctx.symbol == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
{
uint32_t permissions;
addr_t current_pc_addr = m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr());
@@ -757,8 +750,24 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
return unwind_plan_sp;
}
+ // If we're on the first instruction of a function, and we have an architectural default UnwindPlan
+ // for the initial instruction of a function, use that.
+ if (m_current_offset_backed_up_one == 0)
+ {
+ unwind_plan_sp = func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry (m_thread);
+ if (unwind_plan_sp)
+ {
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
+ return unwind_plan_sp;
+ }
+ }
+
// If nothing else, use the architectural default UnwindPlan and hope that does the job.
- UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
+ if (arch_default_unwind_plan_sp)
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
+ else
+ UnwindLogMsg ("Unable to find any UnwindPlan for full unwind of this frame.");
+
return arch_default_unwind_plan_sp;
}
@@ -1101,7 +1110,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
if (reg_info && abi->RegisterIsVolatile (reg_info))
{
- UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum);
+ UnwindLogMsg ("did not supply reg location for %d (%s) because it is volatile",
+ lldb_regnum, reg_info->name ? reg_info->name : "??");
return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
}
}
@@ -1186,7 +1196,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
unwindplan_regloc.GetDWARFExpressionLength(),
process->GetByteOrder(), process->GetAddressByteSize());
- DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
+ ModuleSP opcode_ctx;
+ DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (unwindplan_registerkind);
Value result;
Error error;
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
index 2c3eee452488..5b6d9fe9f3bb 100644
--- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -147,9 +147,9 @@ RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info,
}
break;
- // TOOD: need a better way to detect when "long double" types are
+ // TOOD: need a better way to detect when "long double" types are
// the same bytes size as "double"
-#if !defined(__arm__)
+#if !defined(__arm__) && !defined(_MSC_VER) && !defined(__mips__)
case sizeof (long double):
if (sizeof (long double) == sizeof(uint32_t))
{
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 0eea00363498..552ae501bd21 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -185,21 +185,7 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
}
goto unwind_done;
}
- if (!m_frames.empty())
- {
- if (m_frames.back()->start_pc == cursor_sp->start_pc)
- {
- if (m_frames.back()->cfa == cursor_sp->cfa)
- goto unwind_done; // Infinite loop where the current cursor is the same as the previous one...
- else if (abi && abi->StackUsesFrames())
- {
- // We might have a CFA that is not using the frame pointer and
- // we want to validate that the frame pointer is valid.
- if (reg_ctx_sp->GetFP() == 0)
- goto unwind_done;
- }
- }
- }
+
cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
m_frames.push_back (cursor_sp);
return true;
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index dd553ce36c89..acb3154f6290 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -338,9 +338,9 @@ ProcessElfCore::GetImageInfoAddress()
{
Target *target = &GetTarget();
ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress();
+ Address addr = obj_file->GetImageInfoAddress(target);
- if (addr.IsValid())
+ if (addr.IsValid())
return addr.GetLoadAddress(target);
return LLDB_INVALID_ADDRESS;
}
@@ -363,13 +363,6 @@ enum {
NT_FREEBSD_PROCSTAT_AUXV = 16
};
-/// Align the given value to next boundary specified by the alignment bytes
-static uint32_t
-AlignToNext(uint32_t value, int alignment_bytes)
-{
- return (value + alignment_bytes - 1) & ~(alignment_bytes - 1);
-}
-
/// Note Structure found in ELF core dumps.
/// This is PT_NOTE type program/segments in the core file.
struct ELFNote
@@ -421,7 +414,7 @@ struct ELFNote
}
}
- const char *cstr = data.GetCStr(offset, AlignToNext(n_namesz, 4));
+ const char *cstr = data.GetCStr(offset, llvm::RoundUpToAlignment(n_namesz, 4));
if (cstr == NULL)
{
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
@@ -441,7 +434,8 @@ ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data,
ArchSpec &arch)
{
lldb::offset_t offset = 0;
- bool have_padding = (arch.GetMachine() == llvm::Triple::x86_64);
+ bool have_padding = (arch.GetMachine() == llvm::Triple::mips64 ||
+ arch.GetMachine() == llvm::Triple::x86_64);
int pr_version = data.GetU32(&offset);
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
@@ -525,7 +519,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
size_t note_start, note_size;
note_start = offset;
- note_size = AlignToNext(note.n_descsz, 4);
+ note_size = llvm::RoundUpToAlignment(note.n_descsz, 4);
// Store the NOTE information in the current thread
DataExtractor note_data (segment_data, note_start, note_size);
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp
deleted file mode 100644
index 6210175f9a7f..000000000000
--- a/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-//===-- RegisterContextCoreFreeBSD_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.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Target/Thread.h"
-#include "RegisterContextCoreFreeBSD_x86_64.h"
-
-RegisterContextCoreFreeBSD_x86_64::RegisterContextCoreFreeBSD_x86_64(Thread &thread,
- const DataExtractor &gpregset, const DataExtractor &fpregset)
- : RegisterContextFreeBSD_x86_64(thread, 0)
-{
- size_t size, len;
-
- size = GetGPRSize();
- m_gpregset = new uint8_t[size];
- len = gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset);
- assert(len == size);
-}
-
-RegisterContextCoreFreeBSD_x86_64::~RegisterContextCoreFreeBSD_x86_64()
-{
- delete [] m_gpregset;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
-{
- value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
- return true;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
-{
- return false;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::UpdateAfterBreakpoint()
-{
- return false;
-}
-
-bool
-RegisterContextCoreFreeBSD_x86_64::HardwareSingleStep(bool enable)
-{
- return false;
-}
-
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h
deleted file mode 100644
index acd594a6e666..000000000000
--- a/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===-- RegisterContextCoreFreeBSD_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_RegisterContextCoreFreeBSD_x86_64_H_
-#define liblldb_RegisterContextCoreFreeBSD_x86_64_H_
-
-#include "Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h"
-
-using namespace lldb_private;
-
-class RegisterContextCoreFreeBSD_x86_64: public RegisterContextFreeBSD_x86_64
-{
-public:
- RegisterContextCoreFreeBSD_x86_64 (Thread &thread, const DataExtractor &gpregset,
- const DataExtractor &fpregset);
-
- ~RegisterContextCoreFreeBSD_x86_64();
-
- virtual bool
- ReadRegister(const RegisterInfo *reg_info, RegisterValue &value);
-
- bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
-
- virtual bool
- WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value);
-
- bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
-
- bool
- HardwareSingleStep(bool enable);
-
- bool
- UpdateAfterBreakpoint();
-
-private:
- uint8_t *m_gpregset;
-};
-
-#endif // #ifndef liblldb_RegisterContextCoreFreeBSD_x86_64_H_
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp
deleted file mode 100644
index d9e3f6d5f90b..000000000000
--- a/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-//===-- RegisterContextCoreLinux_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.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Target/Thread.h"
-#include "RegisterContextCoreLinux_x86_64.h"
-
-RegisterContextCoreLinux_x86_64::RegisterContextCoreLinux_x86_64(Thread &thread,
- const DataExtractor &gpregset,
- const DataExtractor &fpregset)
- : RegisterContextLinux_x86_64(thread, 0)
-{
- size_t size, len;
-
- size = GetGPRSize();
- m_gpregset = new uint8_t[size];
- len = gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset);
- assert(len == size);
-}
-
-RegisterContextCoreLinux_x86_64::~RegisterContextCoreLinux_x86_64()
-{
- delete [] m_gpregset;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
-{
- value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
- return true;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
-{
- return false;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
-{
- return false;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::UpdateAfterBreakpoint()
-{
- return false;
-}
-
-bool
-RegisterContextCoreLinux_x86_64::HardwareSingleStep(bool enable)
-{
- return false;
-}
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h
deleted file mode 100644
index 9cf545afd56a..000000000000
--- a/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===-- RegisterContextCoreLinux_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_RegisterContextCoreLinux_x86_64_H_
-#define liblldb_RegisterContextCoreLinux_x86_64_H_
-
-#include "Plugins/Process/POSIX/RegisterContextLinux_x86_64.h"
-
-using namespace lldb_private;
-
-class RegisterContextCoreLinux_x86_64: public RegisterContextLinux_x86_64
-{
-public:
- RegisterContextCoreLinux_x86_64 (Thread &thread, const DataExtractor &gpregset,
- const DataExtractor &fpregset);
-
- ~RegisterContextCoreLinux_x86_64();
-
- virtual bool
- ReadRegister(const RegisterInfo *reg_info, RegisterValue &value);
-
- bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
-
- virtual bool
- WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value);
-
- bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
-
- bool
- HardwareSingleStep(bool enable);
-
- bool
- UpdateAfterBreakpoint();
-
-protected:
- bool
- ReadFPR()
- {
- assert(0);
- }
-
-private:
- uint8_t *m_gpregset;
-};
-
-#endif // #ifndef liblldb_RegisterContextCoreLinux_x86_64_H_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
new file mode 100644
index 000000000000..b95a51130ca7
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -0,0 +1,94 @@
+//===-- RegisterContextCorePOSIX_mips64.cpp ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Target/Thread.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContextPOSIXCore_mips64.h"
+
+using namespace lldb_private;
+
+RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64(Thread &thread,
+ RegisterInfoInterface *register_info,
+ const DataExtractor &gpregset,
+ const DataExtractor &fpregset)
+ : RegisterContextPOSIX_mips64(thread, 0, register_info)
+{
+ size_t i;
+ lldb::offset_t offset = 0;
+
+ for (i = 0; i < k_num_gpr_registers_mips64; i++)
+ {
+ m_reg[i] = gpregset.GetU64(&offset);
+ }
+}
+
+RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64()
+{
+}
+
+bool
+RegisterContextCorePOSIX_mips64::ReadGPR()
+{
+ return true;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::ReadFPR()
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::WriteGPR()
+{
+ assert(0);
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::WriteFPR()
+{
+ assert(0);
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+ int reg_num = reg_info->byte_offset / 8;
+ assert(reg_num < k_num_gpr_registers_mips64);
+ value = m_reg[reg_num];
+ return true;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_mips64::HardwareSingleStep(bool enable)
+{
+ return false;
+}
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
new file mode 100644
index 000000000000..92e486bf2235
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
@@ -0,0 +1,58 @@
+//===-- RegisterContextCorePOSIX_mips64.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_RegisterContextCorePOSIX_mips64_H_
+#define liblldb_RegisterContextCorePOSIX_mips64_H_
+
+#include "Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h"
+
+class RegisterContextCorePOSIX_mips64 :
+ public RegisterContextPOSIX_mips64
+{
+public:
+ RegisterContextCorePOSIX_mips64 (lldb_private::Thread &thread,
+ RegisterInfoInterface *register_info,
+ const lldb_private::DataExtractor &gpregset,
+ const lldb_private::DataExtractor &fpregset);
+
+ ~RegisterContextCorePOSIX_mips64();
+
+ 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);
+
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+ bool
+ HardwareSingleStep(bool enable);
+
+protected:
+ bool
+ ReadGPR();
+
+ bool
+ ReadFPR();
+
+ bool
+ WriteGPR();
+
+ bool
+ WriteFPR();
+
+private:
+ uint64_t m_reg[40];
+};
+
+#endif // #ifndef liblldb_RegisterContextCorePOSIX_mips64_H_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
new file mode 100644
index 000000000000..610506c20a0b
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -0,0 +1,92 @@
+//===-- RegisterContextCorePOSIX_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.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Target/Thread.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContextPOSIXCore_x86_64.h"
+
+using namespace lldb_private;
+
+RegisterContextCorePOSIX_x86_64::RegisterContextCorePOSIX_x86_64(Thread &thread,
+ RegisterInfoInterface *register_info,
+ const DataExtractor &gpregset,
+ const DataExtractor &fpregset)
+ : RegisterContextPOSIX_x86 (thread, 0, register_info)
+{
+ size_t size, len;
+
+ size = GetGPRSize();
+ m_gpregset = new uint8_t[size];
+ len = gpregset.ExtractBytes (0, size, lldb::eByteOrderLittle, m_gpregset);
+ assert(len == size);
+}
+
+RegisterContextCorePOSIX_x86_64::~RegisterContextCorePOSIX_x86_64()
+{
+ delete [] m_gpregset;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::ReadGPR()
+{
+ return m_gpregset != NULL;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::ReadFPR()
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::WriteGPR()
+{
+ assert(0);
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::WriteFPR()
+{
+ assert(0);
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+ value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
+ return true;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_x86_64::HardwareSingleStep(bool enable)
+{
+ return false;
+}
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
new file mode 100644
index 000000000000..d4ea14fab7b1
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
@@ -0,0 +1,58 @@
+//===-- RegisterContextCorePOSIX_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_RegisterContextCorePOSIX_x86_64_H_
+#define liblldb_RegisterContextCorePOSIX_x86_64_H_
+
+#include "Plugins/Process/POSIX/RegisterContextPOSIX_x86.h"
+
+class RegisterContextCorePOSIX_x86_64 :
+ public RegisterContextPOSIX_x86
+{
+public:
+ RegisterContextCorePOSIX_x86_64 (lldb_private::Thread &thread,
+ RegisterInfoInterface *register_info,
+ const lldb_private::DataExtractor &gpregset,
+ const lldb_private::DataExtractor &fpregset);
+
+ ~RegisterContextCorePOSIX_x86_64();
+
+ 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);
+
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+ bool
+ HardwareSingleStep(bool enable);
+
+protected:
+ bool
+ ReadGPR();
+
+ bool
+ ReadFPR();
+
+ bool
+ WriteGPR();
+
+ bool
+ WriteFPR();
+
+private:
+ uint8_t *m_gpregset;
+};
+
+#endif // #ifndef liblldb_RegisterContextCorePOSIX_x86_64_H_
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index a7229663dc89..3bda86dc0f73 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -16,8 +16,11 @@
#include "ThreadElfCore.h"
#include "ProcessElfCore.h"
-#include "RegisterContextCoreFreeBSD_x86_64.h"
-#include "RegisterContextCoreLinux_x86_64.h"
+#include "RegisterContextLinux_x86_64.h"
+#include "RegisterContextFreeBSD_mips64.h"
+#include "RegisterContextFreeBSD_x86_64.h"
+#include "RegisterContextPOSIXCore_mips64.h"
+#include "RegisterContextPOSIXCore_x86_64.h"
using namespace lldb;
using namespace lldb_private;
@@ -84,14 +87,28 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
ArchSpec arch = process->GetArchitecture();
switch (arch.GetMachine())
{
+ case llvm::Triple::mips64:
+ switch (arch.GetTriple().getOS())
+ {
+ case llvm::Triple::FreeBSD:
+ m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, new RegisterContextFreeBSD_mips64(arch), m_gpregset_data, m_fpregset_data));
+ break;
+ default:
+ if (log)
+ log->Printf ("elf-core::%s:: OS(%d) not supported",
+ __FUNCTION__, arch.GetTriple().getOS());
+ assert (false && "OS not supported");
+ break;
+ }
+ break;
case llvm::Triple::x86_64:
switch (arch.GetTriple().getOS())
{
case llvm::Triple::FreeBSD:
- m_thread_reg_ctx_sp.reset(new RegisterContextCoreFreeBSD_x86_64 (*this, m_gpregset_data, m_fpregset_data));
+ m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, new RegisterContextFreeBSD_x86_64(arch), m_gpregset_data, m_fpregset_data));
break;
case llvm::Triple::Linux:
- m_thread_reg_ctx_sp.reset(new RegisterContextCoreLinux_x86_64 (*this, m_gpregset_data, m_fpregset_data));
+ m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, new RegisterContextLinux_x86_64(arch), m_gpregset_data, m_fpregset_data));
break;
default:
if (log)
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h
index ca6339d7ec9d..2661edfa50cd 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.h
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -29,6 +29,10 @@ struct compat_timeval
#define ELFLINUXPRSTATUS64_SIZE (112)
#define ELFLINUXPRPSINFO64_SIZE (132)
+#undef si_signo
+#undef si_code
+#undef si_errno
+
struct ELFLinuxPrStatus
{
int32_t si_signo;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index d7efdf2302d8..f67e1b5d49c3 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -133,7 +133,11 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
const char *listener_name,
bool is_platform) :
Communication(comm_name),
+#ifdef LLDB_CONFIGURATION_DEBUG
+ m_packet_timeout (1000),
+#else
m_packet_timeout (1),
+#endif
m_sequence_mutex (Mutex::eMutexTypeRecursive),
m_public_is_running (false),
m_private_is_running (false),
@@ -173,7 +177,7 @@ GDBRemoteCommunication::SendAck ()
char ch = '+';
const size_t bytes_written = Write (&ch, 1, status, NULL);
if (log)
- log->Printf ("<%4zu> send packet: %c", bytes_written, ch);
+ log->Printf ("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
return bytes_written;
}
@@ -186,7 +190,7 @@ GDBRemoteCommunication::SendNack ()
char ch = '-';
const size_t bytes_written = Write (&ch, 1, status, NULL);
if (log)
- log->Printf ("<%4zu> send packet: %c", bytes_written, ch);
+ log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
return bytes_written;
}
@@ -222,7 +226,7 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le
if (!m_history.DidDumpToLog ())
m_history.Dump (log);
- log->Printf ("<%4zu> send packet: %.*s", bytes_written, (int)packet.GetSize(), packet.GetData());
+ log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet.GetSize(), packet.GetData());
}
m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written);
@@ -456,13 +460,38 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
if (!m_history.DidDumpToLog ())
m_history.Dump (log);
- log->Printf ("<%4zu> read packet: %.*s", total_length, (int)(total_length), m_bytes.c_str());
+ log->Printf("<%4" PRIu64 "> read packet: %.*s", (uint64_t)total_length, (int)(total_length), m_bytes.c_str());
}
m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length);
- packet_str.assign (m_bytes, content_start, content_length);
-
+ // Clear packet_str in case there is some existing data in it.
+ packet_str.clear();
+ // Copy the packet from m_bytes to packet_str expanding the
+ // run-length encoding in the process.
+ // Reserve enough byte for the most common case (no RLE used)
+ packet_str.reserve(m_bytes.length());
+ for (std::string::const_iterator c = m_bytes.begin() + content_start; c != m_bytes.begin() + content_start + content_length; ++c)
+ {
+ if (*c == '*')
+ {
+ // '*' indicates RLE. Next character will give us the
+ // repeat count and previous character is what is to be
+ // repeated.
+ char char_to_repeat = packet_str.back();
+ // Number of time the previous character is repeated
+ int repeat_count = *++c + 3 - ' ';
+ // We have the char_to_repeat and repeat_count. Now push
+ // it in the packet.
+ for (int i = 0; i < repeat_count; ++i)
+ packet_str.push_back(char_to_repeat);
+ }
+ else
+ {
+ packet_str.push_back(*c);
+ }
+ }
+
if (m_bytes[0] == '$')
{
assert (checksum_idx < m_bytes.size());
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index ca594a8f3fd5..2ac7d20c6c60 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -11,6 +11,8 @@
#include "GDBRemoteCommunicationClient.h"
// C Includes
+#include <sys/stat.h>
+
// C++ Includes
#include <sstream>
@@ -20,6 +22,7 @@
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/StreamGDBRemote.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/Host.h"
@@ -29,10 +32,15 @@
#include "Utility/StringExtractorGDBRemote.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
+#include "lldb/Host/Config.h"
using namespace lldb;
using namespace lldb_private;
+#ifdef LLDB_DISABLE_POSIX
+#define SIGSTOP 17
+#endif
+
//----------------------------------------------------------------------
// GDBRemoteCommunicationClient constructor
//----------------------------------------------------------------------
@@ -56,6 +64,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
m_attach_or_wait_reply(eLazyBoolCalculate),
m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
+ m_supports_p (eLazyBoolCalculate),
m_supports_qProcessInfoPID (true),
m_supports_qfProcessInfo (true),
m_supports_qUserName (true),
@@ -66,6 +75,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_supports_z2 (true),
m_supports_z3 (true),
m_supports_z4 (true),
+ m_supports_QEnvironment (true),
+ m_supports_QEnvironmentHexEncoded (true),
m_curr_tid (LLDB_INVALID_THREAD_ID),
m_curr_tid_run (LLDB_INVALID_THREAD_ID),
m_num_supported_hardware_watchpoints (0),
@@ -79,7 +90,11 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_process_arch(),
m_os_version_major (UINT32_MAX),
m_os_version_minor (UINT32_MAX),
- m_os_version_update (UINT32_MAX)
+ m_os_version_update (UINT32_MAX),
+ m_os_build (),
+ m_os_kernel (),
+ m_hostname (),
+ m_default_packet_timeout (0)
{
}
@@ -192,6 +207,7 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_vCont_C = eLazyBoolCalculate;
m_supports_vCont_s = eLazyBoolCalculate;
m_supports_vCont_S = eLazyBoolCalculate;
+ m_supports_p = eLazyBoolCalculate;
m_qHostInfo_is_valid = eLazyBoolCalculate;
m_qProcessInfo_is_valid = eLazyBoolCalculate;
m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
@@ -209,6 +225,8 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_z2 = true;
m_supports_z3 = true;
m_supports_z4 = true;
+ m_supports_QEnvironment = true;
+ m_supports_QEnvironmentHexEncoded = true;
m_host_arch.Clear();
m_process_arch.Clear();
}
@@ -287,6 +305,32 @@ GDBRemoteCommunicationClient::GetVContSupported (char flavor)
return false;
}
+// Check if the target supports 'p' packet. It sends out a 'p'
+// packet and checks the response. A normal packet will tell us
+// that support is available.
+//
+// Takes a valid thread ID because p needs to apply to a thread.
+bool
+GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid)
+{
+ if (m_supports_p == eLazyBoolCalculate)
+ {
+ StringExtractorGDBRemote response;
+ m_supports_p = eLazyBoolNo;
+ char packet[256];
+ if (GetThreadSuffixSupported())
+ snprintf(packet, sizeof(packet), "p0;thread:%" PRIx64 ";", tid);
+ else
+ snprintf(packet, sizeof(packet), "p0");
+
+ if (SendPacketAndWaitForResponse(packet, response, false))
+ {
+ if (response.IsNormalResponse())
+ m_supports_p = eLazyBoolYes;
+ }
+ }
+ return m_supports_p;
+}
size_t
GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
@@ -978,15 +1022,61 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu
if (name_equal_value && name_equal_value[0])
{
StreamString packet;
- packet.Printf("QEnvironment:%s", name_equal_value);
+ bool send_hex_encoding = false;
+ for (const char *p = name_equal_value; *p != '\0' && send_hex_encoding == false; ++p)
+ {
+ if (isprint(*p))
+ {
+ switch (*p)
+ {
+ case '$':
+ case '#':
+ send_hex_encoding = true;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // We have non printable characters, lets hex encode this...
+ send_hex_encoding = true;
+ }
+ }
+
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (send_hex_encoding)
{
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
+ if (m_supports_QEnvironmentHexEncoded)
+ {
+ packet.PutCString("QEnvironmentHexEncoded:");
+ packet.PutBytesAsRawHex8 (name_equal_value, strlen(name_equal_value));
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ if (response.IsUnsupportedResponse())
+ m_supports_QEnvironmentHexEncoded = false;
+ }
+ }
+
+ }
+ else if (m_supports_QEnvironment)
+ {
+ packet.Printf("QEnvironment:%s", name_equal_value);
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ if (response.IsUnsupportedResponse())
+ m_supports_QEnvironment = false;
+ }
}
}
return -1;
@@ -1213,6 +1303,15 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
else
--num_keys_decoded;
}
+ else if (name.compare("default_packet_timeout") == 0)
+ {
+ m_default_packet_timeout = Args::StringToUInt32(value.c_str(), 0);
+ if (m_default_packet_timeout > 0)
+ {
+ SetPacketTimeout(m_default_packet_timeout);
+ ++num_keys_decoded;
+ }
+ }
}
@@ -1347,6 +1446,14 @@ GDBRemoteCommunicationClient::GetHostArchitecture ()
return m_host_arch;
}
+uint32_t
+GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout ()
+{
+ if (m_qHostInfo_is_valid == eLazyBoolCalculate)
+ GetHostInfo ();
+ return m_default_packet_timeout;
+}
+
addr_t
GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
{
@@ -2132,21 +2239,37 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t
}
uint16_t
-GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
+GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
{
+ pid = LLDB_INVALID_PROCESS_ID;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qLaunchGDBServer", strlen("qLaunchGDBServer"), response, false))
+ StreamString stream;
+ stream.PutCString("qLaunchGDBServer:port:0;");
+ std::string hostname;
+ if (Host::GetHostname (hostname))
+ {
+ // Make the GDB server we launch only accept connections from this host
+ stream.Printf("host:%s;", hostname.c_str());
+ }
+ else
+ {
+ // Make the GDB server we launch accept connections from any host since we can't figure out the hostname
+ stream.Printf("host:*;");
+ }
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
std::string name;
std::string value;
uint16_t port = 0;
- //lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
while (response.GetNameColonValue(name, value))
{
- if (name.size() == 4 && name.compare("port") == 0)
+ if (name.compare("port") == 0)
port = Args::StringToUInt32(value.c_str(), 0, 0);
-// if (name.size() == 3 && name.compare("pid") == 0)
-// pid = Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
+ else if (name.compare("pid") == 0)
+ pid = Args::StringToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
}
return port;
}
@@ -2154,6 +2277,23 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
}
bool
+GDBRemoteCommunicationClient::KillSpawnedProcess (lldb::pid_t pid)
+{
+ StreamString stream;
+ stream.Printf ("qKillSpawnedProcess:%" PRId64 , pid);
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.IsOKResponse())
+ return true;
+ }
+ return false;
+}
+
+bool
GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)
{
if (m_curr_tid == tid)
@@ -2222,7 +2362,9 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto
assert (packet_len < (int)sizeof(packet));
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
- if (response.IsNormalResponse())
+ if (response.IsUnsupportedResponse())
+ m_supports_qThreadStopInfo = false;
+ else if (response.IsNormalResponse())
return true;
else
return false;
@@ -2232,8 +2374,6 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto
m_supports_qThreadStopInfo = false;
}
}
-// if (SetCurrentThread (tid))
-// return GetStopReply (response);
return false;
}
@@ -2346,3 +2486,326 @@ GDBRemoteCommunicationClient::GetShlibInfoAddr()
return LLDB_INVALID_ADDRESS;
}
+lldb_private::Error
+GDBRemoteCommunicationClient::RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("qPlatform_RunCommand:");
+ stream.PutBytesAsRawHex8(command, strlen(command));
+ stream.PutChar(',');
+ stream.PutHex32(timeout_sec);
+ if (working_dir && *working_dir)
+ {
+ stream.PutChar(',');
+ stream.PutBytesAsRawHex8(working_dir, strlen(working_dir));
+ }
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return Error("malformed reply");
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX);
+ if (exitcode == UINT32_MAX)
+ return Error("unable to run remote process");
+ else if (status_ptr)
+ *status_ptr = exitcode;
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX);
+ if (signo_ptr)
+ *signo_ptr = signo;
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ std::string output;
+ response.GetEscapedBinaryData(output);
+ if (command_output)
+ command_output->assign(output);
+ return Error();
+ }
+ return Error("unable to send packet");
+}
+
+uint32_t
+GDBRemoteCommunicationClient::MakeDirectory (const std::string &path,
+ mode_t mode)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("qPlatform_IO_MkDir:");
+ stream.PutHex32(mode);
+ stream.PutChar(',');
+ stream.PutBytesAsRawHex8(path.c_str(), path.size());
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ return response.GetHexMaxU32(false, UINT32_MAX);
+ }
+ return UINT32_MAX;
+
+}
+
+static uint64_t
+ParseHostIOPacketResponse (StringExtractorGDBRemote &response,
+ uint64_t fail_result,
+ Error &error)
+{
+ response.SetFilePos(0);
+ if (response.GetChar() != 'F')
+ return fail_result;
+ int32_t result = response.GetS32 (-2);
+ if (result == -2)
+ return fail_result;
+ if (response.GetChar() == ',')
+ {
+ int result_errno = response.GetS32 (-2);
+ if (result_errno != -2)
+ error.SetError(result_errno, eErrorTypePOSIX);
+ else
+ error.SetError(-1, eErrorTypeGeneric);
+ }
+ else
+ error.Clear();
+ return result;
+}
+lldb::user_id_t
+GDBRemoteCommunicationClient::OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:open:");
+ std::string path (file_spec.GetPath());
+ if (path.empty())
+ return UINT64_MAX;
+ stream.PutCStringAsRawHex8(path.c_str());
+ stream.PutChar(',');
+ const uint32_t posix_open_flags = File::ConvertOpenOptionsForPOSIXOpen(flags);
+ stream.PutHex32(posix_open_flags);
+ stream.PutChar(',');
+ stream.PutHex32(mode);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ return ParseHostIOPacketResponse (response, UINT64_MAX, error);
+ }
+ return UINT64_MAX;
+}
+
+bool
+GDBRemoteCommunicationClient::CloseFile (lldb::user_id_t fd,
+ Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.Printf("vFile:close:%i", (int)fd);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ return ParseHostIOPacketResponse (response, -1, error) == 0;
+ }
+ return false;
+}
+
+// Extension of host I/O packets to get the file size.
+lldb::user_id_t
+GDBRemoteCommunicationClient::GetFileSize (const lldb_private::FileSpec& file_spec)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:size:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return UINT64_MAX;
+ uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
+ return retcode;
+ }
+ return UINT64_MAX;
+}
+
+uint32_t
+GDBRemoteCommunicationClient::GetFilePermissions(const lldb_private::FileSpec& file_spec, Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:mode:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ {
+ error.SetErrorStringWithFormat ("invalid response to '%s' packet", packet);
+ return 0;
+ }
+ const uint32_t mode = response.GetS32(-1);
+ if (mode == -1)
+ {
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ else
+ error.SetErrorToGenericError();
+ }
+ }
+ else
+ error.Clear();
+ return mode & (S_IRWXU|S_IRWXG|S_IRWXO);
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("failed to send '%s' packet", packet);
+ }
+ return 0;
+}
+
+uint64_t
+GDBRemoteCommunicationClient::ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return 0;
+ uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
+ if (retcode == UINT32_MAX)
+ return retcode;
+ const char next = (response.Peek() ? *response.Peek() : 0);
+ if (next == ',')
+ return 0;
+ if (next == ';')
+ {
+ response.GetChar(); // skip the semicolon
+ std::string buffer;
+ if (response.GetEscapedBinaryData(buffer))
+ {
+ const uint64_t data_to_write = std::min<uint64_t>(dst_len, buffer.size());
+ if (data_to_write > 0)
+ memcpy(dst, &buffer[0], data_to_write);
+ return data_to_write;
+ }
+ }
+ }
+ return 0;
+}
+
+uint64_t
+GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
+{
+ lldb_private::StreamGDBRemote stream;
+ stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
+ stream.PutEscapedBytes(src, src_len);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ {
+ error.SetErrorStringWithFormat("write file failed");
+ return 0;
+ }
+ uint64_t bytes_written = response.GetU64(UINT64_MAX);
+ if (bytes_written == UINT64_MAX)
+ {
+ error.SetErrorToGenericError();
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ }
+ return 0;
+ }
+ return bytes_written;
+ }
+ else
+ {
+ error.SetErrorString ("failed to send vFile:pwrite packet");
+ }
+ return 0;
+}
+
+// Extension of host I/O packets to get whether a file exists.
+bool
+GDBRemoteCommunicationClient::GetFileExists (const lldb_private::FileSpec& file_spec)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:exists:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return false;
+ if (response.GetChar() != ',')
+ return false;
+ bool retcode = (response.GetChar() != '0');
+ return retcode;
+ }
+ return false;
+}
+
+bool
+GDBRemoteCommunicationClient::CalculateMD5 (const lldb_private::FileSpec& file_spec,
+ uint64_t &high,
+ uint64_t &low)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:MD5:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return false;
+ if (response.GetChar() != ',')
+ return false;
+ if (response.Peek() && *response.Peek() == 'x')
+ return false;
+ low = response.GetHexMaxU64(false, UINT64_MAX);
+ high = response.GetHexMaxU64(false, UINT64_MAX);
+ return true;
+ }
+ return false;
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 5bb8387b9094..d5535bbb1df3 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -89,7 +89,10 @@ public:
GetLaunchSuccess (std::string &error_str);
uint16_t
- LaunchGDBserverAndGetPort ();
+ LaunchGDBserverAndGetPort (lldb::pid_t &pid);
+
+ bool
+ KillSpawnedProcess (lldb::pid_t pid);
//------------------------------------------------------------------
/// Sends a GDB remote protocol 'A' packet that delivers program
@@ -217,6 +220,9 @@ public:
const lldb_private::ArchSpec &
GetHostArchitecture ();
+
+ uint32_t
+ GetHostDefaultPacketTimeout();
const lldb_private::ArchSpec &
GetProcessArchitecture ();
@@ -225,6 +231,9 @@ public:
GetVContSupported (char flavor);
bool
+ GetpPacketSupported (lldb::tid_t tid);
+
+ bool
GetVAttachOrWaitSupported ();
bool
@@ -347,10 +356,61 @@ public:
return m_interrupt_sent;
}
+ virtual lldb::user_id_t
+ OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ lldb_private::Error &error);
+
+ virtual bool
+ CloseFile (lldb::user_id_t fd,
+ lldb_private::Error &error);
+
+ virtual lldb::user_id_t
+ GetFileSize (const lldb_private::FileSpec& file_spec);
+
+ virtual uint32_t
+ GetFilePermissions(const lldb_private::FileSpec& file_spec,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ lldb_private::Error &error);
+
+ virtual uint32_t
+ MakeDirectory (const std::string &path,
+ mode_t mode);
+
+ virtual bool
+ GetFileExists (const lldb_private::FileSpec& file_spec);
+
+ virtual lldb_private::Error
+ RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
+
+ virtual bool
+ CalculateMD5 (const lldb_private::FileSpec& file_spec,
+ uint64_t &high,
+ uint64_t &low);
+
std::string
HarmonizeThreadIdsForProfileData (ProcessGDBRemote *process,
StringExtractorGDBRemote &inputStringExtractor);
-
+
protected:
bool
@@ -377,6 +437,7 @@ protected:
lldb_private::LazyBool m_watchpoints_trigger_after_instruction;
lldb_private::LazyBool m_attach_or_wait_reply;
lldb_private::LazyBool m_prepare_for_reg_writing_reply;
+ lldb_private::LazyBool m_supports_p;
bool
m_supports_qProcessInfoPID:1,
@@ -388,7 +449,9 @@ protected:
m_supports_z1:1,
m_supports_z2:1,
m_supports_z3:1,
- m_supports_z4:1;
+ m_supports_z4:1,
+ m_supports_QEnvironment:1,
+ m_supports_QEnvironmentHexEncoded:1;
lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations
@@ -416,6 +479,7 @@ protected:
std::string m_os_build;
std::string m_os_kernel;
std::string m_hostname;
+ uint32_t m_default_packet_timeout;
bool
DecodeProcessInfoResponse (StringExtractorGDBRemote &response,
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 3a14e9fe759a..df036cdcc8e0 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -7,8 +7,10 @@
//
//===----------------------------------------------------------------------===//
+#include <errno.h>
#include "GDBRemoteCommunicationServer.h"
+#include "lldb/Core/StreamGDBRemote.h"
// C Includes
// C++ Includes
@@ -20,6 +22,7 @@
#include "lldb/Core/State.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Endian.h"
+#include "lldb/Host/File.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Target/Process.h"
@@ -40,11 +43,31 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
m_async_thread (LLDB_INVALID_HOST_THREAD),
m_process_launch_info (),
m_process_launch_error (),
+ m_spawned_pids (),
+ m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
m_proc_infos (),
m_proc_infos_index (0),
m_lo_port_num (0),
- m_hi_port_num (0)
+ m_hi_port_num (0),
+ m_next_port (0),
+ m_use_port_range (false)
{
+ // We seldom need to override the port number that the debugserver process
+ // starts with. We just pass in 0 to let the system choose a random port.
+ // In rare situation where the need arises, use two environment variables
+ // to override.
+ uint16_t lo_port_num = 0;
+ uint16_t hi_port_num = 0;
+ const char *lo_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_LO_PORT");
+ if (lo_port_c_str)
+ lo_port_num = ::atoi(lo_port_c_str);
+ const char *hi_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_HI_PORT");
+ if (hi_port_c_str)
+ hi_port_num = ::atoi(hi_port_c_str);
+ if (lo_port_num && hi_port_num && lo_port_num < hi_port_num)
+ {
+ SetPortRange(lo_port_num, hi_port_num);
+ }
}
//----------------------------------------------------------------------
@@ -65,7 +88,7 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
//
// StringExtractorGDBRemote packet;
-//
+//
// while ()
// {
// if (packet.
@@ -79,9 +102,9 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
//}
//
bool
-GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
+GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
Error &error,
- bool &interrupt,
+ bool &interrupt,
bool &quit)
{
StringExtractorGDBRemote packet;
@@ -103,7 +126,7 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
error.SetErrorString("interrupt received");
interrupt = true;
break;
-
+
case StringExtractorGDBRemote::eServerPacketType_unimplemented:
return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
@@ -112,22 +135,25 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
return Handle_qfProcessInfo (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
return Handle_qsProcessInfo (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qC:
return Handle_qC (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
return Handle_qHostInfo (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
return Handle_qLaunchGDBServer (packet);
-
+
+ case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
+ return Handle_qKillSpawnedProcess (packet);
+
case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
return Handle_qLaunchSuccess (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qGroupName:
return Handle_qGroupName (packet);
@@ -142,24 +168,60 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
return Handle_QEnvironment (packet);
-
+
+ case StringExtractorGDBRemote::eServerPacketType_QLaunchArch:
+ return Handle_QLaunchArch (packet);
+
case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
return Handle_QSetDisableASLR (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
return Handle_QSetSTDIN (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
return Handle_QSetSTDOUT (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
return Handle_QSetSTDERR (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
return Handle_QSetWorkingDir (packet);
case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
return Handle_QStartNoAckMode (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_IO_MkDir:
+ return Handle_qPlatform_IO_MkDir (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_RunCommand:
+ return Handle_qPlatform_RunCommand (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Open:
+ return Handle_vFile_Open (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Close:
+ return Handle_vFile_Close (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_pRead:
+ return Handle_vFile_pRead (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_pWrite:
+ return Handle_vFile_pWrite (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Size:
+ return Handle_vFile_Size (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Mode:
+ return Handle_vFile_Mode (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Exists:
+ return Handle_vFile_Exists (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Stat:
+ return Handle_vFile_Stat (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_MD5:
+ return Handle_vFile_MD5 (packet);
}
return true;
}
@@ -207,7 +269,7 @@ bool
GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
{
StreamString response;
-
+
// $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
ArchSpec host_arch (Host::GetArchitecture ());
@@ -222,12 +284,12 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.Printf ("cputype:%u;", cpu);
if (sub != LLDB_INVALID_CPUTYPE)
response.Printf ("cpusubtype:%u;", sub);
-
+
if (cpu == ArchSpec::kCore_arm_any)
response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
else
response.Printf("watchpoint_exceptions_received:after;");
-
+
switch (lldb::endian::InlHostByteOrder())
{
case eByteOrderBig: response.PutCString ("endian:big;"); break;
@@ -235,7 +297,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
default: response.PutCString ("endian:unknown;"); break;
}
-
+
uint32_t major = UINT32_MAX;
uint32_t minor = UINT32_MAX;
uint32_t update = UINT32_MAX;
@@ -273,7 +335,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.PutCStringAsRawHex8(s.c_str());
response.PutChar(';');
}
-
+
return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
}
@@ -319,7 +381,7 @@ GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &
return SendErrorResponse (1);
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
{
m_proc_infos_index = 0;
@@ -329,7 +391,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
packet.SetFilePos(::strlen ("qfProcessInfo"));
if (packet.GetChar() == ':')
{
-
+
std::string key;
std::string value;
while (packet.GetNameColonValue(key, value))
@@ -360,11 +422,11 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
{
match_info.SetNameMatchType (eNameMatchContains);
}
- else if (value.compare("regex") == 0)
+ else if (value.compare("regex") == 0)
{
match_info.SetNameMatchType (eNameMatchRegularExpression);
}
- else
+ else
{
success = false;
}
@@ -405,7 +467,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
{
success = false;
}
-
+
if (!success)
return SendErrorResponse (2);
}
@@ -420,7 +482,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
return SendErrorResponse (3);
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
{
if (m_proc_infos_index < m_proc_infos.GetSize())
@@ -433,7 +495,7 @@ GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &pa
return SendErrorResponse (4);
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
{
// Packet format: "qUserName:%i" where %i is the uid
@@ -450,10 +512,10 @@ GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet
}
}
return SendErrorResponse (5);
-
+
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
{
// Packet format: "qGroupName:%i" where %i is the gid
@@ -539,11 +601,11 @@ AcceptPortFromInferior (void *arg)
// for (int i=0; i<num_retries; i++)
// {
// struct proc_bsdinfo bsd_info;
-// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
-// (uint64_t) 0,
-// &bsd_info,
+// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
+// (uint64_t) 0,
+// &bsd_info,
// PROC_PIDTBSDINFO_SIZE);
-//
+//
// switch (error)
// {
// case EINVAL:
@@ -551,10 +613,10 @@ AcceptPortFromInferior (void *arg)
// case ESRCH:
// case EPERM:
// return false;
-//
+//
// default:
// break;
-//
+//
// case 0:
// if (bsd_info.pbi_status == SSTOP)
// return true;
@@ -567,9 +629,9 @@ AcceptPortFromInferior (void *arg)
bool
GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
{
- // The 'A' packet is the most over designed packet ever here with
- // redundant argument indexes, redundant argument lengths and needed hex
- // encoded argument string values. Really all that is needed is a comma
+ // The 'A' packet is the most over designed packet ever here with
+ // redundant argument indexes, redundant argument lengths and needed hex
+ // encoded argument string values. Really all that is needed is a comma
// separated hex encoded argument value list, but we will stay true to the
// documented version of the 'A' packet here...
@@ -615,7 +677,7 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
if (packet.GetChar() != ',')
success = false;
}
-
+
if (success)
{
if (arg_idx == 0)
@@ -649,11 +711,11 @@ GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
response.Printf("QC%" PRIx64, pid);
if (m_is_platform)
{
- // If we launch a process and this GDB server is acting as a platform,
- // then we need to clear the process launch state so we can start
+ // If we launch a process and this GDB server is acting as a platform,
+ // then we need to clear the process launch state so we can start
// launching another process. In order to launch a process a bunch or
// packets need to be sent: environment packets, working directory,
- // disable ASLR, and many more settings. When we launch a process we
+ // disable ASLR, and many more settings. When we launch a process we
// then need to know when to clear this information. Currently we are
// selecting the 'qC' packet as that packet which seems to make the most
// sense.
@@ -666,8 +728,30 @@ GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
}
bool
+GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
+{
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ return m_spawned_pids.erase(pid) > 0;
+}
+bool
+GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal, // Zero for no signal
+ int status) // Exit value of process if signal is zero
+{
+ GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
+ server->DebugserverProcessReaped (pid);
+ return true;
+}
+
+bool
GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
{
+#ifdef _WIN32
+ // No unix sockets on windows
+ return false;
+#else
// Spawn a local debugserver as a platform so we can then attach or launch
// a process...
@@ -677,49 +761,101 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
ConnectionFileDescriptor file_conn;
char connect_url[PATH_MAX];
Error error;
- char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
- if (::mktemp (unix_socket_name) == NULL)
+ std::string hostname;
+ // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
+ // with the TMPDIR environnement variable
+ char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
+ if (::mkstemp (unix_socket_name) == -1)
{
- error.SetErrorString ("failed to make temporary path for a unix socket");
+ error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno));
}
else
{
+ packet.SetFilePos(::strlen ("qLaunchGDBServer:"));
+ std::string name;
+ std::string value;
+ uint16_t port = UINT16_MAX;
+ while (packet.GetNameColonValue(name, value))
+ {
+ if (name.compare ("host") == 0)
+ hostname.swap(value);
+ else if (name.compare ("port") == 0)
+ port = Args::StringToUInt32(value.c_str(), 0, 0);
+ }
+ if (port == UINT16_MAX)
+ port = GetAndUpdateNextPort();
+
::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
// Spawn a new thread to accept the port that gets bound after
// binding to port 0 (zero).
- lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
- AcceptPortFromInferior,
- connect_url,
- &error);
-
+ lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD;
+
+ if (port == 0)
+ {
+ accept_thread = Host::ThreadCreate (unix_socket_name,
+ AcceptPortFromInferior,
+ connect_url,
+ &error);
+ }
+
if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
{
- // Spawn a debugserver and try to get
+ // Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
- error = StartDebugserverProcess ("localhost:0",
- unix_socket_name,
+ StreamString host_and_port;
+ if (hostname.empty())
+ hostname = "localhost";
+ host_and_port.Printf("%s:%u", hostname.c_str(), port);
+ const char *host_and_port_cstr = host_and_port.GetString().c_str();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr);
+ error = StartDebugserverProcess (host_and_port_cstr,
+ unix_socket_name,
debugserver_launch_info);
-
+
lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ {
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ m_spawned_pids.insert(debugserver_pid);
+ }
+ Host::StartMonitoringChildProcess (ReapDebugserverProcess, this, debugserver_pid, false);
+ }
+
if (error.Success())
{
bool success = false;
-
- thread_result_t accept_thread_result = NULL;
- if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
+
+ if (accept_thread)
{
- if (accept_thread_result)
+ thread_result_t accept_thread_result = NULL;
+ if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
{
- uint16_t port = (intptr_t)accept_thread_result;
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
- assert (response_len < (int)sizeof(response));
- //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
- success = SendPacketNoLock (response, response_len) > 0;
+ if (accept_thread_result)
+ {
+ port = (intptr_t)accept_thread_result;
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacketNoLock (response, response_len) > 0;
+ }
}
}
+ else
+ {
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacketNoLock (response, response_len) > 0;
+
+ }
::unlink (unix_socket_name);
-
+
if (!success)
{
if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
@@ -730,7 +866,61 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
}
}
}
- return SendErrorResponse (13);
+ return SendErrorResponse (9);
+#endif
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+{
+ // Spawn a local debugserver as a platform so we can then attach or launch
+ // a process...
+
+ if (m_is_platform)
+ {
+ packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+
+ lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return SendErrorResponse (10);
+ }
+ Host::Kill (pid, SIGTERM);
+
+ for (size_t i=0; i<10; ++i)
+ {
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ usleep (10000);
+ }
+
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ Host::Kill (pid, SIGKILL);
+
+ for (size_t i=0; i<10; ++i)
+ {
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ usleep (10000);
+ }
+ }
+ return SendErrorResponse (10);
}
bool
@@ -738,7 +928,7 @@ GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &p
{
if (m_process_launch_error.Success())
return SendOKResponse();
- StreamString response;
+ StreamString response;
response.PutChar('E');
response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
return SendPacketNoLock (response.GetData(), response.GetSize());
@@ -754,7 +944,22 @@ GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &pa
m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
return SendOKResponse ();
}
- return SendErrorResponse (9);
+ return SendErrorResponse (11);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("QLaunchArch:"));
+ const uint32_t bytes_left = packet.GetBytesLeft();
+ if (bytes_left > 0)
+ {
+ const char* arch_triple = packet.Peek();
+ ArchSpec arch_spec(arch_triple,NULL);
+ m_process_launch_info.SetArchitecture(arch_spec);
+ return SendOKResponse();
+ }
+ return SendErrorResponse(12);
}
bool
@@ -792,7 +997,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (10);
+ return SendErrorResponse (13);
}
bool
@@ -809,7 +1014,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (11);
+ return SendErrorResponse (14);
}
bool
@@ -826,7 +1031,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (12);
+ return SendErrorResponse (15);
}
bool
@@ -837,3 +1042,277 @@ GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &
m_send_acks = false;
return true;
}
+
+bool
+GDBRemoteCommunicationServer::Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("qPlatform_IO_MkDir:"));
+ mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ std::string path;
+ packet.GetHexByteString(path);
+ uint32_t retcode = Host::MakeDirectory(path.c_str(),mode);
+ StreamString response;
+ response.PutHex32(retcode);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:open:"));
+ std::string path;
+ packet.GetHexByteStringTerminatedBy(path,',');
+ if (path.size() == 0)
+ return false;
+ if (packet.GetChar() != ',')
+ return false;
+ uint32_t flags = packet.GetHexMaxU32(false, UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
+ Error error;
+ int fd = ::open (path.c_str(), flags, mode);
+ const int save_errno = fd == -1 ? errno : 0;
+ StreamString response;
+ response.PutChar('F');
+ response.Printf("%i", fd);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:close:"));
+ int fd = packet.GetS32(-1);
+ Error error;
+ int err = -1;
+ int save_errno = 0;
+ if (fd >= 0)
+ {
+ err = close(fd);
+ save_errno = err == -1 ? errno : 0;
+ }
+ else
+ {
+ save_errno = EINVAL;
+ }
+ StreamString response;
+ response.PutChar('F');
+ response.Printf("%i", err);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
+{
+#ifdef _WIN32
+ // Not implemented on Windows
+ return false;
+#else
+ StreamGDBRemote response;
+ packet.SetFilePos(::strlen("vFile:pread:"));
+ int fd = packet.GetS32(-1);
+ if (packet.GetChar() != ',')
+ return false;
+ uint64_t count = packet.GetU64(UINT64_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ uint64_t offset = packet.GetU64(UINT32_MAX);
+ if (count == UINT64_MAX)
+ {
+ response.Printf("F-1:%i", EINVAL);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+ }
+ std::string buffer(count, 0);
+ const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
+ const int save_errno = bytes_read == -1 ? errno : 0;
+ response.PutChar('F');
+ response.Printf("%zi", bytes_read);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ else
+ {
+ response.PutChar(';');
+ response.PutEscapedBytes(&buffer[0], bytes_read);
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+#endif
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
+{
+#ifdef _WIN32
+ // Not implemented on Windows
+ return false;
+#else
+ packet.SetFilePos(::strlen("vFile:pwrite:"));
+
+ StreamGDBRemote response;
+ response.PutChar('F');
+
+ int fd = packet.GetU32(UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ off_t offset = packet.GetU64(UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ std::string buffer;
+ if (packet.GetEscapedBinaryData(buffer))
+ {
+ const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
+ const int save_errno = bytes_written == -1 ? errno : 0;
+ response.Printf("%zi", bytes_written);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ }
+ else
+ {
+ response.Printf ("-1,%i", EINVAL);
+ }
+
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+#endif
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:size:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.empty())
+ return false;
+ lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
+ StreamString response;
+ response.PutChar('F');
+ response.PutHex64(retcode);
+ if (retcode == UINT64_MAX)
+ {
+ response.PutChar(',');
+ response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:mode:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.empty())
+ return false;
+ Error error;
+ const uint32_t mode = File::GetPermissions(path.c_str(), error);
+ StreamString response;
+ response.Printf("F%u", mode);
+ if (mode == 0 || error.Fail())
+ response.Printf(",%i", (int)error.GetError());
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:exists:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.empty())
+ return false;
+ bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
+ StreamString response;
+ response.PutChar('F');
+ response.PutChar(',');
+ if (retcode)
+ response.PutChar('1');
+ else
+ response.PutChar('0');
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("qPlatform_RunCommand:"));
+ std::string path;
+ std::string working_dir;
+ packet.GetHexByteStringTerminatedBy(path,',');
+ if (path.size() == 0)
+ return false;
+ if (packet.GetChar() != ',')
+ return false;
+ // FIXME: add timeout to qPlatform_RunCommand packet
+ // uint32_t timeout = packet.GetHexMaxU32(false, 32);
+ uint32_t timeout = 10;
+ if (packet.GetChar() == ',')
+ packet.GetHexByteString(working_dir);
+ int status, signo;
+ std::string output;
+ Error err = Host::RunShellCommand(path.c_str(),
+ working_dir.empty() ? NULL : working_dir.c_str(),
+ &status, &signo, &output, timeout);
+ StreamGDBRemote response;
+ if (err.Fail())
+ {
+ response.PutCString("F,");
+ response.PutHex32(UINT32_MAX);
+ }
+ else
+ {
+ response.PutCString("F,");
+ response.PutHex32(status);
+ response.PutChar(',');
+ response.PutHex32(signo);
+ response.PutChar(',');
+ response.PutEscapedBytes(output.c_str(), output.size());
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
+{
+ return false;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:exists:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.size() == 0)
+ return false;
+ uint64_t a,b;
+ StreamGDBRemote response;
+ if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
+ {
+ response.PutCString("F,");
+ response.PutCString("x");
+ }
+ else
+ {
+ response.PutCString("F,");
+ response.PutHex64(a);
+ response.PutHex64(b);
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index cce0e4e64c1e..64f6f8de1a21 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -12,10 +12,12 @@
// C Includes
// C++ Includes
+#include <vector>
+#include <set>
// Other libraries and framework includes
// Project includes
+#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
-
#include "GDBRemoteCommunication.h"
class ProcessGDBRemote;
@@ -60,6 +62,21 @@ public:
{
m_lo_port_num = lo_port_num;
m_hi_port_num = hi_port_num;
+ m_next_port = m_lo_port_num;
+ m_use_port_range = true;
+ }
+
+ // If we are using a port range, get and update the next port to be used variable.
+ // Otherwise, just return 0.
+ uint16_t
+ GetAndUpdateNextPort ()
+ {
+ if (!m_use_port_range)
+ return 0;
+ uint16_t val = m_next_port;
+ if (++m_next_port > m_hi_port_num)
+ m_next_port = m_lo_port_num;
+ return val;
}
protected:
@@ -68,11 +85,16 @@ protected:
lldb::thread_t m_async_thread;
lldb_private::ProcessLaunchInfo m_process_launch_info;
lldb_private::Error m_process_launch_error;
+ std::set<lldb::pid_t> m_spawned_pids;
+ lldb_private::Mutex m_spawned_pids_mutex;
lldb_private::ProcessInstanceInfoList m_proc_infos;
uint32_t m_proc_infos_index;
uint16_t m_lo_port_num;
uint16_t m_hi_port_num;
//PortToPIDMap m_port_to_pid_map;
+ uint16_t m_next_port;
+ bool m_use_port_range;
+
size_t
SendUnimplementedResponse (const char *packet);
@@ -85,7 +107,7 @@ protected:
bool
Handle_A (StringExtractorGDBRemote &packet);
-
+
bool
Handle_qLaunchSuccess (StringExtractorGDBRemote &packet);
@@ -94,8 +116,14 @@ protected:
bool
Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
bool
+ Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet);
+
+ bool
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
bool
@@ -120,6 +148,9 @@ protected:
Handle_QEnvironment (StringExtractorGDBRemote &packet);
bool
+ Handle_QLaunchArch (StringExtractorGDBRemote &packet);
+
+ bool
Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
bool
@@ -137,7 +168,47 @@ protected:
bool
Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
+ bool
+ Handle_vFile_Open (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Close (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_pRead (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_pWrite (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Size (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Mode (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Exists (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Stat (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_MD5 (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet);
+
private:
+ bool
+ DebugserverProcessReaped (lldb::pid_t pid);
+
+ static bool
+ ReapDebugserverProcess (void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal,
+ int status);
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServer only
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index b1612a5f3c2f..c4e468f89f35 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -17,6 +17,9 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
+#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Interpreter/PythonDataObjects.h"
+#endif
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/Utils.h"
// Project includes
@@ -54,7 +57,7 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext
// Make a heap based buffer that is big enough to store all registers
DataBufferSP reg_data_sp(new DataBufferHeap (reg_info.GetRegisterDataByteSize(), 0));
m_reg_data.SetData (reg_data_sp);
-
+ m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder());
}
//----------------------------------------------------------------------
@@ -696,6 +699,7 @@ GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, ui
return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
}
+
void
GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)
{
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 3110ddf8edf9..7a49d693d44e 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -21,23 +21,20 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Target/RegisterContext.h"
+#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
+
#include "GDBRemoteCommunicationClient.h"
class ThreadGDBRemote;
class ProcessGDBRemote;
class StringExtractor;
-class GDBRemoteDynamicRegisterInfo
+class GDBRemoteDynamicRegisterInfo :
+ public DynamicRegisterInfo
{
public:
GDBRemoteDynamicRegisterInfo () :
- m_regs (),
- m_sets (),
- m_set_reg_nums (),
- m_reg_names (),
- m_reg_alt_names (),
- m_set_names (),
- m_reg_data_byte_size (0)
+ DynamicRegisterInfo()
{
}
@@ -46,151 +43,8 @@ public:
}
void
- AddRegister (lldb_private::RegisterInfo reg_info,
- lldb_private::ConstString &reg_name,
- lldb_private::ConstString &reg_alt_name,
- lldb_private::ConstString &set_name)
- {
- const uint32_t reg_num = (uint32_t)m_regs.size();
- m_reg_names.push_back (reg_name);
- m_reg_alt_names.push_back (reg_alt_name);
- reg_info.name = reg_name.AsCString();
- assert (reg_info.name);
- reg_info.alt_name = reg_alt_name.AsCString(NULL);
- uint32_t i;
- if (reg_info.value_regs)
- {
- for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i)
- m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]);
- m_value_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
- reg_info.value_regs = m_value_regs_map[reg_num].data();
- }
- if (reg_info.invalidate_regs)
- {
- for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i)
- m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]);
- m_invalidate_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
- reg_info.invalidate_regs = m_invalidate_regs_map[reg_num].data();
- }
- m_regs.push_back (reg_info);
- uint32_t set = GetRegisterSetIndexByName (set_name);
- assert (set < m_sets.size());
- assert (set < m_set_reg_nums.size());
- assert (set < m_set_names.size());
- m_set_reg_nums[set].push_back(reg_num);
- size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
- if (m_reg_data_byte_size < end_reg_offset)
- m_reg_data_byte_size = end_reg_offset;
- }
-
- void
- Finalize ()
- {
- for (uint32_t set = 0; set < m_sets.size(); ++set)
- {
- assert (m_sets.size() == m_set_reg_nums.size());
- m_sets[set].num_registers = m_set_reg_nums[set].size();
- m_sets[set].registers = &m_set_reg_nums[set][0];
- }
- }
-
- size_t
- GetNumRegisters() const
- {
- return m_regs.size();
- }
-
- size_t
- GetNumRegisterSets() const
- {
- return m_sets.size();
- }
-
- size_t
- GetRegisterDataByteSize() const
- {
- return m_reg_data_byte_size;
- }
-
- const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (uint32_t i) const
- {
- if (i < m_regs.size())
- return &m_regs[i];
- return NULL;
- }
-
- const lldb_private::RegisterSet *
- GetRegisterSet (uint32_t i) const
- {
- if (i < m_sets.size())
- return &m_sets[i];
- return NULL;
- }
-
- uint32_t
- GetRegisterSetIndexByName (lldb_private::ConstString &set_name)
- {
- name_collection::iterator pos, end = m_set_names.end();
- for (pos = m_set_names.begin(); pos != end; ++pos)
- {
- if (*pos == set_name)
- return static_cast<uint32_t>(std::distance (m_set_names.begin(), pos));
- }
-
- m_set_names.push_back(set_name);
- m_set_reg_nums.resize(m_set_reg_nums.size()+1);
- lldb_private::RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
- m_sets.push_back (new_set);
- return static_cast<uint32_t>(m_sets.size() - 1);
- }
-
- uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
- {
- reg_collection::const_iterator pos, end = m_regs.end();
- for (pos = m_regs.begin(); pos != end; ++pos)
- {
- if (pos->kinds[kind] == num)
- return static_cast<uint32_t>(std::distance (m_regs.begin(), pos));
- }
-
- return LLDB_INVALID_REGNUM;
- }
- void
- Clear()
- {
- m_regs.clear();
- m_sets.clear();
- m_set_reg_nums.clear();
- m_reg_names.clear();
- m_reg_alt_names.clear();
- m_set_names.clear();
- }
-
- void
HardcodeARMRegisters(bool from_scratch);
-protected:
- //------------------------------------------------------------------
- // Classes that inherit from GDBRemoteRegisterContext can see and modify these
- //------------------------------------------------------------------
- typedef std::vector <lldb_private::RegisterInfo> reg_collection;
- typedef std::vector <lldb_private::RegisterSet> set_collection;
- typedef std::vector <uint32_t> reg_num_collection;
- typedef std::vector <reg_num_collection> set_reg_num_collection;
- typedef std::vector <lldb_private::ConstString> name_collection;
- typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map;
-
- reg_collection m_regs;
- set_collection m_sets;
- set_reg_num_collection m_set_reg_nums;
- name_collection m_reg_names;
- name_collection m_reg_alt_names;
- name_collection m_set_names;
- reg_to_regs_map m_value_regs_map;
- reg_to_regs_map m_invalidate_regs_map;
- size_t m_reg_data_byte_size; // The number of bytes required to store all registers
};
class GDBRemoteRegisterContext : public lldb_private::RegisterContext
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index d27207f121d3..aff9c7bc977c 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -8,13 +8,16 @@
//===----------------------------------------------------------------------===//
#include "lldb/lldb-python.h"
+#include "lldb/Host/Config.h"
// C Includes
#include <errno.h>
-#include <spawn.h>
#include <stdlib.h>
+#ifndef LLDB_DISABLE_POSIX
+#include <spawn.h>
#include <netinet/in.h>
#include <sys/mman.h> // for mmap
+#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
@@ -46,6 +49,9 @@
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Interpreter/PythonDataObjects.h"
+#endif
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
@@ -94,12 +100,14 @@ namespace {
g_properties[] =
{
{ "packet-timeout" , OptionValue::eTypeUInt64 , true , 1, NULL, NULL, "Specify the default packet timeout in seconds." },
+ { "target-definition-file" , OptionValue::eTypeFileSpec , true, 0 , NULL, NULL, "The file that provides the description for remote target registers." },
{ NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL }
};
enum
{
- ePropertyPacketTimeout
+ ePropertyPacketTimeout,
+ ePropertyTargetDefinitionFile
};
class PluginProperties : public Properties
@@ -130,6 +138,20 @@ namespace {
const uint32_t idx = ePropertyPacketTimeout;
return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value);
}
+
+ bool
+ SetPacketTimeout(uint64_t timeout)
+ {
+ const uint32_t idx = ePropertyPacketTimeout;
+ return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout);
+ }
+
+ FileSpec
+ GetTargetDefinitionFile () const
+ {
+ const uint32_t idx = ePropertyTargetDefinitionFile;
+ return m_collection_sp->GetPropertyAtIndexAsFileSpec (NULL, idx);
+ }
};
typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
@@ -254,13 +276,13 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
m_continue_C_tids (),
m_continue_s_tids (),
m_continue_S_tids (),
- m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS),
m_max_memory_size (512),
m_addr_to_mmap_size (),
m_thread_create_bp_sp (),
m_waiting_for_attach (false),
m_destroy_tried_resuming (false),
- m_command_sp ()
+ m_command_sp (),
+ m_breakpoint_pc_offset (0)
{
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
@@ -305,6 +327,48 @@ ProcessGDBRemote::GetPluginVersion()
return 1;
}
+bool
+ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_fspec)
+{
+#ifndef LLDB_DISABLE_PYTHON
+ ScriptInterpreter *interpreter = GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ Error error;
+ lldb::ScriptInterpreterObjectSP module_object_sp (interpreter->LoadPluginModule(target_definition_fspec, error));
+ if (module_object_sp)
+ {
+ lldb::ScriptInterpreterObjectSP target_definition_sp (interpreter->GetDynamicSettings(module_object_sp,
+ &GetTarget(),
+ "gdb-server-target-definition",
+ error));
+
+ PythonDictionary target_dict(target_definition_sp);
+
+ if (target_dict)
+ {
+ PythonDictionary host_info_dict (target_dict.GetItemForKey("host-info"));
+ if (host_info_dict)
+ {
+ ArchSpec host_arch (host_info_dict.GetItemForKeyAsString(PythonString("triple")));
+
+ if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture()))
+ {
+ GetTarget().SetArchitecture(host_arch);
+ }
+
+ }
+ m_breakpoint_pc_offset = target_dict.GetItemForKeyAsInteger("breakpoint-pc-offset", 0);
+
+ if (m_register_info.SetRegisterInfo (target_dict, GetTarget().GetArchitecture().GetByteOrder()) > 0)
+ {
+ return true;
+ }
+ }
+ }
+#endif
+ return false;
+}
+
+
void
ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
{
@@ -480,6 +544,28 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
}
}
+ // Check if qHostInfo specified a specific packet timeout for this connection.
+ // If so then lets update our setting so the user knows what the timeout is
+ // and can see it.
+ const uint32_t host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
+ if (host_packet_timeout)
+ {
+ GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout);
+ }
+
+
+ if (reg_num == 0)
+ {
+ FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
+
+ if (target_definition_fspec)
+ {
+ // See if we can get register definitions from a python file
+ if (ParsePythonTargetDefinition (target_definition_fspec))
+ return;
+ }
+ }
+
// We didn't get anything if the accumulated reg_num is zero. See if we are
// debugging ARM and fill with a hard coded register set until we can get an
// updated debugserver down on the devices.
@@ -561,6 +647,11 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
GetThreadList();
if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
{
+ if (!m_target.GetArchitecture().IsValid()) { // Make sure we have an architecture
+ m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ }
+
+
const StateType state = SetThreadStopInfo (m_last_stop_packet);
if (state == eStateStopped)
{
@@ -759,6 +850,10 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, const ProcessLaunchInfo &launch_
if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
{
+ if (!m_target.GetArchitecture().IsValid()) { // Make sure we have an architecture
+ m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ }
+
SetPrivateState (SetThreadStopInfo (m_last_stop_packet));
if (!disable_stdio)
@@ -863,8 +958,6 @@ ProcessGDBRemote::DidLaunchOrAttach ()
log->Printf ("ProcessGDBRemote::DidLaunch()");
if (GetID() != LLDB_INVALID_PROCESS_ID)
{
- m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
-
BuildDynamicRegisterInfo (false);
// See if the GDB server supports the qHostInfo information
@@ -1654,7 +1747,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
// Currently we are going to assume SIGTRAP means we are either
// hitting a breakpoint or hardware single stepping.
handled = true;
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
if (bp_site_sp)
@@ -1664,6 +1757,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
// will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
if (bp_site_sp->ValidForThisThread (thread_sp.get()))
{
+ if(m_breakpoint_pc_offset != 0)
+ thread_sp->GetRegisterContext()->SetPC(pc);
thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
}
else
@@ -2220,7 +2315,7 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
{
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
- if (bp_site->HardwarePreferred())
+ if (bp_site->HardwareRequired())
{
// Try and set hardware breakpoint, and if that fails, fall through
// and set a software breakpoint?
@@ -2230,12 +2325,19 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
{
bp_site->SetEnabled(true);
bp_site->SetType (BreakpointSite::eHardware);
- return error;
}
+ else
+ {
+ error.SetErrorString("failed to set hardware breakpoint (hardware breakpoint resources might be exhausted or unavailable)");
+ }
+ }
+ else
+ {
+ error.SetErrorString("hardware breakpoints are not supported");
}
+ return error;
}
-
- if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
+ else if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
{
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
{
@@ -2687,7 +2789,7 @@ ProcessGDBRemote::KillDebugserverProcess ()
{
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
{
- ::kill (m_debugserver_pid, SIGINT);
+ Host::Kill (m_debugserver_pid, SIGINT);
m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
}
}
@@ -2794,7 +2896,7 @@ ProcessGDBRemote::StopAsyncThread ()
}
-void *
+thread_result_t
ProcessGDBRemote::AsyncThread (void *arg)
{
ProcessGDBRemote *process = (ProcessGDBRemote*) arg;
@@ -2916,97 +3018,6 @@ ProcessGDBRemote::AsyncThread (void *arg)
return NULL;
}
-const char *
-ProcessGDBRemote::GetDispatchQueueNameForThread
-(
- addr_t thread_dispatch_qaddr,
- std::string &dispatch_queue_name
-)
-{
- dispatch_queue_name.clear();
- if (thread_dispatch_qaddr != 0 && thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- // Cache the dispatch_queue_offsets_addr value so we don't always have
- // to look it up
- if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
- {
- static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
- const Symbol *dispatch_queue_offsets_symbol = NULL;
- ModuleSpec libSystem_module_spec (FileSpec("libSystem.B.dylib", false));
- ModuleSP module_sp(GetTarget().GetImages().FindFirstModule (libSystem_module_spec));
- if (module_sp)
- dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
-
- if (dispatch_queue_offsets_symbol == NULL)
- {
- ModuleSpec libdispatch_module_spec (FileSpec("libdispatch.dylib", false));
- module_sp = GetTarget().GetImages().FindFirstModule (libdispatch_module_spec);
- if (module_sp)
- dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
- }
- if (dispatch_queue_offsets_symbol)
- m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetAddress().GetLoadAddress(&m_target);
-
- if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
- return NULL;
- }
-
- uint8_t memory_buffer[8];
- DataExtractor data (memory_buffer,
- sizeof(memory_buffer),
- m_target.GetArchitecture().GetByteOrder(),
- m_target.GetArchitecture().GetAddressByteSize());
-
- // Excerpt from src/queue_private.h
- struct dispatch_queue_offsets_s
- {
- uint16_t dqo_version;
- uint16_t dqo_label; // in version 1-3, offset to string; in version 4+, offset to a pointer to a string
- uint16_t dqo_label_size; // in version 1-3, length of string; in version 4+, size of a (void*) in this process
- } dispatch_queue_offsets;
-
-
- Error error;
- if (ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets))
- {
- lldb::offset_t data_offset = 0;
- if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
- {
- if (ReadMemory (thread_dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
- {
- data_offset = 0;
- lldb::addr_t queue_addr = data.GetAddress(&data_offset);
- if (dispatch_queue_offsets.dqo_version >= 4)
- {
- // libdispatch versions 4+, pointer to dispatch name is in the
- // queue structure.
- lldb::addr_t pointer_to_label_address = queue_addr + dispatch_queue_offsets.dqo_label;
- if (ReadMemory (pointer_to_label_address, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
- {
- data_offset = 0;
- lldb::addr_t label_addr = data.GetAddress(&data_offset);
- ReadCStringFromMemory (label_addr, dispatch_queue_name, error);
- }
- }
- else
- {
- // libdispatch versions 1-3, dispatch name is a fixed width char array
- // in the queue structure.
- lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
- dispatch_queue_name.resize(dispatch_queue_offsets.dqo_label_size, '\0');
- size_t bytes_read = ReadMemory (label_addr, &dispatch_queue_name[0], dispatch_queue_offsets.dqo_label_size, error);
- if (bytes_read < dispatch_queue_offsets.dqo_label_size)
- dispatch_queue_name.erase (bytes_read);
- }
- }
- }
- }
- }
- if (dispatch_queue_name.empty())
- return NULL;
- return dispatch_queue_name.c_str();
-}
-
//uint32_t
//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
//{
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index e104b7191eab..b18ac5b1723e 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -291,6 +291,12 @@ protected:
void
SetLastStopPacket (const StringExtractorGDBRemote &response);
+ bool
+ ParsePythonTargetDefinition(const lldb_private::FileSpec &target_definition_fspec);
+
+ bool
+ ParseRegisters(lldb_private::ScriptInterpreterObject *registers_array);
+
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
//------------------------------------------------------------------
@@ -326,13 +332,13 @@ protected:
tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
tid_collection m_continue_s_tids; // 's' for step
tid_sig_collection m_continue_S_tids; // 'S' for step with signal
- lldb::addr_t m_dispatch_queue_offsets_addr;
size_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
MMapMap m_addr_to_mmap_size;
lldb::BreakpointSP m_thread_create_bp_sp;
bool m_waiting_for_attach;
bool m_destroy_tried_resuming;
lldb::CommandObjectSP m_command_sp;
+ int64_t m_breakpoint_pc_offset;
bool
StartAsyncThread ();
@@ -340,7 +346,7 @@ protected:
void
StopAsyncThread ();
- static void *
+ static lldb::thread_result_t
AsyncThread (void *arg);
static bool
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 38fb84d66ef3..4e475c80bdab 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -10,16 +10,17 @@
#include "ThreadGDBRemote.h"
+#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Platform.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/Watchpoint.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
@@ -73,13 +74,38 @@ ThreadGDBRemote::GetQueueName ()
ProcessSP process_sp (GetProcess());
if (process_sp)
{
- ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
- return gdb_process->GetDispatchQueueNameForThread (m_thread_dispatch_qaddr, m_dispatch_queue_name);
+ PlatformSP platform_sp (process_sp->GetTarget().GetPlatform());
+ if (platform_sp)
+ {
+ m_dispatch_queue_name = platform_sp->GetQueueNameForThreadQAddress (process_sp.get(), m_thread_dispatch_qaddr);
+ }
+ if (m_dispatch_queue_name.length() > 0)
+ {
+ return m_dispatch_queue_name.c_str();
+ }
}
}
return NULL;
}
+queue_id_t
+ThreadGDBRemote::GetQueueID ()
+{
+ if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ {
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
+ {
+ PlatformSP platform_sp (process_sp->GetTarget().GetPlatform());
+ if (platform_sp)
+ {
+ return platform_sp->GetQueueIDForThreadQAddress (process_sp.get(), m_thread_dispatch_qaddr);
+ }
+ }
+ }
+ return LLDB_INVALID_QUEUE_ID;
+}
+
void
ThreadGDBRemote::WillResume (StateType resume_state)
{
@@ -164,7 +190,6 @@ lldb::RegisterContextSP
ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
{
lldb::RegisterContextSP reg_ctx_sp;
- const bool read_all_registers_at_once = false;
uint32_t concrete_frame_idx = 0;
if (frame)
@@ -177,6 +202,8 @@ ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
if (process_sp)
{
ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
+ // read_all_registers_at_once will be true if 'p' packet is not supported.
+ bool read_all_registers_at_once = !gdb_process->GetGDBRemote().GetpPacketSupported (GetID());
reg_ctx_sp.reset (new GDBRemoteRegisterContext (*this, concrete_frame_idx, gdb_process->m_register_info, read_all_registers_at_once));
}
}
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index 50a3f19c6505..dd4cc036ef8b 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -38,6 +38,9 @@ public:
virtual const char *
GetQueueName ();
+ virtual lldb::queue_id_t
+ GetQueueID ();
+
virtual lldb::RegisterContextSP
GetRegisterContext ();
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
index 06e87eab33ce..ff2e3762556a 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -32,13 +32,13 @@ DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t
}
bool
-DWARFAbbreviationDeclaration::Extract(const DataExtractor& data, lldb::offset_t* offset_ptr)
+DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor& data, lldb::offset_t* offset_ptr)
{
return Extract(data, offset_ptr, data.GetULEB128(offset_ptr));
}
bool
-DWARFAbbreviationDeclaration::Extract(const DataExtractor& data, lldb::offset_t *offset_ptr, dw_uleb128_t code)
+DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor& data, lldb::offset_t *offset_ptr, dw_uleb128_t code)
{
m_code = code;
m_attributes.clear();
@@ -139,7 +139,7 @@ DWARFAbbreviationDeclaration::CopyExcludingAddressAttributes(const DWARFAbbrevia
void
DWARFAbbreviationDeclaration::CopyChangingStringToStrp(
const DWARFAbbreviationDeclaration& abbr_decl,
- const DataExtractor& debug_info_data,
+ const DWARFDataExtractor& debug_info_data,
dw_offset_t debug_info_offset,
const DWARFCompileUnit* cu,
const uint32_t strp_min_len
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
index f462b7fc108d..48b9ebe37ee7 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
@@ -58,13 +58,13 @@ public:
void CopyExcludingAddressAttributes(const DWARFAbbreviationDeclaration& abbr_decl, const uint32_t idx);
void CopyChangingStringToStrp(
const DWARFAbbreviationDeclaration& abbr_decl,
- const lldb_private::DataExtractor& debug_info_data,
+ const lldb_private::DWARFDataExtractor& debug_info_data,
dw_offset_t debug_info_offset,
const DWARFCompileUnit* cu,
const uint32_t strp_min_len);
uint32_t FindAttributeIndex(dw_attr_t attr) const;
- bool Extract(const lldb_private::DataExtractor& data, lldb::offset_t *offset_ptr);
- bool Extract(const lldb_private::DataExtractor& data, lldb::offset_t *offset_ptr, dw_uleb128_t code);
+ bool Extract(const lldb_private::DWARFDataExtractor& data, lldb::offset_t *offset_ptr);
+ bool Extract(const lldb_private::DWARFDataExtractor& data, lldb::offset_t *offset_ptr, dw_uleb128_t code);
// void Append(BinaryStreamBuf& out_buff) const;
bool IsValid();
void Dump(lldb_private::Stream *s) const;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
index 8310b1dda5f1..40c8af3d6e8e 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -28,7 +28,7 @@ public:
dw_form_t get_form() const { return (dw_form_t)m_attr_form; }
void get(dw_attr_t& attr, dw_form_t& form) const
{
- register uint32_t attr_form = m_attr_form;
+ uint32_t attr_form = m_attr_form;
attr = attr_form >> 16;
form = (dw_form_t)attr_form;
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index 493b3af6ecd1..cf664db28acd 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -69,7 +69,7 @@ DWARFCompileUnit::Clear()
}
bool
-DWARFCompileUnit::Extract(const DataExtractor &debug_info, lldb::offset_t *offset_ptr)
+DWARFCompileUnit::Extract(const DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr)
{
Clear();
@@ -103,30 +103,6 @@ DWARFCompileUnit::Extract(const DataExtractor &debug_info, lldb::offset_t *offse
}
-dw_offset_t
-DWARFCompileUnit::Extract(lldb::offset_t offset, const DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs)
-{
- Clear();
-
- m_offset = offset;
-
- if (debug_info_data.ValidOffset(offset))
- {
- m_length = debug_info_data.GetU32(&offset);
- m_version = debug_info_data.GetU16(&offset);
- bool abbrevs_OK = debug_info_data.GetU32(&offset) == abbrevs->GetOffset();
- m_abbrevs = abbrevs;
- m_addr_size = debug_info_data.GetU8 (&offset);
-
- bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
- bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
-
- if (version_OK && addr_size_OK && abbrevs_OK && debug_info_data.ValidOffset(offset))
- return offset;
- }
- return DW_INVALID_OFFSET;
-}
-
void
DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die)
{
@@ -187,7 +163,7 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
uint32_t depth = 0;
// We are in our compile unit, parse starting at the offset
// we were told to parse
- const DataExtractor& debug_info_data = m_dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor& debug_info_data = m_dwarf2Data->get_debug_info_data();
std::vector<uint32_t> die_index_stack;
die_index_stack.reserve(32);
die_index_stack.push_back(0);
@@ -312,7 +288,7 @@ DWARFCompileUnit::GetAbbrevOffset() const
bool
DWARFCompileUnit::Verify(Stream *s) const
{
- const DataExtractor& debug_info = m_dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor& debug_info = m_dwarf2Data->get_debug_info_data();
bool valid_offset = debug_info.ValidOffset(m_offset);
bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1);
bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
@@ -612,7 +588,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
NameToDIE& types,
NameToDIE& namespaces)
{
- const DataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data();
+ const DWARFDataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data();
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize());
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index 9fee0a2d2236..35597f389423 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -29,8 +29,7 @@ public:
DWARFCompileUnit(SymbolFileDWARF* dwarf2Data);
- bool Extract(const lldb_private::DataExtractor &debug_info, lldb::offset_t *offset_ptr);
- dw_offset_t Extract(lldb::offset_t offset, const lldb_private::DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs);
+ bool Extract(const lldb_private::DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr);
size_t ExtractDIEsIfNeeded (bool cu_die_only);
bool LookupAddress(
const dw_addr_t address,
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
new file mode 100644
index 000000000000..9bf47cd7a9ac
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
@@ -0,0 +1,30 @@
+//===-- DWARFDataExtractor.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDataExtractor.h"
+
+namespace lldb_private {
+
+uint64_t
+DWARFDataExtractor::GetDWARFInitialLength(lldb::offset_t *offset_ptr) const
+{
+ uint64_t length = GetU32(offset_ptr);
+ m_is_dwarf64 = (length == UINT32_MAX);
+ if (m_is_dwarf64)
+ length = GetU64(offset_ptr);
+ return length;
+}
+
+dw_offset_t
+DWARFDataExtractor::GetDWARFOffset(lldb::offset_t *offset_ptr) const
+{
+ return GetMaxU64(offset_ptr, m_is_dwarf64 ? 8 : 4);
+}
+
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
new file mode 100644
index 000000000000..6e5b974a71ff
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
@@ -0,0 +1,43 @@
+//===-- DWARFDataExtractor.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_DWARFDataExtractor_h_
+#define liblldb_DWARFDataExtractor_h_
+
+// Other libraries and framework includes.
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/dwarf.h"
+
+namespace lldb_private {
+
+class DWARFDataExtractor : public lldb_private::DataExtractor
+{
+public:
+ DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) { };
+
+ DWARFDataExtractor (const DWARFDataExtractor& data, lldb::offset_t offset, lldb::offset_t length) :
+ DataExtractor(data, offset, length), m_is_dwarf64(false) { };
+
+ uint64_t
+ GetDWARFInitialLength(lldb::offset_t *offset_ptr) const;
+
+ dw_offset_t
+ GetDWARFOffset(lldb::offset_t *offset_ptr) const;
+
+ size_t
+ GetDWARFSizeofInitialLength() const { return m_is_dwarf64 ? 12 : 4; }
+
+protected:
+ mutable bool m_is_dwarf64;
+};
+
+}
+
+#endif // liblldb_DWARFDataExtractor_h_
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
index 47657d5089b2..6773d0762a21 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "DWARFDebugAbbrev.h"
-#include "lldb/Core/DataExtractor.h"
+#include "DWARFDataExtractor.h"
#include "lldb/Core/Stream.h"
using namespace lldb;
@@ -30,7 +30,7 @@ DWARFAbbreviationDeclarationSet::Clear()
// DWARFAbbreviationDeclarationSet::Extract()
//----------------------------------------------------------------------
bool
-DWARFAbbreviationDeclarationSet::Extract(const DataExtractor& data, lldb::offset_t *offset_ptr)
+DWARFAbbreviationDeclarationSet::Extract(const DWARFDataExtractor& data, lldb::offset_t *offset_ptr)
{
const lldb::offset_t begin_offset = *offset_ptr;
m_offset = begin_offset;
@@ -142,7 +142,7 @@ DWARFDebugAbbrev::DWARFDebugAbbrev() :
// DWARFDebugAbbrev::Parse()
//----------------------------------------------------------------------
void
-DWARFDebugAbbrev::Parse(const DataExtractor& data)
+DWARFDebugAbbrev::Parse(const DWARFDataExtractor& data)
{
lldb::offset_t offset = 0;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
index eba439928a2c..8ec2c4ba8e21 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
@@ -43,7 +43,7 @@ public:
void Clear();
dw_offset_t GetOffset() const { return m_offset; }
void Dump(lldb_private::Stream *s) const;
- bool Extract(const lldb_private::DataExtractor& data, lldb::offset_t *offset_ptr);
+ bool Extract(const lldb_private::DWARFDataExtractor& data, lldb::offset_t *offset_ptr);
//void Encode(BinaryStreamBuf& debug_abbrev_buf) const;
dw_uleb128_t AppendAbbrevDeclSequential(const DWARFAbbreviationDeclaration& abbrevDecl);
@@ -65,7 +65,7 @@ public:
DWARFDebugAbbrev();
const DWARFAbbreviationDeclarationSet* GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const;
void Dump(lldb_private::Stream *s) const;
- void Parse(const lldb_private::DataExtractor& data);
+ void Parse(const lldb_private::DWARFDataExtractor& data);
protected:
DWARFAbbreviationDeclarationCollMap m_abbrevCollMap;
mutable DWARFAbbreviationDeclarationCollMapConstIter m_prev_abbr_offset_pos;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
index b1eb27299efb..d083f8a615c4 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
@@ -162,7 +162,7 @@ DWARFDebugArangeSet::AddDescriptor(const DWARFDebugArangeSet::Descriptor& range)
}
bool
-DWARFDebugArangeSet::Extract(const DataExtractor &data, lldb::offset_t *offset_ptr)
+DWARFDebugArangeSet::Extract(const DWARFDataExtractor &data, lldb::offset_t *offset_ptr)
{
if (data.ValidOffset(*offset_ptr))
{
@@ -183,9 +183,9 @@ DWARFDebugArangeSet::Extract(const DataExtractor &data, lldb::offset_t *offset_p
// descriptor on the target system. This header is followed by a series
// of tuples. Each tuple consists of an address and a length, each in
// the size appropriate for an address on the target architecture.
- m_header.length = data.GetU32(offset_ptr);
+ m_header.length = data.GetDWARFInitialLength(offset_ptr);
m_header.version = data.GetU16(offset_ptr);
- m_header.cu_offset = data.GetU32(offset_ptr);
+ m_header.cu_offset = data.GetDWARFOffset(offset_ptr);
m_header.addr_size = data.GetU8(offset_ptr);
m_header.seg_size = data.GetU8(offset_ptr);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
index 19ec8d042e72..fde36b7e0adc 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
@@ -41,7 +41,7 @@ public:
void SetHeader(uint16_t version, uint32_t cu_offset, uint8_t addr_size, uint8_t seg_size);
void AddDescriptor(const DWARFDebugArangeSet::Descriptor& range);
void Compact();
- bool Extract(const lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr);
+ bool Extract(const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr);
void Dump(lldb_private::Stream *s) const;
dw_offset_t GetCompileUnitDIEOffset() const { return m_header.cu_offset; }
dw_offset_t GetOffsetOfNextEntry() const;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
index 3b004c4b3890..4f77bff86bdc 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -56,7 +56,7 @@ public:
// Extract
//----------------------------------------------------------------------
bool
-DWARFDebugAranges::Extract(const DataExtractor &debug_aranges_data)
+DWARFDebugAranges::Extract(const DWARFDataExtractor &debug_aranges_data)
{
if (debug_aranges_data.ValidOffset(0))
{
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
index 88db929226ab..206aa3a60f49 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
@@ -35,7 +35,7 @@ public:
}
bool
- Extract(const lldb_private::DataExtractor &debug_aranges_data);
+ Extract(const lldb_private::DWARFDataExtractor &debug_aranges_data);
bool
Generate(SymbolFileDWARF* dwarf2Data);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 4c76eed8166f..d4db12c17a40 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -57,7 +57,7 @@ DWARFDebugInfo::GetCompileUnitAranges ()
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
m_cu_aranges_ap.reset (new DWARFDebugAranges());
- const DataExtractor &debug_aranges_data = m_dwarf2Data->get_debug_aranges_data();
+ const DWARFDataExtractor &debug_aranges_data = m_dwarf2Data->get_debug_aranges_data();
if (debug_aranges_data.GetByteSize() > 0)
{
if (log)
@@ -66,18 +66,35 @@ DWARFDebugInfo::GetCompileUnitAranges ()
m_cu_aranges_ap->Extract (debug_aranges_data);
}
- else
+
+ // Make a list of all CUs represented by the arange data in the file.
+ std::set<dw_offset_t> cus_with_data;
+ for (size_t n=0;n<m_cu_aranges_ap.get()->GetNumRanges();n++)
{
- if (log)
- log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing",
- m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
- const size_t num_compile_units = GetNumCompileUnits();
- const bool clear_dies_if_already_not_parsed = true;
- for (size_t idx = 0; idx < num_compile_units; ++idx)
+ dw_offset_t offset = m_cu_aranges_ap.get()->OffsetAtIndex(n);
+ if (offset != DW_INVALID_OFFSET)
+ cus_with_data.insert (offset);
+ }
+
+ // Manually build arange data for everything that wasn't in the .debug_aranges table.
+ bool printed = false;
+ const size_t num_compile_units = GetNumCompileUnits();
+ const bool clear_dies_if_already_not_parsed = true;
+ for (size_t idx = 0; idx < num_compile_units; ++idx)
+ {
+ DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx);
+
+ dw_offset_t offset = cu-&