aboutsummaryrefslogtreecommitdiffstats
path: root/source/Plugins
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2015-02-06 21:38:51 +0000
committerEd Maste <emaste@FreeBSD.org>2015-02-06 21:38:51 +0000
commit205afe679855a4ce8149cdaa94d3f0868ce796dc (patch)
tree09bc83f73246ee3c7a779605cd0122093d2a8a19 /source/Plugins
parent0cac4ca3916ac24ab6139d03cbfd18db9e715bfe (diff)
downloadsrc-205afe679855a4ce8149cdaa94d3f0868ce796dc.tar.gz
src-205afe679855a4ce8149cdaa94d3f0868ce796dc.zip
Import LLDB as of upstream SVN r225923 (git 2b588ecd)vendor/lldb/lldb-r225923
This corresponds with the branchpoint for the 3.6 release. A number of files not required for the FreeBSD build have been removed. Sponsored by: DARPA, AFRL
Notes
Notes: svn path=/vendor/lldb/dist/; revision=278332 svn path=/vendor/lldb/lldb-r225923/; revision=278333; tag=vendor/lldb/lldb-r225923
Diffstat (limited to 'source/Plugins')
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp30
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h14
-rw-r--r--source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp34
-rw-r--r--source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h16
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h14
-rw-r--r--source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h14
-rw-r--r--source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp1120
-rw-r--r--source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h143
-rw-r--r--source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp1124
-rw-r--r--source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h143
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp14
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h14
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp37
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp28
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp189
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h4
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp2
-rw-r--r--source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp314
-rw-r--r--source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h86
-rw-r--r--source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp30
-rw-r--r--source/Plugins/JITLoader/GDB/JITLoaderGDB.h4
-rw-r--r--source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp183
-rw-r--r--source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h62
-rw-r--r--source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp2
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.cpp9
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp135
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h3
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp77
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h6
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp130
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h56
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp26
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h7
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp3
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp66
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h7
-rw-r--r--source/Plugins/Process/POSIX/POSIXThread.cpp45
-rw-r--r--source/Plugins/Process/POSIX/POSIXThread.h2
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.cpp39
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.h59
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp4
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp4
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp321
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h95
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp9
-rw-r--r--source/Plugins/Process/Utility/ARMDefines.h34
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.cpp12
-rw-r--r--source/Plugins/Process/Utility/HistoryThread.cpp2
-rw-r--r--source/Plugins/Process/Utility/HistoryThread.h12
-rw-r--r--source/Plugins/Process/Utility/HistoryUnwind.cpp2
-rw-r--r--source/Plugins/Process/Utility/HistoryUnwind.h3
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.cpp24
-rw-r--r--source/Plugins/Process/Utility/InstructionUtils.h2
-rw-r--r--source/Plugins/Process/Utility/LinuxSignals.cpp2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp230
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h66
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp703
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.h26
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp3
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp273
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h173
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp578
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h277
-rw-r--r--source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp2
-rw-r--r--source/Plugins/Process/Utility/RegisterContext_powerpc.h163
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_arm64.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_i386.h18
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_powerpc.h144
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_x86_64.h34
-rw-r--r--source/Plugins/Process/Utility/StopInfoMachException.cpp8
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp46
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.h3
-rw-r--r--source/Plugins/Process/Utility/lldb-x86-register-enums.h461
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp25
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.h24
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp2
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp109
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h62
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp2
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.cpp20
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp118
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp61
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp236
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h19
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp134
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h97
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp16
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp29
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h15
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h3
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp24
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp91
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp20
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h1
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp153
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.h23
-rw-r--r--source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h6
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp280
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h5
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp3
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp473
103 files changed, 7910 insertions, 2176 deletions
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index a9f8f3b668dc..5073b13f09ab 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -801,6 +801,36 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info)
break;
}
}
+ else if (name[0] == 'q')
+ {
+ switch (name[1])
+ {
+ case '1':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // q1 is volatile
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ return true; // q10-q15 are volatile
+ default:
+ break;
+ };
+ case '0':
+ case '2':
+ case '3':
+ return name[2] == '\0'; // q0-q3 are volatile
+ case '8':
+ case '9':
+ return name[2] == '\0'; // q8-q9 are volatile
+ default:
+ break;
+ }
+ }
else if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')
return true;
}
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
index 6f7b339e28a2..eee43943d73a 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
@@ -53,13 +53,7 @@ public:
virtual bool
RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
-
- virtual bool
- StackUsesFrames ()
- {
- return true;
- }
-
+
virtual bool
CallFrameAddressIsValid (lldb::addr_t cfa)
{
@@ -88,12 +82,6 @@ public:
return pc & ~(lldb::addr_t)1;
}
- virtual bool
- FunctionCallsChangeCFA ()
- {
- return false;
- }
-
virtual const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count);
diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
index 8f7962d095fc..465257db31d8 100644
--- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
+++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
@@ -440,11 +440,11 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO
}
const uint32_t type_flags = return_value_type.GetTypeInfo (NULL);
- if (type_flags & ClangASTType::eTypeIsScalar ||
- type_flags & ClangASTType::eTypeIsPointer)
+ if (type_flags & eTypeIsScalar ||
+ type_flags & eTypeIsPointer)
{
- if (type_flags & ClangASTType::eTypeIsInteger ||
- type_flags & ClangASTType::eTypeIsPointer )
+ if (type_flags & eTypeIsInteger ||
+ type_flags & eTypeIsPointer )
{
// Extract the register context so we can read arguments from registers
lldb::offset_t offset = 0;
@@ -477,9 +477,9 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO
error.SetErrorString("We don't support returning longer than 128 bit integer values at present.");
}
}
- else if (type_flags & ClangASTType::eTypeIsFloat)
+ else if (type_flags & eTypeIsFloat)
{
- if (type_flags & ClangASTType::eTypeIsComplex)
+ if (type_flags & eTypeIsComplex)
{
// Don't handle complex yet.
error.SetErrorString ("returning complex float values are not supported");
@@ -519,7 +519,7 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO
}
}
}
- else if (type_flags & ClangASTType::eTypeIsVector)
+ else if (type_flags & eTypeIsVector)
{
if (byte_size > 0)
{
@@ -874,14 +874,14 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
const size_t byte_size = return_clang_type.GetByteSize();
const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);
- if (type_flags & ClangASTType::eTypeIsScalar ||
- type_flags & ClangASTType::eTypeIsPointer)
+ if (type_flags & eTypeIsScalar ||
+ type_flags & eTypeIsPointer)
{
value.SetValueType(Value::eValueTypeScalar);
bool success = false;
- if (type_flags & ClangASTType::eTypeIsInteger ||
- type_flags & ClangASTType::eTypeIsPointer )
+ if (type_flags & eTypeIsInteger ||
+ type_flags & eTypeIsPointer )
{
// Extract the register context so we can read arguments from registers
if (byte_size <= 8)
@@ -890,7 +890,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
if (x0_reg_info)
{
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(x0_reg_info, 0);
- const bool is_signed = (type_flags & ClangASTType::eTypeIsSigned) != 0;
+ const bool is_signed = (type_flags & eTypeIsSigned) != 0;
switch (byte_size)
{
default:
@@ -965,9 +965,9 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
}
}
}
- else if (type_flags & ClangASTType::eTypeIsFloat)
+ else if (type_flags & eTypeIsFloat)
{
- if (type_flags & ClangASTType::eTypeIsComplex)
+ if (type_flags & eTypeIsComplex)
{
// Don't handle complex yet.
}
@@ -1010,7 +1010,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
ConstString(""));
}
- else if (type_flags & ClangASTType::eTypeIsVector)
+ else if (type_flags & eTypeIsVector)
{
if (byte_size > 0)
{
@@ -1046,8 +1046,8 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
}
}
}
- else if (type_flags & ClangASTType::eTypeIsStructUnion ||
- type_flags & ClangASTType::eTypeIsClass)
+ else if (type_flags & eTypeIsStructUnion ||
+ type_flags & eTypeIsClass)
{
DataExtractor data;
diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
index 0753b23ce2a2..6cce6a6f1174 100644
--- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
+++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
@@ -46,15 +46,7 @@ public:
virtual bool
RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
-
-
- virtual bool
- StackUsesFrames ()
- {
- // MacOSX uses frame pointers.
- return true;
- }
-
+
// The arm64 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
// code, we've seen that the stack pointer is often not aligned properly
@@ -87,12 +79,6 @@ public:
return true;
}
- virtual bool
- FunctionCallsChangeCFA ()
- {
- return false;
- }
-
virtual const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count);
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
index 43784a5c9111..d81b7a7e684b 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
@@ -64,13 +64,7 @@ public:
virtual bool
RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
-
- virtual bool
- StackUsesFrames ()
- {
- return true;
- }
-
+
// The Darwin i386 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
// code, we've seen that the stack pointer is often not aligned properly
@@ -102,12 +96,6 @@ public:
return pc <= UINT32_MAX;
}
- virtual bool
- FunctionCallsChangeCFA ()
- {
- return true;
- }
-
virtual const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count);
diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
index 989c4a16710a..1550a38c4f3b 100644
--- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
+++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
@@ -75,13 +75,7 @@ public:
virtual bool
RegisterIsVolatile ( const lldb_private::RegisterInfo *reg_info );
-
- virtual bool
- StackUsesFrames ( void )
- {
- return true;
- }
-
+
virtual bool
CallFrameAddressIsValid ( lldb::addr_t cfa )
{
@@ -101,12 +95,6 @@ public:
return true;
}
- virtual bool
- FunctionCallsChangeCFA ( void )
- {
- return true;
- }
-
virtual const lldb_private::RegisterInfo *
GetRegisterInfoArray ( uint32_t &count );
diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
new file mode 100644
index 000000000000..adb3313d1a30
--- /dev/null
+++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
@@ -0,0 +1,1120 @@
+//===-- ABISysV_ppc.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_ppc.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum gcc_dwarf_regnums
+{
+ gcc_dwarf_r0 = 0,
+ gcc_dwarf_r1,
+ gcc_dwarf_r2,
+ gcc_dwarf_r3,
+ gcc_dwarf_r4,
+ gcc_dwarf_r5,
+ gcc_dwarf_r6,
+ gcc_dwarf_r7,
+ gcc_dwarf_r8,
+ gcc_dwarf_r9,
+ gcc_dwarf_r10,
+ gcc_dwarf_r11,
+ gcc_dwarf_r12,
+ gcc_dwarf_r13,
+ gcc_dwarf_r14,
+ gcc_dwarf_r15,
+ gcc_dwarf_r16,
+ gcc_dwarf_r17,
+ gcc_dwarf_r18,
+ gcc_dwarf_r19,
+ gcc_dwarf_r20,
+ gcc_dwarf_r21,
+ gcc_dwarf_r22,
+ gcc_dwarf_r23,
+ gcc_dwarf_r24,
+ gcc_dwarf_r25,
+ gcc_dwarf_r26,
+ gcc_dwarf_r27,
+ gcc_dwarf_r28,
+ gcc_dwarf_r29,
+ gcc_dwarf_r30,
+ gcc_dwarf_r31,
+ gcc_dwarf_f0,
+ gcc_dwarf_f1,
+ gcc_dwarf_f2,
+ gcc_dwarf_f3,
+ gcc_dwarf_f4,
+ gcc_dwarf_f5,
+ gcc_dwarf_f6,
+ gcc_dwarf_f7,
+ gcc_dwarf_f8,
+ gcc_dwarf_f9,
+ gcc_dwarf_f10,
+ gcc_dwarf_f11,
+ gcc_dwarf_f12,
+ gcc_dwarf_f13,
+ gcc_dwarf_f14,
+ gcc_dwarf_f15,
+ gcc_dwarf_f16,
+ gcc_dwarf_f17,
+ gcc_dwarf_f18,
+ gcc_dwarf_f19,
+ gcc_dwarf_f20,
+ gcc_dwarf_f21,
+ gcc_dwarf_f22,
+ gcc_dwarf_f23,
+ gcc_dwarf_f24,
+ gcc_dwarf_f25,
+ gcc_dwarf_f26,
+ gcc_dwarf_f27,
+ gcc_dwarf_f28,
+ gcc_dwarf_f29,
+ gcc_dwarf_f30,
+ gcc_dwarf_f31,
+ gcc_dwarf_cr,
+ gcc_dwarf_fpscr,
+ gcc_dwarf_xer = 101,
+ gcc_dwarf_lr = 108,
+ gcc_dwarf_ctr,
+ gcc_dwarf_pc,
+ gcc_dwarf_cfa,
+};
+
+enum gdb_regnums
+{
+ gdb_r0 = 0,
+ gdb_r1,
+ gdb_r2,
+ gdb_r3,
+ gdb_r4,
+ gdb_r5,
+ gdb_r6,
+ gdb_r7,
+ gdb_r8,
+ gdb_r9,
+ gdb_r10,
+ gdb_r11,
+ gdb_r12,
+ gdb_r13,
+ gdb_r14,
+ gdb_r15,
+ gdb_r16,
+ gdb_r17,
+ gdb_r18,
+ gdb_r19,
+ gdb_r20,
+ gdb_r21,
+ gdb_r22,
+ gdb_r23,
+ gdb_r24,
+ gdb_r25,
+ gdb_r26,
+ gdb_r27,
+ gdb_r28,
+ gdb_r29,
+ gdb_r30,
+ gdb_r31,
+ gdb_lr,
+ gdb_cr,
+ gdb_xer,
+ gdb_ctr,
+ gdb_pc,
+};
+
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
+ { #reg, alt, 8, 0, eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4}, NULL, NULL }
+static const RegisterInfo
+g_register_infos[] =
+{
+ // General purpose registers. GCC, DWARF, Generic, GDB
+ DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0),
+ DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1),
+ DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2),
+ DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3),
+ DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4),
+ DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5),
+ DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6),
+ DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7),
+ DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8),
+ DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9),
+ DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10),
+ DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11),
+ DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12),
+ DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13),
+ DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14),
+ DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15),
+ DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16),
+ DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17),
+ DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18),
+ DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19),
+ DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20),
+ DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21),
+ DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22),
+ DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23),
+ DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24),
+ DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25),
+ DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26),
+ DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27),
+ DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28),
+ DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29),
+ DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30),
+ DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31),
+ DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr),
+ DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
+};
+
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+
+const lldb_private::RegisterInfo *
+ABISysV_ppc::GetRegisterInfoArray (uint32_t &count)
+{
+ count = k_num_register_infos;
+ return g_register_infos;
+}
+
+
+size_t
+ABISysV_ppc::GetRedZoneSize () const
+{
+ return 224;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_ppc::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc)
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_ppc);
+ return g_abi_sp;
+ }
+ return ABISP();
+}
+
+bool
+ABISysV_ppc::PrepareTrivialCall (Thread &thread,
+ addr_t sp,
+ addr_t func_addr,
+ addr_t return_addr,
+ llvm::ArrayRef<addr_t> args) const
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ StreamString s;
+ s.Printf("ABISysV_ppc::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64,
+ thread.GetID(),
+ (uint64_t)sp,
+ (uint64_t)func_addr,
+ (uint64_t)return_addr);
+
+ for (size_t i = 0; i < args.size(); ++i)
+ s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
+ s.PutCString (")");
+ log->PutCString(s.GetString().c_str());
+ }
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ const RegisterInfo *reg_info = NULL;
+
+ if (args.size() > 8) // TODO handle more than 8 arguments
+ return false;
+
+ for (size_t i = 0; i < args.size(); ++i)
+ {
+ reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+ if (log)
+ log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+ if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
+ return false;
+ }
+
+ // First, align the SP
+
+ if (log)
+ log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, (uint64_t)sp, (uint64_t)(sp & ~0xfull));
+
+ sp &= ~(0xfull); // 16-byte 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;
+
+#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: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr);
+
+ // Save return address onto the stack
+ if (!process_sp->WritePointerToMemory(sp, return_addr, error))
+ return false;
+
+ // %r1 is set to the actual stack value.
+
+ if (log)
+ log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
+ return false;
+
+ // %pc is set to the address of the called function.
+
+ if (log)
+ log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
+ return false;
+
+ return true;
+}
+
+static bool ReadIntegerArgument(Scalar &scalar,
+ unsigned int bit_width,
+ bool is_signed,
+ Thread &thread,
+ uint32_t *argument_register_ids,
+ unsigned int &current_argument_register,
+ addr_t &current_stack_argument)
+{
+ if (bit_width > 64)
+ return false; // Scalar can't hold large integer arguments
+
+ if (current_argument_register < 6)
+ {
+ scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0);
+ current_argument_register++;
+ if (is_signed)
+ scalar.SignExtend (bit_width);
+ }
+ else
+ {
+ uint32_t byte_size = (bit_width + (8-1))/8;
+ Error error;
+ if (thread.GetProcess()->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
+ {
+ current_stack_argument += byte_size;
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
+bool
+ABISysV_ppc::GetArgumentValues (Thread &thread,
+ ValueList &values) const
+{
+ unsigned int num_values = values.GetSize();
+ unsigned int value_index;
+
+ // Extract the register context so we can read arguments from registers
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+
+ if (!reg_ctx)
+ return false;
+
+ // Get the pointer to the first stack argument so we have a place to start
+ // when reading data
+
+ addr_t sp = reg_ctx->GetSP(0);
+
+ if (!sp)
+ return false;
+
+ addr_t current_stack_argument = sp + 48; // jump over return address
+
+ uint32_t argument_register_ids[8];
+
+ 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];
+ argument_register_ids[6] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG7)->kinds[eRegisterKindLLDB];
+ argument_register_ids[7] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG8)->kinds[eRegisterKindLLDB];
+
+ unsigned int current_argument_register = 0;
+
+ for (value_index = 0;
+ value_index < num_values;
+ ++value_index)
+ {
+ Value *value = values.GetValueAtIndex(value_index);
+
+ if (!value)
+ return false;
+
+ // We currently only support extracting values with Clang QualTypes.
+ // Do we care about others?
+ ClangASTType clang_type = value->GetClangType();
+ if (!clang_type)
+ return false;
+ bool is_signed;
+
+ if (clang_type.IsIntegerType (is_signed))
+ {
+ ReadIntegerArgument(value->GetScalar(),
+ clang_type.GetBitSize(),
+ is_signed,
+ thread,
+ argument_register_ids,
+ current_argument_register,
+ current_stack_argument);
+ }
+ else if (clang_type.IsPointerType ())
+ {
+ ReadIntegerArgument(value->GetScalar(),
+ clang_type.GetBitSize(),
+ false,
+ thread,
+ argument_register_ids,
+ current_argument_register,
+ current_stack_argument);
+ }
+ }
+
+ return true;
+}
+
+Error
+ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ ClangASTType clang_type = new_value_sp->GetClangType();
+ if (!clang_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+ lldb::offset_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (reg_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+
+ }
+ else if (clang_type.IsFloatingPointType (count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ {
+ size_t bit_width = clang_type.GetBitSize();
+ if (bit_width <= 64)
+ {
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+
+ unsigned char buffer[16];
+ ByteOrder byte_order = data.GetByteOrder();
+
+ data.CopyByteOrderedData (0, num_bytes, buffer, 16, byte_order);
+ set_it_simple = true;
+ }
+ else
+ {
+ // FIXME - don't know how to do 80 bit long doubles yet.
+ error.SetErrorString ("We don't support returning float values > 64 bits at present");
+ }
+ }
+ }
+
+ if (!set_it_simple)
+ {
+ // Okay we've got a structure or something that doesn't fit in a simple register.
+ // We should figure out where it really goes, but we don't support this yet.
+ error.SetErrorString ("We only support setting simple integer and float return types at present.");
+ }
+
+ return error;
+}
+
+
+ValueObjectSP
+ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
+ ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ Value value;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ //value.SetContext (Value::eContextTypeClangType, return_value_type);
+ value.SetClangType (return_clang_type);
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ if (type_flags & eTypeIsScalar)
+ {
+ value.SetValueType(Value::eValueTypeScalar);
+
+ bool success = false;
+ if (type_flags & eTypeIsInteger)
+ {
+ // Extract the register context so we can read arguments from registers
+
+ const size_t byte_size = return_clang_type.GetByteSize();
+ uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0);
+ const bool is_signed = (type_flags & eTypeIsSigned) != 0;
+ switch (byte_size)
+ {
+ default:
+ break;
+
+ case sizeof(uint64_t):
+ if (is_signed)
+ value.GetScalar() = (int64_t)(raw_value);
+ else
+ value.GetScalar() = (uint64_t)(raw_value);
+ success = true;
+ break;
+
+ case sizeof(uint32_t):
+ if (is_signed)
+ value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+ else
+ value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint16_t):
+ if (is_signed)
+ value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+ else
+ value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint8_t):
+ if (is_signed)
+ value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+ else
+ value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+ success = true;
+ break;
+ }
+ }
+ else if (type_flags & eTypeIsFloat)
+ {
+ if (type_flags & eTypeIsComplex)
+ {
+ // Don't handle complex yet.
+ }
+ else
+ {
+ const size_t byte_size = return_clang_type.GetByteSize();
+ if (byte_size <= sizeof(long double))
+ {
+ const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
+ RegisterValue f1_value;
+ if (reg_ctx->ReadRegister (f1_info, f1_value))
+ {
+ DataExtractor data;
+ if (f1_value.GetData(data))
+ {
+ lldb::offset_t offset = 0;
+ if (byte_size == sizeof(float))
+ {
+ value.GetScalar() = (float) data.GetFloat(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(double))
+ {
+ value.GetScalar() = (double) data.GetDouble(&offset);
+ success = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (success)
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+
+ }
+ else if (type_flags & eTypeIsPointer)
+ {
+ unsigned r3_id = reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
+ value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
+ value.SetValueType(Value::eValueTypeScalar);
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ }
+ else if (type_flags & eTypeIsVector)
+ {
+ const size_t byte_size = return_clang_type.GetByteSize();
+ if (byte_size > 0)
+ {
+
+ const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v0", 0);
+ if (altivec_reg == NULL)
+ altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
+ if (altivec_reg)
+ {
+ if (byte_size <= altivec_reg->byte_size)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister(altivec_reg, reg_value))
+ {
+ Error error;
+ if (reg_value.GetAsMemoryData (altivec_reg,
+ heap_data_ap->GetBytes(),
+ heap_data_ap->GetByteSize(),
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return return_valobj_sp;
+}
+
+ValueObjectSP
+ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ if (return_valobj_sp)
+ return return_valobj_sp;
+
+ RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
+ if (!reg_ctx_sp)
+ return return_valobj_sp;
+
+ const size_t bit_width = return_clang_type.GetBitSize();
+ if (return_clang_type.IsAggregateType())
+ {
+ Target *target = exe_ctx.GetTargetPtr();
+ bool is_memory = true;
+ if (bit_width <= 128)
+ {
+ ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
+ DataBufferSP data_sp (new DataBufferHeap(16, 0));
+ DataExtractor return_ext (data_sp,
+ target_byte_order,
+ target->GetArchitecture().GetAddressByteSize());
+
+ const RegisterInfo *r3_info = reg_ctx_sp->GetRegisterInfoByName("r3", 0);
+ const RegisterInfo *rdx_info = reg_ctx_sp->GetRegisterInfoByName("rdx", 0);
+
+ RegisterValue r3_value, rdx_value;
+ reg_ctx_sp->ReadRegister (r3_info, r3_value);
+ reg_ctx_sp->ReadRegister (rdx_info, rdx_value);
+
+ DataExtractor r3_data, rdx_data;
+
+ r3_value.GetData(r3_data);
+ rdx_value.GetData(rdx_data);
+
+ uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
+ uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far
+
+ const uint32_t num_children = return_clang_type.GetNumFields ();
+
+ // Since we are in the small struct regime, assume we are not in memory.
+ is_memory = false;
+
+ for (uint32_t idx = 0; idx < num_children; idx++)
+ {
+ std::string name;
+ uint64_t field_bit_offset = 0;
+ bool is_signed;
+ bool is_complex;
+ uint32_t count;
+
+ ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_bit_width = field_clang_type.GetBitSize();
+
+ // If there are any unaligned fields, this is stored in memory.
+ if (field_bit_offset % field_bit_width != 0)
+ {
+ is_memory = true;
+ break;
+ }
+
+ uint32_t field_byte_width = field_bit_width/8;
+ uint32_t field_byte_offset = field_bit_offset/8;
+
+
+ DataExtractor *copy_from_extractor = NULL;
+ uint32_t copy_from_offset = 0;
+
+ if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+ {
+ if (integer_bytes < 8)
+ {
+ if (integer_bytes + field_byte_width <= 8)
+ {
+ // This is in RAX, copy from register to our result structure:
+ copy_from_extractor = &r3_data;
+ copy_from_offset = integer_bytes;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ // The next field wouldn't fit in the remaining space, so we pushed it to rdx.
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = 0;
+ integer_bytes = 8 + field_byte_width;
+
+ }
+ }
+ else if (integer_bytes + field_byte_width <= 16)
+ {
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = integer_bytes - 8;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ // The last field didn't fit. I can't see how that would happen w/o the overall size being
+ // greater than 16 bytes. For now, return a NULL return value object.
+ return return_valobj_sp;
+ }
+ }
+ else if (field_clang_type.IsFloatingPointType (count, is_complex))
+ {
+ // Structs with long doubles are always passed in memory.
+ if (field_bit_width == 128)
+ {
+ is_memory = true;
+ break;
+ }
+ else if (field_bit_width == 64)
+ {
+ copy_from_offset = 0;
+ fp_bytes += field_byte_width;
+ }
+ else if (field_bit_width == 32)
+ {
+ // This one is kind of complicated. If we are in an "eightbyte" with another float, we'll
+ // be stuffed into an xmm register with it. If we are in an "eightbyte" with one or more ints,
+ // then we will be stuffed into the appropriate GPR with them.
+ bool in_gpr;
+ if (field_byte_offset % 8 == 0)
+ {
+ // We are at the beginning of one of the eightbytes, so check the next element (if any)
+ if (idx == num_children - 1)
+ in_gpr = false;
+ else
+ {
+ uint64_t next_field_bit_offset = 0;
+ ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+ name,
+ &next_field_bit_offset,
+ NULL,
+ NULL);
+ if (next_field_clang_type.IsIntegerType (is_signed))
+ in_gpr = true;
+ else
+ {
+ copy_from_offset = 0;
+ in_gpr = false;
+ }
+ }
+
+ }
+ else if (field_byte_offset % 4 == 0)
+ {
+ // We are inside of an eightbyte, so see if the field before us is floating point:
+ // This could happen if somebody put padding in the structure.
+ if (idx == 0)
+ in_gpr = false;
+ else
+ {
+ uint64_t prev_field_bit_offset = 0;
+ ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+ name,
+ &prev_field_bit_offset,
+ NULL,
+ NULL);
+ if (prev_field_clang_type.IsIntegerType (is_signed))
+ in_gpr = true;
+ else
+ {
+ copy_from_offset = 4;
+ in_gpr = false;
+ }
+ }
+
+ }
+ else
+ {
+ is_memory = true;
+ continue;
+ }
+
+ // Okay, we've figured out whether we are in GPR or XMM, now figure out which one.
+ if (in_gpr)
+ {
+ if (integer_bytes < 8)
+ {
+ // This is in RAX, copy from register to our result structure:
+ copy_from_extractor = &r3_data;
+ copy_from_offset = integer_bytes;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = integer_bytes - 8;
+ integer_bytes += field_byte_width;
+ }
+ }
+ else
+ {
+ fp_bytes += field_byte_width;
+ }
+ }
+ }
+
+ // These two tests are just sanity checks. If I somehow get the
+ // type calculation wrong above it is better to just return nothing
+ // than to assert or crash.
+ if (!copy_from_extractor)
+ return return_valobj_sp;
+ if (copy_from_offset + field_byte_width > copy_from_extractor->GetByteSize())
+ return return_valobj_sp;
+
+ copy_from_extractor->CopyByteOrderedData (copy_from_offset,
+ field_byte_width,
+ data_sp->GetBytes() + field_byte_offset,
+ field_byte_width,
+ target_byte_order);
+ }
+
+ if (!is_memory)
+ {
+ // The result is in our data buffer. Let's make a variable object out of it:
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ return_ext);
+ }
+ }
+
+
+ // FIXME: This is just taking a guess, r3 may very well no longer hold the return storage location.
+ // If we are going to do this right, when we make a new frame we should check to see if it uses a memory
+ // return, and if we are at the first instruction and if so stash away the return location. Then we would
+ // only return the memory return value if we know it is valid.
+
+ if (is_memory)
+ {
+ unsigned r3_id = reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
+ lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
+ return_valobj_sp = ValueObjectMemory::Create (&thread,
+ "",
+ Address (storage_addr, NULL),
+ return_clang_type);
+ }
+ }
+
+ return return_valobj_sp;
+}
+
+bool
+ABISysV_ppc::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t lr_reg_num = gcc_dwarf_lr;
+ uint32_t sp_reg_num = gcc_dwarf_r1;
+ uint32_t pc_reg_num = gcc_dwarf_pc;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our Call Frame Address is the stack pointer value
+ row->SetCFARegister (sp_reg_num);
+
+ // The previous PC is in the LR
+ row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+
+ unwind_plan.SetSourceName ("ppc at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+
+ return true;
+}
+
+bool
+ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t sp_reg_num = gcc_dwarf_r1;
+ uint32_t pc_reg_num = gcc_dwarf_lr;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ const int32_t ptr_size = 4;
+ row->SetCFARegister (sp_reg_num);
+ row->SetCFAType(lldb_private::UnwindPlan::Row::CFAIsRegisterDereferenced);
+
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 1, true);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("ppc default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+ unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr);
+ return true;
+}
+
+bool
+ABISysV_ppc::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ return !RegisterIsCalleeSaved (reg_info);
+}
+
+
+
+// See "Register Usage" in the
+// "System V Application Binary Interface"
+// "64-bit PowerPC ELF Application Binary Interface Supplement"
+// current version is 1.9 released 2004 at http://refspecs.linuxfoundation.org/ELF/ppc/PPC-elf64abi-1.9.pdf
+
+bool
+ABISysV_ppc::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ // Preserved registers are :
+ // r1,r2,r13-r31
+ // f14-f31 (not yet)
+ // v20-v31 (not yet)
+ // vrsave (not yet)
+
+ const char *name = reg_info->name;
+ if (name[0] == 'r')
+ {
+ if ((name[1] == '1' || name[1] == '2') && name[2] == '\0')
+ return true;
+ if (name[1] == '1' && name[2] > '2')
+ return true;
+ if ((name[1] == '2' || name[1] == '3') && name[2] != '\0')
+ return true;
+ }
+
+ if (name[0] == 'f' && name[1] >= '0' && name[1] <= '9')
+ {
+ if (name[3] == '1' && name[4] >= '4')
+ return true;
+ if ((name[3] == '2' || name[3] == '3') && name[4] != '\0')
+ return true;
+ }
+
+ if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
+ return true;
+ if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
+ return true;
+ if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
+ return true;
+ }
+ return false;
+}
+
+
+
+void
+ABISysV_ppc::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "System V ABI for ppc targets",
+ CreateInstance);
+}
+
+void
+ABISysV_ppc::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABISysV_ppc::GetPluginNameStatic()
+{
+ static ConstString g_name("sysv-ppc");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABISysV_ppc::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_ppc::GetPluginVersion()
+{
+ return 1;
+}
+
diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
new file mode 100644
index 000000000000..a7aad300e297
--- /dev/null
+++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
@@ -0,0 +1,143 @@
+//===-- ABISysV_ppc.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_ABISysV_ppc_h_
+#define liblldb_ABISysV_ppc_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABISysV_ppc :
+ public lldb_private::ABI
+{
+public:
+
+ ~ABISysV_ppc()
+ {
+ }
+
+ virtual size_t
+ GetRedZoneSize () const;
+
+ virtual bool
+ PrepareTrivialCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const;
+
+ virtual bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const;
+
+ virtual lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
+protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &ast_type) const;
+
+public:
+ virtual lldb::ValueObjectSP
+ GetReturnValueObjectImpl (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &type) const;
+
+ virtual bool
+ CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+
+ virtual bool
+ StackUsesFrames ()
+ {
+ return true;
+ }
+
+ // The SysV ppc ABI requires that stack frames be 16 byte aligned.
+ // When there is a trap handler on the stack, e.g. _sigtramp in userland
+ // code, we've seen that the stack pointer is often not aligned properly
+ // before the handler is invoked. This means that lldb will stop the unwind
+ // early -- before the function which caused the trap.
+ //
+ // To work around this, we relax that alignment to be just word-size (8-bytes).
+ // Whitelisting the trap handlers for user space would be easy (_sigtramp) but
+ // in other environments there can be a large number of different functions
+ // involved in async traps.
+ virtual bool
+ CallFrameAddressIsValid (lldb::addr_t cfa)
+ {
+ // Make sure the stack call frame addresses are 8 byte aligned
+ if (cfa & (8ull - 1ull))
+ return false; // Not 8 byte aligned
+ if (cfa == 0)
+ return false; // Zero is not a valid stack address
+ return true;
+ }
+
+ virtual bool
+ CodeAddressIsValid (lldb::addr_t pc)
+ {
+ // We have a 64 bit address space, so anything is valid as opcodes
+ // aren't fixed width...
+ return true;
+ }
+
+ virtual bool
+ FunctionCallsChangeCFA ()
+ {
+ return true;
+ }
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfoArray (uint32_t &count);
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ABISP
+ CreateInstance (const lldb_private::ArchSpec &arch);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual lldb_private::ConstString
+ GetPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+protected:
+ void
+ CreateRegisterMapIfNeeded ();
+
+ bool
+ RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
+
+private:
+ ABISysV_ppc() : lldb_private::ABI() { } // Call CreateInstance instead.
+};
+
+#endif // liblldb_ABI_h_
diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
new file mode 100644
index 000000000000..46f1e1023f0a
--- /dev/null
+++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
@@ -0,0 +1,1124 @@
+//===-- ABISysV_ppc64.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_ppc64.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum gcc_dwarf_regnums
+{
+ gcc_dwarf_r0 = 0,
+ gcc_dwarf_r1,
+ gcc_dwarf_r2,
+ gcc_dwarf_r3,
+ gcc_dwarf_r4,
+ gcc_dwarf_r5,
+ gcc_dwarf_r6,
+ gcc_dwarf_r7,
+ gcc_dwarf_r8,
+ gcc_dwarf_r9,
+ gcc_dwarf_r10,
+ gcc_dwarf_r11,
+ gcc_dwarf_r12,
+ gcc_dwarf_r13,
+ gcc_dwarf_r14,
+ gcc_dwarf_r15,
+ gcc_dwarf_r16,
+ gcc_dwarf_r17,
+ gcc_dwarf_r18,
+ gcc_dwarf_r19,
+ gcc_dwarf_r20,
+ gcc_dwarf_r21,
+ gcc_dwarf_r22,
+ gcc_dwarf_r23,
+ gcc_dwarf_r24,
+ gcc_dwarf_r25,
+ gcc_dwarf_r26,
+ gcc_dwarf_r27,
+ gcc_dwarf_r28,
+ gcc_dwarf_r29,
+ gcc_dwarf_r30,
+ gcc_dwarf_r31,
+ gcc_dwarf_f0,
+ gcc_dwarf_f1,
+ gcc_dwarf_f2,
+ gcc_dwarf_f3,
+ gcc_dwarf_f4,
+ gcc_dwarf_f5,
+ gcc_dwarf_f6,
+ gcc_dwarf_f7,
+ gcc_dwarf_f8,
+ gcc_dwarf_f9,
+ gcc_dwarf_f10,
+ gcc_dwarf_f11,
+ gcc_dwarf_f12,
+ gcc_dwarf_f13,
+ gcc_dwarf_f14,
+ gcc_dwarf_f15,
+ gcc_dwarf_f16,
+ gcc_dwarf_f17,
+ gcc_dwarf_f18,
+ gcc_dwarf_f19,
+ gcc_dwarf_f20,
+ gcc_dwarf_f21,
+ gcc_dwarf_f22,
+ gcc_dwarf_f23,
+ gcc_dwarf_f24,
+ gcc_dwarf_f25,
+ gcc_dwarf_f26,
+ gcc_dwarf_f27,
+ gcc_dwarf_f28,
+ gcc_dwarf_f29,
+ gcc_dwarf_f30,
+ gcc_dwarf_f31,
+ gcc_dwarf_cr,
+ gcc_dwarf_fpscr,
+ gcc_dwarf_xer = 101,
+ gcc_dwarf_lr = 108,
+ gcc_dwarf_ctr,
+ gcc_dwarf_pc,
+ gcc_dwarf_cfa,
+};
+
+enum gdb_regnums
+{
+ gdb_r0 = 0,
+ gdb_r1,
+ gdb_r2,
+ gdb_r3,
+ gdb_r4,
+ gdb_r5,
+ gdb_r6,
+ gdb_r7,
+ gdb_r8,
+ gdb_r9,
+ gdb_r10,
+ gdb_r11,
+ gdb_r12,
+ gdb_r13,
+ gdb_r14,
+ gdb_r15,
+ gdb_r16,
+ gdb_r17,
+ gdb_r18,
+ gdb_r19,
+ gdb_r20,
+ gdb_r21,
+ gdb_r22,
+ gdb_r23,
+ gdb_r24,
+ gdb_r25,
+ gdb_r26,
+ gdb_r27,
+ gdb_r28,
+ gdb_r29,
+ gdb_r30,
+ gdb_r31,
+ gdb_lr,
+ gdb_cr,
+ gdb_xer,
+ gdb_ctr,
+ gdb_pc,
+};
+
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
+ { #reg, alt, 8, 0, eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4}, NULL, NULL }
+static const RegisterInfo
+g_register_infos[] =
+{
+ // General purpose registers. GCC, DWARF, Generic, GDB
+ DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0),
+ DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1),
+ DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2),
+ DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3),
+ DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4),
+ DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5),
+ DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6),
+ DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7),
+ DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8),
+ DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9),
+ DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10),
+ DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11),
+ DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12),
+ DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13),
+ DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14),
+ DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15),
+ DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16),
+ DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17),
+ DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18),
+ DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19),
+ DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20),
+ DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21),
+ DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22),
+ DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23),
+ DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24),
+ DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25),
+ DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26),
+ DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27),
+ DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28),
+ DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29),
+ DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30),
+ DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31),
+ DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr),
+ DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
+};
+
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+
+const lldb_private::RegisterInfo *
+ABISysV_ppc64::GetRegisterInfoArray (uint32_t &count)
+{
+ count = k_num_register_infos;
+ return g_register_infos;
+}
+
+
+size_t
+ABISysV_ppc64::GetRedZoneSize () const
+{
+ return 224;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_ppc64::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc64)
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_ppc64);
+ return g_abi_sp;
+ }
+ return ABISP();
+}
+
+bool
+ABISysV_ppc64::PrepareTrivialCall (Thread &thread,
+ addr_t sp,
+ addr_t func_addr,
+ addr_t return_addr,
+ llvm::ArrayRef<addr_t> args) const
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ StreamString s;
+ s.Printf("ABISysV_ppc64::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64,
+ thread.GetID(),
+ (uint64_t)sp,
+ (uint64_t)func_addr,
+ (uint64_t)return_addr);
+
+ for (size_t i = 0; i < args.size(); ++i)
+ s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
+ s.PutCString (")");
+ log->PutCString(s.GetString().c_str());
+ }
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ const RegisterInfo *reg_info = NULL;
+
+ if (args.size() > 8) // TODO handle more than 8 arguments
+ return false;
+
+ for (size_t i = 0; i < args.size(); ++i)
+ {
+ reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+ if (log)
+ log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+ if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
+ return false;
+ }
+
+ // First, align the SP
+
+ if (log)
+ log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, (uint64_t)sp, (uint64_t)(sp & ~0xfull));
+
+ sp &= ~(0xfull); // 16-byte 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;
+
+#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: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr);
+
+ // Save return address onto the stack
+ if (!process_sp->WritePointerToMemory(sp, return_addr, error))
+ return false;
+
+ // %r1 is set to the actual stack value.
+
+ if (log)
+ log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
+ return false;
+
+ // %pc is set to the address of the called function.
+
+ if (log)
+ log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
+ return false;
+
+ return true;
+}
+
+static bool ReadIntegerArgument(Scalar &scalar,
+ unsigned int bit_width,
+ bool is_signed,
+ Thread &thread,
+ uint32_t *argument_register_ids,
+ unsigned int &current_argument_register,
+ addr_t &current_stack_argument)
+{
+ if (bit_width > 64)
+ return false; // Scalar can't hold large integer arguments
+
+ if (current_argument_register < 6)
+ {
+ scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0);
+ current_argument_register++;
+ if (is_signed)
+ scalar.SignExtend (bit_width);
+ }
+ else
+ {
+ uint32_t byte_size = (bit_width + (8-1))/8;
+ Error error;
+ if (thread.GetProcess()->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
+ {
+ current_stack_argument += byte_size;
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
+bool
+ABISysV_ppc64::GetArgumentValues (Thread &thread,
+ ValueList &values) const
+{
+ unsigned int num_values = values.GetSize();
+ unsigned int value_index;
+
+ // Extract the register context so we can read arguments from registers
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+
+ if (!reg_ctx)
+ return false;
+
+ // Get the pointer to the first stack argument so we have a place to start
+ // when reading data
+
+ addr_t sp = reg_ctx->GetSP(0);
+
+ if (!sp)
+ return false;
+
+ addr_t current_stack_argument = sp + 48; // jump over return address
+
+ uint32_t argument_register_ids[8];
+
+ 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];
+ argument_register_ids[6] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG7)->kinds[eRegisterKindLLDB];
+ argument_register_ids[7] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG8)->kinds[eRegisterKindLLDB];
+
+ unsigned int current_argument_register = 0;
+
+ for (value_index = 0;
+ value_index < num_values;
+ ++value_index)
+ {
+ Value *value = values.GetValueAtIndex(value_index);
+
+ if (!value)
+ return false;
+
+ // We currently only support extracting values with Clang QualTypes.
+ // Do we care about others?
+ ClangASTType clang_type = value->GetClangType();
+ if (!clang_type)
+ return false;
+ bool is_signed;
+
+ if (clang_type.IsIntegerType (is_signed))
+ {
+ ReadIntegerArgument(value->GetScalar(),
+ clang_type.GetBitSize(),
+ is_signed,
+ thread,
+ argument_register_ids,
+ current_argument_register,
+ current_stack_argument);
+ }
+ else if (clang_type.IsPointerType ())
+ {
+ ReadIntegerArgument(value->GetScalar(),
+ clang_type.GetBitSize(),
+ false,
+ thread,
+ argument_register_ids,
+ current_argument_register,
+ current_stack_argument);
+ }
+ }
+
+ return true;
+}
+
+Error
+ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ ClangASTType clang_type = new_value_sp->GetClangType();
+ if (!clang_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+ lldb::offset_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (reg_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+
+ }
+ else if (clang_type.IsFloatingPointType (count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ {
+ size_t bit_width = clang_type.GetBitSize();
+ if (bit_width <= 64)
+ {
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+
+ unsigned char buffer[16];
+ ByteOrder byte_order = data.GetByteOrder();
+
+ data.CopyByteOrderedData (0, num_bytes, buffer, 16, byte_order);
+ set_it_simple = true;
+ }
+ else
+ {
+ // FIXME - don't know how to do 80 bit long doubles yet.
+ error.SetErrorString ("We don't support returning float values > 64 bits at present");
+ }
+ }
+ }
+
+ if (!set_it_simple)
+ {
+ // Okay we've got a structure or something that doesn't fit in a simple register.
+ // We should figure out where it really goes, but we don't support this yet.
+ error.SetErrorString ("We only support setting simple integer and float return types at present.");
+ }
+
+ return error;
+}
+
+
+ValueObjectSP
+ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
+ ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ Value value;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ //value.SetContext (Value::eContextTypeClangType, return_value_type);
+ value.SetClangType (return_clang_type);
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ if (type_flags & eTypeIsScalar)
+ {
+ value.SetValueType(Value::eValueTypeScalar);
+
+ bool success = false;
+ if (type_flags & eTypeIsInteger)
+ {
+ // Extract the register context so we can read arguments from registers
+
+ const size_t byte_size = return_clang_type.GetByteSize();
+ uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0);
+ const bool is_signed = (type_flags & eTypeIsSigned) != 0;
+ switch (byte_size)
+ {
+ default:
+ break;
+
+ case sizeof(uint64_t):
+ if (is_signed)
+ value.GetScalar() = (int64_t)(raw_value);
+ else
+ value.GetScalar() = (uint64_t)(raw_value);
+ success = true;
+ break;
+
+ case sizeof(uint32_t):
+ if (is_signed)
+ value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+ else
+ value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint16_t):
+ if (is_signed)
+ value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+ else
+ value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint8_t):
+ if (is_signed)
+ value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+ else
+ value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+ success = true;
+ break;
+ }
+ }
+ else if (type_flags & eTypeIsFloat)
+ {
+ if (type_flags & eTypeIsComplex)
+ {
+ // Don't handle complex yet.
+ }
+ else
+ {
+ const size_t byte_size = return_clang_type.GetByteSize();
+ if (byte_size <= sizeof(long double))
+ {
+ const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
+ RegisterValue f1_value;
+ if (reg_ctx->ReadRegister (f1_info, f1_value))
+ {
+ DataExtractor data;
+ if (f1_value.GetData(data))
+ {
+ lldb::offset_t offset = 0;
+ if (byte_size == sizeof(float))
+ {
+ value.GetScalar() = (float) data.GetFloat(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(double))
+ {
+ value.GetScalar() = (double) data.GetDouble(&offset);
+ success = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (success)
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+
+ }
+ else if (type_flags & eTypeIsPointer)
+ {
+ unsigned r3_id = reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
+ value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
+ value.SetValueType(Value::eValueTypeScalar);
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ }
+ else if (type_flags & eTypeIsVector)
+ {
+ const size_t byte_size = return_clang_type.GetByteSize();
+ if (byte_size > 0)
+ {
+
+ const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v0", 0);
+ if (altivec_reg == NULL)
+ altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
+ if (altivec_reg)
+ {
+ if (byte_size <= altivec_reg->byte_size)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister(altivec_reg, reg_value))
+ {
+ Error error;
+ if (reg_value.GetAsMemoryData (altivec_reg,
+ heap_data_ap->GetBytes(),
+ heap_data_ap->GetByteSize(),
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return return_valobj_sp;
+}
+
+ValueObjectSP
+ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ if (return_valobj_sp)
+ return return_valobj_sp;
+
+ RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
+ if (!reg_ctx_sp)
+ return return_valobj_sp;
+
+ const size_t bit_width = return_clang_type.GetBitSize();
+ if (return_clang_type.IsAggregateType())
+ {
+ Target *target = exe_ctx.GetTargetPtr();
+ bool is_memory = true;
+ if (bit_width <= 128)
+ {
+ ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
+ DataBufferSP data_sp (new DataBufferHeap(16, 0));
+ DataExtractor return_ext (data_sp,
+ target_byte_order,
+ target->GetArchitecture().GetAddressByteSize());
+
+ const RegisterInfo *r3_info = reg_ctx_sp->GetRegisterInfoByName("r3", 0);
+ const RegisterInfo *rdx_info = reg_ctx_sp->GetRegisterInfoByName("rdx", 0);
+
+ RegisterValue r3_value, rdx_value;
+ reg_ctx_sp->ReadRegister (r3_info, r3_value);
+ reg_ctx_sp->ReadRegister (rdx_info, rdx_value);
+
+ DataExtractor r3_data, rdx_data;
+
+ r3_value.GetData(r3_data);
+ rdx_value.GetData(rdx_data);
+
+ uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
+ uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far
+
+ const uint32_t num_children = return_clang_type.GetNumFields ();
+
+ // Since we are in the small struct regime, assume we are not in memory.
+ is_memory = false;
+
+ for (uint32_t idx = 0; idx < num_children; idx++)
+ {
+ std::string name;
+ uint64_t field_bit_offset = 0;
+ bool is_signed;
+ bool is_complex;
+ uint32_t count;
+
+ ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_bit_width = field_clang_type.GetBitSize();
+
+ // If there are any unaligned fields, this is stored in memory.
+ if (field_bit_offset % field_bit_width != 0)
+ {
+ is_memory = true;
+ break;
+ }
+
+ uint32_t field_byte_width = field_bit_width/8;
+ uint32_t field_byte_offset = field_bit_offset/8;
+
+
+ DataExtractor *copy_from_extractor = NULL;
+ uint32_t copy_from_offset = 0;
+
+ if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+ {
+ if (integer_bytes < 8)
+ {
+ if (integer_bytes + field_byte_width <= 8)
+ {
+ // This is in RAX, copy from register to our result structure:
+ copy_from_extractor = &r3_data;
+ copy_from_offset = integer_bytes;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ // The next field wouldn't fit in the remaining space, so we pushed it to rdx.
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = 0;
+ integer_bytes = 8 + field_byte_width;
+
+ }
+ }
+ else if (integer_bytes + field_byte_width <= 16)
+ {
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = integer_bytes - 8;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ // The last field didn't fit. I can't see how that would happen w/o the overall size being
+ // greater than 16 bytes. For now, return a NULL return value object.
+ return return_valobj_sp;
+ }
+ }
+ else if (field_clang_type.IsFloatingPointType (count, is_complex))
+ {
+ // Structs with long doubles are always passed in memory.
+ if (field_bit_width == 128)
+ {
+ is_memory = true;
+ break;
+ }
+ else if (field_bit_width == 64)
+ {
+ copy_from_offset = 0;
+ fp_bytes += field_byte_width;
+ }
+ else if (field_bit_width == 32)
+ {
+ // This one is kind of complicated. If we are in an "eightbyte" with another float, we'll
+ // be stuffed into an xmm register with it. If we are in an "eightbyte" with one or more ints,
+ // then we will be stuffed into the appropriate GPR with them.
+ bool in_gpr;
+ if (field_byte_offset % 8 == 0)
+ {
+ // We are at the beginning of one of the eightbytes, so check the next element (if any)
+ if (idx == num_children - 1)
+ in_gpr = false;
+ else
+ {
+ uint64_t next_field_bit_offset = 0;
+ ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+ name,
+ &next_field_bit_offset,
+ NULL,
+ NULL);
+ if (next_field_clang_type.IsIntegerType (is_signed))
+ in_gpr = true;
+ else
+ {
+ copy_from_offset = 0;
+ in_gpr = false;
+ }
+ }
+
+ }
+ else if (field_byte_offset % 4 == 0)
+ {
+ // We are inside of an eightbyte, so see if the field before us is floating point:
+ // This could happen if somebody put padding in the structure.
+ if (idx == 0)
+ in_gpr = false;
+ else
+ {
+ uint64_t prev_field_bit_offset = 0;
+ ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+ name,
+ &prev_field_bit_offset,
+ NULL,
+ NULL);
+ if (prev_field_clang_type.IsIntegerType (is_signed))
+ in_gpr = true;
+ else
+ {
+ copy_from_offset = 4;
+ in_gpr = false;
+ }
+ }
+
+ }
+ else
+ {
+ is_memory = true;
+ continue;
+ }
+
+ // Okay, we've figured out whether we are in GPR or XMM, now figure out which one.
+ if (in_gpr)
+ {
+ if (integer_bytes < 8)
+ {
+ // This is in RAX, copy from register to our result structure:
+ copy_from_extractor = &r3_data;
+ copy_from_offset = integer_bytes;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = integer_bytes - 8;
+ integer_bytes += field_byte_width;
+ }
+ }
+ else
+ {
+ fp_bytes += field_byte_width;
+ }
+ }
+ }
+
+ // These two tests are just sanity checks. If I somehow get the
+ // type calculation wrong above it is better to just return nothing
+ // than to assert or crash.
+ if (!copy_from_extractor)
+ return return_valobj_sp;
+ if (copy_from_offset + field_byte_width > copy_from_extractor->GetByteSize())
+ return return_valobj_sp;
+
+ copy_from_extractor->CopyByteOrderedData (copy_from_offset,
+ field_byte_width,
+ data_sp->GetBytes() + field_byte_offset,
+ field_byte_width,
+ target_byte_order);
+ }
+
+ if (!is_memory)
+ {
+ // The result is in our data buffer. Let's make a variable object out of it:
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ return_ext);
+ }
+ }
+
+
+ // FIXME: This is just taking a guess, r3 may very well no longer hold the return storage location.
+ // If we are going to do this right, when we make a new frame we should check to see if it uses a memory
+ // return, and if we are at the first instruction and if so stash away the return location. Then we would
+ // only return the memory return value if we know it is valid.
+
+ if (is_memory)
+ {
+ unsigned r3_id = reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
+ lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
+ return_valobj_sp = ValueObjectMemory::Create (&thread,
+ "",
+ Address (storage_addr, NULL),
+ return_clang_type);
+ }
+ }
+
+ return return_valobj_sp;
+}
+
+bool
+ABISysV_ppc64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t lr_reg_num = gcc_dwarf_lr;
+ uint32_t sp_reg_num = gcc_dwarf_r1;
+ uint32_t pc_reg_num = gcc_dwarf_pc;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our Call Frame Address is the stack pointer value
+ row->SetCFARegister (sp_reg_num);
+
+ // The previous PC is in the LR
+ row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+
+ unwind_plan.SetSourceName ("ppc64 at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+
+ return true;
+}
+
+bool
+ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t sp_reg_num = gcc_dwarf_r1;
+ uint32_t pc_reg_num = gcc_dwarf_lr;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ const int32_t ptr_size = 8;
+ row->SetCFARegister (sp_reg_num);
+ row->SetCFAType(lldb_private::UnwindPlan::Row::CFAIsRegisterDereferenced);
+
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(gcc_dwarf_cr, ptr_size, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("ppc64 default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+ unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr);
+ return true;
+}
+
+bool
+ABISysV_ppc64::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ return !RegisterIsCalleeSaved (reg_info);
+}
+
+
+
+// See "Register Usage" in the
+// "System V Application Binary Interface"
+// "64-bit PowerPC ELF Application Binary Interface Supplement"
+// current version is 1.9 released 2004 at http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.pdf
+
+bool
+ABISysV_ppc64::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ // Preserved registers are :
+ // r1,r2,r13-r31
+ // cr2-cr4 (partially preserved)
+ // f14-f31 (not yet)
+ // v20-v31 (not yet)
+ // vrsave (not yet)
+
+ const char *name = reg_info->name;
+ if (name[0] == 'r')
+ {
+ if ((name[1] == '1' || name[1] == '2') && name[2] == '\0')
+ return true;
+ if (name[1] == '1' && name[2] > '2')
+ return true;
+ if ((name[1] == '2' || name[1] == '3') && name[2] != '\0')
+ return true;
+ }
+
+ if (name[0] == 'f' && name[1] >= '0' && name[2] <= '9')
+ {
+ if (name[2] == '\0')
+ return false;
+ if (name[1] == '1' && name[2] >= '4')
+ return true;
+ if ((name[1] == '2' || name[1] == '3') && name[2] != '\0')
+ return true;
+ }
+
+ if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
+ return true;
+ if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
+ return true;
+ if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
+ return true;
+ }
+ return false;
+}
+
+
+
+void
+ABISysV_ppc64::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "System V ABI for ppc64 targets",
+ CreateInstance);
+}
+
+void
+ABISysV_ppc64::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABISysV_ppc64::GetPluginNameStatic()
+{
+ static ConstString g_name("sysv-ppc64");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABISysV_ppc64::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_ppc64::GetPluginVersion()
+{
+ return 1;
+}
+
diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
new file mode 100644
index 000000000000..d77cb9f1efe3
--- /dev/null
+++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
@@ -0,0 +1,143 @@
+//===-- ABISysV_ppc64.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_ABISysV_ppc64_h_
+#define liblldb_ABISysV_ppc64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABISysV_ppc64 :
+ public lldb_private::ABI
+{
+public:
+
+ ~ABISysV_ppc64()
+ {
+ }
+
+ virtual size_t
+ GetRedZoneSize () const;
+
+ virtual bool
+ PrepareTrivialCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const;
+
+ virtual bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const;
+
+ virtual lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
+protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &ast_type) const;
+
+public:
+ virtual lldb::ValueObjectSP
+ GetReturnValueObjectImpl (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &type) const;
+
+ virtual bool
+ CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+
+ virtual bool
+ StackUsesFrames ()
+ {
+ return true;
+ }
+
+ // The SysV ppc64 ABI requires that stack frames be 16 byte aligned.
+ // When there is a trap handler on the stack, e.g. _sigtramp in userland
+ // code, we've seen that the stack pointer is often not aligned properly
+ // before the handler is invoked. This means that lldb will stop the unwind
+ // early -- before the function which caused the trap.
+ //
+ // To work around this, we relax that alignment to be just word-size (8-bytes).
+ // Whitelisting the trap handlers for user space would be easy (_sigtramp) but
+ // in other environments there can be a large number of different functions
+ // involved in async traps.
+ virtual bool
+ CallFrameAddressIsValid (lldb::addr_t cfa)
+ {
+ // Make sure the stack call frame addresses are 8 byte aligned
+ if (cfa & (8ull - 1ull))
+ return false; // Not 8 byte aligned
+ if (cfa == 0)
+ return false; // Zero is not a valid stack address
+ return true;
+ }
+
+ virtual bool
+ CodeAddressIsValid (lldb::addr_t pc)
+ {
+ // We have a 64 bit address space, so anything is valid as opcodes
+ // aren't fixed width...
+ return true;
+ }
+
+ virtual bool
+ FunctionCallsChangeCFA ()
+ {
+ return true;
+ }
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfoArray (uint32_t &count);
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ABISP
+ CreateInstance (const lldb_private::ArchSpec &arch);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual lldb_private::ConstString
+ GetPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+protected:
+ void
+ CreateRegisterMapIfNeeded ();
+
+ bool
+ RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
+
+private:
+ ABISysV_ppc64() : lldb_private::ABI() { } // Call CreateInstance instead.
+};
+
+#endif // liblldb_ABI_h_
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 b537415bf055..776e7fea67c7 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -649,18 +649,18 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
return return_valobj_sp;
const uint32_t type_flags = return_clang_type.GetTypeInfo ();
- if (type_flags & ClangASTType::eTypeIsScalar)
+ if (type_flags & eTypeIsScalar)
{
value.SetValueType(Value::eValueTypeScalar);
bool success = false;
- if (type_flags & ClangASTType::eTypeIsInteger)
+ if (type_flags & eTypeIsInteger)
{
// Extract the register context so we can read arguments from registers
const size_t byte_size = return_clang_type.GetByteSize();
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0);
- const bool is_signed = (type_flags & ClangASTType::eTypeIsSigned) != 0;
+ const bool is_signed = (type_flags & eTypeIsSigned) != 0;
switch (byte_size)
{
default:
@@ -699,9 +699,9 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
break;
}
}
- else if (type_flags & ClangASTType::eTypeIsFloat)
+ else if (type_flags & eTypeIsFloat)
{
- if (type_flags & ClangASTType::eTypeIsComplex)
+ if (type_flags & eTypeIsComplex)
{
// Don't handle complex yet.
}
@@ -744,7 +744,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
ConstString(""));
}
- else if (type_flags & ClangASTType::eTypeIsPointer)
+ else if (type_flags & eTypeIsPointer)
{
unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0);
@@ -753,7 +753,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
value,
ConstString(""));
}
- else if (type_flags & ClangASTType::eTypeIsVector)
+ else if (type_flags & eTypeIsVector)
{
const size_t byte_size = return_clang_type.GetByteSize();
if (byte_size > 0)
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 7fd1b6c4b0f3..6fefcc2a9c74 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -61,13 +61,7 @@ public:
virtual bool
RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
-
- virtual bool
- StackUsesFrames ()
- {
- return true;
- }
-
+
// The SysV x86_64 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
// code, we've seen that the stack pointer is often not aligned properly
@@ -97,12 +91,6 @@ public:
return true;
}
- virtual bool
- FunctionCallsChangeCFA ()
- {
- return true;
- }
-
virtual const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count);
//------------------------------------------------------------------
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index c14371d0589c..97ddbef0e307 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -21,7 +21,6 @@
#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/ADT/SmallString.h"
@@ -489,41 +488,19 @@ DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler()
{
}
-namespace {
- // This is the memory object we use in GetInstruction.
- class LLDBDisasmMemoryObject : public llvm::MemoryObject {
- const uint8_t *m_bytes;
- uint64_t m_size;
- uint64_t m_base_PC;
- public:
- LLDBDisasmMemoryObject(const uint8_t *bytes, uint64_t size, uint64_t basePC) :
- m_bytes(bytes), m_size(size), m_base_PC(basePC) {}
-
- uint64_t getBase() const { return m_base_PC; }
- uint64_t getExtent() const { return m_size; }
-
- int readByte(uint64_t addr, uint8_t *byte) const {
- if (addr - m_base_PC >= m_size)
- return -1;
- *byte = m_bytes[addr - m_base_PC];
- return 0;
- }
- };
-} // End Anonymous Namespace
-
uint64_t
DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
size_t opcode_data_len,
lldb::addr_t pc,
llvm::MCInst &mc_inst)
{
- LLDBDisasmMemoryObject memory_object (opcode_data, opcode_data_len, pc);
+ llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len);
llvm::MCDisassembler::DecodeStatus status;
uint64_t new_inst_size;
status = m_disasm_ap->getInstruction(mc_inst,
new_inst_size,
- memory_object,
+ data,
pc,
llvm::nulls(),
llvm::nulls());
@@ -832,11 +809,19 @@ const char *DisassemblerLLVMC::SymbolLookup (uint64_t value,
value_so_addr.Dump (&ss,
target,
- Address::DumpStyleResolvedDescriptionNoModule,
+ Address::DumpStyleResolvedDescriptionNoFunctionArguments,
Address::DumpStyleSectionNameOffset);
if (!ss.GetString().empty())
{
+ // If Address::Dump returned a multi-line description, most commonly seen when we
+ // have multiple levels of inlined functions at an address, only show the first line.
+ std::string &str(ss.GetString());
+ size_t first_eol_char = str.find_first_of ("\r\n");
+ if (first_eol_char != std::string::npos)
+ {
+ str.erase (first_eol_char);
+ }
m_inst->AppendComment(ss.GetString());
}
}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 0e203fe43a79..d8279e44e14a 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -34,6 +34,13 @@ ResolveRendezvousAddress(Process *process)
addr_t info_addr;
Error error;
+ if (!process)
+ {
+ if (log)
+ log->Printf ("%s null process provided", __FUNCTION__);
+ return LLDB_INVALID_ADDRESS;
+ }
+
// Try to get it from our process. This might be a remote process and might
// grab it via some remote-specific mechanism.
info_location = process->GetImageInfoAddress();
@@ -43,7 +50,7 @@ ResolveRendezvousAddress(Process *process)
// If the process fails to return an address, fall back to seeing if the local object file can help us find it.
if (info_location == LLDB_INVALID_ADDRESS)
{
- Target *target = process ? &process->GetTarget() : nullptr;
+ Target *target = &process->GetTarget();
if (target)
{
ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
@@ -70,6 +77,9 @@ ResolveRendezvousAddress(Process *process)
return LLDB_INVALID_ADDRESS;
}
+ if (log)
+ log->Printf ("%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, __FUNCTION__, process->GetAddressByteSize(), info_location);
+
info_addr = process->ReadPointerFromMemory(info_location, error);
if (error.Fail())
{
@@ -193,7 +203,7 @@ DYLDRendezvous::UpdateSOEntries()
// state and take a snapshot of the currently loaded images.
if (m_current.state == eAdd || m_current.state == eDelete)
{
- assert(m_previous.state == eConsistent);
+ assert(m_previous.state == eConsistent || (m_previous.state == eAdd && m_current.state == eDelete));
m_soentries.clear();
m_added_soentries.clear();
m_removed_soentries.clear();
@@ -320,23 +330,11 @@ DYLDRendezvous::ReadStringFromMemory(addr_t addr)
{
std::string str;
Error error;
- size_t size;
- char c;
if (addr == LLDB_INVALID_ADDRESS)
return std::string();
- for (;;) {
- size = m_process->DoReadMemory(addr, &c, 1, error);
- if (size != 1 || error.Fail())
- return std::string();
- if (c == 0)
- break;
- else {
- str.push_back(c);
- addr++;
- }
- }
+ m_process->ReadCStringFromMemory(addr, str, error);
return str;
}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 549e5f9b5345..6b0b6f5cc8b8 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -111,27 +111,88 @@ DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD()
void
DynamicLoaderPOSIXDYLD::DidAttach()
{
- ModuleSP executable;
- addr_t load_offset;
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID);
m_auxv.reset(new AuxVector(m_process));
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID);
- executable = GetTargetExecutable();
- load_offset = ComputeLoadOffset();
+ ModuleSP executable_sp = GetTargetExecutable();
+ ModuleSpec process_module_spec;
+ if (GetProcessModuleSpec(process_module_spec))
+ {
+ if (executable_sp == nullptr || !executable_sp->MatchesModuleSpec(process_module_spec))
+ {
+ executable_sp.reset(new Module(process_module_spec));
+ assert(m_process != nullptr);
+ m_process->GetTarget().SetExecutableModule(executable_sp, false);
+ }
+ }
- if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
+ addr_t load_offset = ComputeLoadOffset();
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp ? executable_sp->GetFileSpec().GetPath().c_str () : "<null executable>", load_offset);
+
+
+ if (executable_sp && load_offset != LLDB_INVALID_ADDRESS)
{
ModuleList module_list;
- module_list.Append(executable);
- UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
- LoadAllCurrentModules();
+
+ module_list.Append(executable_sp);
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " added executable '%s' to module load list",
+ __FUNCTION__,
+ m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID,
+ executable_sp->GetFileSpec().GetPath().c_str ());
+
+ UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset);
+
+ // When attaching to a target, there are two possible states:
+ // (1) We already crossed the entry point and therefore the rendezvous
+ // structure is ready to be used and we can load the list of modules
+ // and place the rendezvous breakpoint.
+ // (2) We didn't cross the entry point yet, so these structures are not
+ // ready; we should behave as if we just launched the target and
+ // call ProbeEntry(). This will place a breakpoint on the entry
+ // point which itself will be hit after the rendezvous structure is
+ // set up and will perform actions described in (1).
+ if (m_rendezvous.Resolve())
+ {
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 " rendezvous could resolve: attach assuming dynamic loader info is available now", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID);
+ LoadAllCurrentModules();
+ SetRendezvousBreakpoint();
+ }
+ else
+ {
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 " rendezvous could not yet resolve: adding breakpoint to catch future rendezvous setup", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID);
+ ProbeEntry();
+ }
+
m_process->GetTarget().ModulesDidLoad(module_list);
+ if (log)
+ {
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s told the target about the modules that loaded:", __FUNCTION__);
+ for (auto module_sp : module_list.Modules ())
+ {
+ log->Printf ("-- [module] %s (pid %" PRIu64 ")",
+ module_sp ? module_sp->GetFileSpec().GetPath().c_str () : "<null>",
+ m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID);
+ }
+ }
}
}
void
DynamicLoaderPOSIXDYLD::DidLaunch()
{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__);
+
ModuleSP executable;
addr_t load_offset;
@@ -145,7 +206,11 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
ModuleList module_list;
module_list.Append(executable);
UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
+
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__);
ProbeEntry();
+
m_process->GetTarget().ModulesDidLoad(module_list);
}
}
@@ -187,15 +252,28 @@ DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module)
void
DynamicLoaderPOSIXDYLD::ProbeEntry()
{
- Breakpoint *entry_break;
- addr_t entry;
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
- if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+ const addr_t entry = GetEntryPoint();
+ if (entry == LLDB_INVALID_ADDRESS)
+ {
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " GetEntryPoint() returned no address, not setting entry breakpoint", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID);
return;
-
- entry_break = m_process->GetTarget().CreateBreakpoint(entry, true, false).get();
- entry_break->SetCallback(EntryBreakpointHit, this, true);
- entry_break->SetBreakpointKind("shared-library-event");
+ }
+
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " GetEntryPoint() returned address 0x%" PRIx64 ", setting entry breakpoint", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, entry);
+
+ if (m_process)
+ {
+ Breakpoint *const entry_break = m_process->GetTarget().CreateBreakpoint(entry, true, false).get();
+ entry_break->SetCallback(EntryBreakpointHit, this, true);
+ entry_break->SetBreakpointKind("shared-library-event");
+
+ // Shoudn't hit this more than once.
+ entry_break->SetOneShot (true);
+ }
}
// The runtime linker has run and initialized the rendezvous structure once the
@@ -210,9 +288,40 @@ DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton,
user_id_t break_id,
user_id_t break_loc_id)
{
- DynamicLoaderPOSIXDYLD* dyld_instance;
+ assert(baton && "null baton");
+ if (!baton)
+ return false;
+
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton);
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID () : LLDB_INVALID_PROCESS_ID);
+
+ // Disable the breakpoint --- if a stop happens right after this, which we've seen on occasion, we don't
+ // want the breakpoint stepping thread-plan logic to show a breakpoint instruction at the disassembled
+ // entry point to the program. Disabling it prevents it. (One-shot is not enough - one-shot removal logic
+ // only happens after the breakpoint goes public, which wasn't happening in our scenario).
+ if (dyld_instance->m_process)
+ {
+ BreakpointSP breakpoint_sp = dyld_instance->m_process->GetTarget().GetBreakpointByID (break_id);
+ if (breakpoint_sp)
+ {
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " disabling breakpoint id %" PRIu64, __FUNCTION__, dyld_instance->m_process->GetID (), break_id);
+ breakpoint_sp->SetEnabled (false);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " failed to find breakpoint for breakpoint id %" PRIu64, __FUNCTION__, dyld_instance->m_process->GetID (), break_id);
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64 " no Process instance! Cannot disable breakpoint", __FUNCTION__, break_id);
+ }
- dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton);
dyld_instance->LoadAllCurrentModules();
dyld_instance->SetRendezvousBreakpoint();
return false; // Continue running.
@@ -221,16 +330,25 @@ DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton,
void
DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint()
{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
addr_t break_addr = m_rendezvous.GetBreakAddress();
Target &target = m_process->GetTarget();
if (m_dyld_bid == LLDB_INVALID_BREAK_ID)
{
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " setting rendezvous break address at 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, break_addr);
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();
}
+ else
+ {
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reusing break id %" PRIu32 ", address at 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, m_dyld_bid, break_addr);
+ }
// Make sure our breakpoint is at the right address.
assert (target.GetBreakpointByID(m_dyld_bid)->FindLocationByAddress(break_addr)->GetBreakpoint().GetID() == m_dyld_bid);
@@ -242,13 +360,22 @@ DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(void *baton,
user_id_t break_id,
user_id_t break_loc_id)
{
- DynamicLoaderPOSIXDYLD* dyld_instance;
+ assert (baton && "null baton");
+ if (!baton)
+ return false;
+
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton);
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID () : LLDB_INVALID_PROCESS_ID);
- dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton);
dyld_instance->RefreshModules();
// Return true to stop the target, false to just let the target run.
- return dyld_instance->GetStopWhenImagesChange();
+ const bool stop_when_images_change = dyld_instance->GetStopWhenImagesChange();
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " stop_when_images_change=%s", __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID () : LLDB_INVALID_PROCESS_ID, stop_when_images_change ? "true" : "false");
+ return stop_when_images_change;
}
void
@@ -439,6 +566,13 @@ DynamicLoaderPOSIXDYLD::GetEntryPoint()
return LLDB_INVALID_ADDRESS;
m_entry_point = static_cast<addr_t>(I->value);
+
+ const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
+
+ // On ppc64, the entry point is actually a descriptor. Dereference it.
+ if (arch.GetMachine() == llvm::Triple::ppc64)
+ m_entry_point = ReadUnsignedIntWithSizeInBytes(m_entry_point, 8);
+
return m_entry_point;
}
@@ -487,3 +621,18 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const l
return tls_block;
}
+
+bool
+DynamicLoaderPOSIXDYLD::GetProcessModuleSpec (ModuleSpec& module_spec)
+{
+ if (m_process == nullptr)
+ return false;
+
+ auto& target = m_process->GetTarget ();
+ ProcessInstanceInfo process_info;
+ if (!target.GetPlatform ()->GetProcessInfo (m_process->GetID (), process_info))
+ return false;
+
+ module_spec = ModuleSpec (process_info.GetExecutableFile (), process_info.GetArchitecture ());
+ return true;
+}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 9ced5da8a015..747ff3f2be36 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -168,6 +168,10 @@ protected:
lldb::addr_t
GetEntryPoint();
+ /// Loads ModuleSpec data from inferior process.
+ bool
+ GetProcessModuleSpec(lldb_private::ModuleSpec& module_spec);
+
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
};
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index fa8681ed69fe..bc358a985248 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -9873,12 +9873,14 @@ EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding en
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
return false;
}
+#if 0 // unreachable because if true
else
{
// R[d] = 1;
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
return false;
}
+#endif // unreachable because if true
}
return true;
}
diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
new file mode 100644
index 000000000000..96754ff78787
--- /dev/null
+++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
@@ -0,0 +1,314 @@
+//===-- AddressSanitizerRuntime.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AddressSanitizerRuntime.h"
+
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/InstrumentationRuntimeStopInfo.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+lldb::InstrumentationRuntimeSP
+AddressSanitizerRuntime::CreateInstance (const lldb::ProcessSP &process_sp)
+{
+ return InstrumentationRuntimeSP(new AddressSanitizerRuntime(process_sp));
+}
+
+void
+AddressSanitizerRuntime::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "AddressSanitizer instrumentation runtime plugin.",
+ CreateInstance,
+ GetTypeStatic);
+}
+
+void
+AddressSanitizerRuntime::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+AddressSanitizerRuntime::GetPluginNameStatic()
+{
+ return ConstString("AddressSanitizer");
+}
+
+lldb::InstrumentationRuntimeType
+AddressSanitizerRuntime::GetTypeStatic()
+{
+ return eInstrumentationRuntimeTypeAddressSanitizer;
+}
+
+AddressSanitizerRuntime::AddressSanitizerRuntime(const ProcessSP &process_sp) :
+ m_is_active(false),
+ m_runtime_module(),
+ m_process(process_sp),
+ m_breakpoint_id(0)
+{
+}
+
+AddressSanitizerRuntime::~AddressSanitizerRuntime()
+{
+ Deactivate();
+}
+
+bool ModuleContainsASanRuntime(Module * module)
+{
+ SymbolContextList sc_list;
+ const bool include_symbols = true;
+ const bool append = true;
+ const bool include_inlines = true;
+
+ size_t num_matches = module->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);
+
+ return num_matches > 0;
+}
+
+void
+AddressSanitizerRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list)
+{
+ if (IsActive())
+ return;
+
+ if (m_runtime_module) {
+ Activate();
+ return;
+ }
+
+ Mutex::Locker modules_locker(module_list.GetMutex());
+ const size_t num_modules = module_list.GetSize();
+ for (size_t i = 0; i < num_modules; ++i)
+ {
+ Module *module_pointer = module_list.GetModulePointerAtIndexUnlocked(i);
+ const FileSpec & file_spec = module_pointer->GetFileSpec();
+ if (! file_spec)
+ continue;
+
+ static RegularExpression g_asan_runtime_regex("libclang_rt.asan_(.*)_dynamic\\.dylib");
+ if (g_asan_runtime_regex.Execute (file_spec.GetFilename().GetCString()) || module_pointer->IsExecutable())
+ {
+ if (ModuleContainsASanRuntime(module_pointer))
+ {
+ m_runtime_module = module_pointer->shared_from_this();
+ Activate();
+ return;
+ }
+ }
+ }
+}
+
+bool
+AddressSanitizerRuntime::IsActive()
+{
+ return m_is_active;
+}
+
+#define RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC 2*1000*1000
+
+const char *
+address_sanitizer_retrieve_report_data_command = R"(
+ struct {
+ int present;
+ void *pc, *bp, *sp, *address;
+ int access_type;
+ size_t access_size;
+ const char *description;
+ } t;
+
+ t.present = ((int (*) ())__asan_report_present)();
+ t.pc = ((void * (*) ())__asan_get_report_pc)();
+ /* commented out because rdar://problem/18533301
+ t.bp = ((void * (*) ())__asan_get_report_bp)();
+ t.sp = ((void * (*) ())__asan_get_report_sp)();
+ */
+ t.address = ((void * (*) ())__asan_get_report_address)();
+ t.description = ((const char * (*) ())__asan_get_report_description)();
+ t.access_type = ((int (*) ())__asan_get_report_access_type)();
+ t.access_size = ((size_t (*) ())__asan_get_report_access_size)();
+
+ t;
+)";
+
+StructuredData::ObjectSP
+AddressSanitizerRuntime::RetrieveReportData()
+{
+ ThreadSP thread_sp = m_process->GetThreadList().GetSelectedThread();
+ StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+
+ if (!frame_sp)
+ return StructuredData::ObjectSP();
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(true);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC);
+
+ ValueObjectSP return_value_sp;
+ if (m_process->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
+ return StructuredData::ObjectSP();
+
+ int present = return_value_sp->GetValueForExpressionPath(".present")->GetValueAsUnsigned(0);
+ if (present != 1)
+ return StructuredData::ObjectSP();
+
+ addr_t pc = return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0);
+ addr_t bp = return_value_sp->GetValueForExpressionPath(".bp")->GetValueAsUnsigned(0);
+ addr_t sp = return_value_sp->GetValueForExpressionPath(".sp")->GetValueAsUnsigned(0);
+ addr_t address = return_value_sp->GetValueForExpressionPath(".address")->GetValueAsUnsigned(0);
+ addr_t access_type = return_value_sp->GetValueForExpressionPath(".access_type")->GetValueAsUnsigned(0);
+ addr_t access_size = return_value_sp->GetValueForExpressionPath(".access_size")->GetValueAsUnsigned(0);
+ addr_t description_ptr = return_value_sp->GetValueForExpressionPath(".description")->GetValueAsUnsigned(0);
+ std::string description;
+ Error error;
+ m_process->ReadCStringFromMemory(description_ptr, description, error);
+
+ StructuredData::Dictionary *dict = new StructuredData::Dictionary();
+ dict->AddStringItem("instrumentation_class", "AddressSanitizer");
+ dict->AddStringItem("stop_type", "fatal_error");
+ dict->AddIntegerItem("pc", pc);
+ dict->AddIntegerItem("bp", bp);
+ dict->AddIntegerItem("sp", sp);
+ dict->AddIntegerItem("address", address);
+ dict->AddIntegerItem("access_type", access_type);
+ dict->AddIntegerItem("access_size", access_size);
+ dict->AddStringItem("description", description);
+
+ return StructuredData::ObjectSP(dict);
+}
+
+std::string
+AddressSanitizerRuntime::FormatDescription(StructuredData::ObjectSP report)
+{
+ std::string description = report->GetAsDictionary()->GetValueForKey("description")->GetAsString()->GetValue();
+ if (description == "heap-use-after-free") {
+ return "Use of deallocated memory detected";
+ } else if (description == "heap-buffer-overflow") {
+ return "Heap buffer overflow detected";
+ } else if (description == "stack-buffer-underflow") {
+ return "Stack buffer underflow detected";
+ } else if (description == "initialization-order-fiasco") {
+ return "Initialization order problem detected";
+ } else if (description == "stack-buffer-overflow") {
+ return "Stack buffer overflow detected";
+ } else if (description == "stack-use-after-return") {
+ return "Use of returned stack memory detected";
+ } else if (description == "use-after-poison") {
+ return "Use of poisoned memory detected";
+ } else if (description == "container-overflow") {
+ return "Container overflow detected";
+ } else if (description == "stack-use-after-scope") {
+ return "Use of out-of-scope stack memory detected";
+ } else if (description == "global-buffer-overflow") {
+ return "Global buffer overflow detected";
+ } else if (description == "unknown-crash") {
+ return "Invalid memory access detected";
+ }
+
+ // for unknown report codes just show the code
+ return description;
+}
+
+bool
+AddressSanitizerRuntime::NotifyBreakpointHit(void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id)
+{
+ assert (baton && "null baton");
+ if (!baton)
+ return false;
+
+ AddressSanitizerRuntime *const instance = static_cast<AddressSanitizerRuntime*>(baton);
+
+ StructuredData::ObjectSP report = instance->RetrieveReportData();
+ std::string description;
+ if (report) {
+ description = instance->FormatDescription(report);
+ }
+ ThreadSP thread = context->exe_ctx_ref.GetThreadSP();
+ thread->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread, description.c_str(), report));
+
+ if (instance->m_process)
+ {
+ StreamFileSP stream_sp (instance->m_process->GetTarget().GetDebugger().GetOutputFile());
+ if (stream_sp)
+ {
+ stream_sp->Printf ("AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.\n");
+ }
+ }
+ // Return true to stop the target, false to just let the target run.
+ return true;
+}
+
+void
+AddressSanitizerRuntime::Activate()
+{
+ if (m_is_active)
+ return;
+
+ ConstString symbol_name ("__asan::AsanDie()");
+ const Symbol *symbol = m_runtime_module->FindFirstSymbolWithNameAndType (symbol_name, eSymbolTypeCode);
+
+ if (symbol == NULL)
+ return;
+
+ if (!symbol->GetAddress().IsValid())
+ return;
+
+ Target &target = m_process->GetTarget();
+ addr_t symbol_address = symbol->GetAddress().GetOpcodeLoadAddress(&target);
+
+ if (symbol_address == LLDB_INVALID_ADDRESS)
+ return;
+
+ bool internal = true;
+ bool hardware = false;
+ Breakpoint *breakpoint = m_process->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get();
+ breakpoint->SetCallback (AddressSanitizerRuntime::NotifyBreakpointHit, this, true);
+ breakpoint->SetBreakpointKind ("address-sanitizer-report");
+ m_breakpoint_id = breakpoint->GetID();
+
+ if (m_process)
+ {
+ StreamFileSP stream_sp (m_process->GetTarget().GetDebugger().GetOutputFile());
+ if (stream_sp)
+ {
+ stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n");
+ }
+ }
+
+ m_is_active = true;
+}
+
+void
+AddressSanitizerRuntime::Deactivate()
+{
+ if (m_breakpoint_id != LLDB_INVALID_BREAK_ID)
+ {
+ m_process->GetTarget().RemoveBreakpointByID(m_breakpoint_id);
+ m_breakpoint_id = LLDB_INVALID_BREAK_ID;
+ }
+ m_is_active = false;
+}
diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h
new file mode 100644
index 000000000000..69c134cbedaf
--- /dev/null
+++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h
@@ -0,0 +1,86 @@
+//===-- AddressSanitizerRuntime.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_AddressSanitizerRuntime_h_
+#define liblldb_AddressSanitizerRuntime_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/InstrumentationRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/StructuredData.h"
+
+namespace lldb_private {
+
+class AddressSanitizerRuntime : public lldb_private::InstrumentationRuntime
+{
+public:
+
+ static lldb::InstrumentationRuntimeSP
+ CreateInstance (const lldb::ProcessSP &process_sp);
+
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static lldb::InstrumentationRuntimeType
+ GetTypeStatic();
+
+ virtual
+ ~AddressSanitizerRuntime();
+
+ virtual lldb_private::ConstString
+ GetPluginName() { return GetPluginNameStatic(); }
+
+ virtual lldb::InstrumentationRuntimeType
+ GetType() { return GetTypeStatic(); }
+
+ virtual uint32_t
+ GetPluginVersion() { return 1; }
+
+ virtual void
+ ModulesDidLoad(lldb_private::ModuleList &module_list);
+
+ virtual bool
+ IsActive();
+
+private:
+
+ AddressSanitizerRuntime(const lldb::ProcessSP &process_sp);
+
+ void
+ Activate();
+
+ void
+ Deactivate();
+
+ static bool
+ NotifyBreakpointHit(void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
+
+ StructuredData::ObjectSP
+ RetrieveReportData();
+
+ std::string
+ FormatDescription(StructuredData::ObjectSP report);
+
+ bool m_is_active;
+ lldb::ModuleSP m_runtime_module;
+ lldb::ProcessSP m_process;
+ lldb::user_id_t m_breakpoint_id;
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_InstrumentationRuntime_h_
diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
index 905984d33410..cd303cb0768f 100644
--- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
+++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
@@ -36,21 +36,24 @@ typedef enum
JIT_UNREGISTER_FN
} jit_actions_t;
+#pragma pack(push, 4)
+template <typename ptr_t>
struct jit_code_entry
{
- struct jit_code_entry *next_entry;
- struct jit_code_entry *prev_entry;
- const char *symfile_addr;
+ ptr_t next_entry; // pointer
+ ptr_t prev_entry; // pointer
+ ptr_t symfile_addr; // pointer
uint64_t symfile_size;
};
-
+template <typename ptr_t>
struct jit_descriptor
{
uint32_t version;
uint32_t action_flag; // Values are jit_action_t
- struct jit_code_entry *relevant_entry;
- struct jit_code_entry *first_entry;
+ ptr_t relevant_entry; // pointer
+ ptr_t first_entry; // pointer
};
+#pragma pack(pop)
JITLoaderGDB::JITLoaderGDB (lldb_private::Process *process) :
JITLoader(process),
@@ -198,6 +201,17 @@ static void updateSectionLoadAddress(const SectionList &section_list,
bool
JITLoaderGDB::ReadJITDescriptor(bool all_entries)
{
+ Target &target = m_process->GetTarget();
+ if (target.GetArchitecture().GetAddressByteSize() == 8)
+ return ReadJITDescriptorImpl<uint64_t>(all_entries);
+ else
+ return ReadJITDescriptorImpl<uint32_t>(all_entries);
+}
+
+template <typename ptr_t>
+bool
+JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries)
+{
if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
return false;
@@ -205,7 +219,7 @@ JITLoaderGDB::ReadJITDescriptor(bool all_entries)
Target &target = m_process->GetTarget();
ModuleList &module_list = target.GetImages();
- jit_descriptor jit_desc;
+ jit_descriptor<ptr_t> jit_desc;
const size_t jit_desc_size = sizeof(jit_desc);
Error error;
size_t bytes_read = m_process->DoReadMemory(
@@ -228,7 +242,7 @@ JITLoaderGDB::ReadJITDescriptor(bool all_entries)
while (jit_relevant_entry != 0)
{
- jit_code_entry jit_entry;
+ jit_code_entry<ptr_t> jit_entry;
const size_t jit_entry_size = sizeof(jit_entry);
bytes_read = m_process->DoReadMemory(jit_relevant_entry, &jit_entry, jit_entry_size, error);
if (bytes_read != jit_entry_size || !error.Success())
diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
index 5fa66b874972..bfa1721d3349 100644
--- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
+++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
@@ -81,6 +81,10 @@ private:
bool
ReadJITDescriptor(bool all_entries);
+ template <typename ptr_t>
+ bool
+ ReadJITDescriptorImpl(bool all_entries);
+
static bool
JITDebugBreakpointHit(void *baton,
lldb_private::StoppointCallbackContext *context,
diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
new file mode 100644
index 000000000000..c7c64ed54d87
--- /dev/null
+++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
@@ -0,0 +1,183 @@
+//===-- MemoryHistoryASan.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MemoryHistoryASan.h"
+
+#include "lldb/Target/MemoryHistory.h"
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Target/ThreadList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Core/Module.h"
+#include "Plugins/Process/Utility/HistoryThread.h"
+#include "lldb/Core/ValueObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+MemoryHistorySP
+MemoryHistoryASan::CreateInstance (const ProcessSP &process_sp)
+{
+ if (!process_sp.get())
+ return NULL;
+
+ Target & target = process_sp->GetTarget();
+
+ bool found_asan_runtime = false;
+
+ const ModuleList &target_modules = target.GetImages();
+ Mutex::Locker modules_locker(target_modules.GetMutex());
+ const size_t num_modules = target_modules.GetSize();
+ for (size_t i = 0; i < num_modules; ++i)
+ {
+ Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i);
+
+ SymbolContextList sc_list;
+ const bool include_symbols = true;
+ const bool append = true;
+ const bool include_inlines = true;
+
+ size_t num_matches = module_pointer->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);
+
+ if (num_matches)
+ {
+ found_asan_runtime = true;
+ break;
+ }
+ }
+
+ if (! found_asan_runtime)
+ return MemoryHistorySP();
+
+ return MemoryHistorySP(new MemoryHistoryASan(process_sp));
+}
+
+void
+MemoryHistoryASan::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "ASan memory history provider.",
+ CreateInstance);
+}
+
+void
+MemoryHistoryASan::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+ConstString
+MemoryHistoryASan::GetPluginNameStatic()
+{
+ static ConstString g_name("asan");
+ return g_name;
+}
+
+MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp)
+{
+ this->m_process_sp = process_sp;
+}
+
+const char *
+memory_history_asan_command_format = R"(
+ struct t {
+ void *alloc_trace[256];
+ size_t alloc_count;
+ int alloc_tid;
+
+ void *free_trace[256];
+ size_t free_count;
+ int free_tid;
+ } t;
+
+ t.alloc_count = ((size_t (*) (void *, void **, size_t, int *))__asan_get_alloc_stack)((void *)0x%)" PRIx64 R"(, t.alloc_trace, 256, &t.alloc_tid);
+ t.free_count = ((size_t (*) (void *, void **, size_t, int *))__asan_get_free_stack)((void *)0x%)" PRIx64 R"(, t.free_trace, 256, &t.free_tid);
+
+ t;
+)";
+
+static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObjectSP return_value_sp, const char *type, const char *thread_name, HistoryThreads & result)
+{
+ std::string count_path = "." + std::string(type) + "_count";
+ std::string tid_path = "." + std::string(type) + "_tid";
+ std::string trace_path = "." + std::string(type) + "_trace";
+
+ int count = return_value_sp->GetValueForExpressionPath(count_path.c_str())->GetValueAsUnsigned(0);
+ tid_t tid = return_value_sp->GetValueForExpressionPath(tid_path.c_str())->GetValueAsUnsigned(0);
+
+ if (count <= 0)
+ return;
+
+ ValueObjectSP trace_sp = return_value_sp->GetValueForExpressionPath(trace_path.c_str());
+
+ std::vector<lldb::addr_t> pcs;
+ for (int i = 0; i < count; i++)
+ {
+ addr_t pc = trace_sp->GetChildAtIndex(i, true)->GetValueAsUnsigned(0);
+ if (pc == 0 || pc == 1 || pc == LLDB_INVALID_ADDRESS)
+ continue;
+ pcs.push_back(pc);
+ }
+
+ HistoryThread *history_thread = new HistoryThread(*process_sp, tid, pcs, 0, false);
+ ThreadSP new_thread_sp(history_thread);
+ // let's use thread name for the type of history thread, since history threads don't have names anyway
+ history_thread->SetThreadName(thread_name);
+ // Save this in the Process' ExtendedThreadList so a strong pointer retains the object
+ process_sp->GetExtendedThreadList().AddThread (new_thread_sp);
+ result.push_back(new_thread_sp);
+}
+
+#define GET_STACK_FUNCTION_TIMEOUT_USEC 2*1000*1000
+
+HistoryThreads
+MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address)
+{
+ ProcessSP process_sp = m_process_sp;
+ ThreadSP thread_sp = m_process_sp->GetThreadList().GetSelectedThread();
+ StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+
+ if (!frame_sp)
+ {
+ return HistoryThreads();
+ }
+
+ ExecutionContext exe_ctx (frame_sp);
+ ValueObjectSP return_value_sp;
+ StreamString expr;
+ expr.Printf(memory_history_asan_command_format, address, address);
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(true);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);
+
+ if (m_process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
+ {
+ return HistoryThreads();
+ }
+ if (!return_value_sp)
+ {
+ return HistoryThreads();
+ }
+
+ HistoryThreads result;
+
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result);
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result);
+
+ return result;
+}
diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
new file mode 100644
index 000000000000..5307e0b34081
--- /dev/null
+++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
@@ -0,0 +1,62 @@
+//===-- MemoryHistoryASan.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_MemoryHistoryASan_h_
+#define liblldb_MemoryHistoryASan_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/MemoryHistory.h"
+#include "lldb/Target/Process.h"
+
+namespace lldb_private {
+
+class MemoryHistoryASan : public lldb_private::MemoryHistory
+{
+public:
+
+ static lldb::MemoryHistorySP
+ CreateInstance (const lldb::ProcessSP &process_sp);
+
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ virtual
+ ~MemoryHistoryASan () {}
+
+ virtual lldb_private::ConstString
+ GetPluginName() { return GetPluginNameStatic(); }
+
+ virtual uint32_t
+ GetPluginVersion() { return 1; }
+
+ virtual lldb_private::HistoryThreads
+ GetHistoryThreads(lldb::addr_t address);
+
+private:
+
+ MemoryHistoryASan(const lldb::ProcessSP &process_sp);
+
+ lldb::ProcessSP m_process_sp;
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_MemoryHistoryASan_h_
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index 0263c23ce307..1e2a0c721ff6 100644
--- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -9,7 +9,7 @@
#include "ObjectContainerBSDArchive.h"
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__ANDROID_NDK__)
// Defines from ar, missing on Windows
#define ARMAG "!<arch>\n"
#define SARMAG 8
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
index f027294b7c57..12392c24407b 100644
--- a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
@@ -173,6 +173,12 @@ ELFHeader::GetRelocationJumpSlotType() const
default:
assert(false && "architecture not supported");
break;
+ case EM_PPC:
+ slot = R_PPC_JMP_SLOT;
+ break;
+ case EM_PPC64:
+ slot = R_PPC64_JMP_SLOT;
+ break;
case EM_386:
case EM_486:
slot = R_386_JUMP_SLOT;
@@ -189,6 +195,9 @@ ELFHeader::GetRelocationJumpSlotType() const
case EM_AARCH64:
slot = R_AARCH64_JUMP_SLOT;
break;
+ case EM_MIPS:
+ slot = R_MIPS_JUMP_SLOT;
+ break;
}
return slot;
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index d86aee78947f..e7bf20e18008 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -267,10 +267,14 @@ kalimbaVariantFromElfFlags(const elf::elf_word e_flags)
{
// TODO(mg11) Support more variants
case 10:
- kal_arch_variant = 3;
+ kal_arch_variant = llvm::Triple::KalimbaSubArch_v3;
break;
case 14:
- kal_arch_variant = 4;
+ kal_arch_variant = llvm::Triple::KalimbaSubArch_v4;
+ break;
+ case 17:
+ case 20:
+ kal_arch_variant = llvm::Triple::KalimbaSubArch_v5;
break;
default:
break;
@@ -287,6 +291,34 @@ subTypeFromElfHeader(const elf::ELFHeader& header)
LLDB_INVALID_CPUTYPE;
}
+//! The kalimba toolchain identifies a code section as being
+//! one with the SHT_PROGBITS set in the section sh_type and the top
+//! bit in the 32-bit address field set.
+static lldb::SectionType
+kalimbaSectionType(
+ const elf::ELFHeader& header,
+ const elf::ELFSectionHeader& sect_hdr)
+{
+ if (llvm::ELF::EM_CSR_KALIMBA != header.e_machine)
+ {
+ return eSectionTypeOther;
+ }
+
+ if (llvm::ELF::SHT_NOBITS == sect_hdr.sh_type)
+ {
+ return eSectionTypeZeroFill;
+ }
+
+ if (llvm::ELF::SHT_PROGBITS == sect_hdr.sh_type)
+ {
+ const lldb::addr_t KAL_CODE_BIT = 1 << 31;
+ return KAL_CODE_BIT & sect_hdr.sh_addr ?
+ eSectionTypeCode : eSectionTypeData;
+ }
+
+ return eSectionTypeOther;
+}
+
// Arbitrary constant used as UUID prefix for core files.
const uint32_t
ObjectFileELF::g_core_uuid_magic(0xE210C);
@@ -826,6 +858,38 @@ ObjectFileELF::GetAddressByteSize() const
return m_data.GetAddressByteSize();
}
+// Top 16 bits of the `Symbol` flags are available.
+#define ARM_ELF_SYM_IS_THUMB (1 << 16)
+
+AddressClass
+ObjectFileELF::GetAddressClass (addr_t file_addr)
+{
+ auto res = ObjectFile::GetAddressClass (file_addr);
+
+ if (res != eAddressClassCode)
+ return res;
+
+ ArchSpec arch_spec;
+ GetArchitecture(arch_spec);
+ if (arch_spec.GetMachine() != llvm::Triple::arm)
+ return res;
+
+ auto symtab = GetSymtab();
+ if (symtab == nullptr)
+ return res;
+
+ auto symbol = symtab->FindSymbolContainingFileAddress(file_addr);
+ if (symbol == nullptr)
+ return res;
+
+ // Thumb symbols have the lower bit set in the flags field so we just check
+ // for that.
+ if (symbol->GetFlags() & ARM_ELF_SYM_IS_THUMB)
+ res = eAddressClassCodeAlternateISA;
+
+ return res;
+}
+
size_t
ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I)
{
@@ -1560,6 +1624,20 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
break;
}
+ if (eSectionTypeOther == sect_type)
+ {
+ // the kalimba toolchain assumes that ELF section names are free-form. It does
+ // supports linkscripts which (can) give rise to various arbitarily named
+ // sections being "Code" or "Data".
+ sect_type = kalimbaSectionType(m_header, header);
+ }
+
+ const uint32_t target_bytes_size =
+ (eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type) ?
+ m_arch_spec.GetDataByteSize() :
+ eSectionTypeCode == sect_type ?
+ m_arch_spec.GetCodeByteSize() : 1;
+
elf::elf_xword log2align = (header.sh_addralign==0)
? 0
: llvm::Log2_64(header.sh_addralign);
@@ -1573,7 +1651,8 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
header.sh_offset, // Offset of this section in the file.
file_size, // Size of the section as found in the file.
log2align, // Alignment of the section
- header.sh_flags)); // Flags for this section.
+ header.sh_flags, // Flags for this section.
+ target_bytes_size));// Number of host bytes per target byte
if (is_thread_specific)
section_sp->SetIsThreadSpecific (is_thread_specific);
@@ -1645,6 +1724,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
static ConstString rodata1_section_name(".rodata1");
static ConstString data2_section_name(".data1");
static ConstString bss_section_name(".bss");
+ static ConstString opd_section_name(".opd"); // For ppc64
//StreamFile strm(stdout, false);
unsigned i;
@@ -1746,6 +1826,48 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
}
}
+ ArchSpec arch;
+ int64_t symbol_value_offset = 0;
+ uint32_t additional_flags = 0;
+
+ if (GetArchitecture(arch) &&
+ arch.GetMachine() == llvm::Triple::arm)
+ {
+ // ELF symbol tables may contain some mapping symbols. They provide
+ // information about the underlying data. There are three of them
+ // currently defined:
+ // $a[.<any>]* - marks an ARM instruction sequence
+ // $t[.<any>]* - marks a THUMB instruction sequence
+ // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
+ // These symbols interfere with normal debugger operations and we
+ // don't need them. We can drop them here.
+
+ static const llvm::StringRef g_armelf_arm_marker("$a");
+ static const llvm::StringRef g_armelf_thumb_marker("$t");
+ static const llvm::StringRef g_armelf_data_marker("$d");
+ llvm::StringRef symbol_name_ref(symbol_name);
+
+ if (symbol_name &&
+ (symbol_name_ref.startswith(g_armelf_arm_marker) ||
+ symbol_name_ref.startswith(g_armelf_thumb_marker) ||
+ symbol_name_ref.startswith(g_armelf_data_marker)))
+ continue;
+
+ // THUMB functions have the lower bit of their address set. Fixup
+ // the actual address and mark the symbol as THUMB.
+ if (symbol_type == eSymbolTypeCode && symbol.st_value & 1)
+ {
+ // Substracting 1 from the address effectively unsets
+ // the low order bit, which results in the address
+ // actually pointing to the beginning of the symbol.
+ // This delta will be used below in conjuction with
+ // symbol.st_value to produce the final symbol_value
+ // that we store in the symtab.
+ symbol_value_offset = -1;
+ additional_flags = ARM_ELF_SYM_IS_THUMB;
+ }
+ }
+
// If the symbol section we've found has no data (SHT_NOBITS), then check the module section
// list. This can happen if we're parsing the debug file and it has no .text section, for example.
if (symbol_section_sp && (symbol_section_sp->GetFileSize() == 0))
@@ -1766,12 +1888,15 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
}
}
- uint64_t symbol_value = symbol.st_value;
+ // symbol_value_offset may contain 0 for ARM symbols or -1 for
+ // THUMB symbols. See above for more details.
+ uint64_t symbol_value = symbol.st_value | symbol_value_offset;
if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile)
symbol_value -= symbol_section_sp->GetFileAddress();
bool is_global = symbol.getBinding() == STB_GLOBAL;
- uint32_t flags = symbol.st_other << 8 | symbol.st_info;
+ uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags;
bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false;
+
Symbol dc_symbol(
i + start_id, // ID is the original symbol table index.
symbol_name, // Symbol name.
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 6b036af7aeff..b10dfb532cd0 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -133,6 +133,9 @@ public:
virtual uint32_t
GetAddressByteSize() const;
+ virtual lldb::AddressClass
+ GetAddressClass (lldb::addr_t file_addr);
+
virtual lldb_private::Symtab *
GetSymtab();
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index 7aa940a530b4..3b38a5819934 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -32,7 +32,7 @@
using namespace lldb;
using namespace lldb_private;
-Platform *
+PlatformSP
PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
{
// The only time we create an instance is when we are creating a remote
@@ -84,8 +84,8 @@ PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
}
}
if (create)
- return new PlatformFreeBSD (is_host);
- return NULL;
+ return PlatformSP(new PlatformFreeBSD (is_host));
+ return PlatformSP();
}
@@ -124,7 +124,7 @@ PlatformFreeBSD::Initialize ()
// Force a host flag to true for the default platform object.
PlatformSP default_platform_sp (new PlatformFreeBSD(true));
default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
- Platform::SetDefaultPlatform (default_platform_sp);
+ Platform::SetHostPlatform (default_platform_sp);
#endif
PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false),
PlatformFreeBSD::GetDescriptionStatic(false),
@@ -180,8 +180,7 @@ PlatformFreeBSD::RunShellCommand (const char *command,
Error
-PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
- const ArchSpec &exe_arch,
+PlatformFreeBSD::ResolveExecutable (const ModuleSpec &module_spec,
lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr)
{
@@ -189,35 +188,33 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
// Nothing special to do here, just use the actual file and architecture
char exe_path[PATH_MAX];
- FileSpec resolved_exe_file (exe_file);
+ ModuleSpec resolved_module_spec(module_spec);
if (IsHost())
{
- // If we have "ls" as the exe_file, resolve the executable location based on
+ // If we have "ls" as the module_spec's file, resolve the executable location based on
// the current path variables
- if (!resolved_exe_file.Exists())
+ if (!resolved_module_spec.GetFileSpec().Exists())
{
- exe_file.GetPath(exe_path, sizeof(exe_path));
- resolved_exe_file.SetFile(exe_path, true);
+ module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
+ resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
}
- if (!resolved_exe_file.Exists())
- resolved_exe_file.ResolveExecutableLocation ();
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();
- if (resolved_exe_file.Exists())
+ if (resolved_module_spec.GetFileSpec().Exists())
error.Clear();
else
{
- exe_file.GetPath(exe_path, sizeof(exe_path));
- error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
+ error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str());
}
}
else
{
if (m_remote_platform_sp)
{
- error = m_remote_platform_sp->ResolveExecutable (exe_file,
- exe_arch,
+ error = m_remote_platform_sp->ResolveExecutable (module_spec,
exe_module_sp,
module_search_paths_ptr);
}
@@ -226,25 +223,24 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
// We may connect to a process and use the provided executable (Don't use local $PATH).
// Resolve any executable within a bundle on MacOSX
- Host::ResolveExecutableInBundle (resolved_exe_file);
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
- if (resolved_exe_file.Exists()) {
+ if (resolved_module_spec.GetFileSpec().Exists())
+ {
error.Clear();
}
else
{
- exe_file.GetPath(exe_path, sizeof(exe_path));
- error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
+ error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetPath().c_str());
}
}
}
if (error.Success())
{
- ModuleSpec module_spec (resolved_exe_file, exe_arch);
- if (module_spec.GetArchitecture().IsValid())
+ if (resolved_module_spec.GetArchitecture().IsValid())
{
- error = ModuleList::GetSharedModule (module_spec,
+ error = ModuleList::GetSharedModule (resolved_module_spec,
exe_module_sp,
module_search_paths_ptr,
NULL,
@@ -254,8 +250,8 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
{
exe_module_sp.reset();
error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
- exe_file.GetPath().c_str(),
- exe_arch.GetArchitectureName());
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ resolved_module_spec.GetArchitecture().GetArchitectureName());
}
}
else
@@ -264,10 +260,9 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
// the architectures that we should be using (in the correct order)
// and see if we can find a match that way
StreamString arch_names;
- ArchSpec platform_arch;
- for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
{
- error = ModuleList::GetSharedModule (module_spec,
+ error = ModuleList::GetSharedModule (resolved_module_spec,
exe_module_sp,
module_search_paths_ptr,
NULL,
@@ -283,21 +278,21 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
if (idx > 0)
arch_names.PutCString (", ");
- arch_names.PutCString (platform_arch.GetArchitectureName());
+ arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
}
if (error.Fail() || !exe_module_sp)
{
- if (exe_file.Readable())
+ if (resolved_module_spec.GetFileSpec().Readable())
{
error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
- exe_file.GetPath().c_str(),
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
GetPluginName().GetCString(),
arch_names.GetString().c_str());
}
else
{
- error.SetErrorStringWithFormat("'%s' is not readable", exe_file.GetPath().c_str());
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
}
}
}
@@ -326,6 +321,13 @@ PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite
trap_opcode_size = sizeof(g_i386_opcode);
}
break;
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ {
+ static const uint8_t g_ppc_opcode[] = { 0x7f, 0xe0, 0x00, 0x08 };
+ trap_opcode = g_ppc_opcode;
+ trap_opcode_size = sizeof(g_ppc_opcode);
+ }
}
if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
@@ -404,7 +406,7 @@ PlatformFreeBSD::ConnectRemote (Args& args)
else
{
if (!m_remote_platform_sp)
- m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
+ m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error);
if (m_remote_platform_sp)
{
@@ -507,7 +509,6 @@ lldb::ProcessSP
PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
Debugger &debugger,
Target *target,
- Listener &listener,
Error &error)
{
lldb::ProcessSP process_sp;
@@ -535,7 +536,7 @@ PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
// The freebsd always currently uses the GDB remote debugger plug-in
// so even when debugging locally we are debugging remotely!
// Just like the darwin plugin.
- process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
+ process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
if (process_sp)
error = process_sp->Attach (attach_info);
@@ -544,7 +545,7 @@ PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
else
{
if (m_remote_platform_sp)
- process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
+ process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error);
else
error.SetErrorString ("the platform is not currently connected");
}
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
index 62958a08a9e0..ce3f8cfad976 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -24,7 +24,7 @@ public:
//------------------------------------------------------------
// Class functions
//------------------------------------------------------------
- static lldb_private::Platform*
+ static lldb::PlatformSP
CreateInstance (bool force, const lldb_private::ArchSpec *arch);
static void
@@ -80,8 +80,7 @@ public:
uint32_t timeout_sec);
virtual lldb_private::Error
- ResolveExecutable (const lldb_private::FileSpec &exe_file,
- const lldb_private::ArchSpec &arch,
+ ResolveExecutable (const lldb_private::ModuleSpec &module_spec,
lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr);
@@ -135,7 +134,6 @@ public:
Attach(lldb_private::ProcessAttachInfo &attach_info,
lldb_private::Debugger &debugger,
lldb_private::Target *target,
- lldb_private::Listener &listener,
lldb_private::Error &error);
// FreeBSD processes can not be launched by spawning and attaching.
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index cc4c693e1b43..b1be0f5b1fe1 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -15,7 +15,9 @@
// Project includes
#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileCache.h"
@@ -330,8 +332,14 @@ PlatformPOSIX::PutFile (const lldb_private::FileSpec& source,
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;
+ const uint64_t bytes_written = WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error);
+ offset += bytes_written;
+ if (bytes_written != bytes_read)
+ {
+ // We didn't write the correct numbe of bytes, so adjust
+ // the file position in the source file we are reading from...
+ source_file.SeekFromStart(offset);
+ }
}
else
break;
@@ -343,6 +351,18 @@ PlatformPOSIX::PutFile (const lldb_private::FileSpec& source,
// std::string dst_path (destination.GetPath());
// if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
// return Error("unable to perform chown");
+
+
+ uint64_t src_md5[2];
+ uint64_t dst_md5[2];
+
+ if (FileSystem::CalculateMD5 (source, src_md5[0], src_md5[1]) && CalculateMD5 (destination, dst_md5[0], dst_md5[1]))
+ {
+ if (src_md5[0] != dst_md5[0] || src_md5[1] != dst_md5[1])
+ {
+ error.SetErrorString("md5 checksum of installed file doesn't match, installation failed");
+ }
+ }
return error;
}
return Platform::PutFile(source,destination,uid,gid);
@@ -616,6 +636,18 @@ PlatformPOSIX::GetRemoteOSBuildString (std::string &s)
return false;
}
+size_t
+PlatformPOSIX::GetEnvironment (StringList &env)
+{
+ if (IsRemote())
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetEnvironment(env);
+ return 0;
+ }
+ return Host::GetEnvironment(env);
+}
+
bool
PlatformPOSIX::GetRemoteOSKernelDescription (std::string &s)
{
@@ -681,7 +713,7 @@ PlatformPOSIX::ConnectRemote (Args& args)
else
{
if (!m_remote_platform_sp)
- m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
+ m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error);
if (m_remote_platform_sp && error.Success())
error = m_remote_platform_sp->ConnectRemote (args);
@@ -739,11 +771,97 @@ PlatformPOSIX::DisconnectRemote ()
return error;
}
+Error
+PlatformPOSIX::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error error;
+
+ if (IsHost())
+ {
+ error = Platform::LaunchProcess (launch_info);
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ error = m_remote_platform_sp->LaunchProcess (launch_info);
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return error;
+}
+
+lldb::ProcessSP
+PlatformPOSIX::Attach (ProcessAttachInfo &attach_info,
+ Debugger &debugger,
+ Target *target,
+ Error &error)
+{
+ lldb::ProcessSP process_sp;
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+
+ if (IsHost())
+ {
+ if (target == NULL)
+ {
+ TargetSP new_target_sp;
+
+ error = debugger.GetTargetList().CreateTarget (debugger,
+ NULL,
+ NULL,
+ false,
+ NULL,
+ new_target_sp);
+ target = new_target_sp.get();
+ if (log)
+ log->Printf ("PlatformPOSIX::%s created new target", __FUNCTION__);
+ }
+ else
+ {
+ error.Clear();
+ if (log)
+ log->Printf ("PlatformPOSIX::%s target already existed, setting target", __FUNCTION__);
+ }
+
+ if (target && error.Success())
+ {
+ debugger.GetTargetList().SetSelectedTarget(target);
+ if (log)
+ {
+ ModuleSP exe_module_sp = target->GetExecutableModule ();
+ log->Printf ("PlatformPOSIX::%s set selected target to %p %s", __FUNCTION__,
+ target,
+ exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<null>" );
+ }
+
+
+ process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), attach_info.GetProcessPluginName(), NULL);
+
+ if (process_sp)
+ {
+ // Set UnixSignals appropriately.
+ process_sp->SetUnixSignals (Host::GetUnixSignals ());
+
+ ListenerSP listener_sp (new Listener("lldb.PlatformPOSIX.attach.hijack"));
+ attach_info.SetHijackListener(listener_sp);
+ process_sp->HijackProcessEvents(listener_sp.get());
+ error = process_sp->Attach (attach_info);
+ }
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error);
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return process_sp;
+}
+
lldb::ProcessSP
PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info,
Debugger &debugger,
Target *target, // Can be NULL, if NULL create a new target, else use existing one
- Listener &listener,
Error &error)
{
ProcessSP process_sp;
@@ -754,12 +872,12 @@ PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info,
// We still need to reap it from lldb but if we let the monitor thread also set the exit status, we set up a
// race between debugserver & us for who will find out about the debugged process's death.
launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus);
- process_sp = Platform::DebugProcess (launch_info, debugger, target, listener, error);
+ process_sp = Platform::DebugProcess (launch_info, debugger, target, error);
}
else
{
if (m_remote_platform_sp)
- process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, listener, error);
+ process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, error);
else
error.SetErrorString ("the platform is not currently connected");
}
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 374e36495d88..aae415e6eefa 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -31,8 +31,9 @@ public:
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
- virtual lldb_private::OptionGroupOptions*
- GetConnectionOptions (lldb_private::CommandInterpreter& interpreter);
+ virtual lldb_private::OptionGroupOptions
+ *GetConnectionOptions(
+ lldb_private::CommandInterpreter &interpreter) override;
const char *
GetHostname () override;
@@ -47,47 +48,47 @@ public:
PutFile (const lldb_private::FileSpec& source,
const lldb_private::FileSpec& destination,
uint32_t uid = UINT32_MAX,
- uint32_t gid = UINT32_MAX);
+ uint32_t gid = UINT32_MAX) override;
virtual lldb::user_id_t
OpenFile (const lldb_private::FileSpec& file_spec,
uint32_t flags,
uint32_t mode,
- lldb_private::Error &error);
+ lldb_private::Error &error) override;
virtual bool
CloseFile (lldb::user_id_t fd,
- lldb_private::Error &error);
+ lldb_private::Error &error) override;
virtual uint64_t
ReadFile (lldb::user_id_t fd,
uint64_t offset,
void *dst,
uint64_t dst_len,
- lldb_private::Error &error);
+ lldb_private::Error &error) override;
virtual uint64_t
WriteFile (lldb::user_id_t fd,
uint64_t offset,
const void* src,
uint64_t src_len,
- lldb_private::Error &error);
+ lldb_private::Error &error) override;
virtual lldb::user_id_t
- GetFileSize (const lldb_private::FileSpec& file_spec);
+ GetFileSize (const lldb_private::FileSpec& file_spec) override;
virtual lldb_private::Error
- CreateSymlink(const char *src, const char *dst);
+ CreateSymlink(const char *src, const char *dst) override;
virtual lldb_private::Error
GetFile (const lldb_private::FileSpec& source,
- const lldb_private::FileSpec& destination);
+ const lldb_private::FileSpec& destination) override;
virtual lldb_private::ConstString
- GetRemoteWorkingDirectory();
+ GetRemoteWorkingDirectory() override;
virtual bool
- SetRemoteWorkingDirectory(const lldb_private::ConstString &path);
+ SetRemoteWorkingDirectory(const lldb_private::ConstString &path) override;
bool
GetRemoteOSVersion () override;
@@ -101,6 +102,9 @@ public:
lldb_private::ArchSpec
GetRemoteSystemArchitecture () override;
+ size_t
+ GetEnvironment (lldb_private::StringList &environment) override;
+
bool
IsConnected () const override;
@@ -110,40 +114,48 @@ public:
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
+ uint32_t timeout_sec) override;// Timeout in seconds to wait for shell program to finish
virtual lldb_private::Error
- MakeDirectory (const char *path, uint32_t mode);
+ MakeDirectory (const char *path, uint32_t mode) override;
virtual lldb_private::Error
- GetFilePermissions (const char *path, uint32_t &file_permissions);
+ GetFilePermissions (const char *path, uint32_t &file_permissions) override;
virtual lldb_private::Error
- SetFilePermissions (const char *path, uint32_t file_permissions);
+ SetFilePermissions (const char *path, uint32_t file_permissions) override;
virtual bool
- GetFileExists (const lldb_private::FileSpec& file_spec);
+ GetFileExists (const lldb_private::FileSpec& file_spec) override;
virtual lldb_private::Error
- Unlink (const char *path);
+ Unlink (const char *path) override;
+
+ lldb_private::Error
+ LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info) override;
+
+ lldb::ProcessSP
+ Attach (lldb_private::ProcessAttachInfo &attach_info,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ lldb_private::Error &error) override;
lldb::ProcessSP
DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,
lldb_private::Debugger &debugger,
lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
- lldb_private::Listener &listener,
lldb_private::Error &error) override;
virtual std::string
- GetPlatformSpecificConnectionInformation();
+ GetPlatformSpecificConnectionInformation() override;
virtual bool
CalculateMD5 (const lldb_private::FileSpec& file_spec,
uint64_t &low,
- uint64_t &high);
+ uint64_t &high) override;
virtual void
- CalculateTrapHandlerSymbolNames ();
+ CalculateTrapHandlerSymbolNames () override;
lldb_private::Error
ConnectRemote (lldb_private::Args& args) override;
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 05fbc5101278..43eae4d906ec 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -16,14 +16,15 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Process.h"
@@ -56,7 +57,7 @@ PlatformRemoteGDBServer::Terminate ()
}
}
-Platform*
+PlatformSP
PlatformRemoteGDBServer::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
{
bool create = force;
@@ -65,8 +66,8 @@ PlatformRemoteGDBServer::CreateInstance (bool force, const lldb_private::ArchSpe
create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified();
}
if (create)
- return new PlatformRemoteGDBServer ();
- return NULL;
+ return PlatformSP(new PlatformRemoteGDBServer());
+ return PlatformSP();
}
@@ -100,14 +101,13 @@ PlatformRemoteGDBServer::GetDescription ()
}
Error
-PlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file,
- const ArchSpec &exe_arch,
+PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec,
lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr)
{
Error error;
//error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented");
- if (m_gdb_client.GetFileExists(exe_file))
+ if (m_gdb_client.GetFileExists(module_spec.GetFileSpec()))
return error;
// TODO: get the remote end to somehow resolve this file
error.SetErrorString("file not found on remote end");
@@ -421,7 +421,6 @@ lldb::ProcessSP
PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,
lldb_private::Debugger &debugger,
lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
- lldb_private::Listener &listener,
lldb_private::Error &error)
{
lldb::ProcessSP process_sp;
@@ -473,7 +472,7 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i
// The darwin always currently uses the GDB remote debugger plug-in
// so even when debugging locally we are debugging remotely!
- process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
+ process_sp = target->CreateProcess (launch_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
if (process_sp)
{
@@ -488,10 +487,16 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i
port + port_offset);
assert (connect_url_len < (int)sizeof(connect_url));
error = process_sp->ConnectRemote (NULL, connect_url);
+ // Retry the connect remote one time...
+ if (error.Fail())
+ error = process_sp->ConnectRemote (NULL, connect_url);
if (error.Success())
error = process_sp->Launch(launch_info);
else if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ {
+ printf ("error: connect remote failed (%s)\n", error.AsCString());
m_gdb_client.KillSpawnedProcess(debugserver_pid);
+ }
}
}
}
@@ -509,7 +514,6 @@ lldb::ProcessSP
PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
Debugger &debugger,
Target *target, // Can be NULL, if NULL create a new target, else use existing one
- Listener &listener,
Error &error)
{
lldb::ProcessSP process_sp;
@@ -561,7 +565,7 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
// The darwin always currently uses the GDB remote debugger plug-in
// so even when debugging locally we are debugging remotely!
- process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
+ process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
if (process_sp)
{
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index e236e97c8bb3..90b16b8b8fa9 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -29,7 +29,7 @@ public:
static void
Terminate ();
- static lldb_private::Platform*
+ static lldb::PlatformSP
CreateInstance (bool force, const lldb_private::ArchSpec *arch);
static lldb_private::ConstString
@@ -64,8 +64,7 @@ public:
// lldb_private::Platform functions
//------------------------------------------------------------
virtual lldb_private::Error
- ResolveExecutable (const lldb_private::FileSpec &exe_file,
- const lldb_private::ArchSpec &arch,
+ ResolveExecutable (const lldb_private::ModuleSpec &module_spec,
lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr);
@@ -92,14 +91,12 @@ public:
DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,
lldb_private::Debugger &debugger,
lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
- lldb_private::Listener &listener,
lldb_private::Error &error);
virtual lldb::ProcessSP
Attach (lldb_private::ProcessAttachInfo &attach_info,
lldb_private::Debugger &debugger,
lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
- lldb_private::Listener &listener,
lldb_private::Error &error);
virtual bool
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index 4b488444de1e..5a0b5ed14194 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -258,8 +258,7 @@ ProcessFreeBSD::SendMessage(const ProcessMessage &message)
case ProcessMessage::eLimboMessage:
case ProcessMessage::eExitMessage:
- m_exit_status = message.GetExitStatus();
- SetExitStatus(m_exit_status, NULL);
+ SetExitStatus(message.GetExitStatus(), NULL);
break;
case ProcessMessage::eSignalMessage:
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 63439b155111..84e35ba22644 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -25,6 +25,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/PseudoTerminal.h"
@@ -112,6 +113,7 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax);
}
#endif
+#ifndef __powerpc__
if (req == PT_GETDBREGS || req == PT_SETDBREGS) {
struct dbreg *r = (struct dbreg *) addr;
char setget = (req == PT_GETDBREGS) ? 'G' : 'S';
@@ -119,6 +121,7 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
for (int i = 0; i <= 7; i++)
log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]);
}
+#endif
}
return result;
@@ -309,9 +312,14 @@ ReadRegOperation::Execute(ProcessMonitor *monitor)
if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)&regs, 0)) < 0) {
m_result = false;
} else {
- if (m_size == sizeof(uintptr_t))
- m_value = *(uintptr_t *)(((caddr_t)&regs) + m_offset);
- else
+ // 'struct reg' contains only 32- or 64-bit register values. Punt on
+ // others. Also, not all entries may be uintptr_t sized, such as 32-bit
+ // processes on powerpc64 (probably the same for i386 on amd64)
+ if (m_size == sizeof(uint32_t))
+ m_value = *(uint32_t *)(((caddr_t)&regs) + m_offset);
+ else if (m_size == sizeof(uint64_t))
+ m_value = *(uint64_t *)(((caddr_t)&regs) + m_offset);
+ else
memcpy(&m_value, (((caddr_t)&regs) + m_offset), m_size);
m_result = true;
}
@@ -810,8 +818,6 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
const lldb_private::ProcessLaunchInfo & /* launch_info */,
lldb_private::Error &error)
: m_process(static_cast<ProcessFreeBSD *>(process)),
- m_operation_thread(LLDB_INVALID_HOST_THREAD),
- m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_pid(LLDB_INVALID_PROCESS_ID),
m_terminal_fd(-1),
m_operation(0)
@@ -852,7 +858,7 @@ WAIT_AGAIN:
// Finally, start monitoring the child process for change in state.
m_monitor_thread = Host::StartMonitoringChildProcess(
ProcessMonitor::MonitorCallback, this, GetPID(), true);
- if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))
+ if (!m_monitor_thread.IsJoinable())
{
error.SetErrorToGenericError();
error.SetErrorString("Process launch failed.");
@@ -864,8 +870,6 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
lldb::pid_t pid,
lldb_private::Error &error)
: m_process(static_cast<ProcessFreeBSD *>(process)),
- m_operation_thread(LLDB_INVALID_HOST_THREAD),
- m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_pid(pid),
m_terminal_fd(-1),
m_operation(0)
@@ -904,7 +908,7 @@ WAIT_AGAIN:
// Finally, start monitoring the child process for change in state.
m_monitor_thread = Host::StartMonitoringChildProcess(
ProcessMonitor::MonitorCallback, this, GetPID(), true);
- if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))
+ if (!m_monitor_thread.IsJoinable())
{
error.SetErrorToGenericError();
error.SetErrorString("Process attach failed.");
@@ -924,11 +928,10 @@ ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error)
{
static const char *g_thread_name = "lldb.process.freebsd.operation";
- if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+ if (m_operation_thread.IsJoinable())
return;
- m_operation_thread =
- Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error);
+ m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args, &error);
}
void *
@@ -1101,11 +1104,10 @@ ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error
{
static const char *g_thread_name = "lldb.process.freebsd.operation";
- if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+ if (m_operation_thread.IsJoinable())
return;
- m_operation_thread =
- Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error);
+ m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args, &error);
}
void *
@@ -1113,14 +1115,13 @@ ProcessMonitor::AttachOpThread(void *arg)
{
AttachArgs *args = static_cast<AttachArgs*>(arg);
- if (!Attach(args))
- return NULL;
+ Attach(args);
ServeOperation(args);
return NULL;
}
-bool
+void
ProcessMonitor::Attach(AttachArgs *args)
{
lldb::pid_t pid = args->m_pid;
@@ -1132,27 +1133,24 @@ ProcessMonitor::Attach(AttachArgs *args)
{
args->m_error.SetErrorToGenericError();
args->m_error.SetErrorString("Attaching to process 1 is not allowed.");
- goto FINISH;
+ return;
}
// Attach to the requested process.
if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0)
{
args->m_error.SetErrorToErrno();
- goto FINISH;
+ return;
}
int status;
if ((status = waitpid(pid, NULL, 0)) < 0)
{
args->m_error.SetErrorToErrno();
- goto FINISH;
+ return;
}
process.SendMessage(ProcessMessage::Attach(pid));
-
-FINISH:
- return args->m_error.Success();
}
size_t
@@ -1714,13 +1712,11 @@ ProcessMonitor::DupDescriptor(const char *path, int fd, int flags)
void
ProcessMonitor::StopMonitoringChildProcess()
{
- lldb::thread_result_t thread_result;
-
- if (IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))
+ if (m_monitor_thread.IsJoinable())
{
- Host::ThreadCancel(m_monitor_thread, NULL);
- Host::ThreadJoin(m_monitor_thread, &thread_result, NULL);
- m_monitor_thread = LLDB_INVALID_HOST_THREAD;
+ m_monitor_thread.Cancel();
+ m_monitor_thread.Join(nullptr);
+ m_monitor_thread.Reset();
}
}
@@ -1764,12 +1760,10 @@ ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid)
void
ProcessMonitor::StopOpThread()
{
- lldb::thread_result_t result;
-
- if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+ if (!m_operation_thread.IsJoinable())
return;
- Host::ThreadCancel(m_operation_thread, NULL);
- Host::ThreadJoin(m_operation_thread, &result, NULL);
- m_operation_thread = LLDB_INVALID_HOST_THREAD;
+ m_operation_thread.Cancel();
+ m_operation_thread.Join(nullptr);
+ m_operation_thread.Reset();
}
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index 314743b00754..935fd85ed37a 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -17,6 +17,7 @@
// C++ Includes
// Other libraries and framework includes
#include "lldb/lldb-types.h"
+#include "lldb/Host/HostThread.h"
#include "lldb/Host/Mutex.h"
namespace lldb_private
@@ -212,8 +213,8 @@ public:
private:
ProcessFreeBSD *m_process;
- lldb::thread_t m_operation_thread;
- lldb::thread_t m_monitor_thread;
+ lldb_private::HostThread m_operation_thread;
+ lldb_private::HostThread m_monitor_thread;
lldb::pid_t m_pid;
int m_terminal_fd;
@@ -289,7 +290,7 @@ private:
static void *
AttachOpThread(void *args);
- static bool
+ static void
Attach(AttachArgs *args);
static void
diff --git a/source/Plugins/Process/POSIX/POSIXThread.cpp b/source/Plugins/Process/POSIX/POSIXThread.cpp
index d48f8f9dd307..1057585e1b2a 100644
--- a/source/Plugins/Process/POSIX/POSIXThread.cpp
+++ b/source/Plugins/Process/POSIX/POSIXThread.cpp
@@ -20,27 +20,30 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostNativeThread.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
+#include "llvm/ADT/SmallString.h"
#include "POSIXStopInfo.h"
#include "POSIXThread.h"
#include "ProcessPOSIX.h"
#include "ProcessPOSIXLog.h"
-#include "ProcessMonitor.h"
+#include "Plugins/Process/Linux/ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_arm64.h"
#include "RegisterContextPOSIXProcessMonitor_mips64.h"
+#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
#include "RegisterContextPOSIXProcessMonitor_x86.h"
-#include "RegisterContextLinux_arm64.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"
+#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
+#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
+#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
+#include "Plugins/Process/Utility/UnwindLLDB.h"
using namespace lldb;
using namespace lldb_private;
@@ -140,7 +143,9 @@ POSIXThread::GetName ()
{
if (!m_thread_name_valid)
{
- SetName(Host::GetThreadName(GetProcess()->GetID(), GetID()).c_str());
+ llvm::SmallString<32> thread_name;
+ HostNativeThread::GetName(GetID(), thread_name);
+ m_thread_name = thread_name.c_str();
m_thread_name_valid = true;
}
@@ -164,6 +169,14 @@ POSIXThread::GetRegisterContext()
case llvm::Triple::FreeBSD:
switch (target_arch.GetMachine())
{
+ case llvm::Triple::ppc:
+#ifndef __powerpc64__
+ reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch);
+ break;
+#endif
+ case llvm::Triple::ppc64:
+ reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch);
+ break;
case llvm::Triple::mips64:
reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
break;
@@ -226,6 +239,14 @@ POSIXThread::GetRegisterContext()
m_reg_context_sp.reset(reg_ctx);
break;
}
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ {
+ RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
case llvm::Triple::x86:
case llvm::Triple::x86_64:
{
@@ -621,6 +642,8 @@ POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
case llvm::Triple::aarch64:
case llvm::Triple::mips64:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
{
@@ -652,6 +675,8 @@ POSIXThread::GetRegisterName(unsigned reg)
case llvm::Triple::aarch64:
case llvm::Triple::mips64:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
name = GetRegisterContext()->GetRegisterName(reg);
diff --git a/source/Plugins/Process/POSIX/POSIXThread.h b/source/Plugins/Process/POSIX/POSIXThread.h
index 51d6645f209d..56dcccbfb0f9 100644
--- a/source/Plugins/Process/POSIX/POSIXThread.h
+++ b/source/Plugins/Process/POSIX/POSIXThread.h
@@ -17,7 +17,7 @@
// Other libraries and framework includes
#include "lldb/Target/Thread.h"
-#include "RegisterContextPOSIX.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
class ProcessMessage;
class ProcessMonitor;
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index f340631c7d07..0e5ab5a8d8b1 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -16,6 +16,7 @@
// Other libraries and framework includes
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Host/FileSpec.h"
@@ -28,7 +29,7 @@
#include "ProcessPOSIX.h"
#include "ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
-#include "ProcessMonitor.h"
+#include "Plugins/Process/Linux/ProcessMonitor.h"
#include "POSIXThread.h"
using namespace lldb;
@@ -140,8 +141,8 @@ ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid)
// Resolve the executable module
ModuleSP exe_module_sp;
FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
- error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(),
- m_target.GetArchitecture(),
+ ModuleSpec exe_module_spec(process_info.GetExecutableFile(), m_target.GetArchitecture());
+ error = platform_sp->ResolveExecutable(exe_module_spec,
exe_module_sp,
executable_search_paths.GetSize() ? &executable_search_paths : NULL);
if (!error.Success())
@@ -176,9 +177,9 @@ ProcessPOSIX::WillLaunch(Module* module)
}
const char *
-ProcessPOSIX::GetFilePath(const lldb_private::FileAction *file_action, const char *default_path)
+ProcessPOSIX::GetFilePath(const lldb_private::FileAction *file_action, const char *default_path,
+ const char *dbg_pts_path)
{
- const char *pts_name = "/dev/pts/";
const char *path = NULL;
if (file_action)
@@ -190,11 +191,11 @@ ProcessPOSIX::GetFilePath(const lldb_private::FileAction *file_action, const cha
// (/dev/pts). If so, convert to using a different default path
// instead to redirect I/O to the debugger console. This should
// also handle user overrides to /dev/null or a different file.
- if (!path || ::strncmp(path, pts_name, ::strlen(pts_name)) == 0)
+ if (!path || (dbg_pts_path &&
+ ::strncmp(path, dbg_pts_path, ::strlen(dbg_pts_path)) == 0))
path = default_path;
}
}
-
return path;
}
@@ -224,14 +225,16 @@ ProcessPOSIX::DoLaunch (Module *module,
const char *stdout_path = NULL;
const char *stderr_path = NULL;
+ const char * dbg_pts_path = launch_info.GetPTY().GetSlaveName(NULL,0);
+
file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
- stdin_path = GetFilePath(file_action, stdin_path);
+ stdin_path = GetFilePath(file_action, stdin_path, dbg_pts_path);
file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
- stdout_path = GetFilePath(file_action, stdout_path);
+ stdout_path = GetFilePath(file_action, stdout_path, dbg_pts_path);
file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
- stderr_path = GetFilePath(file_action, stderr_path);
+ stderr_path = GetFilePath(file_action, stderr_path, dbg_pts_path);
m_monitor = new ProcessMonitor (this,
module,
@@ -338,6 +341,11 @@ ProcessPOSIX::DoDestroy()
{
assert(m_monitor);
m_exit_now = true;
+ if (GetID() == LLDB_INVALID_PROCESS_ID)
+ {
+ error.SetErrorString("invalid process id");
+ return error;
+ }
if (!m_monitor->Kill())
{
error.SetErrorToErrno();
@@ -363,11 +371,11 @@ ProcessPOSIX::DoDidExec()
ProcessInstanceInfo process_info;
platform_sp->GetProcessInfo(GetID(), process_info);
ModuleSP exe_module_sp;
+ ModuleSpec exe_module_spec(process_info.GetExecutableFile(), target->GetArchitecture());
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);
+ Error error = platform_sp->ResolveExecutable(exe_module_spec,
+ exe_module_sp,
+ executable_search_paths.GetSize() ? &executable_search_paths : NULL);
if (!error.Success())
return;
target->SetExecutableModule(exe_module_sp, true);
@@ -432,8 +440,7 @@ ProcessPOSIX::SendMessage(const ProcessMessage &message)
// FIXME: I'm not sure we need to do this.
if (message.GetTID() == GetID())
{
- m_exit_status = message.GetExitStatus();
- SetExitStatus(m_exit_status, NULL);
+ SetExitStatus(message.GetExitStatus(), NULL);
}
else if (!IsAThreadRunning())
SetPrivateState(eStateStopped);
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.h b/source/Plugins/Process/POSIX/ProcessPOSIX.h
index 033accf17f29..f152356b3093 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.h
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.h
@@ -42,104 +42,104 @@ public:
// Process protocol.
//------------------------------------------------------------------
virtual void
- Finalize();
+ Finalize() override;
virtual bool
- CanDebug(lldb_private::Target &target, bool plugin_specified_by_name);
+ CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override;
virtual lldb_private::Error
- WillLaunch(lldb_private::Module *module);
+ WillLaunch(lldb_private::Module *module) override;
virtual lldb_private::Error
- DoAttachToProcessWithID(lldb::pid_t pid);
+ DoAttachToProcessWithID(lldb::pid_t pid) override;
virtual lldb_private::Error
- DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info);
+ DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override;
virtual lldb_private::Error
DoLaunch (lldb_private::Module *exe_module,
- lldb_private::ProcessLaunchInfo &launch_info);
+ lldb_private::ProcessLaunchInfo &launch_info) override;
virtual void
- DidLaunch();
+ DidLaunch() override;
virtual lldb_private::Error
- DoResume();
+ DoResume() override;
virtual lldb_private::Error
- DoHalt(bool &caused_stop);
+ DoHalt(bool &caused_stop) override;
virtual lldb_private::Error
- DoDetach(bool keep_stopped) = 0;
+ DoDetach(bool keep_stopped) override = 0;
virtual lldb_private::Error
- DoSignal(int signal);
+ DoSignal(int signal) override;
virtual lldb_private::Error
- DoDestroy();
+ DoDestroy() override;
virtual void
- DoDidExec();
+ DoDidExec() override;
virtual void
- RefreshStateAfterStop();
+ RefreshStateAfterStop() override;
virtual bool
- IsAlive();
+ IsAlive() override;
virtual size_t
DoReadMemory(lldb::addr_t vm_addr,
void *buf,
size_t size,
- lldb_private::Error &error);
+ lldb_private::Error &error) override;
virtual size_t
DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
- lldb_private::Error &error);
+ lldb_private::Error &error) override;
virtual lldb::addr_t
DoAllocateMemory(size_t size, uint32_t permissions,
- lldb_private::Error &error);
+ lldb_private::Error &error) override;
virtual lldb_private::Error
- DoDeallocateMemory(lldb::addr_t ptr);
+ DoDeallocateMemory(lldb::addr_t ptr) override;
virtual size_t
GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
virtual lldb_private::Error
- EnableBreakpointSite(lldb_private::BreakpointSite *bp_site);
+ EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
virtual lldb_private::Error
- DisableBreakpointSite(lldb_private::BreakpointSite *bp_site);
+ DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
virtual lldb_private::Error
- EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true);
+ EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
virtual lldb_private::Error
- DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true);
+ DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
virtual lldb_private::Error
- GetWatchpointSupportInfo(uint32_t &num);
+ GetWatchpointSupportInfo(uint32_t &num) override;
virtual lldb_private::Error
- GetWatchpointSupportInfo(uint32_t &num, bool &after);
+ GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
virtual uint32_t
UpdateThreadListIfNeeded();
virtual bool
UpdateThreadList(lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &new_thread_list) = 0;
+ lldb_private::ThreadList &new_thread_list) override = 0;
virtual lldb::ByteOrder
GetByteOrder() const;
virtual lldb::addr_t
- GetImageInfoAddress();
+ GetImageInfoAddress() override;
virtual size_t
- PutSTDIN(const char *buf, size_t len, lldb_private::Error &error);
+ PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override;
const lldb::DataBufferSP
GetAuxvData () override;
@@ -154,7 +154,8 @@ public:
ProcessMonitor &
GetMonitor() { assert(m_monitor); return *m_monitor; }
- const char *GetFilePath(const lldb_private::FileAction *file_action, const char *default_path);
+ const char *GetFilePath(const lldb_private::FileAction *file_action, const char *default_path,
+ const char *dbg_pts_path);
/// Stops all threads in the process.
/// The \p stop_tid parameter indicates the thread which initiated the stop.
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp
index 9109cdb000ae..ec34d9e28161 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp
@@ -10,10 +10,10 @@
#include "lldb/Target/Thread.h"
#include "lldb/Core/RegisterValue.h"
-#include "RegisterContextPOSIX_arm64.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
#include "ProcessPOSIX.h"
#include "RegisterContextPOSIXProcessMonitor_arm64.h"
-#include "ProcessMonitor.h"
+#include "Plugins/Process/Linux/ProcessMonitor.h"
#define REG_CONTEXT_SIZE (GetGPRSize())
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp
index 9bfe236de139..6717d20da056 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp
@@ -10,10 +10,10 @@
#include "lldb/Target/Thread.h"
#include "lldb/Core/RegisterValue.h"
-#include "RegisterContextPOSIX_mips64.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
#include "ProcessPOSIX.h"
#include "RegisterContextPOSIXProcessMonitor_mips64.h"
-#include "ProcessMonitor.h"
+#include "Plugins/Process/Linux/ProcessMonitor.h"
using namespace lldb_private;
using namespace lldb;
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp
new file mode 100644
index 000000000000..b542db4779db
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp
@@ -0,0 +1,321 @@
+//===-- RegisterContextPOSIXProcessMonitor_powerpc.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_powerpc.h"
+#include "ProcessPOSIX.h"
+#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
+#include "ProcessMonitor.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+#define REG_CONTEXT_SIZE (GetGPRSize())
+
+RegisterContextPOSIXProcessMonitor_powerpc::RegisterContextPOSIXProcessMonitor_powerpc(Thread &thread,
+ uint32_t concrete_frame_idx,
+ lldb_private::RegisterInfoInterface *register_info)
+ : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info)
+{
+}
+
+ProcessMonitor &
+RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor()
+{
+ ProcessSP base = CalculateProcess();
+ ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ return process->GetMonitor();
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR()
+{
+ // XXX not yet implemented
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR()
+{
+ // XXX not yet implemented
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const unsigned reg,
+ RegisterValue &value)
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg),
+ GetRegisterName(reg),
+ GetRegisterSize(reg),
+ value);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::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();
+ // Account for the fact that 32-bit targets on powerpc64 really use 64-bit
+ // registers in ptrace, but expose here 32-bit registers with a higher
+ // offset.
+ uint64_t offset = GetRegisterOffset(reg_to_write);
+ offset &= ~(sizeof(uintptr_t) - 1);
+ return monitor.WriteRegisterValue(m_thread.GetID(),
+ offset,
+ GetRegisterName(reg_to_write),
+ value_to_write);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::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_powerpc::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_powerpc::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_powerpc, GetGPRSize());
+ dst += GetGPRSize();
+ }
+ }
+ return success;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::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_powerpc, src, GetGPRSize());
+
+ if (WriteGPR())
+ {
+ src += GetGPRSize();
+ }
+ }
+ }
+ return success;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_powerpc::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_powerpc::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(bool enable)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint()
+{
+ lldb::addr_t pc;
+
+ if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+ return false;
+
+ return true;
+}
+
+unsigned
+RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg;
+ for (reg = 0; reg < k_num_registers_powerpc; reg++)
+ {
+ if (GetRegisterInfo()[reg].byte_offset == offset)
+ break;
+ }
+ assert(reg < k_num_registers_powerpc && "Invalid register offset.");
+ return reg;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits()
+{
+ return false;
+}
+
+addr_t
+RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(uint32_t hw_index)
+{
+ return LLDB_INVALID_ADDRESS;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(uint32_t hw_index)
+{
+ return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
+ bool read, bool write,
+ uint32_t hw_index)
+{
+ return false;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints()
+{
+ return 0;
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h
new file mode 100644
index 000000000000..92a331285515
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h
@@ -0,0 +1,95 @@
+//===-- RegisterContextPOSIXProcessMonitor_powerpc.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_powerpc_H_
+#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
+
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
+
+class RegisterContextPOSIXProcessMonitor_powerpc:
+ public RegisterContextPOSIX_powerpc,
+ public POSIXBreakpointProtocol
+{
+public:
+ RegisterContextPOSIXProcessMonitor_powerpc(lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ lldb_private::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
index e534f3b4f9d0..1956e4584fa9 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -10,9 +10,13 @@
#include "lldb/Target/Thread.h"
#include "lldb/Core/RegisterValue.h"
-#include "ProcessPOSIX.h"
+#include "Plugins/Process/POSIX/ProcessPOSIX.h"
#include "RegisterContextPOSIXProcessMonitor_x86.h"
-#include "ProcessMonitor.h"
+#if defined(__FreeBSD__)
+#include "Plugins/Process/FreeBSD/ProcessMonitor.h"
+#else
+#include "Plugins/Process/Linux/ProcessMonitor.h"
+#endif
using namespace lldb_private;
using namespace lldb;
@@ -48,6 +52,7 @@ size_and_rw_bits(size_t size, bool read, bool write)
return (0x2 << 2) | rw;
default:
assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
+ return 0; // Unreachable. Just to silence compiler.
}
}
diff --git a/source/Plugins/Process/Utility/ARMDefines.h b/source/Plugins/Process/Utility/ARMDefines.h
index 2c8ad3586af1..cfb33beb447a 100644
--- a/source/Plugins/Process/Utility/ARMDefines.h
+++ b/source/Plugins/Process/Utility/ARMDefines.h
@@ -45,7 +45,8 @@ typedef enum
#define COND_AL 0xE // Always (unconditional) Always (unconditional) Any
#define COND_UNCOND 0xF
-static inline const char *ARMCondCodeToString(uint32_t CC)
+static inline const char *
+ARMCondCodeToString(uint32_t CC)
{
switch (CC) {
default: assert(0 && "Unknown condition code");
@@ -67,6 +68,37 @@ static inline const char *ARMCondCodeToString(uint32_t CC)
}
}
+static inline bool
+ARMConditionPassed(const uint32_t condition, const uint32_t cpsr)
+{
+ const uint32_t cpsr_n = (cpsr >> 31) & 1u; // Negative condition code flag
+ const uint32_t cpsr_z = (cpsr >> 30) & 1u; // Zero condition code flag
+ const uint32_t cpsr_c = (cpsr >> 29) & 1u; // Carry condition code flag
+ const uint32_t cpsr_v = (cpsr >> 28) & 1u; // Overflow condition code flag
+
+ switch (condition) {
+ case COND_EQ: return (cpsr_z == 1);
+ case COND_NE: return (cpsr_z == 0);
+ case COND_CS: return (cpsr_c == 1);
+ case COND_CC: return (cpsr_c == 0);
+ case COND_MI: return (cpsr_n == 1);
+ case COND_PL: return (cpsr_n == 0);
+ case COND_VS: return (cpsr_v == 1);
+ case COND_VC: return (cpsr_v == 0);
+ case COND_HI: return ((cpsr_c == 1) && (cpsr_z == 0));
+ case COND_LS: return ((cpsr_c == 0) || (cpsr_z == 1));
+ case COND_GE: return (cpsr_n == cpsr_v);
+ case COND_LT: return (cpsr_n != cpsr_v);
+ case COND_GT: return ((cpsr_z == 0) && (cpsr_n == cpsr_v));
+ case COND_LE: return ((cpsr_z == 1) || (cpsr_n != cpsr_v));
+ case COND_AL:
+ case COND_UNCOND:
+ default:
+ return true;
+ }
+ return false;
+}
+
// Bit positions for CPSR
#define CPSR_T_POS 5
#define CPSR_F_POS 6
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 3507ccf92065..1088924bfeac 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -81,6 +81,7 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
else
{
Clear();
+ printf("error: register sets must have valid names\n");
return 0;
}
}
@@ -121,6 +122,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
if (reg_info.name == NULL)
{
Clear();
+ printf("error: registers must have valid names\n");
+ reg_info_dict.Dump();
return 0;
}
@@ -290,6 +293,7 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
if (!success)
{
Clear();
+ reg_info_dict.Dump();
return 0;
}
}
@@ -297,6 +301,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
if (bitsize == 0)
{
Clear();
+ printf("error: invalid or missing 'bitsize' key/value pair in register dictionary\n");
+ reg_info_dict.Dump();
return 0;
}
@@ -308,6 +314,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail())
{
Clear();
+ printf("error: invalid 'format' value in register dictionary\n");
+ reg_info_dict.Dump();
return 0;
}
}
@@ -326,6 +334,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
if (static_cast<size_t>(set) >= m_sets.size())
{
Clear();
+ printf("error: invalid 'set' value in register dictionary, valid values are 0 - %i\n", (int)set);
+ reg_info_dict.Dump();
return 0;
}
@@ -409,6 +419,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
else
{
Clear();
+ printf("error: items in the 'registers' array must be dictionaries\n");
+ regs.Dump();
return 0;
}
}
diff --git a/source/Plugins/Process/Utility/HistoryThread.cpp b/source/Plugins/Process/Utility/HistoryThread.cpp
index 590bb0162c8a..206b8290c5fd 100644
--- a/source/Plugins/Process/Utility/HistoryThread.cpp
+++ b/source/Plugins/Process/Utility/HistoryThread.cpp
@@ -39,7 +39,7 @@ HistoryThread::HistoryThread (lldb_private::Process &process,
m_originating_unique_thread_id (tid),
m_queue_id (LLDB_INVALID_QUEUE_ID)
{
- m_unwinder_ap.reset (new HistoryUnwind (*this, pcs, stop_id, stop_id_is_valid));
+ m_unwinder_ap.reset (new HistoryUnwind (*this, pcs, stop_id_is_valid));
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
log->Printf ("%p HistoryThread::HistoryThread",
diff --git a/source/Plugins/Process/Utility/HistoryThread.h b/source/Plugins/Process/Utility/HistoryThread.h
index f9a431d8340b..51173c626d71 100644
--- a/source/Plugins/Process/Utility/HistoryThread.h
+++ b/source/Plugins/Process/Utility/HistoryThread.h
@@ -101,6 +101,18 @@ public:
{
m_thread_name = name;
}
+
+ virtual const char *
+ GetName ()
+ {
+ return m_thread_name.c_str();
+ }
+
+ virtual void
+ SetName(const char *name)
+ {
+ m_thread_name = name;
+ }
protected:
virtual lldb::StackFrameListSP
diff --git a/source/Plugins/Process/Utility/HistoryUnwind.cpp b/source/Plugins/Process/Utility/HistoryUnwind.cpp
index f809ebedcfc8..14afcbee0b49 100644
--- a/source/Plugins/Process/Utility/HistoryUnwind.cpp
+++ b/source/Plugins/Process/Utility/HistoryUnwind.cpp
@@ -24,11 +24,9 @@ using namespace lldb_private;
HistoryUnwind::HistoryUnwind (Thread &thread,
std::vector<lldb::addr_t> pcs,
- uint32_t stop_id,
bool stop_id_is_valid) :
Unwind (thread),
m_pcs (pcs),
- m_stop_id (stop_id),
m_stop_id_is_valid (stop_id_is_valid)
{
}
diff --git a/source/Plugins/Process/Utility/HistoryUnwind.h b/source/Plugins/Process/Utility/HistoryUnwind.h
index 0661b8028608..733f93e1ff87 100644
--- a/source/Plugins/Process/Utility/HistoryUnwind.h
+++ b/source/Plugins/Process/Utility/HistoryUnwind.h
@@ -21,7 +21,7 @@ namespace lldb_private {
class HistoryUnwind : public lldb_private::Unwind
{
public:
- HistoryUnwind (Thread &thread, std::vector<lldb::addr_t> pcs, uint32_t stop_id, bool stop_id_is_valid);
+ HistoryUnwind (Thread &thread, std::vector<lldb::addr_t> pcs, bool stop_id_is_valid);
virtual ~HistoryUnwind ();
@@ -42,7 +42,6 @@ protected:
private:
std::vector<lldb::addr_t> m_pcs;
- uint32_t m_stop_id;
bool m_stop_id_is_valid;
};
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 4a94457466be..7db83ae5467f 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -98,13 +98,11 @@ lldb_private::InferiorCallMmap (Process *process,
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset };
- ThreadPlanCallFunction *call_function_thread_plan
- = new ThreadPlanCallFunction (*thread,
- mmap_range.GetBaseAddress(),
- clang_void_ptr_type,
- args,
- options);
- lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
+ lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
+ mmap_range.GetBaseAddress(),
+ clang_void_ptr_type,
+ args,
+ options));
if (call_plan_sp)
{
StreamFile error_strm;
@@ -241,13 +239,11 @@ lldb_private::InferiorCall (Process *process,
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- ThreadPlanCallFunction *call_function_thread_plan
- = new ThreadPlanCallFunction (*thread,
- *address,
- clang_void_ptr_type,
- llvm::ArrayRef<addr_t>(),
- options);
- lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
+ lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
+ *address,
+ clang_void_ptr_type,
+ llvm::ArrayRef<addr_t>(),
+ options));
if (call_plan_sp)
{
StreamString error_strm;
diff --git a/source/Plugins/Process/Utility/InstructionUtils.h b/source/Plugins/Process/Utility/InstructionUtils.h
index 813990095c49..6226fbc04b08 100644
--- a/source/Plugins/Process/Utility/InstructionUtils.h
+++ b/source/Plugins/Process/Utility/InstructionUtils.h
@@ -20,7 +20,7 @@ static inline uint64_t
Bits64 (const uint64_t bits, const uint32_t msbit, const uint32_t lsbit)
{
assert(msbit < 64 && lsbit <= msbit);
- return (bits >> lsbit) & ((1u << (msbit - lsbit + 1)) - 1);
+ return (bits >> lsbit) & ((1ull << (msbit - lsbit + 1)) - 1);
}
// Return the bit field(s) from the most significant bit (msbit) to the
diff --git a/source/Plugins/Process/Utility/LinuxSignals.cpp b/source/Plugins/Process/Utility/LinuxSignals.cpp
index fb49df681cae..11a3eef23529 100644
--- a/source/Plugins/Process/Utility/LinuxSignals.cpp
+++ b/source/Plugins/Process/Utility/LinuxSignals.cpp
@@ -53,7 +53,7 @@ LinuxSignals::Reset()
AddSignal (24, "SIGXCPU", "XCPU", false, true , true , "CPU resource exceeded");
AddSignal (25, "SIGXFSZ", "XFSZ", false, true , true , "file size limit exceeded");
AddSignal (26, "SIGVTALRM", "VTALRM", false, true , true , "virtual time alarm");
- AddSignal (27, "SIGPROF", "PROF", false, true , true , "profiling time alarm");
+ AddSignal (27, "SIGPROF", "PROF", false, false, false, "profiling time alarm");
AddSignal (28, "SIGWINCH", "WINCH", false, true , true , "window size changes");
AddSignal (29, "SIGPOLL", "POLL", false, true , true , "pollable event");
AddSignal (29, "SIGIO", "IO", false, true , true , "input/output ready");
diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
new file mode 100644
index 000000000000..5170e6d2accb
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
@@ -0,0 +1,230 @@
+//===-- RegisterContextFreeBSD_powerpc.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_powerpc.h"
+#include "RegisterContextFreeBSD_powerpc.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// http://svnweb.freebsd.org/base/head/sys/powerpc/include/reg.h
+typedef struct _GPR64
+{
+ uint64_t r0;
+ 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 r28;
+ uint64_t r29;
+ uint64_t r30;
+ uint64_t r31;
+ uint64_t lr;
+ uint64_t cr;
+ uint64_t xer;
+ uint64_t ctr;
+ uint64_t pc;
+} GPR64;
+
+typedef struct _GPR32
+{
+ uint32_t r0;
+ uint32_t r1;
+ uint32_t r2;
+ uint32_t r3;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t r12;
+ uint32_t r13;
+ uint32_t r14;
+ uint32_t r15;
+ uint32_t r16;
+ uint32_t r17;
+ uint32_t r18;
+ uint32_t r19;
+ uint32_t r20;
+ uint32_t r21;
+ uint32_t r22;
+ uint32_t r23;
+ uint32_t r24;
+ uint32_t r25;
+ uint32_t r26;
+ uint32_t r27;
+ uint32_t r28;
+ uint32_t r29;
+ uint32_t r30;
+ uint32_t r31;
+ uint32_t lr;
+ uint32_t cr;
+ uint32_t xer;
+ uint32_t ctr;
+ uint32_t pc;
+} GPR32;
+
+typedef struct _FPR
+{
+ uint64_t f0;
+ uint64_t f1;
+ uint64_t f2;
+ uint64_t f3;
+ uint64_t f4;
+ uint64_t f5;
+ uint64_t f6;
+ uint64_t f7;
+ uint64_t f8;
+ uint64_t f9;
+ uint64_t f10;
+ uint64_t f11;
+ uint64_t f12;
+ uint64_t f13;
+ uint64_t f14;
+ uint64_t f15;
+ uint64_t f16;
+ uint64_t f17;
+ uint64_t f18;
+ uint64_t f19;
+ uint64_t f20;
+ uint64_t f21;
+ uint64_t f22;
+ uint64_t f23;
+ uint64_t f24;
+ uint64_t f25;
+ uint64_t f26;
+ uint64_t f27;
+ uint64_t f28;
+ uint64_t f29;
+ uint64_t f30;
+ uint64_t f31;
+ uint64_t fpscr;
+} FPR;
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_powerpc to declare our g_register_infos_powerpc structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_POWERPC_STRUCT
+#include "RegisterInfos_powerpc.h"
+#undef DECLARE_REGISTER_INFOS_POWERPC_STRUCT
+
+RegisterContextFreeBSD_powerpc::RegisterContextFreeBSD_powerpc(const ArchSpec &target_arch) :
+ RegisterInfoInterface(target_arch)
+{
+}
+
+RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc()
+{
+}
+
+size_t
+RegisterContextFreeBSD_powerpc::GetGPRSize() const
+{
+ // This is an 'abstract' base, so no GPR struct.
+ return 0;
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_powerpc::GetRegisterInfo() const
+{
+ //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc);
+ llvm_unreachable("Abstract class!");
+ return NULL;
+}
+
+uint32_t
+RegisterContextFreeBSD_powerpc::GetRegisterCount () const
+{
+ return 0;
+}
+
+RegisterContextFreeBSD_powerpc32::RegisterContextFreeBSD_powerpc32(const ArchSpec &target_arch) :
+ RegisterContextFreeBSD_powerpc(target_arch)
+{
+}
+
+RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32()
+{
+}
+
+size_t
+RegisterContextFreeBSD_powerpc32::GetGPRSize() const
+{
+ return sizeof(GPR32);
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_powerpc32::GetRegisterInfo() const
+{
+ //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc);
+ return g_register_infos_powerpc32;
+}
+
+uint32_t
+RegisterContextFreeBSD_powerpc32::GetRegisterCount () const
+{
+ return static_cast<uint32_t> (sizeof (g_register_infos_powerpc32) / sizeof (g_register_infos_powerpc32 [0]));
+}
+
+RegisterContextFreeBSD_powerpc64::RegisterContextFreeBSD_powerpc64(const ArchSpec &target_arch) :
+ RegisterContextFreeBSD_powerpc(target_arch)
+{
+}
+
+RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64()
+{
+}
+
+size_t
+RegisterContextFreeBSD_powerpc64::GetGPRSize() const
+{
+ return sizeof(GPR64);
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_powerpc64::GetRegisterInfo() const
+{
+ //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc);
+ if (m_target_arch.GetMachine() == llvm::Triple::ppc)
+ return g_register_infos_powerpc64_32;
+ return g_register_infos_powerpc64;
+}
+
+uint32_t
+RegisterContextFreeBSD_powerpc64::GetRegisterCount () const
+{
+ return static_cast<uint32_t> (sizeof (g_register_infos_powerpc64) / sizeof (g_register_infos_powerpc64 [0]));
+}
diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
new file mode 100644
index 000000000000..b907fe99b5e0
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
@@ -0,0 +1,66 @@
+//===-- RegisterContextFreeBSD_powerpc.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_powerpc_H_
+#define liblldb_RegisterContextFreeBSD_powerpc_H_
+
+#include "RegisterContextPOSIX.h"
+
+class RegisterContextFreeBSD_powerpc:
+ public lldb_private::RegisterInfoInterface
+{
+public:
+ RegisterContextFreeBSD_powerpc(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextFreeBSD_powerpc();
+
+ size_t
+ GetGPRSize() const override;
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo() const override;
+
+ uint32_t
+ GetRegisterCount() const override;
+};
+
+class RegisterContextFreeBSD_powerpc32:
+ public RegisterContextFreeBSD_powerpc
+{
+public:
+ RegisterContextFreeBSD_powerpc32(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextFreeBSD_powerpc32();
+
+ size_t
+ GetGPRSize() const override;
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo() const override;
+
+ uint32_t
+ GetRegisterCount() const override;
+};
+
+class RegisterContextFreeBSD_powerpc64:
+ public RegisterContextFreeBSD_powerpc
+{
+public:
+ RegisterContextFreeBSD_powerpc64(const lldb_private::ArchSpec &target_arch);
+ virtual ~RegisterContextFreeBSD_powerpc64();
+
+ size_t
+ GetGPRSize() const override;
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo() const override;
+
+ uint32_t
+ GetRegisterCount() const override;
+};
+
+#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index b58e6bb607ed..f47d687702ec 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -172,6 +172,21 @@ RegisterContextLLDB::InitializeZerothFrame()
m_sym_ctx_valid = true;
}
+ if (m_sym_ctx.symbol)
+ {
+ UnwindLogMsg ("with pc value of 0x%" PRIx64 ", symbol name is '%s'",
+ current_pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString());
+ }
+ else if (m_sym_ctx.function)
+ {
+ UnwindLogMsg ("with pc value of 0x%" PRIx64 ", function name is '%s'",
+ current_pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.function->GetName().AsCString());
+ }
+ else
+ {
+ UnwindLogMsg ("with pc value of 0x%" PRIx64 ", no symbol/function name is known.", current_pc);
+ }
+
AddressRange addr_range;
m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range);
@@ -217,7 +232,6 @@ RegisterContextLLDB::InitializeZerothFrame()
m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
UnwindPlan::RowSP active_row;
- int cfa_offset = 0;
lldb::RegisterKind row_register_kind = eRegisterKindGeneric;
if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
@@ -239,18 +253,13 @@ RegisterContextLLDB::InitializeZerothFrame()
}
- addr_t cfa_regval = LLDB_INVALID_ADDRESS;
- if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
+ if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))
{
UnwindLogMsg ("could not read CFA register for this frame.");
m_frame_type = eNotAValidFrame;
return;
}
- cfa_offset = active_row->GetCFAOffset ();
- m_cfa = cfa_regval + cfa_offset;
-
- UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan",
(uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),
(uint64_t) m_cfa,
@@ -294,20 +303,27 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (log)
{
- UnwindLogMsg ("pc = 0x%16.16" PRIx64, pc);
+ UnwindLogMsg ("pc = 0x%" PRIx64, pc);
addr_t reg_val;
if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
- UnwindLogMsg ("fp = 0x%16.16" PRIx64, reg_val);
+ UnwindLogMsg ("fp = 0x%" PRIx64, reg_val);
if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
- UnwindLogMsg ("sp = 0x%16.16" PRIx64, reg_val);
+ UnwindLogMsg ("sp = 0x%" PRIx64, reg_val);
}
- // A pc of 0x0 means it's the end of the stack crawl
- if (pc == 0)
+ // A pc of 0x0 means it's the end of the stack crawl unless we're above a trap handler function
+ bool above_trap_handler = false;
+ if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsTrapHandlerFrame())
+ above_trap_handler = true;
+
+ if (pc == 0 || pc == 0x1)
{
- m_frame_type = eNotAValidFrame;
- UnwindLogMsg ("this frame has a pc of 0x0");
- return;
+ if (above_trap_handler == false)
+ {
+ m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("this frame has a pc of 0x0");
+ return;
+ }
}
ExecutionContext exe_ctx(m_thread.shared_from_this());
@@ -363,35 +379,31 @@ RegisterContextLLDB::InitializeNonZerothFrame()
m_all_registers_available = false;
m_current_offset = -1;
m_current_offset_backed_up_one = -1;
- addr_t cfa_regval = LLDB_INVALID_ADDRESS;
RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
if (row.get())
{
- uint32_t cfa_regnum = row->GetCFARegister();
- int cfa_offset = row->GetCFAOffset();
- if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
+ if (!ReadCFAValueForRow (row_register_kind, row, m_cfa))
{
UnwindLogMsg ("failed to get cfa value");
if (m_frame_type != eSkipFrame) // don't override eSkipFrame
{
- m_frame_type = eNormalFrame;
+ m_frame_type = eNotAValidFrame;
}
return;
}
- m_cfa = cfa_regval + cfa_offset;
// A couple of sanity checks..
- if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
+ if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1)
{
UnwindLogMsg ("could not find a valid cfa address");
m_frame_type = eNotAValidFrame;
return;
}
- // cfa_regval should point into the stack memory; if we can query memory region permissions,
+ // m_cfa should point into the stack memory; if we can query memory region permissions,
// see if the memory is allocated & readable.
- if (process->GetLoadAddressPermissions(cfa_regval, permissions)
+ if (process->GetLoadAddressPermissions(m_cfa, permissions)
&& (permissions & ePermissionsReadable) == 0)
{
m_frame_type = eNotAValidFrame;
@@ -406,6 +418,17 @@ RegisterContextLLDB::InitializeNonZerothFrame()
return;
}
+ if (CheckIfLoopingStack ())
+ {
+ TryFallbackUnwindPlan();
+ if (CheckIfLoopingStack ())
+ {
+ UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping");
+ m_frame_type = eNotAValidFrame;
+ return;
+ }
+ }
+
UnwindLogMsg ("initialized frame cfa is 0x%" PRIx64, (uint64_t) m_cfa);
return;
}
@@ -431,6 +454,21 @@ RegisterContextLLDB::InitializeNonZerothFrame()
m_sym_ctx_valid = true;
}
+ if (m_sym_ctx.symbol)
+ {
+ UnwindLogMsg ("with pc value of 0x%" PRIx64 ", symbol name is '%s'",
+ pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString());
+ }
+ else if (m_sym_ctx.function)
+ {
+ UnwindLogMsg ("with pc value of 0x%" PRIx64 ", function name is '%s'",
+ pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.function->GetName().AsCString());
+ }
+ else
+ {
+ UnwindLogMsg ("with pc value of 0x%" PRIx64 ", no symbol/function name is known.", pc);
+ }
+
AddressRange addr_range;
if (!m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range))
{
@@ -461,17 +499,22 @@ RegisterContextLLDB::InitializeNonZerothFrame()
// 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);
+ UnwindLogMsg ("Backing up the pc value of 0x%" PRIx64 " by 1 and re-doing symbol lookup; old symbol was %s",
+ pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString());
+ Address temporary_pc;
+ temporary_pc.SetLoadAddress (pc - 1, &process->GetTarget());
+ m_sym_ctx.Clear (false);
m_sym_ctx_valid = false;
uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
- if (pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, resolve_scope, m_sym_ctx) & resolve_scope)
+ ModuleSP temporary_module_sp = temporary_pc.GetModule();
+ if (temporary_module_sp &&
+ temporary_module_sp->ResolveSymbolContextForAddress (temporary_pc, resolve_scope, m_sym_ctx) & resolve_scope)
{
if (m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range))
m_sym_ctx_valid = true;
}
+ UnwindLogMsg ("Symbol is now %s", m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString());
}
// If we were able to find a symbol/function, set addr_range_ptr to the bounds of that symbol/function.
@@ -479,13 +522,15 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (addr_range.GetBaseAddress().IsValid())
{
m_start_pc = addr_range.GetBaseAddress();
- m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset();
+ m_current_offset = pc - m_start_pc.GetLoadAddress (&process->GetTarget());
m_current_offset_backed_up_one = m_current_offset;
if (decr_pc_and_recompute_addr_range && m_current_offset_backed_up_one > 0)
{
m_current_offset_backed_up_one--;
if (m_sym_ctx_valid)
- m_current_pc.SetOffset(m_current_pc.GetOffset() - 1);
+ {
+ m_current_pc.SetLoadAddress (pc - 1, &process->GetTarget());
+ }
}
}
else
@@ -512,7 +557,6 @@ RegisterContextLLDB::InitializeNonZerothFrame()
m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
UnwindPlan::RowSP active_row;
- int cfa_offset = 0;
RegisterKind row_register_kind = eRegisterKindGeneric;
// Try to get by with just the fast UnwindPlan if possible - the full UnwindPlan may be expensive to get
@@ -553,27 +597,33 @@ RegisterContextLLDB::InitializeNonZerothFrame()
return;
}
- addr_t cfa_regval = LLDB_INVALID_ADDRESS;
- if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
+ if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))
{
UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister());
m_frame_type = eNotAValidFrame;
return;
}
- cfa_offset = active_row->GetCFAOffset ();
- m_cfa = cfa_regval + cfa_offset;
+ UnwindLogMsg ("m_cfa = 0x%" PRIx64, m_cfa);
- UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
-
- // A couple of sanity checks..
- if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
+ if (CheckIfLoopingStack ())
{
- UnwindLogMsg ("could not find a valid cfa address");
- m_frame_type = eNotAValidFrame;
- return;
+ TryFallbackUnwindPlan();
+ if (CheckIfLoopingStack ())
+ {
+ UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping");
+ m_frame_type = eNotAValidFrame;
+ return;
+ }
}
+ UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64,
+ (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
+}
+
+bool
+RegisterContextLLDB::CheckIfLoopingStack ()
+{
// If we have a bad stack setup, we can get the same CFA value multiple times -- or even
// more devious, we can actually oscillate between two CFA values. Detect that here and
// break out to avoid a possible infinite loop in lldb trying to unwind the stack.
@@ -581,29 +631,19 @@ RegisterContextLLDB::InitializeNonZerothFrame()
addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS;
if (GetNextFrame().get() && GetNextFrame()->GetCFA(next_frame_cfa))
{
- bool repeating_frames = false;
if (next_frame_cfa == m_cfa)
{
- repeating_frames = true;
- }
- else
- {
- if (GetNextFrame()->GetNextFrame() && GetNextFrame()->GetNextFrame()->GetCFA(next_next_frame_cfa)
- && next_next_frame_cfa == m_cfa)
- {
- repeating_frames = true;
- }
+ // We have a loop in the stack unwind
+ return true;
}
- if (repeating_frames && abi && abi->FunctionCallsChangeCFA())
+ if (GetNextFrame()->GetNextFrame().get() && GetNextFrame()->GetNextFrame()->GetCFA(next_next_frame_cfa)
+ && next_next_frame_cfa == m_cfa)
{
- UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping");
- m_frame_type = eNotAValidFrame;
- return;
+ // We have a loop in the stack unwind
+ return true;
}
}
-
- UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64,
- (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
+ return false;
}
@@ -715,13 +755,17 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
uint32_t permissions;
addr_t current_pc_addr = m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr());
if (current_pc_addr == 0
- || (process->GetLoadAddressPermissions (current_pc_addr, permissions)
+ || (process &&
+ process->GetLoadAddressPermissions (current_pc_addr, permissions)
&& (permissions & ePermissionsExecutable) == 0))
{
- unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
- abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp);
- m_frame_type = eNormalFrame;
- return unwind_plan_sp;
+ if (abi)
+ {
+ unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+ abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp);
+ m_frame_type = eNormalFrame;
+ return unwind_plan_sp;
+ }
}
}
@@ -764,10 +808,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// is properly encoded in the eh_frame section, so prefer that if available.
// On other platforms we may need to provide a platform-specific UnwindPlan which encodes the details of
// how to unwind out of sigtramp.
- if (m_frame_type == eTrapHandlerFrame)
+ if (m_frame_type == eTrapHandlerFrame && process)
{
m_fast_unwind_plan_sp.reset();
- unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
+ unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes)
{
return unwind_plan_sp;
@@ -782,7 +826,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// But there is not.
if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx))
{
- unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
+ unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
@@ -792,7 +836,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
}
// Typically the NonCallSite UnwindPlan is the unwind created by inspecting the assembly language instructions
- if (behaves_like_zeroth_frame)
+ if (behaves_like_zeroth_frame && process)
{
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (process->GetTarget(), m_thread, m_current_offset_backed_up_one);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
@@ -812,7 +856,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
}
// Typically this is unwind info from an eh_frame section intended for exception handling; only valid at call sites
- unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
+ if (process)
+ {
+ unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one);
+ }
int valid_offset = -1;
if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset))
{
@@ -822,7 +869,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've
// struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible.
- unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (process->GetTarget(), m_thread, m_current_offset_backed_up_one);
+ if (process)
+ {
+ unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (process->GetTarget(), m_thread, m_current_offset_backed_up_one);
+ }
if (unwind_plan_sp && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo)
{
// We probably have an UnwindPlan created by inspecting assembly instructions, and we probably
@@ -908,6 +958,16 @@ RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::Unwind
switch (regloc.type)
{
+ case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext:
+ {
+ const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
+
+ if (!other_reg_info)
+ return false;
+
+ success = m_thread.GetRegisterContext()->ReadRegister (other_reg_info, value);
+ }
+ break;
case UnwindLLDB::RegisterLocation::eRegisterInRegister:
{
const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
@@ -962,6 +1022,12 @@ RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindL
switch (regloc.type)
{
+ case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext:
+ {
+ const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
+ success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value);
+ }
+ break;
case UnwindLLDB::RegisterLocation::eRegisterInRegister:
{
const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
@@ -1004,6 +1070,11 @@ RegisterContextLLDB::IsValid () const
return m_frame_type != eNotAValidFrame;
}
+// After the final stack frame in a stack walk we'll get one invalid (eNotAValidFrame) stack frame --
+// one past the end of the stack walk. But higher-level code will need to tell the differnece between
+// "the unwind plan below this frame failed" versus "we successfully completed the stack walk" so
+// this method helps to disambiguate that.
+
bool
RegisterContextLLDB::IsTrapHandlerFrame () const
{
@@ -1056,57 +1127,42 @@ RegisterContextLLDB::IsTrapHandlerSymbol (lldb_private::Process *process, const
enum UnwindLLDB::RegisterSearchResult
RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc)
{
+ RegisterNumber regnum (m_thread, eRegisterKindLLDB, lldb_regnum);
+
// Have we already found this register location?
if (!m_registers.empty())
{
std::map<uint32_t, lldb_private::UnwindLLDB::RegisterLocation>::const_iterator iterator;
- iterator = m_registers.find (lldb_regnum);
+ iterator = m_registers.find (regnum.GetAsKind (eRegisterKindLLDB));
if (iterator != m_registers.end())
{
regloc = iterator->second;
- UnwindLogMsg ("supplying caller's saved reg %d's location, cached", lldb_regnum);
+ UnwindLogMsg ("supplying caller's saved %s (%d)'s location, cached",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
}
- uint32_t sp_regnum = LLDB_INVALID_REGNUM;
- uint32_t pc_regnum = LLDB_INVALID_REGNUM;
- m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum);
- m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum);
-
- // Are we looking for the CALLER's stack pointer? The stack pointer is defined to be the same as THIS frame's
- // CFA so just return the CFA value. This is true on x86-32/x86-64 at least.
- if (sp_regnum != LLDB_INVALID_REGNUM && sp_regnum == lldb_regnum)
- {
- // make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value)
- assert (sizeof (addr_t) <= sizeof (uint64_t));
- regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
- regloc.location.inferred_value = m_cfa;
- m_registers[lldb_regnum] = regloc;
- UnwindLogMsg ("supplying caller's stack pointer (%d) value, computed from CFA", lldb_regnum);
- return UnwindLLDB::RegisterSearchResult::eRegisterFound;
- }
-
// Look through the available UnwindPlans for the register location.
UnwindPlan::Row::RegisterLocation unwindplan_regloc;
bool have_unwindplan_regloc = false;
- RegisterKind unwindplan_registerkind = (RegisterKind)-1;
+ RegisterKind unwindplan_registerkind = kNumRegisterKinds;
if (m_fast_unwind_plan_sp)
{
UnwindPlan::RowSP active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
unwindplan_registerkind = m_fast_unwind_plan_sp->GetRegisterKind ();
- uint32_t row_regnum;
- if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
+ if (regnum.GetAsKind (unwindplan_registerkind) == LLDB_INVALID_REGNUM)
{
- UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
- lldb_regnum, (int) unwindplan_registerkind);
+ UnwindLogMsg ("could not convert lldb regnum %s (%d) into %d RegisterKind reg numbering scheme",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), (int) unwindplan_registerkind);
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
- if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
+ if (active_row->GetRegisterInfo (regnum.GetAsKind (unwindplan_registerkind), unwindplan_regloc))
{
- UnwindLogMsg ("supplying caller's saved reg %d's location using FastUnwindPlan", lldb_regnum);
+ UnwindLogMsg ("supplying caller's saved %s (%d)'s location using FastUnwindPlan",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
have_unwindplan_regloc = true;
}
}
@@ -1119,37 +1175,49 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
if (m_full_unwind_plan_sp)
{
+ RegisterNumber pc_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+
UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind ();
- uint32_t row_regnum;
- bool row_register_rewritten_to_return_address_reg = false;
+
+ RegisterNumber return_address_reg;
// If we're fetching the saved pc and this UnwindPlan defines a ReturnAddress register (e.g. lr on arm),
// look for the return address register number in the UnwindPlan's row.
- if (lldb_regnum == pc_regnum && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM)
+ if (pc_regnum.IsValid()
+ && pc_regnum == regnum
+ && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM)
{
- row_regnum = m_full_unwind_plan_sp->GetReturnAddressRegister();
- row_register_rewritten_to_return_address_reg = true;
- UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead",
- row_regnum);
+
+ return_address_reg.init (m_thread, m_full_unwind_plan_sp->GetRegisterKind(), m_full_unwind_plan_sp->GetReturnAddressRegister());
+ regnum = return_address_reg;
+ UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting %s (%d) instead",
+ return_address_reg.GetName(), return_address_reg.GetAsKind (eRegisterKindLLDB));
}
else
{
- if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
+ if (regnum.GetAsKind (unwindplan_registerkind) == LLDB_INVALID_REGNUM)
{
if (unwindplan_registerkind == eRegisterKindGeneric)
- UnwindLogMsg ("could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme", lldb_regnum);
+ {
+ UnwindLogMsg ("could not convert lldb regnum %s (%d) into eRegisterKindGeneric reg numbering scheme",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
+ }
else
- UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
- lldb_regnum, (int) unwindplan_registerkind);
+ {
+ UnwindLogMsg ("could not convert lldb regnum %s (%d) into %d RegisterKind reg numbering scheme",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), (int) unwindplan_registerkind);
+ }
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
}
- if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
+ if (regnum.IsValid()
+ && active_row->GetRegisterInfo (regnum.GetAsKind (unwindplan_registerkind), unwindplan_regloc))
{
have_unwindplan_regloc = true;
- UnwindLogMsg ("supplying caller's saved reg %d's location using %s UnwindPlan", lldb_regnum,
+ UnwindLogMsg ("supplying caller's saved %s (%d)'s location using %s UnwindPlan",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB),
m_full_unwind_plan_sp->GetSourceName().GetCString());
}
@@ -1158,19 +1226,19 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
// Handle this specially.
if (have_unwindplan_regloc == false
- && row_register_rewritten_to_return_address_reg == true
- && IsFrameZero()
- && row_regnum != LLDB_INVALID_REGNUM)
+ && return_address_reg.IsValid()
+ && IsFrameZero())
{
- uint32_t ra_regnum_in_lldb_reg_numbering;
- if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, row_regnum, eRegisterKindLLDB, ra_regnum_in_lldb_reg_numbering))
+ if (return_address_reg.GetAsKind (eRegisterKindLLDB) != LLDB_INVALID_REGNUM)
{
lldb_private::UnwindLLDB::RegisterLocation new_regloc;
- new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
- new_regloc.location.register_number = ra_regnum_in_lldb_reg_numbering;
- m_registers[lldb_regnum] = new_regloc;
+ new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext;
+ new_regloc.location.register_number = return_address_reg.GetAsKind (eRegisterKindLLDB);
+ m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc;
regloc = new_regloc;
- UnwindLogMsg ("supplying caller's register %d from the live RegisterContext at frame 0, saved in %d", lldb_regnum, ra_regnum_in_lldb_reg_numbering);
+ UnwindLogMsg ("supplying caller's register %s (%d) from the live RegisterContext at frame 0, saved in %d",
+ return_address_reg.GetName(), return_address_reg.GetAsKind (eRegisterKindLLDB),
+ return_address_reg.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
}
@@ -1187,13 +1255,12 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
// when we're at a call site location.
// arch_default_ra_regnum is the return address register # in the Full UnwindPlan register numbering
- uint32_t arch_default_ra_regnum = LLDB_INVALID_REGNUM;
- if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, unwindplan_registerkind, arch_default_ra_regnum)
- && arch_default_ra_regnum != LLDB_INVALID_REGNUM
- && pc_regnum != LLDB_INVALID_REGNUM
- && pc_regnum == lldb_regnum
+ RegisterNumber arch_default_ra_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+
+ if (arch_default_ra_regnum.GetAsKind (unwindplan_registerkind) != LLDB_INVALID_REGNUM
+ && pc_regnum == regnum
&& unwindplan_regloc.IsInOtherRegister()
- && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum
+ && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum.GetAsKind (unwindplan_registerkind)
&& m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes
&& !m_all_registers_available)
{
@@ -1201,15 +1268,32 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
m_full_unwind_plan_sp->GetSourceName().GetCString());
// Throw away the full unwindplan; install the arch default unwindplan
- if (TryFallbackUnwindPlan())
+ if (ForceSwitchToFallbackUnwindPlan())
{
- // Now re-fetch the pc value we're searching for
- uint32_t arch_default_pc_reg = LLDB_INVALID_REGNUM;
+ // Update for the possibly new unwind plan
+ unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind ();
UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
- if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, m_full_unwind_plan_sp->GetRegisterKind(), arch_default_pc_reg)
- && arch_default_pc_reg != LLDB_INVALID_REGNUM
- && active_row
- && active_row->GetRegisterInfo (arch_default_pc_reg, unwindplan_regloc))
+
+ // Sanity check: Verify that we can fetch a pc value and CFA value with this unwind plan
+
+ RegisterNumber arch_default_pc_reg (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ bool can_fetch_pc_value = false;
+ bool can_fetch_cfa = false;
+ addr_t cfa_value;
+ if (active_row)
+ {
+ if (arch_default_pc_reg.GetAsKind (unwindplan_registerkind) != LLDB_INVALID_REGNUM
+ && active_row->GetRegisterInfo (arch_default_pc_reg.GetAsKind (unwindplan_registerkind), unwindplan_regloc))
+ {
+ can_fetch_pc_value = true;
+ }
+ if (ReadCFAValueForRow (unwindplan_registerkind, active_row, cfa_value))
+ {
+ can_fetch_cfa = true;
+ }
+ }
+
+ if (can_fetch_pc_value && can_fetch_cfa)
{
have_unwindplan_regloc = true;
}
@@ -1218,10 +1302,35 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
have_unwindplan_regloc = false;
}
}
+ else
+ {
+ // We were unable to fall back to another unwind plan
+ have_unwindplan_regloc = false;
+ }
}
}
}
+ if (have_unwindplan_regloc == false)
+ {
+ // Did the UnwindPlan fail to give us the caller's stack pointer?
+ // The stack pointer is defined to be the same as THIS frame's CFA, so return the CFA value as
+ // the caller's stack pointer. This is true on x86-32/x86-64 at least.
+
+ RegisterNumber sp_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ if (sp_regnum.GetAsKind (eRegisterKindLLDB) != LLDB_INVALID_REGNUM
+ && sp_regnum.GetAsKind (eRegisterKindLLDB) == regnum.GetAsKind (eRegisterKindLLDB))
+ {
+ // make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value)
+ assert (sizeof (addr_t) <= sizeof (uint64_t));
+ regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
+ regloc.location.inferred_value = m_cfa;
+ m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg ("supplying caller's stack pointer %s (%d) value, computed from CFA",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+ }
+ }
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
@@ -1232,11 +1341,11 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
ABI *abi = process ? process->GetABI().get() : NULL;
if (abi)
{
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(regnum.GetAsKind (eRegisterKindLLDB));
if (reg_info && abi->RegisterIsVolatile (reg_info))
{
- UnwindLogMsg ("did not supply reg location for %d (%s) because it is volatile",
- lldb_regnum, reg_info->name ? reg_info->name : "??");
+ UnwindLogMsg ("did not supply reg location for %s (%d) because it is volatile",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
}
}
@@ -1245,15 +1354,27 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
{
// This is frame 0 - we should return the actual live register context value
lldb_private::UnwindLLDB::RegisterLocation new_regloc;
- new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
- new_regloc.location.register_number = lldb_regnum;
- m_registers[lldb_regnum] = new_regloc;
+ new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext;
+ new_regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB);
+ m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc;
regloc = new_regloc;
- UnwindLogMsg ("supplying caller's register %d from the live RegisterContext at frame 0", lldb_regnum);
+ UnwindLogMsg ("supplying caller's register %s (%d) from the live RegisterContext at frame 0",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
else
- UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+ {
+ std::string unwindplan_name ("");
+ if (m_full_unwind_plan_sp)
+ {
+ unwindplan_name += "via '";
+ unwindplan_name += m_full_unwind_plan_sp->GetSourceName().AsCString();
+ unwindplan_name += "'";
+ }
+ UnwindLogMsg ("no save location for %s (%d) %s",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB),
+ unwindplan_name.c_str());
+ }
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
@@ -1262,8 +1383,9 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
{
lldb_private::UnwindLLDB::RegisterLocation new_regloc;
new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved;
- m_registers[lldb_regnum] = new_regloc;
- UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+ m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc;
+ UnwindLogMsg ("save location for %s (%d) is unspecified, continue searching",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
@@ -1271,7 +1393,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
{
if (IsFrameZero ())
{
- UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+ UnwindLogMsg ("could not supply caller's %s (%d) location, IsSame",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
else
@@ -1285,8 +1408,10 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
int offset = unwindplan_regloc.GetOffset();
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
regloc.location.inferred_value = m_cfa + offset;
- m_registers[lldb_regnum] = regloc;
- UnwindLogMsg ("supplying caller's register %d, value is CFA plus offset %d", lldb_regnum, offset);
+ m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg ("supplying caller's register %s (%d), value is CFA plus offset %d [value is 0x%" PRIx64 "]",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB),
+ offset, regloc.location.inferred_value);
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
@@ -1295,24 +1420,29 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
int offset = unwindplan_regloc.GetOffset();
regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
regloc.location.target_memory_location = m_cfa + offset;
- m_registers[lldb_regnum] = regloc;
- UnwindLogMsg ("supplying caller's register %d from the stack, saved at CFA plus offset %d", lldb_regnum, offset);
+ m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg ("supplying caller's register %s (%d) from the stack, saved at CFA plus offset %d [saved at 0x%" PRIx64 "]",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB),
+ offset, regloc.location.target_memory_location);
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
if (unwindplan_regloc.IsInOtherRegister())
{
uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber();
- uint32_t row_regnum_in_lldb;
- if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb))
+ RegisterNumber row_regnum (m_thread, unwindplan_registerkind, unwindplan_regnum);
+ if (row_regnum.GetAsKind (eRegisterKindLLDB) == LLDB_INVALID_REGNUM)
{
- UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+ UnwindLogMsg ("could not supply caller's %s (%d) location - was saved in another reg but couldn't convert that regnum",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
- regloc.location.register_number = row_regnum_in_lldb;
- m_registers[lldb_regnum] = regloc;
- UnwindLogMsg ("supplying caller's register %d, saved in register %d", lldb_regnum, row_regnum_in_lldb);
+ regloc.location.register_number = row_regnum.GetAsKind (eRegisterKindLLDB);
+ m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg ("supplying caller's register %s (%d), saved in register %s (%d)",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB),
+ row_regnum.GetName(), row_regnum.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
@@ -1334,75 +1464,277 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
{
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
regloc.location.inferred_value = val;
- m_registers[lldb_regnum] = regloc;
- UnwindLogMsg ("supplying caller's register %d via DWARF expression (IsDWARFExpression)", lldb_regnum);
+ m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg ("supplying caller's register %s (%d) via DWARF expression (IsDWARFExpression)",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
else
{
regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
regloc.location.target_memory_location = val;
- m_registers[lldb_regnum] = regloc;
- UnwindLogMsg ("supplying caller's register %d via DWARF expression (IsAtDWARFExpression)", lldb_regnum);
+ m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg ("supplying caller's register %s (%d) via DWARF expression (IsAtDWARFExpression)",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
}
- UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", lldb_regnum);
+ UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for %s (%d) but failed",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
- UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+ UnwindLogMsg ("no save location for %s (%d) in this stack frame",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
// FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
-// If the Full unwindplan has been determined to be incorrect, this method will
-// replace it with the architecture's default unwindplan, if one is defined.
-// It will also find the FuncUnwinders object for this function and replace the
-// Full unwind method for the function there so we don't use the errant Full unwindplan
-// again in the future of this debug session.
-// We're most likely doing this because the Full unwindplan was generated by assembly
-// instruction profiling and the profiler got something wrong.
+// TryFallbackUnwindPlan() -- this method is a little tricky.
+//
+// When this is called, the frame above -- the caller frame, the "previous" frame --
+// is invalid or bad.
+//
+// Instead of stopping the stack walk here, we'll try a different UnwindPlan and see
+// if we can get a valid frame above us.
+//
+// This most often happens when an unwind plan based on assembly instruction inspection
+// is not correct -- mostly with hand-written assembly functions or functions where the
+// stack frame is set up "out of band", e.g. the kernel saved the register context and
+// then called an asynchronous trap handler like _sigtramp.
+//
+// Often in these cases, if we just do a dumb stack walk we'll get past this tricky
+// frame and our usual techniques can continue to be used.
bool
RegisterContextLLDB::TryFallbackUnwindPlan ()
{
- UnwindPlan::Row::RegisterLocation unwindplan_regloc;
- if (m_fallback_unwind_plan_sp.get() == NULL)
+ if (m_fallback_unwind_plan_sp.get() == nullptr)
+ return false;
+
+ if (m_full_unwind_plan_sp.get() == nullptr)
return false;
+ if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get()
+ || m_full_unwind_plan_sp->GetSourceName() == m_fallback_unwind_plan_sp->GetSourceName())
+ {
+ return false;
+ }
+
+ // If a compiler generated unwind plan failed, trying the arch default unwindplan
+ // isn't going to do any better.
+ if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes)
+ return false;
+
+
+ // Get the caller's pc value and our own CFA value.
+ // Swap in the fallback unwind plan, re-fetch the caller's pc value and CFA value.
+ // If they're the same, then the fallback unwind plan provides no benefit.
+
+ RegisterNumber pc_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+
+ addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS;
+ addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS;
+ addr_t old_this_frame_cfa_value = m_cfa;
+ UnwindLLDB::RegisterLocation regloc;
+ if (SavedLocationForRegister (pc_regnum.GetAsKind (eRegisterKindLLDB), regloc) == UnwindLLDB::RegisterSearchResult::eRegisterFound)
+ {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(pc_regnum.GetAsKind (eRegisterKindLLDB));
+ if (reg_info)
+ {
+ RegisterValue reg_value;
+ if (ReadRegisterValueFromRegisterLocation (regloc, reg_info, reg_value))
+ {
+ old_caller_pc_value = reg_value.GetAsUInt64();
+ }
+ }
+ }
+
+ // This is a tricky wrinkle! If SavedLocationForRegister() detects a really impossible
+ // register location for the full unwind plan, it may call ForceSwitchToFallbackUnwindPlan()
+ // which in turn replaces the full unwindplan with the fallback... in short, we're done,
+ // we're using the fallback UnwindPlan.
+ // We checked if m_fallback_unwind_plan_sp was nullptr at the top -- the only way it
+ // became nullptr since then is via SavedLocationForRegister().
+ if (m_fallback_unwind_plan_sp.get() == nullptr)
+ return true;
+
+
+ // Switch the full UnwindPlan to be the fallback UnwindPlan. If we decide this isn't
+ // working, we need to restore.
+ // We'll also need to save & restore the value of the m_cfa ivar. Save is down below a bit in 'old_cfa'.
UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
+ addr_t old_cfa = m_cfa;
+
+ m_registers.clear();
+
+ m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
+
UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
{
- FuncUnwindersSP func_unwinders_sp;
- if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule())
+ addr_t new_cfa;
+ if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa)
+ || new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS)
+ {
+ UnwindLogMsg ("failed to get cfa with fallback unwindplan");
+ m_fallback_unwind_plan_sp.reset();
+ m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+ m_cfa = old_cfa;
+ return false;
+ }
+ m_cfa = new_cfa;
+
+ if (SavedLocationForRegister (pc_regnum.GetAsKind (eRegisterKindLLDB), regloc) == UnwindLLDB::RegisterSearchResult::eRegisterFound)
{
- func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
- if (func_unwinders_sp)
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(pc_regnum.GetAsKind (eRegisterKindLLDB));
+ if (reg_info)
{
- func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread);
+ RegisterValue reg_value;
+ if (ReadRegisterValueFromRegisterLocation (regloc, reg_info, reg_value))
+ {
+ new_caller_pc_value = reg_value.GetAsUInt64();
+ }
}
}
- m_registers.clear();
- m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
- addr_t cfa_regval = LLDB_INVALID_ADDRESS;
- if (ReadGPRValue (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval))
+
+
+ if (new_caller_pc_value == LLDB_INVALID_ADDRESS)
{
- m_cfa = cfa_regval + active_row->GetCFAOffset ();
+ UnwindLogMsg ("failed to get a pc value for the caller frame with the fallback unwind plan");
+ m_fallback_unwind_plan_sp.reset();
+ m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+ m_cfa = old_cfa;
+ return false;
+ }
+
+ if (old_caller_pc_value != LLDB_INVALID_ADDRESS)
+ {
+ if (old_caller_pc_value == new_caller_pc_value && new_cfa == old_this_frame_cfa_value)
+ {
+ UnwindLogMsg ("fallback unwind plan got the same values for this frame CFA and caller frame pc, not using");
+ m_fallback_unwind_plan_sp.reset();
+ m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+ m_cfa = old_cfa;
+ return false;
+ }
}
- UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.",
- original_full_unwind_plan_sp->GetSourceName().GetCString(), m_fallback_unwind_plan_sp->GetSourceName().GetCString());
+ UnwindLogMsg ("trying to unwind from this function with the UnwindPlan '%s' because UnwindPlan '%s' failed.",
+ m_fallback_unwind_plan_sp->GetSourceName().GetCString(),
+ original_full_unwind_plan_sp->GetSourceName().GetCString());
+
+ // We've copied the fallback unwind plan into the full - now clear the fallback.
m_fallback_unwind_plan_sp.reset();
}
return true;
}
+bool
+RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan ()
+{
+ if (m_fallback_unwind_plan_sp.get() == NULL)
+ return false;
+
+ if (m_full_unwind_plan_sp.get() == NULL)
+ return false;
+
+ if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get()
+ || m_full_unwind_plan_sp->GetSourceName() == m_fallback_unwind_plan_sp->GetSourceName())
+ {
+ return false;
+ }
+
+ UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+
+ if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
+ {
+ addr_t new_cfa;
+ if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa)
+ || new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS)
+ {
+ UnwindLogMsg ("failed to get cfa with fallback unwindplan");
+ m_fallback_unwind_plan_sp.reset();
+ return false;
+ }
+
+ m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
+ m_fallback_unwind_plan_sp.reset();
+
+ m_registers.clear();
+
+ m_cfa = new_cfa;
+
+ UnwindLogMsg ("switched unconditionally to the fallback unwindplan %s", m_full_unwind_plan_sp->GetSourceName().GetCString());
+ return true;
+ }
+ return false;
+}
+
+bool
+RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind,
+ const UnwindPlan::RowSP &row,
+ addr_t &cfa_value)
+{
+ RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFARegister());
+ RegisterValue reg_value;
+
+ cfa_value = LLDB_INVALID_ADDRESS;
+ addr_t cfa_reg_contents;
+
+ if (ReadGPRValue (cfa_reg, cfa_reg_contents))
+ {
+ if (row->GetCFAType() == UnwindPlan::Row::CFAIsRegisterDereferenced)
+ {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex (cfa_reg.GetAsKind (eRegisterKindLLDB));
+ RegisterValue reg_value;
+ if (reg_info)
+ {
+ Error error = ReadRegisterValueFromMemory(reg_info,
+ cfa_reg_contents,
+ reg_info->byte_size,
+ reg_value);
+ if (error.Success ())
+ {
+ cfa_value = reg_value.GetAsUInt64();
+ UnwindLogMsg ("CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64 ", CFA value is 0x%" PRIx64,
+ cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
+ cfa_reg_contents, cfa_value);
+ return true;
+ }
+ else
+ {
+ UnwindLogMsg ("Tried to deref reg %s (%d) [0x%" PRIx64 "] but memory read failed.",
+ cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
+ cfa_reg_contents);
+ }
+ }
+ }
+ else
+ {
+ if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || cfa_reg_contents == 1)
+ {
+ UnwindLogMsg ("Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64,
+ cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
+ cfa_reg_contents);
+ cfa_reg_contents = LLDB_INVALID_ADDRESS;
+ return false;
+ }
+ cfa_value = cfa_reg_contents + row->GetCFAOffset ();
+ UnwindLogMsg ("CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 ", offset is %d",
+ cfa_value,
+ cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
+ cfa_reg_contents, row->GetCFAOffset ());
+ return true;
+ }
+ }
+ return false;
+}
+
// Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that
// this frame called. e.g.
//
@@ -1471,6 +1803,12 @@ RegisterContextLLDB::ReadGPRValue (lldb::RegisterKind register_kind, uint32_t re
return false;
}
+bool
+RegisterContextLLDB::ReadGPRValue (const RegisterNumber &regnum, addr_t &value)
+{
+ return ReadGPRValue (regnum.GetRegisterKind(), regnum.GetRegisterNumber(), value);
+}
+
// Find the value of a register in THIS frame
bool
@@ -1593,6 +1931,10 @@ RegisterContextLLDB::ReadPC (addr_t& pc)
if (!IsValid())
return false;
+ bool above_trap_handler = false;
+ if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsTrapHandlerFrame())
+ above_trap_handler = true;
+
if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc))
{
// A pc value of 0 or 1 is impossible in the middle of the stack -- it indicates the end of a stack walk.
@@ -1601,6 +1943,7 @@ RegisterContextLLDB::ReadPC (addr_t& pc)
// find the bug.
if (m_all_registers_available == false
+ && above_trap_handler == false
&& (pc == 0 || pc == 1))
{
return false;
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h
index d6ecfeb68caa..5f94a977448d 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -16,6 +16,7 @@
#include "lldb/Target/RegisterContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Utility/RegisterNumber.h"
#include "UnwindLLDB.h"
namespace lldb_private {
@@ -98,6 +99,12 @@ private:
// UnwindLLDB needs to pass around references to RegisterLocations
friend class UnwindLLDB;
+
+ // Returns true if we have an unwind loop -- the same stack frame unwinding
+ // multiple times.
+ bool
+ CheckIfLoopingStack ();
+
// Indicates whether this frame is frame zero -- the currently
// executing frame -- or not.
bool
@@ -175,11 +182,30 @@ private:
bool
TryFallbackUnwindPlan ();
+ //------------------------------------------------------------------
+ /// Switch to the fallback unwind plan unconditionally without any safety
+ /// checks that it is providing better results than the normal unwind plan.
+ ///
+ /// The only time it is valid to call this method is if the full unwindplan is
+ /// found to be fundamentally incorrect/impossible.
+ ///
+ /// Returns true if it was able to install the fallback unwind plan.
+ //------------------------------------------------------------------
+ bool
+ ForceSwitchToFallbackUnwindPlan ();
+
// Get the contents of a general purpose (address-size) register for this frame
// (usually retrieved from the next frame)
bool
ReadGPRValue (lldb::RegisterKind register_kind, uint32_t regnum, lldb::addr_t &value);
+ bool
+ ReadGPRValue (const RegisterNumber &reg_num, lldb::addr_t &value);
+
+ // Get the CFA register for a given frame.
+ bool
+ ReadCFAValueForRow (lldb::RegisterKind register_kind, const UnwindPlan::RowSP &row, lldb::addr_t &value);
+
lldb::UnwindPlanSP
GetFastUnwindPlanForFrame ();
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
index e246e715de86..a2ab67438b75 100644
--- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -149,7 +149,8 @@ RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info,
// TOOD: need a better way to detect when "long double" types are
// the same bytes size as "double"
-#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && !defined(__mips__)
+#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && \
+ !defined(__mips__) && !defined(__powerpc__) && !defined(__ANDROID_NDK__)
case sizeof (long double):
if (sizeof (long double) == sizeof(uint32_t))
{
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
new file mode 100644
index 000000000000..a9477d583517
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
@@ -0,0 +1,273 @@
+//===-- RegisterContextPOSIX_powerpc.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 "RegisterContextPOSIX_powerpc.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+static const
+uint32_t g_gpr_regnums[] =
+{
+ gpr_r0_powerpc,
+ gpr_r1_powerpc,
+ gpr_r2_powerpc,
+ gpr_r3_powerpc,
+ gpr_r4_powerpc,
+ gpr_r5_powerpc,
+ gpr_r6_powerpc,
+ gpr_r7_powerpc,
+ gpr_r8_powerpc,
+ gpr_r9_powerpc,
+ gpr_r10_powerpc,
+ gpr_r11_powerpc,
+ gpr_r12_powerpc,
+ gpr_r13_powerpc,
+ gpr_r14_powerpc,
+ gpr_r15_powerpc,
+ gpr_r16_powerpc,
+ gpr_r17_powerpc,
+ gpr_r18_powerpc,
+ gpr_r19_powerpc,
+ gpr_r20_powerpc,
+ gpr_r21_powerpc,
+ gpr_r22_powerpc,
+ gpr_r23_powerpc,
+ gpr_r24_powerpc,
+ gpr_r25_powerpc,
+ gpr_r26_powerpc,
+ gpr_r27_powerpc,
+ gpr_r28_powerpc,
+ gpr_r29_powerpc,
+ gpr_r30_powerpc,
+ gpr_r31_powerpc,
+ gpr_lr_powerpc,
+ gpr_cr_powerpc,
+ gpr_xer_powerpc,
+ gpr_ctr_powerpc,
+ gpr_pc_powerpc,
+};
+
+static const
+uint32_t g_fpr_regnums[] =
+{
+ fpr_f0_powerpc,
+ fpr_f1_powerpc,
+ fpr_f2_powerpc,
+ fpr_f3_powerpc,
+ fpr_f4_powerpc,
+ fpr_f5_powerpc,
+ fpr_f6_powerpc,
+ fpr_f7_powerpc,
+ fpr_f8_powerpc,
+ fpr_f9_powerpc,
+ fpr_f10_powerpc,
+ fpr_f11_powerpc,
+ fpr_f12_powerpc,
+ fpr_f13_powerpc,
+ fpr_f14_powerpc,
+ fpr_f15_powerpc,
+ fpr_f16_powerpc,
+ fpr_f17_powerpc,
+ fpr_f18_powerpc,
+ fpr_f19_powerpc,
+ fpr_f20_powerpc,
+ fpr_f21_powerpc,
+ fpr_f22_powerpc,
+ fpr_f23_powerpc,
+ fpr_f24_powerpc,
+ fpr_f25_powerpc,
+ fpr_f26_powerpc,
+ fpr_f27_powerpc,
+ fpr_f28_powerpc,
+ fpr_f29_powerpc,
+ fpr_f30_powerpc,
+ fpr_f31_powerpc,
+ fpr_fpscr_powerpc,
+};
+
+// Number of register sets provided by this context.
+enum
+{
+ k_num_register_sets = 2
+};
+
+static const RegisterSet
+g_reg_sets_powerpc[k_num_register_sets] =
+{
+ { "General Purpose Registers", "gpr", k_num_gpr_registers_powerpc, g_gpr_regnums },
+ { "Floating Point Registers", "fpr", k_num_fpr_registers_powerpc, g_fpr_regnums },
+};
+
+bool RegisterContextPOSIX_powerpc::IsGPR(unsigned reg)
+{
+ return reg <= k_num_gpr_registers_powerpc; // GPR's come first.
+}
+
+bool
+RegisterContextPOSIX_powerpc::IsFPR(unsigned reg)
+{
+ // XXX
+ return (reg >= k_first_fpr) && (reg <= k_last_fpr);
+}
+
+RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(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_powerpc::~RegisterContextPOSIX_powerpc()
+{
+}
+
+void
+RegisterContextPOSIX_powerpc::Invalidate()
+{
+}
+
+void
+RegisterContextPOSIX_powerpc::InvalidateAllRegisters()
+{
+}
+
+unsigned
+RegisterContextPOSIX_powerpc::GetRegisterOffset(unsigned reg)
+{
+ assert(reg < k_num_registers_powerpc && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContextPOSIX_powerpc::GetRegisterSize(unsigned reg)
+{
+ assert(reg < k_num_registers_powerpc && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_size;
+}
+
+size_t
+RegisterContextPOSIX_powerpc::GetRegisterCount()
+{
+ size_t num_registers = k_num_registers_powerpc;
+ return num_registers;
+}
+
+size_t
+RegisterContextPOSIX_powerpc::GetGPRSize()
+{
+ return m_register_info_ap->GetGPRSize();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_powerpc::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_powerpc::GetRegisterInfoAtIndex(size_t reg)
+{
+ if (reg < k_num_registers_powerpc)
+ return &GetRegisterInfo()[reg];
+ else
+ return NULL;
+}
+
+size_t
+RegisterContextPOSIX_powerpc::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_powerpc::GetRegisterSet(size_t set)
+{
+ if (IsRegisterSetAvailable(set))
+ return &g_reg_sets_powerpc[set];
+ else
+ return NULL;
+}
+
+const char *
+RegisterContextPOSIX_powerpc::GetRegisterName(unsigned reg)
+{
+ assert(reg < k_num_registers_powerpc && "Invalid register offset.");
+ return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContextPOSIX_powerpc::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_powerpc::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_powerpc::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind 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/Utility/RegisterContextPOSIX_powerpc.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
new file mode 100644
index 000000000000..3194c3968c98
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
@@ -0,0 +1,173 @@
+//===-- RegisterContextPOSIX_powerpc.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_powerpc_H_
+#define liblldb_RegisterContextPOSIX_powerpc_H_
+
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContext_powerpc.h"
+
+class ProcessMonitor;
+
+// ---------------------------------------------------------------------------
+// Internal codes for all powerpc registers.
+// ---------------------------------------------------------------------------
+enum
+{
+ k_first_gpr_powerpc,
+ gpr_r0_powerpc = k_first_gpr_powerpc,
+ gpr_r1_powerpc,
+ gpr_r2_powerpc,
+ gpr_r3_powerpc,
+ gpr_r4_powerpc,
+ gpr_r5_powerpc,
+ gpr_r6_powerpc,
+ gpr_r7_powerpc,
+ gpr_r8_powerpc,
+ gpr_r9_powerpc,
+ gpr_r10_powerpc,
+ gpr_r11_powerpc,
+ gpr_r12_powerpc,
+ gpr_r13_powerpc,
+ gpr_r14_powerpc,
+ gpr_r15_powerpc,
+ gpr_r16_powerpc,
+ gpr_r17_powerpc,
+ gpr_r18_powerpc,
+ gpr_r19_powerpc,
+ gpr_r20_powerpc,
+ gpr_r21_powerpc,
+ gpr_r22_powerpc,
+ gpr_r23_powerpc,
+ gpr_r24_powerpc,
+ gpr_r25_powerpc,
+ gpr_r26_powerpc,
+ gpr_r27_powerpc,
+ gpr_r28_powerpc,
+ gpr_r29_powerpc,
+ gpr_r30_powerpc,
+ gpr_r31_powerpc,
+ gpr_lr_powerpc,
+ gpr_cr_powerpc,
+ gpr_xer_powerpc,
+ gpr_ctr_powerpc,
+ gpr_pc_powerpc,
+ k_last_gpr_powerpc = gpr_pc_powerpc,
+
+ k_first_fpr,
+ fpr_f0_powerpc = k_first_fpr,
+ fpr_f1_powerpc,
+ fpr_f2_powerpc,
+ fpr_f3_powerpc,
+ fpr_f4_powerpc,
+ fpr_f5_powerpc,
+ fpr_f6_powerpc,
+ fpr_f7_powerpc,
+ fpr_f8_powerpc,
+ fpr_f9_powerpc,
+ fpr_f10_powerpc,
+ fpr_f11_powerpc,
+ fpr_f12_powerpc,
+ fpr_f13_powerpc,
+ fpr_f14_powerpc,
+ fpr_f15_powerpc,
+ fpr_f16_powerpc,
+ fpr_f17_powerpc,
+ fpr_f18_powerpc,
+ fpr_f19_powerpc,
+ fpr_f20_powerpc,
+ fpr_f21_powerpc,
+ fpr_f22_powerpc,
+ fpr_f23_powerpc,
+ fpr_f24_powerpc,
+ fpr_f25_powerpc,
+ fpr_f26_powerpc,
+ fpr_f27_powerpc,
+ fpr_f28_powerpc,
+ fpr_f29_powerpc,
+ fpr_f30_powerpc,
+ fpr_f31_powerpc,
+ fpr_fpscr_powerpc,
+ k_last_fpr = fpr_fpscr_powerpc,
+
+ k_num_registers_powerpc,
+ k_num_gpr_registers_powerpc = k_last_gpr_powerpc - k_first_gpr_powerpc + 1,
+ k_num_fpr_registers_powerpc = k_last_fpr - k_first_fpr + 1,
+};
+
+class RegisterContextPOSIX_powerpc
+ : public lldb_private::RegisterContext
+{
+public:
+ RegisterContextPOSIX_powerpc (lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx,
+ lldb_private::RegisterInfoInterface *register_info);
+
+ ~RegisterContextPOSIX_powerpc();
+
+ 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(lldb::RegisterKind kind, uint32_t num);
+
+protected:
+ uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers.
+ std::unique_ptr<lldb_private::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_powerpc_H_
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
index 2925a33a1690..77b6385da8bd 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
@@ -30,96 +30,96 @@ 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,
+ lldb_eax_i386,
+ lldb_ebx_i386,
+ lldb_ecx_i386,
+ lldb_edx_i386,
+ lldb_edi_i386,
+ lldb_esi_i386,
+ lldb_ebp_i386,
+ lldb_esp_i386,
+ lldb_eip_i386,
+ lldb_eflags_i386,
+ lldb_cs_i386,
+ lldb_fs_i386,
+ lldb_gs_i386,
+ lldb_ss_i386,
+ lldb_ds_i386,
+ lldb_es_i386,
+ lldb_ax_i386,
+ lldb_bx_i386,
+ lldb_cx_i386,
+ lldb_dx_i386,
+ lldb_di_i386,
+ lldb_si_i386,
+ lldb_bp_i386,
+ lldb_sp_i386,
+ lldb_ah_i386,
+ lldb_bh_i386,
+ lldb_ch_i386,
+ lldb_dh_i386,
+ lldb_al_i386,
+ lldb_bl_i386,
+ lldb_cl_i386,
+ lldb_dl_i386,
LLDB_INVALID_REGNUM, // Register sets must be terminated with LLDB_INVALID_REGNUM.
};
static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - 1 == 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,
+g_lldb_regnums_i386[] =
+{
+ lldb_fctrl_i386,
+ lldb_fstat_i386,
+ lldb_ftag_i386,
+ lldb_fop_i386,
+ lldb_fiseg_i386,
+ lldb_fioff_i386,
+ lldb_foseg_i386,
+ lldb_fooff_i386,
+ lldb_mxcsr_i386,
+ lldb_mxcsrmask_i386,
+ lldb_st0_i386,
+ lldb_st1_i386,
+ lldb_st2_i386,
+ lldb_st3_i386,
+ lldb_st4_i386,
+ lldb_st5_i386,
+ lldb_st6_i386,
+ lldb_st7_i386,
+ lldb_mm0_i386,
+ lldb_mm1_i386,
+ lldb_mm2_i386,
+ lldb_mm3_i386,
+ lldb_mm4_i386,
+ lldb_mm5_i386,
+ lldb_mm6_i386,
+ lldb_mm7_i386,
+ lldb_xmm0_i386,
+ lldb_xmm1_i386,
+ lldb_xmm2_i386,
+ lldb_xmm3_i386,
+ lldb_xmm4_i386,
+ lldb_xmm5_i386,
+ lldb_xmm6_i386,
+ lldb_xmm7_i386,
LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM.
};
-static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) - 1 == k_num_fpr_registers_i386,
- "g_fpu_regnums_i386 has wrong number of register infos");
+static_assert((sizeof(g_lldb_regnums_i386) / sizeof(g_lldb_regnums_i386[0])) - 1 == k_num_fpr_registers_i386,
+ "g_lldb_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,
+ lldb_ymm0_i386,
+ lldb_ymm1_i386,
+ lldb_ymm2_i386,
+ lldb_ymm3_i386,
+ lldb_ymm4_i386,
+ lldb_ymm5_i386,
+ lldb_ymm6_i386,
+ lldb_ymm7_i386,
LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM.
};
static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 == k_num_avx_registers_i386,
@@ -128,212 +128,212 @@ static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 =
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
+ lldb_rax_x86_64,
+ lldb_rbx_x86_64,
+ lldb_rcx_x86_64,
+ lldb_rdx_x86_64,
+ lldb_rdi_x86_64,
+ lldb_rsi_x86_64,
+ lldb_rbp_x86_64,
+ lldb_rsp_x86_64,
+ lldb_r8_x86_64,
+ lldb_r9_x86_64,
+ lldb_r10_x86_64,
+ lldb_r11_x86_64,
+ lldb_r12_x86_64,
+ lldb_r13_x86_64,
+ lldb_r14_x86_64,
+ lldb_r15_x86_64,
+ lldb_rip_x86_64,
+ lldb_rflags_x86_64,
+ lldb_cs_x86_64,
+ lldb_fs_x86_64,
+ lldb_gs_x86_64,
+ lldb_ss_x86_64,
+ lldb_ds_x86_64,
+ lldb_es_x86_64,
+ lldb_eax_x86_64,
+ lldb_ebx_x86_64,
+ lldb_ecx_x86_64,
+ lldb_edx_x86_64,
+ lldb_edi_x86_64,
+ lldb_esi_x86_64,
+ lldb_ebp_x86_64,
+ lldb_esp_x86_64,
+ lldb_r8d_x86_64, // Low 32 bits or r8
+ lldb_r9d_x86_64, // Low 32 bits or r9
+ lldb_r10d_x86_64, // Low 32 bits or r10
+ lldb_r11d_x86_64, // Low 32 bits or r11
+ lldb_r12d_x86_64, // Low 32 bits or r12
+ lldb_r13d_x86_64, // Low 32 bits or r13
+ lldb_r14d_x86_64, // Low 32 bits or r14
+ lldb_r15d_x86_64, // Low 32 bits or r15
+ lldb_ax_x86_64,
+ lldb_bx_x86_64,
+ lldb_cx_x86_64,
+ lldb_dx_x86_64,
+ lldb_di_x86_64,
+ lldb_si_x86_64,
+ lldb_bp_x86_64,
+ lldb_sp_x86_64,
+ lldb_r8w_x86_64, // Low 16 bits or r8
+ lldb_r9w_x86_64, // Low 16 bits or r9
+ lldb_r10w_x86_64, // Low 16 bits or r10
+ lldb_r11w_x86_64, // Low 16 bits or r11
+ lldb_r12w_x86_64, // Low 16 bits or r12
+ lldb_r13w_x86_64, // Low 16 bits or r13
+ lldb_r14w_x86_64, // Low 16 bits or r14
+ lldb_r15w_x86_64, // Low 16 bits or r15
+ lldb_ah_x86_64,
+ lldb_bh_x86_64,
+ lldb_ch_x86_64,
+ lldb_dh_x86_64,
+ lldb_al_x86_64,
+ lldb_bl_x86_64,
+ lldb_cl_x86_64,
+ lldb_dl_x86_64,
+ lldb_dil_x86_64,
+ lldb_sil_x86_64,
+ lldb_bpl_x86_64,
+ lldb_spl_x86_64,
+ lldb_r8l_x86_64, // Low 8 bits or r8
+ lldb_r9l_x86_64, // Low 8 bits or r9
+ lldb_r10l_x86_64, // Low 8 bits or r10
+ lldb_r11l_x86_64, // Low 8 bits or r11
+ lldb_r12l_x86_64, // Low 8 bits or r12
+ lldb_r13l_x86_64, // Low 8 bits or r13
+ lldb_r14l_x86_64, // Low 8 bits or r14
+ lldb_r15l_x86_64, // Low 8 bits or r15
LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM.
};
static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - 1 == 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,
+g_lldb_regnums_x86_64[] =
+{
+ lldb_fctrl_x86_64,
+ lldb_fstat_x86_64,
+ lldb_ftag_x86_64,
+ lldb_fop_x86_64,
+ lldb_fiseg_x86_64,
+ lldb_fioff_x86_64,
+ lldb_foseg_x86_64,
+ lldb_fooff_x86_64,
+ lldb_mxcsr_x86_64,
+ lldb_mxcsrmask_x86_64,
+ lldb_st0_x86_64,
+ lldb_st1_x86_64,
+ lldb_st2_x86_64,
+ lldb_st3_x86_64,
+ lldb_st4_x86_64,
+ lldb_st5_x86_64,
+ lldb_st6_x86_64,
+ lldb_st7_x86_64,
+ lldb_mm0_x86_64,
+ lldb_mm1_x86_64,
+ lldb_mm2_x86_64,
+ lldb_mm3_x86_64,
+ lldb_mm4_x86_64,
+ lldb_mm5_x86_64,
+ lldb_mm6_x86_64,
+ lldb_mm7_x86_64,
+ lldb_xmm0_x86_64,
+ lldb_xmm1_x86_64,
+ lldb_xmm2_x86_64,
+ lldb_xmm3_x86_64,
+ lldb_xmm4_x86_64,
+ lldb_xmm5_x86_64,
+ lldb_xmm6_x86_64,
+ lldb_xmm7_x86_64,
+ lldb_xmm8_x86_64,
+ lldb_xmm9_x86_64,
+ lldb_xmm10_x86_64,
+ lldb_xmm11_x86_64,
+ lldb_xmm12_x86_64,
+ lldb_xmm13_x86_64,
+ lldb_xmm14_x86_64,
+ lldb_xmm15_x86_64,
LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM.
};
-static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) - 1 == k_num_fpr_registers_x86_64,
- "g_fpu_regnums_x86_64 has wrong number of register infos");
+static_assert((sizeof(g_lldb_regnums_x86_64) / sizeof(g_lldb_regnums_x86_64[0])) - 1 == k_num_fpr_registers_x86_64,
+ "g_lldb_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,
+ lldb_ymm0_x86_64,
+ lldb_ymm1_x86_64,
+ lldb_ymm2_x86_64,
+ lldb_ymm3_x86_64,
+ lldb_ymm4_x86_64,
+ lldb_ymm5_x86_64,
+ lldb_ymm6_x86_64,
+ lldb_ymm7_x86_64,
+ lldb_ymm8_x86_64,
+ lldb_ymm9_x86_64,
+ lldb_ymm10_x86_64,
+ lldb_ymm11_x86_64,
+ lldb_ymm12_x86_64,
+ lldb_ymm13_x86_64,
+ lldb_ymm14_x86_64,
+ lldb_ymm15_x86_64,
LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM.
};
static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - 1 == 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 };
+uint32_t RegisterContextPOSIX_x86::g_contained_eax[] = { lldb_eax_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_ebx[] = { lldb_ebx_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_ecx[] = { lldb_ecx_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_edx[] = { lldb_edx_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_edi[] = { lldb_edi_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_esi[] = { lldb_esi_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_ebp[] = { lldb_ebp_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_esp[] = { lldb_esp_i386, LLDB_INVALID_REGNUM };
+
+uint32_t RegisterContextPOSIX_x86::g_invalidate_eax[] = { lldb_eax_i386, lldb_ax_i386, lldb_ah_i386, lldb_al_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_ebx[] = { lldb_ebx_i386, lldb_bx_i386, lldb_bh_i386, lldb_bl_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_ecx[] = { lldb_ecx_i386, lldb_cx_i386, lldb_ch_i386, lldb_cl_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_edx[] = { lldb_edx_i386, lldb_dx_i386, lldb_dh_i386, lldb_dl_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_edi[] = { lldb_edi_i386, lldb_di_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_esi[] = { lldb_esi_i386, lldb_si_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_ebp[] = { lldb_ebp_i386, lldb_bp_i386, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_esp[] = { lldb_esp_i386, lldb_sp_i386, LLDB_INVALID_REGNUM };
+
+uint32_t RegisterContextPOSIX_x86::g_contained_rax[] = { lldb_rax_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rbx[] = { lldb_rbx_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rcx[] = { lldb_rcx_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rdx[] = { lldb_rdx_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rdi[] = { lldb_rdi_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rsi[] = { lldb_rsi_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rbp[] = { lldb_rbp_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_rsp[] = { lldb_rsp_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r8[] = { lldb_r8_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r9[] = { lldb_r9_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r10[] = { lldb_r10_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r11[] = { lldb_r11_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r12[] = { lldb_r12_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r13[] = { lldb_r13_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r14[] = { lldb_r14_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_contained_r15[] = { lldb_r15_x86_64, LLDB_INVALID_REGNUM };
+
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rax[] = { lldb_rax_x86_64, lldb_eax_x86_64, lldb_ax_x86_64, lldb_ah_x86_64, lldb_al_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rbx[] = { lldb_rbx_x86_64, lldb_ebx_x86_64, lldb_bx_x86_64, lldb_bh_x86_64, lldb_bl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rcx[] = { lldb_rcx_x86_64, lldb_ecx_x86_64, lldb_cx_x86_64, lldb_ch_x86_64, lldb_cl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rdx[] = { lldb_rdx_x86_64, lldb_edx_x86_64, lldb_dx_x86_64, lldb_dh_x86_64, lldb_dl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rdi[] = { lldb_rdi_x86_64, lldb_edi_x86_64, lldb_di_x86_64, lldb_dil_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rsi[] = { lldb_rsi_x86_64, lldb_esi_x86_64, lldb_si_x86_64, lldb_sil_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rbp[] = { lldb_rbp_x86_64, lldb_ebp_x86_64, lldb_bp_x86_64, lldb_bpl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_rsp[] = { lldb_rsp_x86_64, lldb_esp_x86_64, lldb_sp_x86_64, lldb_spl_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r8[] = { lldb_r8_x86_64, lldb_r8d_x86_64, lldb_r8w_x86_64, lldb_r8l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r9[] = { lldb_r9_x86_64, lldb_r9d_x86_64, lldb_r9w_x86_64, lldb_r9l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r10[] = { lldb_r10_x86_64, lldb_r10d_x86_64, lldb_r10w_x86_64, lldb_r10l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r11[] = { lldb_r11_x86_64, lldb_r11d_x86_64, lldb_r11w_x86_64, lldb_r11l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r12[] = { lldb_r12_x86_64, lldb_r12d_x86_64, lldb_r12w_x86_64, lldb_r12l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r13[] = { lldb_r13_x86_64, lldb_r13d_x86_64, lldb_r13w_x86_64, lldb_r13l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r14[] = { lldb_r14_x86_64, lldb_r14d_x86_64, lldb_r14w_x86_64, lldb_r14l_x86_64, LLDB_INVALID_REGNUM };
+uint32_t RegisterContextPOSIX_x86::g_invalidate_r15[] = { lldb_r15_x86_64, lldb_r15d_x86_64, lldb_r15w_x86_64, lldb_r15l_x86_64, LLDB_INVALID_REGNUM };
// Number of register sets provided by this context.
enum
@@ -346,7 +346,7 @@ 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 },
+ { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_lldb_regnums_i386 },
{ "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 }
};
@@ -354,7 +354,7 @@ 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 },
+ { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_lldb_regnums_x86_64 },
{ "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 }
};
@@ -399,16 +399,16 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(Thread &thread,
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;
+ m_reg_info.first_st = lldb_st0_i386;
+ m_reg_info.last_st = lldb_st7_i386;
+ m_reg_info.first_mm = lldb_mm0_i386;
+ m_reg_info.last_mm = lldb_mm7_i386;
+ m_reg_info.first_xmm = lldb_xmm0_i386;
+ m_reg_info.last_xmm = lldb_xmm7_i386;
+ m_reg_info.first_ymm = lldb_ymm0_i386;
+ m_reg_info.last_ymm = lldb_ymm7_i386;
+ m_reg_info.first_dr = lldb_dr0_i386;
+ m_reg_info.gpr_flags = lldb_eflags_i386;
break;
case llvm::Triple::x86_64:
m_reg_info.num_registers = k_num_registers_x86_64;
@@ -418,16 +418,16 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(Thread &thread,
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;
+ m_reg_info.first_st = lldb_st0_x86_64;
+ m_reg_info.last_st = lldb_st7_x86_64;
+ m_reg_info.first_mm = lldb_mm0_x86_64;
+ m_reg_info.last_mm = lldb_mm7_x86_64;
+ m_reg_info.first_xmm = lldb_xmm0_x86_64;
+ m_reg_info.last_xmm = lldb_xmm15_x86_64;
+ m_reg_info.first_ymm = lldb_ymm0_x86_64;
+ m_reg_info.last_ymm = lldb_ymm15_x86_64;
+ m_reg_info.first_dr = lldb_dr0_x86_64;
+ m_reg_info.gpr_flags = lldb_rflags_x86_64;
break;
default:
assert(false && "Unhandled target architecture.");
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
index 4db7802e1b44..0eec1d909c1a 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
@@ -11,285 +11,12 @@
#define liblldb_RegisterContextPOSIX_x86_H_
#include "lldb/Core/Log.h"
+#include "lldb-x86-register-enums.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
{
@@ -422,7 +149,7 @@ protected:
uint32_t gpr_flags;
};
- uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; // 64-bit general purpose registers.
+ uint64_t m_gpr_x86_64[lldb_private::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.
diff --git a/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
index 46dafa11d8f7..200ef4d3d651 100644
--- a/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
@@ -59,7 +59,7 @@ RegisterContextThreadMemory::UpdateRegisterContext ()
{
OperatingSystem *os = process_sp->GetOperatingSystem ();
if (os->IsOperatingSystemPluginThread (thread_sp))
- m_reg_ctx_sp = os->CreateRegisterContextForThread (thread_sp.get(), LLDB_INVALID_ADDRESS);
+ m_reg_ctx_sp = os->CreateRegisterContextForThread (thread_sp.get(), m_register_data_addr);
}
}
}
diff --git a/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/source/Plugins/Process/Utility/RegisterContext_powerpc.h
new file mode 100644
index 000000000000..cf54cc0c2145
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContext_powerpc.h
@@ -0,0 +1,163 @@
+//===-- RegisterContext_powerpc.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_powerpc_H_
+#define liblldb_RegisterContext_powerpc_H_
+
+// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
+enum
+{
+ gcc_dwarf_r0_powerpc = 0,
+ gcc_dwarf_r1_powerpc,
+ gcc_dwarf_r2_powerpc,
+ gcc_dwarf_r3_powerpc,
+ gcc_dwarf_r4_powerpc,
+ gcc_dwarf_r5_powerpc,
+ gcc_dwarf_r6_powerpc,
+ gcc_dwarf_r7_powerpc,
+ gcc_dwarf_r8_powerpc,
+ gcc_dwarf_r9_powerpc,
+ gcc_dwarf_r10_powerpc,
+ gcc_dwarf_r11_powerpc,
+ gcc_dwarf_r12_powerpc,
+ gcc_dwarf_r13_powerpc,
+ gcc_dwarf_r14_powerpc,
+ gcc_dwarf_r15_powerpc,
+ gcc_dwarf_r16_powerpc,
+ gcc_dwarf_r17_powerpc,
+ gcc_dwarf_r18_powerpc,
+ gcc_dwarf_r19_powerpc,
+ gcc_dwarf_r20_powerpc,
+ gcc_dwarf_r21_powerpc,
+ gcc_dwarf_r22_powerpc,
+ gcc_dwarf_r23_powerpc,
+ gcc_dwarf_r24_powerpc,
+ gcc_dwarf_r25_powerpc,
+ gcc_dwarf_r26_powerpc,
+ gcc_dwarf_r27_powerpc,
+ gcc_dwarf_r28_powerpc,
+ gcc_dwarf_r29_powerpc,
+ gcc_dwarf_r30_powerpc,
+ gcc_dwarf_r31_powerpc,
+ gcc_dwarf_f0_powerpc,
+ gcc_dwarf_f1_powerpc,
+ gcc_dwarf_f2_powerpc,
+ gcc_dwarf_f3_powerpc,
+ gcc_dwarf_f4_powerpc,
+ gcc_dwarf_f5_powerpc,
+ gcc_dwarf_f6_powerpc,
+ gcc_dwarf_f7_powerpc,
+ gcc_dwarf_f8_powerpc,
+ gcc_dwarf_f9_powerpc,
+ gcc_dwarf_f10_powerpc,
+ gcc_dwarf_f11_powerpc,
+ gcc_dwarf_f12_powerpc,
+ gcc_dwarf_f13_powerpc,
+ gcc_dwarf_f14_powerpc,
+ gcc_dwarf_f15_powerpc,
+ gcc_dwarf_f16_powerpc,
+ gcc_dwarf_f17_powerpc,
+ gcc_dwarf_f18_powerpc,
+ gcc_dwarf_f19_powerpc,
+ gcc_dwarf_f20_powerpc,
+ gcc_dwarf_f21_powerpc,
+ gcc_dwarf_f22_powerpc,
+ gcc_dwarf_f23_powerpc,
+ gcc_dwarf_f24_powerpc,
+ gcc_dwarf_f25_powerpc,
+ gcc_dwarf_f26_powerpc,
+ gcc_dwarf_f27_powerpc,
+ gcc_dwarf_f28_powerpc,
+ gcc_dwarf_f29_powerpc,
+ gcc_dwarf_f30_powerpc,
+ gcc_dwarf_f31_powerpc,
+ gcc_dwarf_cr_powerpc,
+ gcc_dwarf_fpscr_powerpc,
+ gcc_dwarf_xer_powerpc = 101,
+ gcc_dwarf_lr_powerpc = 108,
+ gcc_dwarf_ctr_powerpc,
+ gcc_dwarf_pc_powerpc,
+};
+
+// GDB Register numbers (eRegisterKindGDB)
+enum
+{
+ gdb_r0_powerpc = 0,
+ gdb_r1_powerpc,
+ gdb_r2_powerpc,
+ gdb_r3_powerpc,
+ gdb_r4_powerpc,
+ gdb_r5_powerpc,
+ gdb_r6_powerpc,
+ gdb_r7_powerpc,
+ gdb_r8_powerpc,
+ gdb_r9_powerpc,
+ gdb_r10_powerpc,
+ gdb_r11_powerpc,
+ gdb_r12_powerpc,
+ gdb_r13_powerpc,
+ gdb_r14_powerpc,
+ gdb_r15_powerpc,
+ gdb_r16_powerpc,
+ gdb_r17_powerpc,
+ gdb_r18_powerpc,
+ gdb_r19_powerpc,
+ gdb_r20_powerpc,
+ gdb_r21_powerpc,
+ gdb_r22_powerpc,
+ gdb_r23_powerpc,
+ gdb_r24_powerpc,
+ gdb_r25_powerpc,
+ gdb_r26_powerpc,
+ gdb_r27_powerpc,
+ gdb_r28_powerpc,
+ gdb_r29_powerpc,
+ gdb_r30_powerpc,
+ gdb_r31_powerpc,
+ gdb_f0_powerpc,
+ gdb_f1_powerpc,
+ gdb_f2_powerpc,
+ gdb_f3_powerpc,
+ gdb_f4_powerpc,
+ gdb_f5_powerpc,
+ gdb_f6_powerpc,
+ gdb_f7_powerpc,
+ gdb_f8_powerpc,
+ gdb_f9_powerpc,
+ gdb_f10_powerpc,
+ gdb_f11_powerpc,
+ gdb_f12_powerpc,
+ gdb_f13_powerpc,
+ gdb_f14_powerpc,
+ gdb_f15_powerpc,
+ gdb_f16_powerpc,
+ gdb_f17_powerpc,
+ gdb_f18_powerpc,
+ gdb_f19_powerpc,
+ gdb_f20_powerpc,
+ gdb_f21_powerpc,
+ gdb_f22_powerpc,
+ gdb_f23_powerpc,
+ gdb_f24_powerpc,
+ gdb_f25_powerpc,
+ gdb_f26_powerpc,
+ gdb_f27_powerpc,
+ gdb_f28_powerpc,
+ gdb_f29_powerpc,
+ gdb_f30_powerpc,
+ gdb_f31_powerpc,
+ gdb_cr_powerpc,
+ gdb_fpscr_powerpc,
+ gdb_xer_powerpc = 101,
+ gdb_lr_powerpc = 108,
+ gdb_ctr_powerpc,
+ gdb_pc_powerpc,
+};
+
+#endif // liblldb_RegisterContext_powerpc_H_
diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/source/Plugins/Process/Utility/RegisterInfos_arm64.h
index 1bb4e89c8f78..b687423622a4 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_arm64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_arm64.h
@@ -15,8 +15,8 @@
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
-#include "ARM64_GCC_Registers.h"
-#include "ARM64_DWARF_Registers.h"
+#include "Utility/ARM64_GCC_Registers.h"
+#include "Utility/ARM64_DWARF_Registers.h"
#ifndef GPR_OFFSET
#error GPR_OFFSET must be defined before including this header file
diff --git a/source/Plugins/Process/Utility/RegisterInfos_i386.h b/source/Plugins/Process/Utility/RegisterInfos_i386.h
index fa152b4147ce..fc94b8b2a738 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_i386.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_i386.h
@@ -42,37 +42,37 @@
// 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*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_i386 }, NULL, NULL }
+ eFormatHex, { kind1, kind2, kind3, kind4, lldb_##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 }
+ eFormatHex, { kind1, kind2, kind3, kind4, lldb_##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 }, \
+ { gcc_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, gdb_st##i##_i386, lldb_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 }, \
+ { gcc_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, gdb_mm##i##_i386, lldb_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}, \
+ { gcc_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##_i386, lldb_##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 }, \
+ { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##h_i386, lldb_##reg##i##_i386 }, \
NULL, NULL }
#define DEFINE_DR(reg, i) \
@@ -82,13 +82,13 @@
#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 }
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##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 }
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##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 }
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 }
static RegisterInfo
g_register_infos_i386[] =
diff --git a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
new file mode 100644
index 000000000000..045426648105
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
@@ -0,0 +1,144 @@
+//===-- RegisterInfos_powerpc.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include <stddef.h>
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+ (offsetof(GPR, regname))
+#define FPR_OFFSET(regname) \
+ (offsetof(FPR, regname))
+#define GPR_SIZE(regname) \
+ (sizeof(((GPR*)NULL)->regname))
+
+#ifdef DECLARE_REGISTER_INFOS_POWERPC_STRUCT
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, lldb_kind) \
+ { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
+ eFormatHex, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, gpr_##reg##_powerpc }, NULL, NULL }
+#define DEFINE_FPR(reg, lldb_kind) \
+ { #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \
+ eFormatFloat, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, fpr_##reg##_powerpc }, NULL, NULL }
+
+ // General purpose registers. GCC, DWARF, Generic, GDB
+#define POWERPC_REGS \
+ DEFINE_GPR(r0, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r1, "sp", LLDB_REGNUM_GENERIC_SP), \
+ DEFINE_GPR(r2, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r3, "arg1",LLDB_REGNUM_GENERIC_ARG1), \
+ DEFINE_GPR(r4, "arg2",LLDB_REGNUM_GENERIC_ARG2), \
+ DEFINE_GPR(r5, "arg3",LLDB_REGNUM_GENERIC_ARG3), \
+ DEFINE_GPR(r6, "arg4",LLDB_REGNUM_GENERIC_ARG4), \
+ DEFINE_GPR(r7, "arg5",LLDB_REGNUM_GENERIC_ARG5), \
+ DEFINE_GPR(r8, "arg6",LLDB_REGNUM_GENERIC_ARG6), \
+ DEFINE_GPR(r9, "arg7",LLDB_REGNUM_GENERIC_ARG7), \
+ DEFINE_GPR(r10, "arg8",LLDB_REGNUM_GENERIC_ARG8), \
+ DEFINE_GPR(r11, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r12, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r13, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r14, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r15, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r16, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r17, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r18, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r19, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r20, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r21, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r22, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r23, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r24, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r25, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r26, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r27, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r28, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r29, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r30, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(r31, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(lr, "lr", LLDB_REGNUM_GENERIC_RA), \
+ DEFINE_GPR(cr, "cr", LLDB_REGNUM_GENERIC_FLAGS), \
+ DEFINE_GPR(xer, "xer", LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(ctr, "ctr", LLDB_INVALID_REGNUM), \
+ DEFINE_GPR(pc, "pc", LLDB_REGNUM_GENERIC_PC), \
+ DEFINE_FPR(f0, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f1, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f2, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f3, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f4, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f5, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f6, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f7, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f8, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f9, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f10, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f11, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f12, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f13, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f14, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f15, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f16, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f17, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f18, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f19, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f20, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f21, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f22, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f23, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f24, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f25, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f26, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f27, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f28, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f29, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f30, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR(f31, LLDB_INVALID_REGNUM), \
+ { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL },
+static RegisterInfo
+g_register_infos_powerpc64[] =
+{
+#define GPR GPR64
+ POWERPC_REGS
+#undef GPR
+};
+
+static RegisterInfo
+g_register_infos_powerpc32[] =
+{
+#define GPR GPR32
+ POWERPC_REGS
+#undef GPR
+};
+
+static RegisterInfo
+g_register_infos_powerpc64_32[] =
+{
+#define GPR GPR64
+#undef GPR_SIZE
+#define GPR_SIZE(reg) (sizeof(uint32_t))
+#undef GPR_OFFSET
+#define GPR_OFFSET(regname) \
+ (offsetof(GPR, regname) + (sizeof(((GPR *)NULL)->regname) - GPR_SIZE(reg)))
+ POWERPC_REGS
+#undef GPR
+};
+
+static_assert((sizeof(g_register_infos_powerpc32) / sizeof(g_register_infos_powerpc32[0])) == k_num_registers_powerpc,
+ "g_register_infos_powerpc32 has wrong number of register infos");
+static_assert((sizeof(g_register_infos_powerpc64) / sizeof(g_register_infos_powerpc64[0])) == k_num_registers_powerpc,
+ "g_register_infos_powerpc64 has wrong number of register infos");
+static_assert(sizeof(g_register_infos_powerpc64_32) == sizeof(g_register_infos_powerpc64),
+ "g_register_infos_powerpc64_32 doesn't match size of g_register_infos_powerpc64");
+
+#undef DEFINE_FPR
+#undef DEFINE_GPR
+
+#endif // DECLARE_REGISTER_INFOS_POWERPC_STRUCT
+
+#undef GPR_OFFSET
+
diff --git a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
index c4dc6041ce43..c1bcd27053c6 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
@@ -42,34 +42,34 @@
// 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*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_x86_64 }, NULL, NULL }
+ eFormatHex, { kind1, kind2, kind3, kind4, lldb_##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 }
+ eFormatHex, { kind1, kind2, kind3, kind4, lldb_##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 }, \
+ { gcc_dwarf_st##i##_x86_64, gcc_dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, lldb_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 }, \
+ { gcc_dwarf_mm##i##_x86_64, gcc_dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, lldb_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}, \
+ { gcc_dwarf_##reg##i##_x86_64, gcc_dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##_x86_64, lldb_##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 }, \
+ { gcc_dwarf_##reg##i##h_x86_64, gcc_dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##h_x86_64, lldb_##reg##i##_x86_64 }, \
NULL, NULL }
#define DEFINE_DR(reg, i) \
@@ -79,16 +79,16 @@
#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 }
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##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 }
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##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 }
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##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 }
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 }
static RegisterInfo
g_register_infos_x86_64[] =
@@ -273,37 +273,37 @@ static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[
#define UPDATE_GPR_INFO(reg, reg64) \
do { \
- g_register_infos[gpr_##reg##_i386].byte_offset = GPR_OFFSET(reg64); \
+ g_register_infos[lldb_##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; \
+ g_register_infos[lldb_##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); \
+ g_register_infos[lldb_##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]); \
+ g_register_infos[lldb_##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]); \
+ g_register_infos[lldb_##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]); \
+ g_register_infos[lldb_##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); \
+ g_register_infos[lldb_dr##reg_index##_i386].byte_offset = DR_OFFSET(reg_index); \
} while(false);
// Update the register offsets
diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 0e3e559aef5c..a69b38b6c93e 100644
--- a/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -423,9 +423,11 @@ StopInfoMachException::CreateStopReasonWithMachException
wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
}
- // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS
- if (thread.GetTemporaryResumeState() == eStateStepping)
- return StopInfo::CreateStopReasonToTrace(thread);
+ else
+ {
+ is_actual_breakpoint = true;
+ is_trace_if_actual_breakpoint_missing = true;
+ }
}
else if (exc_code == 1) // EXC_ARM_BREAKPOINT
{
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 37fd4f489552..fc592e60d86d 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -172,8 +172,9 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
if (!reg_ctx_sp->IsValid())
{
- // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // We failed to get a valid RegisterContext.
+ // See if the regctx below this on the stack has a fallback unwind plan it can use.
+ // Subsequent calls to TryFallbackUnwindPlan() will return false.
if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
{
return AddOneMoreFrame (abi);
@@ -207,18 +208,35 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
// these.
if (reg_ctx_sp->IsTrapHandlerFrame() == false)
{
- // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return false.
- if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ // See if we can find a fallback unwind plan for THIS frame. It may be
+ // that the UnwindPlan we're using for THIS frame was bad and gave us a
+ // bad CFA.
+ // If that's not it, then see if we can change the UnwindPlan for the frame
+ // below us ("NEXT") -- see if using that other UnwindPlan gets us a better
+ // unwind state.
+ if (reg_ctx_sp->TryFallbackUnwindPlan() == false
+ || reg_ctx_sp->GetCFA (cursor_sp->cfa) == false
+ || abi->CallFrameAddressIsValid(cursor_sp->cfa) == false)
{
- return AddOneMoreFrame (abi);
+ if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ return AddOneMoreFrame (abi);
+ }
+ if (log)
+ {
+ log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
+ cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+ }
+ goto unwind_done;
}
- if (log)
+ else
{
- log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
- cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+ if (log)
+ {
+ log->Printf("%*sFrame %d had a bad CFA value but we switched the UnwindPlan being used and got one that looks more realistic.",
+ cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+ }
}
- goto unwind_done;
}
}
if (!reg_ctx_sp->ReadPC (cursor_sp->start_pc))
@@ -366,6 +384,14 @@ UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
UnwindLLDB::RegisterSearchResult result;
result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc);
+ // We descended down to the live register context aka stack frame 0 and are reading the value
+ // out of a live register.
+ if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound
+ && regloc.type == UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext)
+ {
+ return true;
+ }
+
// If we have unwind instructions saying that register N is saved in register M in the middle of
// the stack (and N can equal M here, meaning the register was not used in this function), then
// change the register number we're looking for to M and keep looking for a concrete location
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h
index eb5400389df3..35d85e2e3d26 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.h
+++ b/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -48,7 +48,8 @@ protected:
eRegisterSavedAtMemoryLocation, // register is saved at a specific word of target mem (target_memory_location)
eRegisterInRegister, // register is available in a (possible other) register (register_number)
eRegisterSavedAtHostMemoryLocation, // register is saved at a word in lldb's address space
- eRegisterValueInferred // register val was computed (and is in inferred_value)
+ eRegisterValueInferred, // register val was computed (and is in inferred_value)
+ eRegisterInLiveRegisterContext // register value is in a live (stack frame #0) register
};
int type;
union
diff --git a/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/source/Plugins/Process/Utility/lldb-x86-register-enums.h
index c4706d567b70..99fca3005820 100644
--- a/source/Plugins/Process/Utility/lldb-x86-register-enums.h
+++ b/source/Plugins/Process/Utility/lldb-x86-register-enums.h
@@ -12,6 +12,7 @@
namespace lldb_private
{
+ // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB)
//---------------------------------------------------------------------------
// Internal codes for all i386 registers.
@@ -19,100 +20,100 @@ namespace lldb_private
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,
+ lldb_eax_i386 = k_first_gpr_i386,
+ lldb_ebx_i386,
+ lldb_ecx_i386,
+ lldb_edx_i386,
+ lldb_edi_i386,
+ lldb_esi_i386,
+ lldb_ebp_i386,
+ lldb_esp_i386,
+ lldb_eip_i386,
+ lldb_eflags_i386,
+ lldb_cs_i386,
+ lldb_fs_i386,
+ lldb_gs_i386,
+ lldb_ss_i386,
+ lldb_ds_i386,
+ lldb_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,
+ lldb_ax_i386 = k_first_alias_i386,
+ lldb_bx_i386,
+ lldb_cx_i386,
+ lldb_dx_i386,
+ lldb_di_i386,
+ lldb_si_i386,
+ lldb_bp_i386,
+ lldb_sp_i386,
+ lldb_ah_i386,
+ lldb_bh_i386,
+ lldb_ch_i386,
+ lldb_dh_i386,
+ lldb_al_i386,
+ lldb_bl_i386,
+ lldb_cl_i386,
+ lldb_dl_i386,
+ k_last_alias_i386 = lldb_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,
+ lldb_fctrl_i386 = k_first_fpr_i386,
+ lldb_fstat_i386,
+ lldb_ftag_i386,
+ lldb_fop_i386,
+ lldb_fiseg_i386,
+ lldb_fioff_i386,
+ lldb_foseg_i386,
+ lldb_fooff_i386,
+ lldb_mxcsr_i386,
+ lldb_mxcsrmask_i386,
+ lldb_st0_i386,
+ lldb_st1_i386,
+ lldb_st2_i386,
+ lldb_st3_i386,
+ lldb_st4_i386,
+ lldb_st5_i386,
+ lldb_st6_i386,
+ lldb_st7_i386,
+ lldb_mm0_i386,
+ lldb_mm1_i386,
+ lldb_mm2_i386,
+ lldb_mm3_i386,
+ lldb_mm4_i386,
+ lldb_mm5_i386,
+ lldb_mm6_i386,
+ lldb_mm7_i386,
+ lldb_xmm0_i386,
+ lldb_xmm1_i386,
+ lldb_xmm2_i386,
+ lldb_xmm3_i386,
+ lldb_xmm4_i386,
+ lldb_xmm5_i386,
+ lldb_xmm6_i386,
+ lldb_xmm7_i386,
+ k_last_fpr_i386 = lldb_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,
+ lldb_ymm0_i386 = k_first_avx_i386,
+ lldb_ymm1_i386,
+ lldb_ymm2_i386,
+ lldb_ymm3_i386,
+ lldb_ymm4_i386,
+ lldb_ymm5_i386,
+ lldb_ymm6_i386,
+ lldb_ymm7_i386,
+ k_last_avx_i386 = lldb_ymm7_i386,
- dr0_i386,
- dr1_i386,
- dr2_i386,
- dr3_i386,
- dr4_i386,
- dr5_i386,
- dr6_i386,
- dr7_i386,
+ lldb_dr0_i386,
+ lldb_dr1_i386,
+ lldb_dr2_i386,
+ lldb_dr3_i386,
+ lldb_dr4_i386,
+ lldb_dr5_i386,
+ lldb_dr6_i386,
+ lldb_dr7_i386,
k_num_registers_i386,
k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1,
@@ -126,160 +127,160 @@ namespace lldb_private
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,
+ lldb_rax_x86_64 = k_first_gpr_x86_64,
+ lldb_rbx_x86_64,
+ lldb_rcx_x86_64,
+ lldb_rdx_x86_64,
+ lldb_rdi_x86_64,
+ lldb_rsi_x86_64,
+ lldb_rbp_x86_64,
+ lldb_rsp_x86_64,
+ lldb_r8_x86_64,
+ lldb_r9_x86_64,
+ lldb_r10_x86_64,
+ lldb_r11_x86_64,
+ lldb_r12_x86_64,
+ lldb_r13_x86_64,
+ lldb_r14_x86_64,
+ lldb_r15_x86_64,
+ lldb_rip_x86_64,
+ lldb_rflags_x86_64,
+ lldb_cs_x86_64,
+ lldb_fs_x86_64,
+ lldb_gs_x86_64,
+ lldb_ss_x86_64,
+ lldb_ds_x86_64,
+ lldb_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,
+ lldb_eax_x86_64 = k_first_alias_x86_64,
+ lldb_ebx_x86_64,
+ lldb_ecx_x86_64,
+ lldb_edx_x86_64,
+ lldb_edi_x86_64,
+ lldb_esi_x86_64,
+ lldb_ebp_x86_64,
+ lldb_esp_x86_64,
+ lldb_r8d_x86_64, // Low 32 bits of r8
+ lldb_r9d_x86_64, // Low 32 bits of r9
+ lldb_r10d_x86_64, // Low 32 bits of r10
+ lldb_r11d_x86_64, // Low 32 bits of r11
+ lldb_r12d_x86_64, // Low 32 bits of r12
+ lldb_r13d_x86_64, // Low 32 bits of r13
+ lldb_r14d_x86_64, // Low 32 bits of r14
+ lldb_r15d_x86_64, // Low 32 bits of r15
+ lldb_ax_x86_64,
+ lldb_bx_x86_64,
+ lldb_cx_x86_64,
+ lldb_dx_x86_64,
+ lldb_di_x86_64,
+ lldb_si_x86_64,
+ lldb_bp_x86_64,
+ lldb_sp_x86_64,
+ lldb_r8w_x86_64, // Low 16 bits of r8
+ lldb_r9w_x86_64, // Low 16 bits of r9
+ lldb_r10w_x86_64, // Low 16 bits of r10
+ lldb_r11w_x86_64, // Low 16 bits of r11
+ lldb_r12w_x86_64, // Low 16 bits of r12
+ lldb_r13w_x86_64, // Low 16 bits of r13
+ lldb_r14w_x86_64, // Low 16 bits of r14
+ lldb_r15w_x86_64, // Low 16 bits of r15
+ lldb_ah_x86_64,
+ lldb_bh_x86_64,
+ lldb_ch_x86_64,
+ lldb_dh_x86_64,
+ lldb_al_x86_64,
+ lldb_bl_x86_64,
+ lldb_cl_x86_64,
+ lldb_dl_x86_64,
+ lldb_dil_x86_64,
+ lldb_sil_x86_64,
+ lldb_bpl_x86_64,
+ lldb_spl_x86_64,
+ lldb_r8l_x86_64, // Low 8 bits of r8
+ lldb_r9l_x86_64, // Low 8 bits of r9
+ lldb_r10l_x86_64, // Low 8 bits of r10
+ lldb_r11l_x86_64, // Low 8 bits of r11
+ lldb_r12l_x86_64, // Low 8 bits of r12
+ lldb_r13l_x86_64, // Low 8 bits of r13
+ lldb_r14l_x86_64, // Low 8 bits of r14
+ lldb_r15l_x86_64, // Low 8 bits of r15
+ k_last_alias_x86_64 = lldb_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,
+ lldb_fctrl_x86_64 = k_first_fpr_x86_64,
+ lldb_fstat_x86_64,
+ lldb_ftag_x86_64,
+ lldb_fop_x86_64,
+ lldb_fiseg_x86_64,
+ lldb_fioff_x86_64,
+ lldb_foseg_x86_64,
+ lldb_fooff_x86_64,
+ lldb_mxcsr_x86_64,
+ lldb_mxcsrmask_x86_64,
+ lldb_st0_x86_64,
+ lldb_st1_x86_64,
+ lldb_st2_x86_64,
+ lldb_st3_x86_64,
+ lldb_st4_x86_64,
+ lldb_st5_x86_64,
+ lldb_st6_x86_64,
+ lldb_st7_x86_64,
+ lldb_mm0_x86_64,
+ lldb_mm1_x86_64,
+ lldb_mm2_x86_64,
+ lldb_mm3_x86_64,
+ lldb_mm4_x86_64,
+ lldb_mm5_x86_64,
+ lldb_mm6_x86_64,
+ lldb_mm7_x86_64,
+ lldb_xmm0_x86_64,
+ lldb_xmm1_x86_64,
+ lldb_xmm2_x86_64,
+ lldb_xmm3_x86_64,
+ lldb_xmm4_x86_64,
+ lldb_xmm5_x86_64,
+ lldb_xmm6_x86_64,
+ lldb_xmm7_x86_64,
+ lldb_xmm8_x86_64,
+ lldb_xmm9_x86_64,
+ lldb_xmm10_x86_64,
+ lldb_xmm11_x86_64,
+ lldb_xmm12_x86_64,
+ lldb_xmm13_x86_64,
+ lldb_xmm14_x86_64,
+ lldb_xmm15_x86_64,
+ k_last_fpr_x86_64 = lldb_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,
+ lldb_ymm0_x86_64 = k_first_avx_x86_64,
+ lldb_ymm1_x86_64,
+ lldb_ymm2_x86_64,
+ lldb_ymm3_x86_64,
+ lldb_ymm4_x86_64,
+ lldb_ymm5_x86_64,
+ lldb_ymm6_x86_64,
+ lldb_ymm7_x86_64,
+ lldb_ymm8_x86_64,
+ lldb_ymm9_x86_64,
+ lldb_ymm10_x86_64,
+ lldb_ymm11_x86_64,
+ lldb_ymm12_x86_64,
+ lldb_ymm13_x86_64,
+ lldb_ymm14_x86_64,
+ lldb_ymm15_x86_64,
+ k_last_avx_x86_64 = lldb_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,
+ lldb_dr0_x86_64,
+ lldb_dr1_x86_64,
+ lldb_dr2_x86_64,
+ lldb_dr3_x86_64,
+ lldb_dr4_x86_64,
+ lldb_dr5_x86_64,
+ lldb_dr6_x86_64,
+ lldb_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,
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 566816783c7e..fb39d7318a5a 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -405,14 +405,18 @@ enum {
NT_AUXV
};
+namespace FREEBSD {
+
enum {
- NT_FREEBSD_PRSTATUS = 1,
- NT_FREEBSD_FPREGSET,
- NT_FREEBSD_PRPSINFO,
- NT_FREEBSD_THRMISC = 7,
- NT_FREEBSD_PROCSTAT_AUXV = 16
+ NT_PRSTATUS = 1,
+ NT_FPREGSET,
+ NT_PRPSINFO,
+ NT_THRMISC = 7,
+ NT_PROCSTAT_AUXV = 16
};
+}
+
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
static void
ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
@@ -420,6 +424,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
{
lldb::offset_t offset = 0;
bool lp64 = (arch.GetMachine() == llvm::Triple::mips64 ||
+ arch.GetMachine() == llvm::Triple::ppc64 ||
arch.GetMachine() == llvm::Triple::x86_64);
int pr_version = data.GetU32(&offset);
@@ -516,20 +521,20 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
m_os = llvm::Triple::FreeBSD;
switch (note.n_type)
{
- case NT_FREEBSD_PRSTATUS:
+ case FREEBSD::NT_PRSTATUS:
have_prstatus = true;
ParseFreeBSDPrStatus(*thread_data, note_data, arch);
break;
- case NT_FREEBSD_FPREGSET:
+ case FREEBSD::NT_FPREGSET:
thread_data->fpregset = note_data;
break;
- case NT_FREEBSD_PRPSINFO:
+ case FREEBSD::NT_PRPSINFO:
have_prpsinfo = true;
break;
- case NT_FREEBSD_THRMISC:
+ case FREEBSD::NT_THRMISC:
ParseFreeBSDThrMisc(*thread_data, note_data);
break;
- case NT_FREEBSD_PROCSTAT_AUXV:
+ case FREEBSD::NT_PROCSTAT_AUXV:
// FIXME: FreeBSD sticks an int at the beginning of the note
m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4);
break;
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h
index 2fc2e4ee7949..7988bee5ae53 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -68,52 +68,52 @@ public:
//------------------------------------------------------------------
virtual bool
CanDebug (lldb_private::Target &target,
- bool plugin_specified_by_name);
+ bool plugin_specified_by_name) override;
//------------------------------------------------------------------
// Creating a new process, or attaching to an existing one
//------------------------------------------------------------------
virtual lldb_private::Error
- DoLoadCore ();
+ DoLoadCore () override;
virtual lldb_private::DynamicLoader *
- GetDynamicLoader ();
+ GetDynamicLoader () override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual lldb_private::ConstString
- GetPluginName();
+ GetPluginName() override;
virtual uint32_t
- GetPluginVersion();
+ GetPluginVersion() override;
//------------------------------------------------------------------
// Process Control
//------------------------------------------------------------------
virtual lldb_private::Error
- DoDestroy ();
+ DoDestroy () override;
virtual void
- RefreshStateAfterStop();
+ RefreshStateAfterStop() override;
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
virtual bool
- IsAlive ();
+ IsAlive () override;
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
virtual size_t
- ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
+ ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override;
virtual size_t
- DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
+ DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override;
virtual lldb::addr_t
- GetImageInfoAddress ();
+ GetImageInfoAddress () override;
lldb_private::ArchSpec
GetArchitecture();
@@ -128,7 +128,7 @@ protected:
virtual bool
UpdateThreadList (lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &new_thread_list);
+ lldb_private::ThreadList &new_thread_list) override;
private:
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
index fbf397b933cc..f0750a0cee18 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -10,7 +10,7 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "RegisterContextPOSIX.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_mips64.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
new file mode 100644
index 000000000000..15b1b44182d7
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
@@ -0,0 +1,109 @@
+//===-- RegisterContextCorePOSIX_powerpc.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_powerpc.h"
+
+using namespace lldb_private;
+
+RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &thread,
+ RegisterInfoInterface *register_info,
+ const DataExtractor &gpregset,
+ const DataExtractor &fpregset)
+ : RegisterContextPOSIX_powerpc(thread, 0, register_info)
+{
+ m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize()));
+ m_gpr.SetData(m_gpr_buffer);
+ m_gpr.SetByteOrder(gpregset.GetByteOrder());
+ m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize()));
+ m_fpr.SetData(m_fpr_buffer);
+ m_fpr.SetByteOrder(fpregset.GetByteOrder());
+}
+
+RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc()
+{
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::ReadGPR()
+{
+ return true;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::ReadFPR()
+{
+ return true;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::WriteGPR()
+{
+ assert(0);
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::WriteFPR()
+{
+ assert(0);
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+ lldb::offset_t offset = reg_info->byte_offset;
+ if (reg_info->name[0] == 'f') {
+ uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size);
+ if (offset == reg_info->byte_offset + reg_info->byte_size)
+ {
+ value = v;
+ return true;
+ }
+ } else {
+ uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
+ if (offset == reg_info->byte_offset + reg_info->byte_size)
+ {
+ if (reg_info->byte_size < sizeof(v))
+ value = (uint32_t)v;
+ else
+ value = v;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::HardwareSingleStep(bool enable)
+{
+ return false;
+}
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
new file mode 100644
index 000000000000..e6575581b360
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
@@ -0,0 +1,62 @@
+//===-- RegisterContextCorePOSIX_powerpc.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_powerpc_H_
+#define liblldb_RegisterContextCorePOSIX_powerpc_H_
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
+
+class RegisterContextCorePOSIX_powerpc :
+ public RegisterContextPOSIX_powerpc
+{
+public:
+ RegisterContextCorePOSIX_powerpc (lldb_private::Thread &thread,
+ lldb_private::RegisterInfoInterface *register_info,
+ const lldb_private::DataExtractor &gpregset,
+ const lldb_private::DataExtractor &fpregset);
+
+ ~RegisterContextCorePOSIX_powerpc();
+
+ 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:
+ lldb::DataBufferSP m_gpr_buffer;
+ lldb::DataBufferSP m_fpr_buffer;
+ lldb_private::DataExtractor m_gpr;
+ lldb_private::DataExtractor m_fpr;
+};
+
+#endif // #ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
index 3e09c7bc2032..412c7ade8295 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -10,7 +10,7 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "RegisterContextPOSIX.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_x86_64.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index d9f6cc04a343..d62bcfcff600 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -16,11 +16,13 @@
#include "ThreadElfCore.h"
#include "ProcessElfCore.h"
-#include "RegisterContextLinux_x86_64.h"
-#include "RegisterContextFreeBSD_i386.h"
-#include "RegisterContextFreeBSD_mips64.h"
-#include "RegisterContextFreeBSD_x86_64.h"
+#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
#include "RegisterContextPOSIXCore_mips64.h"
+#include "RegisterContextPOSIXCore_powerpc.h"
#include "RegisterContextPOSIXCore_x86_64.h"
using namespace lldb;
@@ -94,6 +96,12 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
{
switch (arch.GetMachine())
{
+ case llvm::Triple::ppc:
+ reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
+ break;
+ case llvm::Triple::ppc64:
+ reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
+ break;
case llvm::Triple::mips64:
reg_interface = new RegisterContextFreeBSD_mips64(arch);
break;
@@ -138,6 +146,10 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
case llvm::Triple::mips64:
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
break;
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data));
+ break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 1f4dd93976ec..919fa5405117 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -17,15 +17,16 @@
// C++ Includes
// Other libraries and framework includes
-#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSpec.h"
-#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/Pipe.h"
#include "lldb/Host/Socket.h"
+#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Target/Process.h"
@@ -153,7 +154,6 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
m_history (512),
m_send_acks (true),
m_is_platform (is_platform),
- m_listen_thread (LLDB_INVALID_HOST_THREAD),
m_listen_url ()
{
}
@@ -227,9 +227,23 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
ConnectionStatus status = eConnectionStatusSuccess;
- size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
+ const char *packet_data = packet.GetData();
+ const size_t packet_length = packet.GetSize();
+ size_t bytes_written = Write (packet_data, packet_length, status, NULL);
if (log)
{
+ size_t binary_start_offset = 0;
+ if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) == 0)
+ {
+ const char *first_comma = strchr(packet_data, ',');
+ if (first_comma)
+ {
+ const char *second_comma = strchr(first_comma + 1, ',');
+ if (second_comma)
+ binary_start_offset = second_comma - packet_data + 1;
+ }
+ }
+
// If logging was just enabled and we have history, then dump out what
// we have to the log so we get the historical context. The Dump() call that
// logs all of the packet will set a boolean so that we don't dump this more
@@ -237,13 +251,27 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le
if (!m_history.DidDumpToLog ())
m_history.Dump (log);
- log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet.GetSize(), packet.GetData());
+ if (binary_start_offset)
+ {
+ StreamString strm;
+ // Print non binary data header
+ strm.Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)binary_start_offset, packet_data);
+ const uint8_t *p;
+ // Print binary data exactly as sent
+ for (p = (uint8_t*)packet_data + binary_start_offset; *p != '#'; ++p)
+ strm.Printf("\\x%2.2x", *p);
+ // Print the checksum
+ strm.Printf("%*s", (int)3, p);
+ log->PutCString(strm.GetString().c_str());
+ }
+ else
+ log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet_length, packet_data);
}
- m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written);
+ m_history.AddPacket (packet.GetString(), packet_length, History::ePacketTypeSend, bytes_written);
- if (bytes_written == packet.GetSize())
+ if (bytes_written == packet_length)
{
if (GetSendAcks ())
return GetAck ();
@@ -253,7 +281,7 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le
else
{
if (log)
- log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData());
+ log->Printf ("error: failed to send packet: %.*s", (int)packet_length, packet_data);
}
}
return PacketResult::ErrorSendFailed;
@@ -447,8 +475,8 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
}
if (log)
log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'",
- __FUNCTION__, idx, idx, m_bytes.c_str());
- m_bytes.erase(0, idx);
+ __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str());
+ m_bytes.erase(0, idx - 1);
}
break;
}
@@ -606,7 +634,7 @@ Error
GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port)
{
Error error;
- if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread))
+ if (m_listen_thread.IsJoinable())
{
error.SetErrorString("listen thread already running");
}
@@ -619,7 +647,7 @@ GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port)
snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
m_listen_url = listen_url;
SetConnection(new ConnectionFileDescriptor());
- m_listen_thread = Host::ThreadCreate (listen_url, GDBRemoteCommunication::ListenThread, this, &error);
+ m_listen_thread = ThreadLauncher::LaunchThread(listen_url, GDBRemoteCommunication::ListenThread, this, &error);
}
return error;
}
@@ -627,11 +655,8 @@ GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port)
bool
GDBRemoteCommunication::JoinListenThread ()
{
- if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread))
- {
- Host::ThreadJoin(m_listen_thread, NULL, NULL);
- m_listen_thread = LLDB_INVALID_HOST_THREAD;
- }
+ if (m_listen_thread.IsJoinable())
+ m_listen_thread.Join(nullptr);
return true;
}
@@ -738,6 +763,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
char named_pipe_path[PATH_MAX];
named_pipe_path[0] = '\0';
+ Pipe port_named_pipe;
bool listen = false;
if (host_and_port[0])
@@ -763,15 +789,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
if (::mktemp (named_pipe_path))
{
-#if defined(_WIN32)
- if ( false )
-#else
- if (::mkfifo(named_pipe_path, 0600) == 0)
-#endif
- {
- debugserver_args.AppendArgument("--named-pipe");
- debugserver_args.AppendArgument(named_pipe_path);
- }
+ error = port_named_pipe.CreateNew(named_pipe_path, false);
+ if (error.Fail())
+ return error;
+ debugserver_args.AppendArgument("--named-pipe");
+ debugserver_args.AppendArgument(named_pipe_path);
}
}
else
@@ -838,11 +860,15 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
}
} while (has_env_var);
- // Close STDIN, STDOUT and STDERR. We might need to redirect them
- // to "/dev/null" if we run into any problems.
+ // Close STDIN, STDOUT and STDERR.
launch_info.AppendCloseFileAction (STDIN_FILENO);
launch_info.AppendCloseFileAction (STDOUT_FILENO);
launch_info.AppendCloseFileAction (STDERR_FILENO);
+
+ // Redirect STDIN, STDOUT and STDERR to "/dev/null".
+ launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false);
+ launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true);
+ launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true);
error = Host::LaunchProcess(launch_info);
@@ -850,20 +876,40 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
{
if (named_pipe_path[0])
{
- File name_pipe_file;
- error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead);
+ error = port_named_pipe.OpenAsReader(named_pipe_path, false);
if (error.Success())
{
char port_cstr[256];
port_cstr[0] = '\0';
size_t num_bytes = sizeof(port_cstr);
- error = name_pipe_file.Read(port_cstr, num_bytes);
- assert (error.Success());
- assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
- out_port = Args::StringToUInt32(port_cstr, 0);
- name_pipe_file.Close();
+ // Read port from pipe with 10 second timeout.
+ error = port_named_pipe.ReadWithTimeout(port_cstr, num_bytes, std::chrono::microseconds(10 * 1000000), num_bytes);
+ if (error.Success())
+ {
+ assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
+ out_port = Args::StringToUInt32(port_cstr, 0);
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() debugserver listens %u port", __FUNCTION__, out_port);
+ }
+ else
+ {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path, error.AsCString());
+
+ }
+ port_named_pipe.Close();
+ }
+ else
+ {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path, error.AsCString());
+ }
+ const auto err = port_named_pipe.Delete(named_pipe_path);
+ if (err.Fail())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path, err.AsCString());
}
- FileSystem::Unlink(named_pipe_path);
}
else if (listen)
{
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index b11d38563207..ac203a62788a 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -20,6 +20,7 @@
#include "lldb/lldb-public.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Listener.h"
+#include "lldb/Host/HostThread.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Predicate.h"
#include "lldb/Host/TimeValue.h"
@@ -281,8 +282,7 @@ protected:
ListenThread (lldb::thread_arg_t arg);
private:
-
- lldb::thread_t m_listen_thread;
+ lldb_private::HostThread m_listen_thread;
std::string m_listen_url;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 5e4ed7648f95..52750de5a25f 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -20,11 +20,11 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "lldb/Interpreter/Args.h"
-#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/ConnectionFileDescriptor.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
@@ -1643,7 +1643,9 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
}
else if (name.compare("triple") == 0)
{
- triple.swap(value);
+ extractor.GetStringRef ().swap (value);
+ extractor.SetFilePos(0);
+ extractor.GetHexByteString (triple);
++num_keys_decoded;
}
else if (name.compare ("distribution_id") == 0)
@@ -2331,6 +2333,10 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot
}
else if (name.compare("triple") == 0)
{
+ StringExtractor extractor;
+ extractor.GetStringRef().swap(value);
+ extractor.SetFilePos(0);
+ extractor.GetHexByteString (value);
process_info.GetArchitecture ().SetTriple (value.c_str());
}
else if (name.compare("name") == 0)
@@ -2404,6 +2410,8 @@ GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceIn
bool
GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
{
+ Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
+
if (m_qProcessInfo_is_valid == eLazyBoolYes)
return true;
if (m_qProcessInfo_is_valid == eLazyBoolNo)
@@ -2426,6 +2434,7 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
std::string triple;
uint32_t pointer_byte_size = 0;
StringExtractor extractor;
+ ByteOrder byte_order = eByteOrderInvalid;
uint32_t num_keys_decoded = 0;
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
while (response.GetNameColonValue(name, value))
@@ -2444,7 +2453,10 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
}
else if (name.compare("triple") == 0)
{
- triple = value;
+ StringExtractor extractor;
+ extractor.GetStringRef().swap(value);
+ extractor.SetFilePos(0);
+ extractor.GetHexByteString (triple);
++num_keys_decoded;
}
else if (name.compare("ostype") == 0)
@@ -2459,10 +2471,15 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
}
else if (name.compare("endian") == 0)
{
- if (value.compare("little") == 0 ||
- value.compare("big") == 0 ||
- value.compare("pdp") == 0)
- ++num_keys_decoded;
+ ++num_keys_decoded;
+ if (value.compare("little") == 0)
+ byte_order = eByteOrderLittle;
+ else if (value.compare("big") == 0)
+ byte_order = eByteOrderBig;
+ else if (value.compare("pdp") == 0)
+ byte_order = eByteOrderPDP;
+ else
+ --num_keys_decoded;
}
else if (name.compare("ptrsize") == 0)
{
@@ -2496,11 +2513,34 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
}
else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty())
{
- m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
+ llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name);
+
+ assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat);
+ switch (triple.getObjectFormat()) {
+ case llvm::Triple::MachO:
+ m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
+ break;
+ case llvm::Triple::ELF:
+ m_process_arch.SetArchitecture (eArchTypeELF, cpu, sub);
+ break;
+ case llvm::Triple::COFF:
+ m_process_arch.SetArchitecture (eArchTypeCOFF, cpu, sub);
+ break;
+ case llvm::Triple::UnknownObjectFormat:
+ if (log)
+ log->Printf("error: failed to determine target architecture");
+ return false;
+ }
+
if (pointer_byte_size)
{
assert (pointer_byte_size == m_process_arch.GetAddressByteSize());
}
+ if (byte_order != eByteOrderInvalid)
+ {
+ assert (byte_order == m_process_arch.GetByteOrder());
+ }
+ m_process_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
m_process_arch.GetTriple().setOSName(llvm::StringRef (os_name));
m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name));
@@ -2931,6 +2971,11 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto
uint8_t
GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert, addr_t addr, uint32_t length)
{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64,
+ __FUNCTION__, insert ? "add" : "remove", addr);
+
// Check if the stub is known not to support this breakpoint type
if (!SupportsGDBStoppointPacket(type))
return UINT8_MAX;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index ffcdd169eb9f..a7149505e869 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -23,11 +23,11 @@
// Other libraries and framework includes
#include "llvm/ADT/Triple.h"
#include "lldb/Interpreter/Args.h"
-#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Debug.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/File.h"
@@ -71,7 +71,7 @@ namespace
//----------------------------------------------------------------------
GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
- m_platform_sp (Platform::GetDefaultPlatform ()),
+ m_platform_sp (Platform::GetHostPlatform ()),
m_async_thread (LLDB_INVALID_HOST_THREAD),
m_process_launch_info (),
m_process_launch_error (),
@@ -429,6 +429,14 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_vAttach:
packet_result = Handle_vAttach (packet);
break;
+
+ case StringExtractorGDBRemote::eServerPacketType_D:
+ packet_result = Handle_D (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo:
+ packet_result = Handle_qThreadStopInfo (packet);
+ break;
}
}
else
@@ -474,13 +482,34 @@ GDBRemoteCommunicationServer::LaunchProcess ()
// FIXME This looks an awful lot like we could override this in
// derived classes, one for lldb-platform, the other for lldb-gdbserver.
if (IsGdbServer ())
- return LaunchDebugServerProcess ();
+ return LaunchProcessForDebugging ();
else
return LaunchPlatformProcess ();
}
+bool
+GDBRemoteCommunicationServer::ShouldRedirectInferiorOutputOverGdbRemote (const lldb_private::ProcessLaunchInfo &launch_info) const
+{
+ // Retrieve the file actions specified for stdout and stderr.
+ auto stdout_file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
+ auto stderr_file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
+
+ // If neither stdout and stderr file actions are specified, we're not doing anything special, so
+ // assume we want to redirect stdout/stderr over gdb-remote $O messages.
+ if ((stdout_file_action == nullptr) && (stderr_file_action == nullptr))
+ {
+ // Send stdout/stderr over the gdb-remote protocol.
+ return true;
+ }
+
+ // Any other setting for either stdout or stderr implies we are either suppressing
+ // it (with /dev/null) or we've got it set to a PTY. Either way, we don't want the
+ // output over gdb-remote.
+ return false;
+}
+
lldb_private::Error
-GDBRemoteCommunicationServer::LaunchDebugServerProcess ()
+GDBRemoteCommunicationServer::LaunchProcessForDebugging ()
{
Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -503,20 +532,34 @@ GDBRemoteCommunicationServer::LaunchDebugServerProcess ()
return error;
}
- // Setup stdout/stderr mapping from inferior.
- auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor ();
- if (terminal_fd >= 0)
+ // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as needed.
+ // llgs local-process debugging may specify PTYs, which will eliminate the need to reflect inferior
+ // stdout/stderr over the gdb-remote protocol.
+ if (ShouldRedirectInferiorOutputOverGdbRemote (m_process_launch_info))
{
if (log)
- log->Printf ("ProcessGDBRemoteCommunicationServer::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd);
- error = SetSTDIOFileDescriptor (terminal_fd);
- if (error.Fail ())
- return error;
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " setting up stdout/stderr redirection via $O gdb-remote commands", __FUNCTION__, m_debugged_process_sp->GetID ());
+
+ // Setup stdout/stderr mapping from inferior to $O
+ auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor ();
+ if (terminal_fd >= 0)
+ {
+ if (log)
+ log->Printf ("ProcessGDBRemoteCommunicationServer::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd);
+ error = SetSTDIOFileDescriptor (terminal_fd);
+ if (error.Fail ())
+ return error;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ProcessGDBRemoteCommunicationServer::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd);
+ }
}
else
{
if (log)
- log->Printf ("ProcessGDBRemoteCommunicationServer::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd);
+ log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " skipping stdout/stderr redirection via $O: inferior will communicate over client-provided file descriptors", __FUNCTION__, m_debugged_process_sp->GetID ());
}
printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID ());
@@ -526,33 +569,10 @@ GDBRemoteCommunicationServer::LaunchDebugServerProcess ()
if ((pid = m_process_launch_info.GetProcessID ()) != LLDB_INVALID_PROCESS_ID)
{
// add to spawned pids
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- // On an lldb-gdbserver, we would expect there to be only one.
- assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed");
- m_spawned_pids.insert (pid);
- }
- }
-
- if (error.Success ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServer::%s beginning check to wait for launched application to hit first stop", __FUNCTION__);
-
- int iteration = 0;
- // Wait for the process to hit its first stop state.
- while (!StateIsStoppedState (m_debugged_process_sp->GetState (), false))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServer::%s waiting for launched process to hit first stop (%d)...", __FUNCTION__, iteration++);
-
- // FIXME use a finer granularity.
- std::this_thread::sleep_for(std::chrono::seconds(1));
- }
-
- if (log)
- log->Printf ("GDBRemoteCommunicationServer::%s launched application has hit first stop", __FUNCTION__);
-
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ // On an lldb-gdbserver, we would expect there to be only one.
+ assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed");
+ m_spawned_pids.insert (pid);
}
return error;
@@ -699,12 +719,18 @@ GDBRemoteCommunicationServer::SendWResponse (lldb_private::NativeProcessProtocol
char return_type_code;
switch (exit_type)
{
- case ExitType::eExitTypeExit: return_type_code = 'W'; break;
- case ExitType::eExitTypeSignal: return_type_code = 'X'; break;
- case ExitType::eExitTypeStop: return_type_code = 'S'; break;
-
+ case ExitType::eExitTypeExit:
+ return_type_code = 'W';
+ break;
+ case ExitType::eExitTypeSignal:
+ return_type_code = 'X';
+ break;
+ case ExitType::eExitTypeStop:
+ return_type_code = 'S';
+ break;
case ExitType::eExitTypeInvalid:
- default: return_type_code = 'E'; break;
+ return_type_code = 'E';
+ break;
}
response.PutChar (return_type_code);
@@ -861,21 +887,21 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid)
response.Printf ("thread:%" PRIx64 ";", tid);
// Include the thread name if there is one.
- const char *thread_name = thread_sp->GetName ();
- if (thread_name && thread_name[0])
+ const std::string thread_name = thread_sp->GetName ();
+ if (!thread_name.empty ())
{
- size_t thread_name_len = strlen(thread_name);
+ size_t thread_name_len = thread_name.length ();
- if (::strcspn (thread_name, "$#+-;:") == thread_name_len)
+ if (::strcspn (thread_name.c_str (), "$#+-;:") == thread_name_len)
{
response.PutCString ("name:");
- response.PutCString (thread_name);
+ response.PutCString (thread_name.c_str ());
}
else
{
// The thread name contains special chars, send as hex bytes.
response.PutCString ("hexname:");
- response.PutCStringAsRawHex8 (thread_name);
+ response.PutCStringAsRawHex8 (thread_name.c_str ());
}
response.PutChar (';');
}
@@ -1197,7 +1223,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
ArchSpec host_arch(HostInfo::GetArchitecture());
const llvm::Triple &host_triple = host_arch.GetTriple();
response.PutCString("triple:");
- response.PutCString(host_triple.getTriple().c_str());
+ response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
const char* distribution_id = host_arch.GetDistributionId ().AsCString ();
@@ -1252,7 +1278,6 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
}
std::string s;
-#if !defined(__linux__)
if (HostInfo::GetOSBuildString(s))
{
response.PutCString ("os_build:");
@@ -1265,7 +1290,6 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.PutCStringAsRawHex8(s.c_str());
response.PutChar(';');
}
-#endif
#if defined(__APPLE__)
@@ -1315,7 +1339,7 @@ CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &r
{
const llvm::Triple &proc_triple = proc_arch.GetTriple();
response.PutCString("triple:");
- response.PutCString(proc_triple.getTriple().c_str());
+ response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
response.PutChar(';');
}
}
@@ -1351,7 +1375,10 @@ CreateProcessInfoResponse_DebugServerStyle (const ProcessInstanceInfo &proc_info
response.Printf ("vendor:%s;", vendor.c_str ());
#else
// We'll send the triple.
- response.Printf ("triple:%s;", proc_triple.getTriple().c_str ());
+ response.PutCString("triple:");
+ response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
+ response.PutChar(';');
+
#endif
std::string ostype = proc_triple.getOSName ();
// Adjust so ostype reports ios for Apple/ARM and Apple/ARM64.
@@ -2372,8 +2399,6 @@ GDBRemoteCommunicationServer::Handle_vCont_actions (StringExtractorGDBRemote &pa
return SendUnimplementedResponse (packet.GetStringRef().c_str());
}
- // We handle $vCont messages for c.
- // TODO add C, s and S.
StreamString response;
response.Printf("vCont;c;C;s;S");
@@ -3388,10 +3413,8 @@ GDBRemoteCommunicationServer::Handle_interrupt (StringExtractorGDBRemote &packet
return SendErrorResponse (0x15);
}
- // Build the ResumeActionList - stop everything.
- lldb_private::ResumeActionList actions (StateType::eStateStopped, 0);
-
- Error error = m_debugged_process_sp->Resume (actions);
+ // Interrupt the process.
+ Error error = m_debugged_process_sp->Interrupt ();
if (error.Fail ())
{
if (log)
@@ -3771,7 +3794,7 @@ GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet)
}
// Parse out software or hardware breakpoint requested.
- packet.SetFilePos (strlen("Z"));
+ packet.SetFilePos (strlen("z"));
if (packet.GetBytesLeft() < 1)
return SendIllFormedResponse(packet, "Too short z packet, missing software/hardware specifier");
@@ -3811,7 +3834,7 @@ GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet)
if (want_breakpoint)
{
- // Try to set the breakpoint.
+ // Try to clear the breakpoint.
const Error error = m_debugged_process_sp->RemoveBreakpoint (breakpoint_addr);
if (error.Success ())
return SendOKResponse ();
@@ -4171,8 +4194,93 @@ GDBRemoteCommunicationServer::Handle_vAttach (StringExtractorGDBRemote &packet)
// Notify we attached by sending a stop packet.
return SendStopReasonForState (m_debugged_process_sp->GetState (), true);
+}
- return PacketResult::Success;
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_D (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
+
+ // We don't support if we're not llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("only supported for lldb-gdbserver");
+
+ // Scope for mutex locker.
+ Mutex::Locker locker (m_spawned_pids_mutex);
+
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__);
+ return SendErrorResponse (0x15);
+ }
+
+ if (m_spawned_pids.find(m_debugged_process_sp->GetID ()) == m_spawned_pids.end())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to find PID %" PRIu64 " in spawned pids list",
+ __FUNCTION__, m_debugged_process_sp->GetID ());
+ return SendErrorResponse (0x1);
+ }
+
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+ // Consume the ';' after D.
+ packet.SetFilePos (1);
+ if (packet.GetBytesLeft ())
+ {
+ if (packet.GetChar () != ';')
+ return SendIllFormedResponse (packet, "D missing expected ';'");
+
+ // Grab the PID from which we will detach (assume hex encoding).
+ pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID, 16);
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendIllFormedResponse (packet, "D failed to parse the process id");
+ }
+
+ if (pid != LLDB_INVALID_PROCESS_ID &&
+ m_debugged_process_sp->GetID () != pid)
+ {
+ return SendIllFormedResponse (packet, "Invalid pid");
+ }
+
+ if (m_stdio_communication.IsConnected ())
+ {
+ m_stdio_communication.StopReadThread ();
+ }
+
+ const Error error = m_debugged_process_sp->Detach ();
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed to detach from pid %" PRIu64 ": %s\n",
+ __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ());
+ return SendErrorResponse (0x01);
+ }
+
+ m_spawned_pids.erase (m_debugged_process_sp->GetID ());
+ return SendOKResponse ();
+}
+
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_qThreadStopInfo (StringExtractorGDBRemote &packet)
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // We don't support if we're not llgs.
+ if (!IsGdbServer())
+ return SendUnimplementedResponse ("only supported for lldb-gdbserver");
+
+ packet.SetFilePos (strlen("qThreadStopInfo"));
+ const lldb::tid_t tid = packet.GetHexMaxU32 (false, LLDB_INVALID_THREAD_ID);
+ if (tid == LLDB_INVALID_THREAD_ID)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s failed, could not parse thread id from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ());
+ return SendErrorResponse (0x15);
+ }
+ return SendStopReplyPacketForThread (tid);
}
void
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 13c037c0287b..07ce98e29ac6 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -58,7 +58,7 @@ public:
bool &quit);
virtual bool
- GetThreadSuffixSupported ()
+ GetThreadSuffixSupported () override
{
return true;
}
@@ -152,8 +152,6 @@ public:
//------------------------------------------------------------------
/// Specify the program to launch and its arguments.
///
- /// The LaunchProcess () command can be executed to do the lauching.
- ///
/// @param[in] args
/// The command line to launch.
///
@@ -170,8 +168,6 @@ public:
//------------------------------------------------------------------
/// Specify the launch flags for the process.
///
- /// The LaunchProcess () command can be executed to do the lauching.
- ///
/// @param[in] launch_flags
/// The launch flags to use when launching this process.
///
@@ -463,6 +459,12 @@ protected:
PacketResult
Handle_vAttach (StringExtractorGDBRemote &packet);
+ PacketResult
+ Handle_D (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_qThreadStopInfo (StringExtractorGDBRemote &packet);
+
void
SetCurrentThreadID (lldb::tid_t tid);
@@ -511,9 +513,9 @@ private:
return !m_is_platform;
}
- /// Launch a process from lldb-gdbserver
+ /// Launch an inferior process from lldb-gdbserver
lldb_private::Error
- LaunchDebugServerProcess ();
+ LaunchProcessForDebugging ();
/// Launch a process from lldb-platform
lldb_private::Error
@@ -540,6 +542,9 @@ private:
void
ClearProcessSpecificData ();
+ bool
+ ShouldRedirectInferiorOutputOverGdbRemote (const lldb_private::ProcessLaunchInfo &launch_info) const;
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServer only
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index f35d954caa7b..fe99706969c8 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -14,7 +14,6 @@
#include <errno.h>
#include <stdlib.h>
#ifndef LLDB_DISABLE_POSIX
-#include <spawn.h>
#include <netinet/in.h>
#include <sys/mman.h> // for mmap
#endif
@@ -32,7 +31,7 @@
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
@@ -42,7 +41,9 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
+#include "lldb/Host/HostThread.h"
#include "lldb/Host/Symbols.h"
+#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
@@ -272,8 +273,6 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
m_last_stop_packet_mutex (Mutex::eMutexTypeNormal),
m_register_info (),
m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"),
- m_async_thread (LLDB_INVALID_HOST_THREAD),
- m_async_thread_state(eAsyncThreadNotStarted),
m_async_thread_state_mutex(Mutex::eMutexTypeRecursive),
m_thread_ids (),
m_continue_c_tids (),
@@ -749,8 +748,12 @@ ProcessGDBRemote::WillLaunchOrAttach ()
Error
ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
{
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Error error;
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s() entered", __FUNCTION__);
+
uint32_t launch_flags = launch_info.GetFlags().Get();
const char *stdin_path = NULL;
const char *stdout_path = NULL;
@@ -777,10 +780,21 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
stderr_path = file_action->GetPath();
}
+ if (log)
+ {
+ if (stdin_path || stdout_path || stderr_path)
+ log->Printf ("ProcessGDBRemote::%s provided with STDIO paths via launch_info: stdin=%s, stdout=%s, stdout=%s",
+ __FUNCTION__,
+ stdin_path ? stdin_path : "<null>",
+ stdout_path ? stdout_path : "<null>",
+ stderr_path ? stderr_path : "<null>");
+ else
+ log->Printf ("ProcessGDBRemote::%s no STDIO paths given via launch_info", __FUNCTION__);
+ }
+
// ::LogSetBitMask (GDBR_LOG_DEFAULT);
// ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
// ::LogSetLogFile ("/dev/stdout");
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
ObjectFile * object_file = exe_module->GetObjectFile();
if (object_file)
@@ -817,6 +831,13 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
if (stderr_path == NULL)
stderr_path = slave_name;
+
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s adjusted STDIO paths for local platform (IsHost() is true) using slave: stdin=%s, stdout=%s, stdout=%s",
+ __FUNCTION__,
+ stdin_path ? stdin_path : "<null>",
+ stdout_path ? stdout_path : "<null>",
+ stderr_path ? stderr_path : "<null>");
}
// Set STDIN to /dev/null if we want STDIO disabled or if either
@@ -834,7 +855,14 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
if (disable_stdio || (stderr_path == NULL && (stdin_path || stdout_path)))
stderr_path = "/dev/null";
- if (stdin_path)
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s final STDIO paths after all adjustments: stdin=%s, stdout=%s, stdout=%s",
+ __FUNCTION__,
+ stdin_path ? stdin_path : "<null>",
+ stdout_path ? stdout_path : "<null>",
+ stderr_path ? stderr_path : "<null>");
+
+ if (stdin_path)
m_gdb_comm.SetSTDIN (stdin_path);
if (stdout_path)
m_gdb_comm.SetSTDOUT (stdout_path);
@@ -1026,18 +1054,38 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
// prefer that over the Host information as it will be more specific
// to our process.
- if (m_gdb_comm.GetProcessArchitecture().IsValid())
- process_arch = m_gdb_comm.GetProcessArchitecture();
+ const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
+ if (remote_process_arch.IsValid())
+ {
+ process_arch = remote_process_arch;
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s gdb-remote had process architecture, using %s %s",
+ __FUNCTION__,
+ process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
+ process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
+ }
else
+ {
process_arch = m_gdb_comm.GetHostArchitecture();
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s gdb-remote did not have process architecture, using gdb-remote host architecture %s %s",
+ __FUNCTION__,
+ process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
+ process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
+ }
if (process_arch.IsValid())
{
ArchSpec &target_arch = GetTarget().GetArchitecture();
-
if (target_arch.IsValid())
{
- // If the remote host is ARM and we have apple as the vendor, then
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s analyzing target arch, currently %s %s",
+ __FUNCTION__,
+ target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>",
+ target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>");
+
+ // If the remote host is ARM and we have apple as the vendor, then
// ARM executables and shared libraries can have mixed ARM architectures.
// You can have an armv6 executable, and if the host is armv7, then the
// system will load the best possible architecture for all shared libraries
@@ -1048,6 +1096,11 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
process_arch.GetTriple().getVendor() == llvm::Triple::Apple)
{
GetTarget().SetArchitecture (process_arch);
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s remote process is ARM/Apple, setting target arch to %s %s",
+ __FUNCTION__,
+ process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
+ process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
}
else
{
@@ -1066,7 +1119,14 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
target_triple.setEnvironment (remote_triple.getEnvironment());
}
}
+
}
+
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s final target arch after adjustments for remote architecture: %s %s",
+ __FUNCTION__,
+ target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>",
+ target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>");
}
else
{
@@ -1095,7 +1155,12 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
Error
ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info)
{
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Error error;
+
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s()", __FUNCTION__);
+
// Clear out and clean up from any current state
Clear();
if (attach_pid != LLDB_INVALID_PROCESS_ID)
@@ -1118,13 +1183,14 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process
if (error.Success())
{
m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
-
+
char packet[64];
const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid);
SetID (attach_pid);
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));
}
}
+
return error;
}
@@ -1432,7 +1498,7 @@ ProcessGDBRemote::DoResume ()
TimeValue timeout;
timeout = TimeValue::Now();
timeout.OffsetWithSeconds (5);
- if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+ if (!m_async_thread.IsJoinable())
{
error.SetErrorString ("Trying to resume but the async thread is dead.");
if (log)
@@ -2891,30 +2957,17 @@ ProcessGDBRemote::StartAsyncThread ()
log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
Mutex::Locker start_locker(m_async_thread_state_mutex);
- if (m_async_thread_state == eAsyncThreadNotStarted)
+ if (!m_async_thread.IsJoinable())
{
// Create a thread that watches our internal state and controls which
// events make it to clients (into the DCProcess event queue).
- m_async_thread = Host::ThreadCreate ("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
- if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
- {
- m_async_thread_state = eAsyncThreadRunning;
- return true;
- }
- else
- return false;
- }
- else
- {
- // Somebody tried to start the async thread while it was either being started or stopped. If the former, and
- // it started up successfully, then say all's well. Otherwise it is an error, since we aren't going to restart it.
- if (log)
- log->Printf ("ProcessGDBRemote::%s () - Called when Async thread was in state: %d.", __FUNCTION__, m_async_thread_state);
- if (m_async_thread_state == eAsyncThreadRunning)
- return true;
- else
- return false;
+
+ m_async_thread = ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
}
+ else if (log)
+ log->Printf("ProcessGDBRemote::%s () - Called when Async thread was already running.", __FUNCTION__);
+
+ return m_async_thread.IsJoinable();
}
void
@@ -2926,7 +2979,7 @@ ProcessGDBRemote::StopAsyncThread ()
log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
Mutex::Locker start_locker(m_async_thread_state_mutex);
- if (m_async_thread_state == eAsyncThreadRunning)
+ if (m_async_thread.IsJoinable())
{
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
@@ -2934,17 +2987,10 @@ ProcessGDBRemote::StopAsyncThread ()
m_gdb_comm.Disconnect(); // Disconnect from the debug server.
// Stop the stdio thread
- if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
- {
- Host::ThreadJoin (m_async_thread, NULL, NULL);
- }
- m_async_thread_state = eAsyncThreadDone;
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s () - Called when Async thread was in state: %d.", __FUNCTION__, m_async_thread_state);
+ m_async_thread.Join(nullptr);
}
+ else if (log)
+ log->Printf("ProcessGDBRemote::%s () - Called when Async thread was not running.", __FUNCTION__);
}
@@ -3086,7 +3132,7 @@ ProcessGDBRemote::AsyncThread (void *arg)
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", __FUNCTION__, arg, process->GetID());
- process->m_async_thread = LLDB_INVALID_HOST_THREAD;
+ process->m_async_thread.Reset();
return NULL;
}
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 942b31c84dde..e0c460a202d6 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -25,6 +25,7 @@
#include "lldb/Core/StringList.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ThreadSafeValue.h"
+#include "lldb/Host/HostThread.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
@@ -74,148 +75,148 @@ public:
//------------------------------------------------------------------
virtual bool
CanDebug (lldb_private::Target &target,
- bool plugin_specified_by_name);
+ bool plugin_specified_by_name) override;
virtual lldb_private::CommandObject *
- GetPluginCommandObject();
+ GetPluginCommandObject() override;
//------------------------------------------------------------------
// Creating a new process, or attaching to an existing one
//------------------------------------------------------------------
virtual lldb_private::Error
- WillLaunch (lldb_private::Module* module);
+ WillLaunch (lldb_private::Module* module) override;
virtual lldb_private::Error
DoLaunch (lldb_private::Module *exe_module,
- lldb_private::ProcessLaunchInfo &launch_info);
+ lldb_private::ProcessLaunchInfo &launch_info) override;
virtual void
- DidLaunch ();
+ DidLaunch () override;
virtual lldb_private::Error
- WillAttachToProcessWithID (lldb::pid_t pid);
+ WillAttachToProcessWithID (lldb::pid_t pid) override;
virtual lldb_private::Error
- WillAttachToProcessWithName (const char *process_name, bool wait_for_launch);
+ WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) override;
virtual lldb_private::Error
- DoConnectRemote (lldb_private::Stream *strm, const char *remote_url);
+ DoConnectRemote (lldb_private::Stream *strm, const char *remote_url) override;
lldb_private::Error
WillLaunchOrAttach ();
virtual lldb_private::Error
- DoAttachToProcessWithID (lldb::pid_t pid);
+ DoAttachToProcessWithID (lldb::pid_t pid) override;
virtual lldb_private::Error
- DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info);
+ DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override;
virtual lldb_private::Error
DoAttachToProcessWithName (const char *process_name,
- const lldb_private::ProcessAttachInfo &attach_info);
+ const lldb_private::ProcessAttachInfo &attach_info) override;
virtual void
- DidAttach (lldb_private::ArchSpec &process_arch);
+ DidAttach (lldb_private::ArchSpec &process_arch) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual lldb_private::ConstString
- GetPluginName();
+ GetPluginName() override;
virtual uint32_t
- GetPluginVersion();
+ GetPluginVersion() override;
//------------------------------------------------------------------
// Process Control
//------------------------------------------------------------------
virtual lldb_private::Error
- WillResume ();
+ WillResume () override;
virtual lldb_private::Error
- DoResume ();
+ DoResume () override;
virtual lldb_private::Error
- DoHalt (bool &caused_stop);
+ DoHalt (bool &caused_stop) override;
virtual lldb_private::Error
- DoDetach (bool keep_stopped);
+ DoDetach (bool keep_stopped) override;
virtual bool
- DetachRequiresHalt() { return true; }
+ DetachRequiresHalt() override { return true; }
virtual lldb_private::Error
- DoSignal (int signal);
+ DoSignal (int signal) override;
virtual lldb_private::Error
- DoDestroy ();
+ DoDestroy () override;
virtual void
- RefreshStateAfterStop();
+ RefreshStateAfterStop() override;
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
virtual bool
- IsAlive ();
+ IsAlive () override;
virtual lldb::addr_t
- GetImageInfoAddress();
+ GetImageInfoAddress() override;
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
virtual size_t
- DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
+ DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override;
virtual size_t
- DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error);
+ DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error) override;
virtual lldb::addr_t
- DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error);
+ DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error) override;
virtual lldb_private::Error
GetMemoryRegionInfo (lldb::addr_t load_addr,
- lldb_private::MemoryRegionInfo &region_info);
+ lldb_private::MemoryRegionInfo &region_info) override;
virtual lldb_private::Error
- DoDeallocateMemory (lldb::addr_t ptr);
+ DoDeallocateMemory (lldb::addr_t ptr) override;
//------------------------------------------------------------------
// Process STDIO
//------------------------------------------------------------------
virtual size_t
- PutSTDIN (const char *buf, size_t buf_size, lldb_private::Error &error);
+ PutSTDIN (const char *buf, size_t buf_size, lldb_private::Error &error) override;
//----------------------------------------------------------------------
// Process Breakpoints
//----------------------------------------------------------------------
virtual lldb_private::Error
- EnableBreakpointSite (lldb_private::BreakpointSite *bp_site);
+ EnableBreakpointSite (lldb_private::BreakpointSite *bp_site) override;
virtual lldb_private::Error
- DisableBreakpointSite (lldb_private::BreakpointSite *bp_site);
+ DisableBreakpointSite (lldb_private::BreakpointSite *bp_site) override;
//----------------------------------------------------------------------
// Process Watchpoints
//----------------------------------------------------------------------
virtual lldb_private::Error
- EnableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true);
+ EnableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true) override;
virtual lldb_private::Error
- DisableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true);
+ DisableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true) override;
virtual lldb_private::Error
- GetWatchpointSupportInfo (uint32_t &num);
+ GetWatchpointSupportInfo (uint32_t &num) override;
virtual lldb_private::Error
- GetWatchpointSupportInfo (uint32_t &num, bool& after);
+ GetWatchpointSupportInfo (uint32_t &num, bool& after) override;
virtual bool
- StartNoticingNewThreads();
+ StartNoticingNewThreads() override;
virtual bool
- StopNoticingNewThreads();
+ StopNoticingNewThreads() override;
GDBRemoteCommunicationClient &
GetGDBRemote()
@@ -224,13 +225,13 @@ public:
}
virtual lldb_private::Error
- SendEventData(const char *data);
+ SendEventData(const char *data) override;
//----------------------------------------------------------------------
// Override SetExitStatus so we can disconnect from the remote GDB server
//----------------------------------------------------------------------
virtual bool
- SetExitStatus (int exit_status, const char *cstr);
+ SetExitStatus (int exit_status, const char *cstr) override;
void
SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max);
@@ -286,7 +287,7 @@ protected:
virtual bool
UpdateThreadList (lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &new_thread_list);
+ lldb_private::ThreadList &new_thread_list) override;
lldb_private::Error
LaunchAndConnectToDebugserver (const lldb_private::ProcessInfo &process_info);
@@ -324,23 +325,15 @@ protected:
eBroadcastBitAsyncThreadShouldExit = (1 << 1),
eBroadcastBitAsyncThreadDidExit = (1 << 2)
};
-
- typedef enum AsyncThreadState
- {
- eAsyncThreadNotStarted,
- eAsyncThreadRunning,
- eAsyncThreadDone
- } AsyncThreadState;
lldb_private::Flags m_flags; // Process specific flags (see eFlags enums)
GDBRemoteCommunicationClient m_gdb_comm;
- lldb::pid_t m_debugserver_pid;
+ std::atomic<lldb::pid_t> m_debugserver_pid;
StringExtractorGDBRemote m_last_stop_packet;
lldb_private::Mutex m_last_stop_packet_mutex;
GDBRemoteDynamicRegisterInfo m_register_info;
lldb_private::Broadcaster m_async_broadcaster;
- lldb::thread_t m_async_thread;
- AsyncThreadState m_async_thread_state;
+ lldb_private::HostThread m_async_thread;
lldb_private::Mutex m_async_thread_state_mutex;
typedef std::vector<lldb::tid_t> tid_collection;
typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
@@ -395,7 +388,7 @@ protected:
std::string &dispatch_queue_name);
lldb_private::DynamicLoader *
- GetDynamicLoader ();
+ GetDynamicLoader () override;
private:
//------------------------------------------------------------------
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
index bc2e7a62b76e..14fc2cea2329 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -73,14 +73,14 @@ DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor& data, lldb::offs
void
DWARFAbbreviationDeclaration::Dump(Stream *s) const
{
-// *ostrm_ptr << std::setfill(' ') << std::dec << '[' << std::setw(3) << std::right << m_code << ']' << ' ' << std::setw(30) << std::left << DW_TAG_value_to_name(m_tag) << DW_CHILDREN_value_to_name(m_has_children) << std::endl;
-//
-// DWARFAttribute::const_iterator pos;
-//
-// for (pos = m_attributes.begin(); pos != m_attributes.end(); ++pos)
-// *ostrm_ptr << " " << std::setw(29) << std::left << DW_AT_value_to_name(pos->attr()) << ' ' << DW_FORM_value_to_name(pos->form()) << std::endl;
-//
-// *ostrm_ptr << std::endl;
+ s->Printf("Debug Abbreviation Declaration: code = 0x%4.4x, tag = %s, has_children = %s\n", m_code, DW_TAG_value_to_name(m_tag), DW_CHILDREN_value_to_name(m_has_children));
+
+ DWARFAttribute::const_iterator pos;
+
+ for (pos = m_attributes.begin(); pos != m_attributes.end(); ++pos)
+ s->Printf(" attr = %s, form = %s\n", DW_AT_value_to_name(pos->get_attr()), DW_FORM_value_to_name(pos->get_form()));
+
+ s->Printf("\n");
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index b2e64ad9f8c8..067449a289be 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -49,7 +49,8 @@ DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) :
m_producer (eProducerInvalid),
m_producer_version_major (0),
m_producer_version_minor (0),
- m_producer_version_update (0)
+ m_producer_version_update (0),
+ m_is_dwarf64 (false)
{
}
@@ -66,6 +67,7 @@ DWARFCompileUnit::Clear()
m_func_aranges_ap.reset();
m_user_data = NULL;
m_producer = eProducerInvalid;
+ m_is_dwarf64 = false;
}
bool
@@ -79,9 +81,10 @@ DWARFCompileUnit::Extract(const DWARFDataExtractor &debug_info, lldb::offset_t *
{
dw_offset_t abbr_offset;
const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev();
- m_length = debug_info.GetU32(offset_ptr);
+ m_length = debug_info.GetDWARFInitialLength(offset_ptr);
+ m_is_dwarf64 = debug_info.IsDWARF64();
m_version = debug_info.GetU16(offset_ptr);
- abbr_offset = debug_info.GetU32(offset_ptr);
+ abbr_offset = debug_info.GetDWARFOffset(offset_ptr);
m_addr_size = debug_info.GetU8 (offset_ptr);
bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1);
@@ -168,7 +171,7 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
die_index_stack.reserve(32);
die_index_stack.push_back(0);
bool prev_die_had_children = false;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize());
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);
while (offset < next_cu_offset &&
die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset))
{
@@ -347,6 +350,14 @@ DWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit* cu)
return DWARFCompileUnit::GetDefaultAddressSize();
}
+bool
+DWARFCompileUnit::IsDWARF64(const DWARFCompileUnit* cu)
+{
+ if (cu)
+ return cu->IsDWARF64();
+ return false;
+}
+
uint8_t
DWARFCompileUnit::GetDefaultAddressSize()
{
@@ -619,7 +630,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
{
const DWARFDataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data();
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize());
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);
Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS));
@@ -761,7 +772,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
case DW_AT_specification:
if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
- specification_die_offset = form_value.Reference(this);
+ specification_die_offset = form_value.Reference();
break;
}
}
@@ -1030,3 +1041,9 @@ DWARFCompileUnit::GetProducerVersionUpdate()
return m_producer_version_update;
}
+bool
+DWARFCompileUnit::IsDWARF64() const
+{
+ return m_is_dwarf64;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index ed1894b8a9f6..3e904892dbd5 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -41,11 +41,11 @@ public:
bool Verify(lldb_private::Stream *s) const;
void Dump(lldb_private::Stream *s) const;
dw_offset_t GetOffset() const { return m_offset; }
- uint32_t Size() const { return 11; /* Size in bytes of the compile unit header */ }
+ uint32_t Size() const { return m_is_dwarf64 ? 23 : 11; /* Size in bytes of the compile unit header */ }
bool ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && die_offset < GetNextCompileUnitOffset(); }
dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); }
- dw_offset_t GetNextCompileUnitOffset() const { return m_offset + m_length + 4; }
- size_t GetDebugInfoSize() const { return m_length + 4 - Size(); /* Size in bytes of the .debug_info data associated with this compile unit. */ }
+ dw_offset_t GetNextCompileUnitOffset() const { return m_offset + m_length + (m_is_dwarf64 ? 12 : 4); }
+ size_t GetDebugInfoSize() const { return m_length + (m_is_dwarf64 ? 12 : 4) - Size(); /* Size in bytes of the .debug_info data associated with this compile unit. */ }
uint32_t GetLength() const { return m_length; }
uint16_t GetVersion() const { return m_version; }
const DWARFAbbreviationDeclarationSet* GetAbbreviations() const { return m_abbrevs; }
@@ -118,6 +118,9 @@ public:
static uint8_t
GetAddressByteSize(const DWARFCompileUnit* cu);
+ static bool
+ IsDWARF64(const DWARFCompileUnit* cu);
+
static uint8_t
GetDefaultAddressSize();
@@ -183,6 +186,9 @@ public:
uint32_t
GetProducerVersionUpdate();
+ bool
+ IsDWARF64() const;
+
protected:
SymbolFileDWARF* m_dwarf2Data;
const DWARFAbbreviationDeclarationSet *m_abbrevs;
@@ -191,13 +197,14 @@ protected:
std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap; // A table similar to the .debug_aranges table, but this one points to the exact DW_TAG_subprogram DIEs
dw_addr_t m_base_addr;
dw_offset_t m_offset;
- uint32_t m_length;
+ dw_offset_t m_length;
uint16_t m_version;
uint8_t m_addr_size;
Producer m_producer;
uint32_t m_producer_version_major;
uint32_t m_producer_version_minor;
uint32_t m_producer_version_update;
+ bool m_is_dwarf64;
void
ParseProducerInfo ();
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
index 6e5b974a71ff..ba2e8ad08acc 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
@@ -33,6 +33,9 @@ public:
size_t
GetDWARFSizeofInitialLength() const { return m_is_dwarf64 ? 12 : 4; }
+ bool
+ IsDWARF64() const { return m_is_dwarf64; }
+
protected:
mutable bool m_is_dwarf64;
};
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index a8c553e2d2ca..393434800c01 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -555,8 +555,15 @@ static dw_offset_t DumpCallback
if (dumpInfo->die_offset == DW_INVALID_OFFSET)
{
// We are dumping everything
- cu->Dump(s);
- return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit
+ if (cu)
+ {
+ cu->Dump(s);
+ return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit
+ }
+ else
+ {
+ return DW_INVALID_OFFSET;
+ }
}
else
{
@@ -568,7 +575,7 @@ static dw_offset_t DumpCallback
// We are dumping only a single DIE possibly with it's children and
// we must find it's compile unit before we can dump it properly
- if (dumpInfo->die_offset < cu->GetFirstDIEOffset())
+ if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset())
{
// Not found, maybe the DIE offset provided wasn't correct?
// *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl;
@@ -577,7 +584,7 @@ static dw_offset_t DumpCallback
else
{
// See if the DIE is in this compile unit?
- if (dumpInfo->die_offset < cu->GetNextCompileUnitOffset())
+ if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset())
{
// This DIE is in this compile unit!
if (s->GetVerbose())
@@ -590,7 +597,14 @@ static dw_offset_t DumpCallback
else
{
// Skip to the next compile unit as the DIE isn't in the current one!
- return cu->GetNextCompileUnitOffset();
+ if (cu)
+ {
+ return cu->GetNextCompileUnitOffset();
+ }
+ else
+ {
+ return DW_INVALID_OFFSET;
+ }
}
}
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 856a7fa7a2ff..10b51ffe0a8a 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -88,9 +88,10 @@ DWARFDebugInfoEntry::Attributes::RemoveAttribute(dw_attr_t attr)
bool
DWARFDebugInfoEntry::Attributes::ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const
{
+ form_value.SetCompileUnit(CompileUnitAtIndex(i));
form_value.SetForm(FormAtIndex(i));
lldb::offset_t offset = DIEOffsetAtIndex(i);
- return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset, CompileUnitAtIndex(i));
+ return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset);
}
uint64_t
@@ -107,7 +108,7 @@ DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwa
{
DWARFFormValue form_value;
if (ExtractFormValueAtIndex(dwarf2Data, i, form_value))
- return form_value.Reference(CompileUnitAtIndex(i));
+ return form_value.Reference();
return fail_value;
}
@@ -190,7 +191,7 @@ DWARFDebugInfoEntry::FastExtract
if (cu->GetVersion() <= 2)
form_size = cu->GetAddressByteSize();
else
- form_size = 4; // 4 bytes for DWARF 32, 8 bytes for DWARF 64, but we don't support DWARF64 yet
+ form_size = cu->IsDWARF64() ? 8 : 4;
break;
// 0 sized form
@@ -212,7 +213,6 @@ DWARFDebugInfoEntry::FastExtract
break;
// 4 byte values
- case DW_FORM_strp :
case DW_FORM_data4 :
case DW_FORM_ref4 :
form_size = 4;
@@ -237,11 +237,12 @@ DWARFDebugInfoEntry::FastExtract
form = debug_info_data.GetULEB128 (&offset);
break;
+ case DW_FORM_strp :
case DW_FORM_sec_offset :
- if (cu->GetAddressByteSize () == 4)
- debug_info_data.GetU32 (offset_ptr);
- else
+ if (cu->IsDWARF64 ())
debug_info_data.GetU64 (offset_ptr);
+ else
+ debug_info_data.GetU32 (offset_ptr);
break;
default:
@@ -284,7 +285,6 @@ DWARFDebugInfoEntry::Extract
const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
// const DWARFDataExtractor& debug_str_data = dwarf2Data->get_debug_str_data();
const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset();
- const uint8_t cu_addr_size = cu->GetAddressByteSize();
lldb::offset_t offset = *offset_ptr;
// if (offset >= cu_end_offset)
// Log::Error("DIE at offset 0x%8.8x is beyond the end of the current compile unit (0x%8.8x)", m_offset, cu_end_offset);
@@ -319,8 +319,8 @@ DWARFDebugInfoEntry::Extract
if (isCompileUnitTag && ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc)))
{
- DWARFFormValue form_value(form);
- if (form_value.ExtractValue(debug_info_data, &offset, cu))
+ DWARFFormValue form_value(cu, form);
+ if (form_value.ExtractValue(debug_info_data, &offset))
{
if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
((DWARFCompileUnit*)cu)->SetBaseAddress(form_value.Unsigned());
@@ -348,13 +348,13 @@ DWARFDebugInfoEntry::Extract
// Compile unit address sized values
case DW_FORM_addr :
- form_size = cu_addr_size;
+ form_size = cu->GetAddressByteSize();
break;
case DW_FORM_ref_addr :
if (cu->GetVersion() <= 2)
- form_size = cu_addr_size;
+ form_size = cu->GetAddressByteSize();
else
- form_size = 4; // 4 bytes for DWARF 32, 8 bytes for DWARF 64, but we don't support DWARF64 yet
+ form_size = cu->IsDWARF64() ? 8 : 4;
break;
// 0 sized form
@@ -376,10 +376,6 @@ DWARFDebugInfoEntry::Extract
break;
// 4 byte values
- case DW_FORM_strp :
- form_size = 4;
- break;
-
case DW_FORM_data4 :
case DW_FORM_ref4 :
form_size = 4;
@@ -404,11 +400,12 @@ DWARFDebugInfoEntry::Extract
form_is_indirect = true;
break;
+ case DW_FORM_strp :
case DW_FORM_sec_offset :
- if (cu->GetAddressByteSize () == 4)
- debug_info_data.GetU32 (offset_ptr);
- else
+ if (cu->IsDWARF64 ())
debug_info_data.GetU64 (offset_ptr);
+ else
+ debug_info_data.GetU32 (offset_ptr);
break;
default:
@@ -781,8 +778,8 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
for (i=0; i<numAttributes; ++i)
{
abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
- DWARFFormValue form_value(form);
- if (form_value.ExtractValue(debug_info_data, &offset, cu))
+ DWARFFormValue form_value(cu, form);
+ if (form_value.ExtractValue(debug_info_data, &offset))
{
switch (attr)
{
@@ -832,11 +829,11 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
break;
case DW_AT_abstract_origin:
- die_offsets.push_back(form_value.Reference(cu));
+ die_offsets.push_back(form_value.Reference());
break;
case DW_AT_specification:
- die_offsets.push_back(form_value.Reference(cu));
+ die_offsets.push_back(form_value.Reference());
break;
case DW_AT_decl_file:
@@ -1033,7 +1030,7 @@ DWARFDebugInfoEntry::DumpLocation
const char *obj_file_name = NULL;
ObjectFile *obj_file = dwarf2Data->GetObjectFile();
if (obj_file)
- obj_file_name = obj_file->GetFileSpec().GetFilename().AsCString();
+ obj_file_name = obj_file->GetFileSpec().GetFilename().AsCString("<Unknown>");
const char *die_name = GetName (dwarf2Data, cu);
s.Printf ("0x%8.8x/0x%8.8x: %-30s (from %s in %s)",
cu->GetOffset(),
@@ -1077,9 +1074,9 @@ DWARFDebugInfoEntry::DumpAttribute
s.Printf( "[%s", DW_FORM_value_to_name(form));
}
- DWARFFormValue form_value(form);
+ DWARFFormValue form_value(cu, form);
- if (!form_value.ExtractValue(debug_info_data, offset_ptr, cu))
+ if (!form_value.ExtractValue(debug_info_data, offset_ptr))
return;
if (show_form)
@@ -1097,7 +1094,7 @@ DWARFDebugInfoEntry::DumpAttribute
// Always dump form value if verbose is enabled
if (verbose)
{
- form_value.Dump(s, debug_str_data, cu);
+ form_value.Dump(s, debug_str_data);
}
@@ -1130,7 +1127,7 @@ DWARFDebugInfoEntry::DumpAttribute
if (blockData)
{
if (!verbose)
- form_value.Dump(s, debug_str_data, cu);
+ form_value.Dump(s, debug_str_data);
// Location description is inlined in data in the form value
DWARFDataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned());
@@ -1147,13 +1144,13 @@ DWARFDebugInfoEntry::DumpAttribute
if (dwarf2Data)
{
if ( !verbose )
- form_value.Dump(s, debug_str_data, cu);
+ form_value.Dump(s, debug_str_data);
DWARFLocationList::Dump(s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset);
}
else
{
if ( !verbose )
- form_value.Dump(s, NULL, cu);
+ form_value.Dump(s, NULL);
}
}
}
@@ -1162,8 +1159,8 @@ DWARFDebugInfoEntry::DumpAttribute
case DW_AT_abstract_origin:
case DW_AT_specification:
{
- uint64_t abstract_die_offset = form_value.Reference(cu);
- form_value.Dump(s, debug_str_data, cu);
+ uint64_t abstract_die_offset = form_value.Reference();
+ form_value.Dump(s, debug_str_data);
// *ostrm_ptr << HEX32 << abstract_die_offset << " ( ";
if ( verbose ) s.PutCString(" ( ");
GetName(dwarf2Data, cu, abstract_die_offset, s);
@@ -1173,9 +1170,9 @@ DWARFDebugInfoEntry::DumpAttribute
case DW_AT_type:
{
- uint64_t type_die_offset = form_value.Reference(cu);
+ uint64_t type_die_offset = form_value.Reference();
if (!verbose)
- form_value.Dump(s, debug_str_data, cu);
+ form_value.Dump(s, debug_str_data);
s.PutCString(" ( ");
AppendTypeName(dwarf2Data, cu, type_die_offset, s);
s.PutCString(" )");
@@ -1185,7 +1182,7 @@ DWARFDebugInfoEntry::DumpAttribute
case DW_AT_ranges:
{
if ( !verbose )
- form_value.Dump(s, debug_str_data, cu);
+ form_value.Dump(s, debug_str_data);
lldb::offset_t ranges_offset = form_value.Unsigned();
dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
if (dwarf2Data)
@@ -1195,7 +1192,7 @@ DWARFDebugInfoEntry::DumpAttribute
default:
if ( !verbose )
- form_value.Dump(s, debug_str_data, cu);
+ form_value.Dump(s, debug_str_data);
break;
}
@@ -1226,13 +1223,12 @@ DWARFDebugInfoEntry::GetAttributes
const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
if (fixed_form_sizes == NULL)
- fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize());
+ fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize(), cu->IsDWARF64());
const uint32_t num_attributes = abbrevDecl->NumAttributes();
uint32_t i;
dw_attr_t attr;
dw_form_t form;
- DWARFFormValue form_value;
for (i=0; i<num_attributes; ++i)
{
abbrevDecl->GetAttrAndFormByIndexUnchecked (i, attr, form);
@@ -1259,11 +1255,11 @@ DWARFDebugInfoEntry::GetAttributes
if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))
{
- form_value.SetForm(form);
- if (form_value.ExtractValue(debug_info_data, &offset, cu))
+ DWARFFormValue form_value (cu, form);
+ if (form_value.ExtractValue(debug_info_data, &offset))
{
const DWARFDebugInfoEntry* die = NULL;
- dw_offset_t die_offset = form_value.Reference(cu);
+ dw_offset_t die_offset = form_value.Reference();
if (cu->ContainsDIEOffset(die_offset))
{
die = const_cast<DWARFCompileUnit*>(cu)->GetDIEPtr(die_offset);
@@ -1331,8 +1327,9 @@ DWARFDebugInfoEntry::GetAttributeValue
DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++), debug_info_data, &offset, cu);
const dw_offset_t attr_offset = offset;
+ form_value.SetCompileUnit(cu);
form_value.SetForm(abbrevDecl->GetFormByIndex(idx));
- if (form_value.ExtractValue(debug_info_data, &offset, cu))
+ if (form_value.ExtractValue(debug_info_data, &offset))
{
if (end_attr_offset_ptr)
*end_attr_offset_ptr = offset;
@@ -1423,7 +1420,7 @@ DWARFDebugInfoEntry::GetAttributeValueAsReference
{
DWARFFormValue form_value;
if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
- return form_value.Reference(cu);
+ return form_value.Reference();
return fail_value;
}
@@ -1590,7 +1587,7 @@ DWARFDebugInfoEntry::GetName
if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
{
DWARFCompileUnitSP cu_sp_ptr;
- const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(cu), &cu_sp_ptr);
+ const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr);
if (die)
return die->GetName(dwarf2Data, cu_sp_ptr.get());
}
@@ -1661,7 +1658,7 @@ DWARFDebugInfoEntry::GetPubname
// The specification DIE may be in another compile unit so we need
// to get a die and its compile unit.
DWARFCompileUnitSP cu_sp_ptr;
- const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(cu), &cu_sp_ptr);
+ const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr);
if (die)
return die->GetPubname(dwarf2Data, cu_sp_ptr.get());
}
@@ -1798,7 +1795,7 @@ DWARFDebugInfoEntry::AppendTypeName
DWARFFormValue form_value;
if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_type, form_value))
{
- uint64_t next_die_offset = form_value.Reference(cu);
+ uint64_t next_die_offset = form_value.Reference();
result = AppendTypeName(dwarf2Data, cu, next_die_offset, s);
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
index 6a2649463b54..11589aede708 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -418,12 +418,16 @@ DWARFDebugLine::ParsePrologue(const DWARFDataExtractor& debug_line_data, lldb::o
const char * s;
prologue->total_length = debug_line_data.GetDWARFInitialLength(offset_ptr);
prologue->version = debug_line_data.GetU16(offset_ptr);
- if (prologue->version < 2 || prologue->version > 3)
+ if (prologue->version < 2 || prologue->version > 4)
return false;
prologue->prologue_length = debug_line_data.GetDWARFOffset(offset_ptr);
const lldb::offset_t end_prologue_offset = prologue->prologue_length + *offset_ptr;
prologue->min_inst_length = debug_line_data.GetU8(offset_ptr);
+ if (prologue->version >= 4)
+ prologue->maximum_operations_per_instruction = debug_line_data.GetU8(offset_ptr);
+ else
+ prologue->maximum_operations_per_instruction = 1;
prologue->default_is_stmt = debug_line_data.GetU8(offset_ptr);
prologue->line_base = debug_line_data.GetU8(offset_ptr);
prologue->line_range = debug_line_data.GetU8(offset_ptr);
@@ -486,13 +490,16 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,
(void)debug_line_data.GetDWARFInitialLength(&offset);
const char * s;
uint32_t version = debug_line_data.GetU16(&offset);
- if (version < 2 || version > 3)
+ if (version < 2 || version > 4)
return false;
const dw_offset_t end_prologue_offset = debug_line_data.GetDWARFOffset(&offset) + offset;
- // Skip instruction length, default is stmt, line base, line range and
- // opcode base, and all opcode lengths
+ // Skip instruction length, default is stmt, line base, line range
offset += 4;
+ // For DWARF4, skip maximum operations per instruction
+ if (version >= 4)
+ offset += 1;
+ // Skip opcode base, and all opcode lengths
const uint8_t opcode_base = debug_line_data.GetU8(&offset);
offset += opcode_base - 1;
std::vector<std::string> include_directories;
@@ -650,7 +657,10 @@ DWARFDebugLine::ParseStatementTable
// relocatable address. All of the other statement program opcodes
// that affect the address register add a delta to it. This instruction
// stores a relocatable value into it instead.
- state.address = debug_line_data.GetAddress(offset_ptr);
+ if (arg_size == 4)
+ state.address = debug_line_data.GetU32(offset_ptr);
+ else // arg_size == 8
+ state.address = debug_line_data.GetU64(offset_ptr);
break;
case DW_LNE_define_file:
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
index 0caaf596add5..7da0e76a22be 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
@@ -75,6 +75,7 @@ public:
uint16_t version; // Version identifier for the statement information format.
uint32_t prologue_length;// The number of bytes following the prologue_length field to the beginning of the first byte of the statement program itself.
uint8_t min_inst_length;// The size in bytes of the smallest target machine instruction. Statement program opcodes that alter the address register first multiply their operands by this value.
+ uint8_t maximum_operations_per_instruction; // New in DWARF4. The maximum number of individual operations that may be encoded in an instruction.
uint8_t default_is_stmt;// The initial value of theis_stmtregister.
int8_t line_base; // This parameter affects the meaning of the special opcodes. See below.
uint8_t line_range; // This parameter affects the meaning of the special opcodes. See below.
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
index 488e9820b6fa..8469b78d0dd5 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
@@ -87,7 +87,7 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize());
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(), cu->IsDWARF64());
bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index ab8e68ab5516..a8c550e9176f 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -96,36 +96,92 @@ g_form_sizes_addr8[] =
8, // 0x20 DW_FORM_ref_sig8
};
+// Difference with g_form_sizes_addr8:
+// DW_FORM_strp and DW_FORM_sec_offset are 8 instead of 4
+static uint8_t
+g_form_sizes_addr8_dwarf64[] =
+{
+ 0, // 0x00 unused
+ 8, // 0x01 DW_FORM_addr
+ 0, // 0x02 unused
+ 0, // 0x03 DW_FORM_block2
+ 0, // 0x04 DW_FORM_block4
+ 2, // 0x05 DW_FORM_data2
+ 4, // 0x06 DW_FORM_data4
+ 8, // 0x07 DW_FORM_data8
+ 0, // 0x08 DW_FORM_string
+ 0, // 0x09 DW_FORM_block
+ 0, // 0x0a DW_FORM_block1
+ 1, // 0x0b DW_FORM_data1
+ 1, // 0x0c DW_FORM_flag
+ 0, // 0x0d DW_FORM_sdata
+ 8, // 0x0e DW_FORM_strp
+ 0, // 0x0f DW_FORM_udata
+ 0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
+ 1, // 0x11 DW_FORM_ref1
+ 2, // 0x12 DW_FORM_ref2
+ 4, // 0x13 DW_FORM_ref4
+ 8, // 0x14 DW_FORM_ref8
+ 0, // 0x15 DW_FORM_ref_udata
+ 0, // 0x16 DW_FORM_indirect
+ 8, // 0x17 DW_FORM_sec_offset
+ 0, // 0x18 DW_FORM_exprloc
+ 0, // 0x19 DW_FORM_flag_present
+ 0, // 0x1a
+ 0, // 0x1b
+ 0, // 0x1c
+ 0, // 0x1d
+ 0, // 0x1e
+ 0, // 0x1f
+ 8, // 0x20 DW_FORM_ref_sig8
+};
+
const uint8_t *
-DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size)
+DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64)
{
- switch (addr_size)
- {
- case 4: return g_form_sizes_addr4;
- case 8: return g_form_sizes_addr8;
+ if (!is_dwarf64) {
+ switch (addr_size)
+ {
+ case 4: return g_form_sizes_addr4;
+ case 8: return g_form_sizes_addr8;
+ }
+ } else {
+ if (addr_size == 8)
+ return g_form_sizes_addr8_dwarf64;
+ // is_dwarf64 && addr_size == 4 : no provider does this.
}
return NULL;
}
-DWARFFormValue::DWARFFormValue(dw_form_t form) :
+DWARFFormValue::DWARFFormValue() :
+ m_cu (NULL),
+ m_form(0),
+ m_value()
+{
+}
+
+DWARFFormValue::DWARFFormValue(const DWARFCompileUnit* cu, dw_form_t form) :
+ m_cu (cu),
m_form(form),
m_value()
{
}
bool
-DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* offset_ptr, const DWARFCompileUnit* cu)
+DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* offset_ptr)
{
bool indirect = false;
bool is_block = false;
m_value.data = NULL;
+ uint8_t ref_addr_size;
// Read the value for the form into value and follow and DW_FORM_indirect instances we run into
do
{
indirect = false;
switch (m_form)
{
- case DW_FORM_addr: m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu)); break;
+ case DW_FORM_addr: assert(m_cu);
+ m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(m_cu)); break;
case DW_FORM_block2: m_value.value.uval = data.GetU16(offset_ptr); is_block = true; break;
case DW_FORM_block4: m_value.value.uval = data.GetU32(offset_ptr); is_block = true; break;
case DW_FORM_data2: m_value.value.uval = data.GetU16(offset_ptr); break;
@@ -142,15 +198,17 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off
case DW_FORM_data1: m_value.value.uval = data.GetU8(offset_ptr); break;
case DW_FORM_flag: m_value.value.uval = data.GetU8(offset_ptr); break;
case DW_FORM_sdata: m_value.value.sval = data.GetSLEB128(offset_ptr); break;
- case DW_FORM_strp: m_value.value.uval = data.GetU32(offset_ptr); break;
+ case DW_FORM_strp: assert(m_cu);
+ m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break;
// case DW_FORM_APPLE_db_str:
case DW_FORM_udata: m_value.value.uval = data.GetULEB128(offset_ptr); break;
- case DW_FORM_ref_addr:
- if (cu->GetVersion() <= 2)
- m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu));
- else
- m_value.value.uval = data.GetU32(offset_ptr); // 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet
- break;
+ case DW_FORM_ref_addr: assert(m_cu);
+ ref_addr_size = 4;
+ if (m_cu->GetVersion() <= 2)
+ ref_addr_size = m_cu->GetAddressByteSize();
+ else
+ ref_addr_size = m_cu->IsDWARF64() ? 8 : 4;
+ m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size); break;
case DW_FORM_ref1: m_value.value.uval = data.GetU8(offset_ptr); break;
case DW_FORM_ref2: m_value.value.uval = data.GetU16(offset_ptr); break;
case DW_FORM_ref4: m_value.value.uval = data.GetU32(offset_ptr); break;
@@ -161,7 +219,8 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off
indirect = true;
break;
- case DW_FORM_sec_offset: m_value.value.uval = data.GetU32(offset_ptr); break;
+ case DW_FORM_sec_offset: assert(m_cu);
+ m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break;
case DW_FORM_flag_present: m_value.value.uval = 1; break;
case DW_FORM_ref_sig8: m_value.value.uval = data.GetU64(offset_ptr); break;
default:
@@ -183,14 +242,15 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off
}
bool
-DWARFFormValue::SkipValue(const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const
+DWARFFormValue::SkipValue(const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr) const
{
- return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, cu);
+ return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_cu);
}
bool
DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu)
{
+ uint8_t ref_addr_size;
switch (form)
{
// Blocks if inlined data that have a length field and the data bytes
@@ -212,10 +272,13 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d
return true;
case DW_FORM_ref_addr:
+ ref_addr_size = 4;
+ assert (cu); // CU must be valid for DW_FORM_ref_addr objects or we will get this wrong
if (cu->GetVersion() <= 2)
- *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu);
+ ref_addr_size = cu->GetAddressByteSize();
else
- *offset_ptr += 4;// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet
+ ref_addr_size = cu->IsDWARF64() ? 8 : 4;
+ *offset_ptr += ref_addr_size;
return true;
// 0 bytes values (implied from DW_FORM)
@@ -237,11 +300,12 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d
// 32 bit for DWARF 32, 64 for DWARF 64
case DW_FORM_sec_offset:
- *offset_ptr += 4;
+ case DW_FORM_strp:
+ assert(cu);
+ *offset_ptr += (cu->IsDWARF64() ? 8 : 4);
return true;
// 4 byte values
- case DW_FORM_strp:
case DW_FORM_data4:
case DW_FORM_ref4:
*offset_ptr += 4;
@@ -278,7 +342,7 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d
void
-DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data, const DWARFCompileUnit* cu) const
+DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const
{
uint64_t uvalue = Unsigned();
bool cu_relative_offset = false;
@@ -348,7 +412,8 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data, const
case DW_FORM_ref_addr:
{
- if (cu->GetVersion() <= 2)
+ assert (m_cu); // CU must be valid for DW_FORM_ref_addr objects or we will get this wrong
+ if (m_cu->GetVersion() <= 2)
s.Address(uvalue, sizeof (uint64_t) * 2);
else
s.Address(uvalue, 4 * 2);// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet
@@ -370,10 +435,11 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data, const
if (cu_relative_offset)
{
+ assert (m_cu); // CU must be valid for DW_FORM_ref forms that are compile unit relative or we will get this wrong
if (verbose)
s.PutCString(" => ");
- s.Printf("{0x%8.8" PRIx64 "}", (uvalue + (cu ? cu->GetOffset() : 0)));
+ s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_cu->GetOffset());
}
}
@@ -388,7 +454,7 @@ DWARFFormValue::AsCString(const DWARFDataExtractor* debug_str_data_ptr) const
}
uint64_t
-DWARFFormValue::Reference(const DWARFCompileUnit* cu) const
+DWARFFormValue::Reference() const
{
uint64_t die_offset = m_value.value.uval;
switch (m_form)
@@ -398,7 +464,8 @@ DWARFFormValue::Reference(const DWARFCompileUnit* cu) const
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- die_offset += (cu ? cu->GetOffset() : 0);
+ assert (m_cu); // CU must be valid for DW_FORM_ref forms that are compile unit relative or we will get this wrong
+ die_offset += m_cu->GetOffset();
break;
default:
@@ -429,32 +496,6 @@ DWARFFormValue::Reference (dw_offset_t base_offset) const
return die_offset;
}
-//----------------------------------------------------------------------
-// Resolve any compile unit specific references so that we don't need
-// the compile unit at a later time in order to work with the form
-// value.
-//----------------------------------------------------------------------
-bool
-DWARFFormValue::ResolveCompileUnitReferences(const DWARFCompileUnit* cu)
-{
- switch (m_form)
- {
- case DW_FORM_ref1:
- case DW_FORM_ref2:
- case DW_FORM_ref4:
- case DW_FORM_ref8:
- case DW_FORM_ref_udata:
- m_value.value.uval += cu->GetOffset();
- m_form = DW_FORM_ref_addr;
- return true;
- break;
-
- default:
- break;
- }
-
- return false;
-}
const uint8_t*
DWARFFormValue::BlockData() const
@@ -496,7 +537,7 @@ DWARFFormValue::IsDataForm(const dw_form_t form)
}
int
-DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const DWARFDataExtractor* debug_str_data_ptr)
+DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFDataExtractor* debug_str_data_ptr)
{
dw_form_t a_form = a_value.Form();
dw_form_t b_form = b_value.Form();
@@ -577,8 +618,8 @@ DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_
case DW_FORM_ref8:
case DW_FORM_ref_udata:
{
- uint64_t a = a_value.Reference(a_cu);
- uint64_t b = b_value.Reference(b_cu);
+ uint64_t a = a_value.Reference();
+ uint64_t b = b_value.Reference();
if (a < b)
return -1;
if (a > b)
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index d6c580c7ab1b..392df26a088e 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -45,35 +45,34 @@ public:
eValueTypeBlock
};
- DWARFFormValue(dw_form_t form = 0);
+ DWARFFormValue();
+ DWARFFormValue(const DWARFCompileUnit* cu, dw_form_t form);
+ const DWARFCompileUnit* GetCompileUnit () const { return m_cu; }
+ void SetCompileUnit (const DWARFCompileUnit* cu) { m_cu = cu; }
dw_form_t Form() const { return m_form; }
void SetForm(dw_form_t form) { m_form = form; }
const ValueType& Value() const { return m_value; }
- void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor* debug_str_data, const DWARFCompileUnit* cu) const;
+ void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor* debug_str_data) const;
bool ExtractValue(const lldb_private::DWARFDataExtractor& data,
- lldb::offset_t* offset_ptr,
- const DWARFCompileUnit* cu);
+ lldb::offset_t* offset_ptr);
bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (const uint8_t*)m_value.value.cstr; }
const uint8_t* BlockData() const;
- uint64_t Reference(const DWARFCompileUnit* cu) const;
+ uint64_t Reference() const;
uint64_t Reference (dw_offset_t offset) const;
- bool ResolveCompileUnitReferences(const DWARFCompileUnit* cu);
bool Boolean() const { return m_value.value.uval != 0; }
uint64_t Unsigned() const { return m_value.value.uval; }
void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }
int64_t Signed() const { return m_value.value.sval; }
void SetSigned(int64_t sval) { m_value.value.sval = sval; }
const char* AsCString(const lldb_private::DWARFDataExtractor* debug_str_data_ptr) const;
- bool SkipValue(const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const;
+ bool SkipValue(const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr) const;
static bool SkipValue(const dw_form_t form, const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu);
-// static bool TransferValue(dw_form_t form, const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff);
-// static bool TransferValue(const DWARFFormValue& formValue, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff);
-// static bool PutUnsigned(dw_form_t form, dw_offset_t offset, uint64_t value, BinaryStreamBuf& out_buff, const DWARFCompileUnit* cu, bool fixup_cu_relative_refs);
static bool IsBlockForm(const dw_form_t form);
static bool IsDataForm(const dw_form_t form);
- static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size);
- static int Compare (const DWARFFormValue& a, const DWARFFormValue& b, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const lldb_private::DWARFDataExtractor* debug_str_data_ptr);
+ static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64);
+ static int Compare (const DWARFFormValue& a, const DWARFFormValue& b, const lldb_private::DWARFDataExtractor* debug_str_data_ptr);
protected:
+ const DWARFCompileUnit* m_cu; // Compile unit for this form
dw_form_t m_form; // Form for this value
ValueType m_value; // Contains all data for the form
};
diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index ab0c37beeac9..f8a8cc60467d 100644
--- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -442,9 +442,9 @@ struct DWARFMappedHash
for (size_t i=0; i<num_atoms; ++i)
{
- DWARFFormValue form_value (header_data.atoms[i].form);
+ DWARFFormValue form_value (NULL, header_data.atoms[i].form);
- if (!form_value.ExtractValue(data, offset_ptr, NULL))
+ if (!form_value.ExtractValue(data, offset_ptr))
return false;
switch (header_data.atoms[i].type)
@@ -481,7 +481,7 @@ struct DWARFMappedHash
if (i > 0)
strm.PutCString (", ");
- DWARFFormValue form_value (header_data.atoms[i].form);
+ DWARFFormValue form_value (NULL, header_data.atoms[i].form);
switch (header_data.atoms[i].type)
{
case eAtomTypeDIEOffset: // DIE offset, check form for encoding
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 842260dbc3ba..b3a5476227f4 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1457,7 +1457,7 @@ SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu,
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter:
{
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
DWARFDebugInfoEntry::Attributes attributes;
const size_t num_attributes = die->GetAttributes (this,
@@ -1486,7 +1486,7 @@ SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu,
case DW_AT_type:
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
- const dw_offset_t type_die_offset = form_value.Reference(dwarf_cu);
+ const dw_offset_t type_die_offset = form_value.Reference();
lldb_type = ResolveTypeUID(type_die_offset);
if (lldb_type)
clang_type = lldb_type->GetClangForwardType();
@@ -1752,7 +1752,7 @@ SymbolFileDWARF::ParseChildMembers
size_t count = 0;
const DWARFDebugInfoEntry *die;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
uint32_t member_idx = 0;
BitfieldInfo last_field_info;
ModuleSP module = GetObjectFile()->GetModule();
@@ -1803,7 +1803,7 @@ SymbolFileDWARF::ParseChildMembers
case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break;
+ case DW_AT_type: encoding_uid = form_value.Reference(); break;
case DW_AT_bit_offset: bit_offset = form_value.Unsigned(); break;
case DW_AT_bit_size: bit_size = form_value.Unsigned(); break;
case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
@@ -2201,7 +2201,7 @@ SymbolFileDWARF::ParseChildMembers
case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break;
+ case DW_AT_type: encoding_uid = form_value.Reference(); break;
case DW_AT_data_member_location:
if (form_value.BlockData())
{
@@ -2990,7 +2990,7 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line,
if (block_die != NULL)
sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset()));
- else
+ else if (function_die != NULL)
sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset()));
}
}
@@ -3033,7 +3033,7 @@ SymbolFileDWARF::Index ()
m_indexed = true;
Timer scoped_timer (__PRETTY_FUNCTION__,
"SymbolFileDWARF::Index (%s)",
- GetObjectFile()->GetFileSpec().GetFilename().AsCString());
+ GetObjectFile()->GetFileSpec().GetFilename().AsCString("<Unknown>"));
DWARFDebugInfo* debug_info = DebugInfo();
if (debug_info)
@@ -3197,13 +3197,13 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
if (m_apple_names_ap.get())
{
const char *name_cstr = name.GetCString();
- const char *base_name_start;
- const char *base_name_end = NULL;
+ llvm::StringRef basename;
+ llvm::StringRef context;
- if (!CPPLanguageRuntime::StripNamespacesFromVariableName(name_cstr, base_name_start, base_name_end))
- base_name_start = name_cstr;
+ if (!CPPLanguageRuntime::ExtractContextAndIdentifier(name_cstr, context, basename))
+ basename = name_cstr;
- m_apple_names_ap->FindByName (base_name_start, die_offsets);
+ m_apple_names_ap->FindByName (basename.data(), die_offsets);
}
}
else
@@ -3402,7 +3402,7 @@ SymbolFileDWARF::ResolveFunction (DWARFCompileUnit *cu,
break;
}
}
- assert (die->Tag() == DW_TAG_subprogram);
+ assert (die && die->Tag() == DW_TAG_subprogram);
if (GetFunction (cu, die, sc))
{
Address addr;
@@ -4231,7 +4231,7 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc,
if (parent_die == NULL)
return 0;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
size_t arg_idx = 0;
const DWARFDebugInfoEntry *die;
@@ -4266,7 +4266,7 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc,
case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: param_type_die_offset = form_value.Reference(dwarf_cu); break;
+ case DW_AT_type: param_type_die_offset = form_value.Reference(); break;
case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
case DW_AT_location:
// if (form_value.BlockData())
@@ -4409,7 +4409,7 @@ SymbolFileDWARF::ParseChildEnumerators
size_t enumerators_added = 0;
const DWARFDebugInfoEntry *die;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
{
@@ -4488,7 +4488,7 @@ SymbolFileDWARF::ParseChildArrayInfo
return;
const DWARFDebugInfoEntry *die;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
{
const dw_tag_t tag = die->Tag();
@@ -4929,7 +4929,7 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
{
DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n",
MakeUserID(die->GetOffset()),
- m_obj_file->GetFileSpec().GetFilename().AsCString(),
+ m_obj_file->GetFileSpec().GetFilename().AsCString("<Unknown>"),
MakeUserID(type_die->GetOffset()),
MakeUserID(type_cu->GetOffset()));
@@ -5060,189 +5060,6 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn
return true;
}
-// This function can be used when a DIE is found that is a forward declaration
-// DIE and we want to try and find a type that has the complete definition.
-// "cu" and "die" must be from this SymbolFileDWARF
-TypeSP
-SymbolFileDWARF::FindDefinitionTypeForDIE (DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry *die,
- const ConstString &type_name)
-{
- TypeSP type_sp;
-
-#if defined (LLDB_CONFIGURATION_DEBUG)
- // You can't and shouldn't call this function with a compile unit from
- // another SymbolFileDWARF instance.
- assert (DebugInfo()->ContainsCompileUnit (cu));
-#endif
-
- if (cu == NULL || die == NULL || !type_name)
- return type_sp;
-
- std::string qualified_name;
-
- Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION|DWARF_LOG_LOOKUPS));
- if (log)
- {
- die->GetQualifiedName(this, cu, qualified_name);
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindDefinitionTypeForDIE(die=0x%8.8x (%s), name='%s')",
- die->GetOffset(),
- qualified_name.c_str(),
- type_name.GetCString());
- }
-
- DIEArray die_offsets;
-
- if (m_using_apple_tables)
- {
- if (m_apple_types_ap.get())
- {
- const bool has_tag = m_apple_types_ap->GetHeader().header_data.ContainsAtom (DWARFMappedHash::eAtomTypeTag);
- const bool has_qualified_name_hash = m_apple_types_ap->GetHeader().header_data.ContainsAtom (DWARFMappedHash::eAtomTypeQualNameHash);
- if (has_tag && has_qualified_name_hash)
- {
- if (qualified_name.empty())
- die->GetQualifiedName(this, cu, qualified_name);
-
- const uint32_t qualified_name_hash = MappedHash::HashStringUsingDJB (qualified_name.c_str());
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTagAndQualifiedNameHash()");
- m_apple_types_ap->FindByNameAndTagAndQualifiedNameHash (type_name.GetCString(), die->Tag(), qualified_name_hash, die_offsets);
- }
- else if (has_tag)
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTag()");
- m_apple_types_ap->FindByNameAndTag (type_name.GetCString(), die->Tag(), die_offsets);
- }
- else
- {
- m_apple_types_ap->FindByName (type_name.GetCString(), die_offsets);
- }
- }
- }
- else
- {
- if (!m_indexed)
- Index ();
-
- m_type_index.Find (type_name, die_offsets);
- }
-
- const size_t num_matches = die_offsets.size();
-
- const dw_tag_t die_tag = die->Tag();
-
- DWARFCompileUnit* type_cu = NULL;
- const DWARFDebugInfoEntry* type_die = NULL;
- if (num_matches)
- {
- DWARFDebugInfo* debug_info = DebugInfo();
- for (size_t i=0; i<num_matches; ++i)
- {
- const dw_offset_t die_offset = die_offsets[i];
- type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu);
-
- if (type_die)
- {
- bool try_resolving_type = false;
-
- // Don't try and resolve the DIE we are looking for with the DIE itself!
- if (type_die != die)
- {
- const dw_tag_t type_die_tag = type_die->Tag();
- // Make sure the tags match
- if (type_die_tag == die_tag)
- {
- // The tags match, lets try resolving this type
- try_resolving_type = true;
- }
- else
- {
- // The tags don't match, but we need to watch our for a
- // forward declaration for a struct and ("struct foo")
- // ends up being a class ("class foo { ... };") or
- // vice versa.
- switch (type_die_tag)
- {
- case DW_TAG_class_type:
- // We had a "class foo", see if we ended up with a "struct foo { ... };"
- try_resolving_type = (die_tag == DW_TAG_structure_type);
- break;
- case DW_TAG_structure_type:
- // We had a "struct foo", see if we ended up with a "class foo { ... };"
- try_resolving_type = (die_tag == DW_TAG_class_type);
- break;
- default:
- // Tags don't match, don't event try to resolve
- // using this type whose name matches....
- break;
- }
- }
- }
-
- if (try_resolving_type)
- {
- if (log)
- {
- std::string qualified_name;
- type_die->GetQualifiedName(this, cu, qualified_name);
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindDefinitionTypeForDIE(die=0x%8.8x, name='%s') trying die=0x%8.8x (%s)",
- die->GetOffset(),
- type_name.GetCString(),
- type_die->GetOffset(),
- qualified_name.c_str());
- }
-
- // Make sure the decl contexts match all the way up
- if (DIEDeclContextsMatch(cu, die, type_cu, type_die))
- {
- Type *resolved_type = ResolveType (type_cu, type_die, false);
- if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
- {
- DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ") from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n",
- MakeUserID(die->GetOffset()),
- MakeUserID(cu->GetOffset()),
- m_obj_file->GetFileSpec().GetFilename().AsCString(),
- MakeUserID(type_die->GetOffset()),
- MakeUserID(type_cu->GetOffset()));
-
- m_die_to_type[die] = resolved_type;
- type_sp = resolved_type->shared_from_this();
- break;
- }
- }
- }
- else
- {
- if (log)
- {
- std::string qualified_name;
- type_die->GetQualifiedName(this, cu, qualified_name);
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindDefinitionTypeForDIE(die=0x%8.8x, name='%s') ignoring die=0x%8.8x (%s)",
- die->GetOffset(),
- type_name.GetCString(),
- type_die->GetOffset(),
- qualified_name.c_str());
- }
- }
- }
- else
- {
- if (m_using_apple_tables)
- {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, type_name.GetCString());
- }
- }
-
- }
- }
- return type_sp;
-}
TypeSP
SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &dwarf_decl_ctx)
@@ -5828,7 +5645,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
break;
case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
case DW_AT_encoding: encoding = form_value.Unsigned(); break;
- case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break;
+ case DW_AT_type: encoding_uid = form_value.Reference(); break;
default:
case DW_AT_sibling:
break;
@@ -6403,7 +6220,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
type_name_cstr = form_value.AsCString(&get_debug_str_data());
type_name_const_str.SetCString(type_name_cstr);
break;
- case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break;
+ case DW_AT_type: encoding_uid = form_value.Reference(); break;
case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_declaration: break; //is_forward_declaration = form_value.Boolean(); break;
@@ -6521,7 +6338,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name: break; // mangled = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break;
+ case DW_AT_type: type_die_offset = form_value.Reference(); break;
case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break;
case DW_AT_inline: is_inline = form_value.Boolean(); break;
@@ -6541,15 +6358,15 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
break;
case DW_AT_specification:
- specification_die_offset = form_value.Reference(dwarf_cu);
+ specification_die_offset = form_value.Reference();
break;
case DW_AT_abstract_origin:
- abstract_origin_die_offset = form_value.Reference(dwarf_cu);
+ abstract_origin_die_offset = form_value.Reference();
break;
case DW_AT_object_pointer:
- object_pointer_die_offset = form_value.Reference(dwarf_cu);
+ object_pointer_die_offset = form_value.Reference();
break;
case DW_AT_allocated:
@@ -6985,7 +6802,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
type_name_const_str.SetCString(type_name_cstr);
break;
- case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break;
+ case DW_AT_type: type_die_offset = form_value.Reference(); break;
case DW_AT_byte_size: break; // byte_size = form_value.Unsigned(); break;
case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break;
case DW_AT_bit_stride: bit_stride = form_value.Unsigned(); break;
@@ -7019,17 +6836,26 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
byte_stride = element_type->GetByteSize();
ClangASTType array_element_type = element_type->GetClangForwardType();
uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
- uint64_t num_elements = 0;
- std::vector<uint64_t>::const_reverse_iterator pos;
- std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend();
- for (pos = element_orders.rbegin(); pos != end; ++pos)
+ if (element_orders.size() > 0)
+ {
+ uint64_t num_elements = 0;
+ std::vector<uint64_t>::const_reverse_iterator pos;
+ std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend();
+ for (pos = element_orders.rbegin(); pos != end; ++pos)
+ {
+ num_elements = *pos;
+ clang_type = ast.CreateArrayType (array_element_type,
+ num_elements,
+ is_vector);
+ array_element_type = clang_type;
+ array_element_bit_stride = num_elements ?
+ array_element_bit_stride * num_elements :
+ array_element_bit_stride;
+ }
+ }
+ else
{
- num_elements = *pos;
- clang_type = ast.CreateArrayType (array_element_type,
- num_elements,
- is_vector);
- array_element_type = clang_type;
- array_element_bit_stride = num_elements ? array_element_bit_stride * num_elements : array_element_bit_stride;
+ clang_type = ast.CreateArrayType (array_element_type, 0, is_vector);
}
ConstString empty_name;
type_sp.reset( new Type (MakeUserID(die->GetOffset()),
@@ -7065,9 +6891,9 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
switch (attr)
{
case DW_AT_type:
- type_die_offset = form_value.Reference(dwarf_cu); break;
+ type_die_offset = form_value.Reference(); break;
case DW_AT_containing_type:
- containing_type_die_offset = form_value.Reference(dwarf_cu); break;
+ containing_type_die_offset = form_value.Reference(); break;
}
}
}
@@ -7114,7 +6940,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
{
symbol_context_scope = sc.comp_unit;
}
- else if (sc.function != NULL)
+ else if (sc.function != NULL && sc_parent_die)
{
symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
if (symbol_context_scope == NULL)
@@ -7347,7 +7173,6 @@ SymbolFileDWARF::ParseVariableDIE
const lldb::addr_t func_low_pc
)
{
-
VariableSP var_sp (m_die_to_variable_sp[die]);
if (var_sp)
return var_sp; // Already been parsed!
@@ -7380,6 +7205,7 @@ SymbolFileDWARF::ParseVariableDIE
{
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
+
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
switch (attr)
@@ -7390,7 +7216,7 @@ SymbolFileDWARF::ParseVariableDIE
case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: type_uid = form_value.Reference(dwarf_cu); break;
+ case DW_AT_type: type_uid = form_value.Reference(); break;
case DW_AT_external: is_external = form_value.Boolean(); break;
case DW_AT_const_value:
// If we have already found a DW_AT_location attribute, ignore this attribute.
@@ -7409,7 +7235,7 @@ SymbolFileDWARF::ParseVariableDIE
else if (DWARFFormValue::IsDataForm(form_value.Form()))
{
// Retrieve the value as a data expression.
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64());
uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
uint32_t data_length = fixed_form_sizes[form_value.Form()];
if (data_length == 0)
@@ -7417,7 +7243,7 @@ SymbolFileDWARF::ParseVariableDIE
const uint8_t *data_pointer = form_value.BlockData();
if (data_pointer)
{
- data_length = form_value.Unsigned();
+ form_value.Unsigned();
}
else if (DWARFFormValue::IsDataForm(form_value.Form()))
{
@@ -7433,7 +7259,7 @@ SymbolFileDWARF::ParseVariableDIE
// Retrieve the value as a string expression.
if (form_value.Form() == DW_FORM_strp)
{
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+ const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64());
uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
uint32_t data_length = fixed_form_sizes[form_value.Form()];
location.CopyOpcodeData(module, debug_info_data, data_offset, data_length);
@@ -7470,7 +7296,7 @@ SymbolFileDWARF::ParseVariableDIE
{
location.CopyOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length);
assert (func_low_pc != LLDB_INVALID_ADDRESS);
- location.SetLocationListSlide (func_low_pc - dwarf_cu->GetBaseAddress());
+ location.SetLocationListSlide (func_low_pc - attributes.CompileUnitAtIndex(i)->GetBaseAddress());
}
}
}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 178e5142d94b..230e1a5d3984 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -421,11 +421,6 @@ protected:
const DWARFMappedHash::MemoryTable &memory_table,
lldb_private::SymbolContextList& sc_list);
- lldb::TypeSP FindDefinitionTypeForDIE (
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- const lldb_private::ConstString &type_name);
-
lldb::TypeSP FindDefinitionTypeForDWARFDeclContext (
const DWARFDeclContext &die_decl_ctx);
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index b8d56d3909e9..7e484bd8dc73 100644
--- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -146,7 +146,8 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
if (log && log->GetVerbose ())
{
StreamString strm;
- inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL);
+ const char *disassemble_format = "${frame.pc}: ";
+ inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL, NULL, NULL, disassemble_format);
log->PutCString (strm.GetData());
}
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index 32a21d2b8bb8..dbf37d8a4de0 100644
--- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -23,6 +23,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnwindAssembly.h"
+#include "lldb/Utility/RegisterNumber.h"
using namespace lldb;
using namespace lldb_private;
@@ -318,7 +319,8 @@ AssemblyParse_x86::nonvolatile_reg_p (int machine_regno)
#define REX_W_DSTREG(opcode) ((opcode) & 0x1)
// pushq %rbp [0x55]
-bool AssemblyParse_x86::push_rbp_pattern_p ()
+bool
+AssemblyParse_x86::push_rbp_pattern_p ()
{
uint8_t *p = m_cur_insn_bytes;
if (*p == 0x55)
@@ -327,7 +329,8 @@ bool AssemblyParse_x86::push_rbp_pattern_p ()
}
// pushq $0 ; the first instruction in start() [0x6a 0x00]
-bool AssemblyParse_x86::push_0_pattern_p ()
+bool
+AssemblyParse_x86::push_0_pattern_p ()
{
uint8_t *p = m_cur_insn_bytes;
if (*p == 0x6a && *(p + 1) == 0x0)
@@ -337,7 +340,8 @@ bool AssemblyParse_x86::push_0_pattern_p ()
// pushq $0
// pushl $0
-bool AssemblyParse_x86::push_imm_pattern_p ()
+bool
+AssemblyParse_x86::push_imm_pattern_p ()
{
uint8_t *p = m_cur_insn_bytes;
if (*p == 0x68 || *p == 0x6a)
@@ -347,7 +351,8 @@ bool AssemblyParse_x86::push_imm_pattern_p ()
// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5]
// movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5]
-bool AssemblyParse_x86::mov_rsp_rbp_pattern_p ()
+bool
+AssemblyParse_x86::mov_rsp_rbp_pattern_p ()
{
uint8_t *p = m_cur_insn_bytes;
if (m_wordsize == 8 && *p == 0x48)
@@ -360,7 +365,8 @@ bool AssemblyParse_x86::mov_rsp_rbp_pattern_p ()
}
// subq $0x20, %rsp
-bool AssemblyParse_x86::sub_rsp_pattern_p (int& amount)
+bool
+AssemblyParse_x86::sub_rsp_pattern_p (int& amount)
{
uint8_t *p = m_cur_insn_bytes;
if (m_wordsize == 8 && *p == 0x48)
@@ -381,7 +387,8 @@ bool AssemblyParse_x86::sub_rsp_pattern_p (int& amount)
}
// addq $0x20, %rsp
-bool AssemblyParse_x86::add_rsp_pattern_p (int& amount)
+bool
+AssemblyParse_x86::add_rsp_pattern_p (int& amount)
{
uint8_t *p = m_cur_insn_bytes;
if (m_wordsize == 8 && *p == 0x48)
@@ -403,7 +410,8 @@ bool AssemblyParse_x86::add_rsp_pattern_p (int& amount)
// pushq %rbx
// pushl %ebx
-bool AssemblyParse_x86::push_reg_p (int& regno)
+bool
+AssemblyParse_x86::push_reg_p (int& regno)
{
uint8_t *p = m_cur_insn_bytes;
int regno_prefix_bit = 0;
@@ -423,7 +431,8 @@ bool AssemblyParse_x86::push_reg_p (int& regno)
// popq %rbx
// popl %ebx
-bool AssemblyParse_x86::pop_reg_p (int& regno)
+bool
+AssemblyParse_x86::pop_reg_p (int& regno)
{
uint8_t *p = m_cur_insn_bytes;
int regno_prefix_bit = 0;
@@ -443,14 +452,16 @@ bool AssemblyParse_x86::pop_reg_p (int& regno)
// popq %rbp [0x5d]
// popl %ebp [0x5d]
-bool AssemblyParse_x86::pop_rbp_pattern_p ()
+bool
+AssemblyParse_x86::pop_rbp_pattern_p ()
{
uint8_t *p = m_cur_insn_bytes;
return (*p == 0x5d);
}
// call $0 [0xe8 0x0 0x0 0x0 0x0]
-bool AssemblyParse_x86::call_next_insn_pattern_p ()
+bool
+AssemblyParse_x86::call_next_insn_pattern_p ()
{
uint8_t *p = m_cur_insn_bytes;
return (*p == 0xe8) && (*(p+1) == 0x0) && (*(p+2) == 0x0)
@@ -468,7 +479,8 @@ bool AssemblyParse_x86::call_next_insn_pattern_p ()
// the actual location. The positive value returned for the offset
// is a convention used elsewhere for CFA offsets et al.
-bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_offset)
+bool
+AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_offset)
{
uint8_t *p = m_cur_insn_bytes;
int src_reg_prefix_bit = 0;
@@ -602,7 +614,6 @@ bool
AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
{
UnwindPlan::RowSP row(new UnwindPlan::Row);
- int non_prologue_insn_count = 0;
m_cur_insn = m_func_bounds.GetBaseAddress ();
int current_func_text_offset = 0;
int current_sp_bytes_offset_from_cfa = 0;
@@ -638,20 +649,38 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
*newrow = *row.get();
row.reset(newrow);
+ // Track which registers have been saved so far in the prologue.
+ // If we see another push of that register, it's not part of the prologue.
+ // The register numbers used here are the machine register #'s
+ // (i386_register_numbers, x86_64_register_numbers).
+ std::vector<bool> saved_registers(32, false);
+
const bool prefer_file_cache = true;
+ // Once the prologue has completed we'll save a copy of the unwind instructions
+ // If there is an epilogue in the middle of the function, after that epilogue we'll reinstate
+ // the unwind setup -- we assume that some code path jumps over the mid-function epilogue
+
+ UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI
+ int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the epilogue started executed
+ std::vector<bool> prologue_completed_saved_registers;
+
Target *target = m_exe_ctx.GetTargetPtr();
- while (m_func_bounds.ContainsFileAddress (m_cur_insn) && non_prologue_insn_count < 10)
+ while (m_func_bounds.ContainsFileAddress (m_cur_insn))
{
int stack_offset, insn_len;
int machine_regno; // register numbers masked directly out of instructions
uint32_t lldb_regno; // register numbers in lldb's eRegisterKindLLDB numbering scheme
+ bool in_epilogue = false; // we're in the middle of an epilogue sequence
+ bool row_updated = false; // The UnwindPlan::Row 'row' has been updated
+
if (!instruction_length (m_cur_insn, insn_len) || insn_len == 0 || insn_len > kMaxInstructionByteSize)
{
// An unrecognized/junk instruction
break;
}
+
if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes,
insn_len, error) == static_cast<size_t>(-1))
{
@@ -661,216 +690,193 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
if (push_rbp_pattern_p ())
{
- row->SetOffset (current_func_text_offset + insn_len);
current_sp_bytes_offset_from_cfa += m_wordsize;
row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
UnwindPlan::Row::RegisterLocation regloc;
regloc.SetAtCFAPlusOffset (-row->GetCFAOffset());
row->SetRegisterInfo (m_lldb_fp_regnum, regloc);
- unwind_plan.AppendRow (row);
- // Allocate a new Row, populate it with the existing Row contents.
- newrow = new UnwindPlan::Row;
- *newrow = *row.get();
- row.reset(newrow);
- goto loopnext;
+ saved_registers[m_machine_fp_regnum] = true;
+ row_updated = true;
}
- if (mov_rsp_rbp_pattern_p ())
+ else if (mov_rsp_rbp_pattern_p ())
{
- row->SetOffset (current_func_text_offset + insn_len);
row->SetCFARegister (m_lldb_fp_regnum);
- unwind_plan.AppendRow (row);
- // Allocate a new Row, populate it with the existing Row contents.
- newrow = new UnwindPlan::Row;
- *newrow = *row.get();
- row.reset(newrow);
- goto loopnext;
+ row_updated = true;
}
// This is the start() function (or a pthread equivalent), it starts with a pushl $0x0 which puts the
// saved pc value of 0 on the stack. In this case we want to pretend we didn't see a stack movement at all --
// normally the saved pc value is already on the stack by the time the function starts executing.
- if (push_0_pattern_p ())
+ else if (push_0_pattern_p ())
{
- goto loopnext;
}
- if (push_reg_p (machine_regno))
+ else if (push_reg_p (machine_regno))
{
current_sp_bytes_offset_from_cfa += m_wordsize;
- bool need_to_push_row = false;
// the PUSH instruction has moved the stack pointer - if the CFA is set in terms of the stack pointer,
// we need to add a new row of instructions.
if (row->GetCFARegister() == m_lldb_sp_regnum)
{
- need_to_push_row = true;
row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
+ row_updated = true;
}
// record where non-volatile (callee-saved, spilled) registers are saved on the stack
- if (nonvolatile_reg_p (machine_regno) && machine_regno_to_lldb_regno (machine_regno, lldb_regno))
+ if (nonvolatile_reg_p (machine_regno)
+ && machine_regno_to_lldb_regno (machine_regno, lldb_regno)
+ && saved_registers[machine_regno] == false)
{
- need_to_push_row = true;
UnwindPlan::Row::RegisterLocation regloc;
regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa);
row->SetRegisterInfo (lldb_regno, regloc);
+ saved_registers[machine_regno] = true;
+ row_updated = true;
}
- if (need_to_push_row)
- {
- row->SetOffset (current_func_text_offset + insn_len);
- unwind_plan.AppendRow (row);
- // Allocate a new Row, populate it with the existing Row contents.
- newrow = new UnwindPlan::Row;
- *newrow = *row.get();
- row.reset(newrow);
- }
- goto loopnext;
}
- if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset) && nonvolatile_reg_p (machine_regno))
+ else if (pop_reg_p (machine_regno))
{
- if (machine_regno_to_lldb_regno (machine_regno, lldb_regno))
+ current_sp_bytes_offset_from_cfa -= m_wordsize;
+
+ if (nonvolatile_reg_p (machine_regno)
+ && machine_regno_to_lldb_regno (machine_regno, lldb_regno)
+ && saved_registers[machine_regno] == true)
{
- row->SetOffset (current_func_text_offset + insn_len);
- UnwindPlan::Row::RegisterLocation regloc;
+ saved_registers[machine_regno] = false;
+ row->RemoveRegisterInfo (lldb_regno);
- // stack_offset for 'movq %r15, -80(%rbp)' will be 80.
- // In the Row, we want to express this as the offset from the CFA. If the frame base
- // is rbp (like the above instruction), the CFA offset for rbp is probably 16. So we
- // want to say that the value is stored at the CFA address - 96.
- regloc.SetAtCFAPlusOffset (-(stack_offset + row->GetCFAOffset()));
+ if (machine_regno == m_machine_fp_regnum)
+ {
+ row->SetCFARegister (m_lldb_sp_regnum);
+ }
- row->SetRegisterInfo (lldb_regno, regloc);
- unwind_plan.AppendRow (row);
- // Allocate a new Row, populate it with the existing Row contents.
- newrow = new UnwindPlan::Row;
- *newrow = *row.get();
- row.reset(newrow);
- goto loopnext;
+ in_epilogue = true;
+ row_updated = true;
}
- }
- if (sub_rsp_pattern_p (stack_offset))
- {
- current_sp_bytes_offset_from_cfa += stack_offset;
+ // the POP instruction has moved the stack pointer - if the CFA is set in terms of the stack pointer,
+ // we need to add a new row of instructions.
if (row->GetCFARegister() == m_lldb_sp_regnum)
{
- row->SetOffset (current_func_text_offset + insn_len);
row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
- unwind_plan.AppendRow (row);
- // Allocate a new Row, populate it with the existing Row contents.
- newrow = new UnwindPlan::Row;
- *newrow = *row.get();
- row.reset(newrow);
+ row_updated = true;
}
- goto loopnext;
}
- if (ret_pattern_p ())
+ else if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset)
+ && nonvolatile_reg_p (machine_regno)
+ && machine_regno_to_lldb_regno (machine_regno, lldb_regno)
+ && saved_registers[machine_regno] == false)
{
- // we know where the end of the function is; set the limit on the PlanValidAddressRange
- // in case our initial "high pc" value was overly large
- // int original_size = m_func_bounds.GetByteSize();
- // int calculated_size = m_cur_insn.GetOffset() - m_func_bounds.GetBaseAddress().GetOffset() + insn_len + 1;
- // m_func_bounds.SetByteSize (calculated_size);
- // unwind_plan.SetPlanValidAddressRange (m_func_bounds);
- break;
- }
+ saved_registers[machine_regno] = true;
- // FIXME recognize the i386 picbase setup instruction sequence,
- // 0x1f16: call 0x1f1b ; main + 11 at /private/tmp/a.c:3
- // 0x1f1b: popl %eax
- // and record the temporary stack movements if the CFA is not expressed in terms of ebp.
+ UnwindPlan::Row::RegisterLocation regloc;
- non_prologue_insn_count++;
-loopnext:
- m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len);
- current_func_text_offset += insn_len;
- }
+ // stack_offset for 'movq %r15, -80(%rbp)' will be 80.
+ // In the Row, we want to express this as the offset from the CFA. If the frame base
+ // is rbp (like the above instruction), the CFA offset for rbp is probably 16. So we
+ // want to say that the value is stored at the CFA address - 96.
+ regloc.SetAtCFAPlusOffset (-(stack_offset + row->GetCFAOffset()));
- // Now look at the byte at the end of the AddressRange for a limited attempt at describing the
- // epilogue. We're looking for the sequence
+ row->SetRegisterInfo (lldb_regno, regloc);
- // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp)
- // [ 0xc3 ] ret
+ row_updated = true;
+ }
- // or
+ else if (sub_rsp_pattern_p (stack_offset))
+ {
+ current_sp_bytes_offset_from_cfa += stack_offset;
+ if (row->GetCFARegister() == m_lldb_sp_regnum)
+ {
+ row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
+ row_updated = true;
+ }
+ }
- // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp)
- // [ 0xe9 xx xx xx xx ] jmp objc_retainAutoreleaseReturnValue (this is sometimes the final insn in the function)
+ else if (add_rsp_pattern_p (stack_offset))
+ {
+ current_sp_bytes_offset_from_cfa -= stack_offset;
+ if (row->GetCFARegister() == m_lldb_sp_regnum)
+ {
+ row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
+ row_updated = true;
+ }
+ in_epilogue = true;
+ }
- // or
+ else if (ret_pattern_p () && prologue_completed_row.get())
+ {
+ // Reinstate the saved prologue setup for any instructions
+ // that come after the ret instruction
- // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp)
- // [ 0xc3 ] ret
- // [ 0xe8 xx xx xx xx ] call __stack_chk_fail (this is sometimes the final insn in the function)
+ UnwindPlan::Row *newrow = new UnwindPlan::Row;
+ *newrow = *prologue_completed_row.get();
+ row.reset (newrow);
+ current_sp_bytes_offset_from_cfa = prologue_completed_sp_bytes_offset_from_cfa;
- // We want to add a Row describing how to unwind when we're stopped on the 'ret' instruction where the
- // CFA is no longer defined in terms of rbp, but is now defined in terms of rsp like on function entry.
- // (or the 'jmp' instruction in the second case)
+ saved_registers.clear();
+ saved_registers.resize(prologue_completed_saved_registers.size(), false);
+ for (size_t i = 0; i < prologue_completed_saved_registers.size(); ++i)
+ {
+ saved_registers[i] = prologue_completed_saved_registers[i];
+ }
- uint64_t ret_insn_offset = LLDB_INVALID_ADDRESS;
- Address end_of_fun(m_func_bounds.GetBaseAddress());
- end_of_fun.SetOffset (end_of_fun.GetOffset() + m_func_bounds.GetByteSize());
+ in_epilogue = true;
+ row_updated = true;
+ }
- if (m_func_bounds.GetByteSize() > 7)
- {
- uint8_t bytebuf[7];
- Address last_seven_bytes(end_of_fun);
- last_seven_bytes.SetOffset (last_seven_bytes.GetOffset() - 7);
- if (target->ReadMemory (last_seven_bytes, prefer_file_cache, bytebuf, 7,
- error) != static_cast<size_t>(-1))
+ // call next instruction
+ // call 0
+ // => pop %ebx
+ // This is used in i386 programs to get the PIC base address for finding global data
+ else if (call_next_insn_pattern_p ())
{
- if (bytebuf[5] == 0x5d && bytebuf[6] == 0xc3) // mov & ret
- {
- ret_insn_offset = m_func_bounds.GetByteSize() - 1;
- }
- else if (bytebuf[1] == 0x5d && bytebuf[2] == 0xe9) // mov & jmp
- {
- // When the pc is sitting on the 'jmp' instruction, we have the same
- // unwind state as if it was sitting on a 'ret' instruction.
- ret_insn_offset = m_func_bounds.GetByteSize() - 5;
- }
- else if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3 && bytebuf[2] == 0xe8) // mov & ret & call
+ current_sp_bytes_offset_from_cfa += m_wordsize;
+ if (row->GetCFARegister() == m_lldb_sp_regnum)
{
- ret_insn_offset = m_func_bounds.GetByteSize() - 6;
+ row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
+ row_updated = true;
}
}
- }
- else if (m_func_bounds.GetByteSize() > 2)
- {
- uint8_t bytebuf[2];
- Address last_two_bytes(end_of_fun);
- last_two_bytes.SetOffset (last_two_bytes.GetOffset() - 2);
- if (target->ReadMemory (last_two_bytes, prefer_file_cache, bytebuf, 2,
- error) != static_cast<size_t>(-1))
+
+ if (row_updated)
{
- if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3) // mov & ret
+ if (current_func_text_offset + insn_len < m_func_bounds.GetByteSize())
{
- ret_insn_offset = m_func_bounds.GetByteSize() - 1;
+ row->SetOffset (current_func_text_offset + insn_len);
+ unwind_plan.AppendRow (row);
+ // Allocate a new Row, populate it with the existing Row contents.
+ newrow = new UnwindPlan::Row;
+ *newrow = *row.get();
+ row.reset(newrow);
}
}
- }
- if (ret_insn_offset != LLDB_INVALID_ADDRESS)
- {
- // Create a fresh, empty Row and RegisterLocation - don't mention any other registers
- UnwindPlan::RowSP epi_row(new UnwindPlan::Row);
- UnwindPlan::Row::RegisterLocation epi_regloc;
-
- // When the ret instruction is about to be executed, here's our state
- epi_row->SetOffset (ret_insn_offset);
- epi_row->SetCFARegister (m_lldb_sp_regnum);
- epi_row->SetCFAOffset (m_wordsize);
+ if (in_epilogue == false && row_updated)
+ {
+ // If we're not in an epilogue sequence, save the updated Row
+ UnwindPlan::Row *newrow = new UnwindPlan::Row;
+ *newrow = *row.get();
+ prologue_completed_row.reset (newrow);
- // caller's stack pointer value before the call insn is the CFA address
- epi_regloc.SetIsCFAPlusOffset (0);
- epi_row->SetRegisterInfo (m_lldb_sp_regnum, epi_regloc);
+ prologue_completed_saved_registers.clear();
+ prologue_completed_saved_registers.resize(saved_registers.size(), false);
+ for (size_t i = 0; i < saved_registers.size(); ++i)
+ {
+ prologue_completed_saved_registers[i] = saved_registers[i];
+ }
+ }
- // saved instruction pointer can be found at CFA - wordsize
- epi_regloc.SetAtCFAPlusOffset (-m_wordsize);
- epi_row->SetRegisterInfo (m_lldb_ip_regnum, epi_regloc);
+ // We may change the sp value without adding a new Row necessarily -- keep
+ // track of it either way.
+ if (in_epilogue == false)
+ {
+ prologue_completed_sp_bytes_offset_from_cfa = current_sp_bytes_offset_from_cfa;
+ }
- unwind_plan.AppendRow (epi_row);
+ m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len);
+ current_func_text_offset += insn_len;
}
unwind_plan.SetSourceName ("assembly insn profiling");
@@ -902,12 +908,20 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
if (cfa_reg != m_lldb_sp_regnum || first_row->GetCFAOffset() != m_wordsize)
return false;
+ UnwindPlan::RowSP original_last_row = unwind_plan.GetRowForFunctionOffset (-1);
+
Target *target = m_exe_ctx.GetTargetPtr();
m_cur_insn = func.GetBaseAddress();
uint64_t offset = 0;
int row_id = 1;
bool unwind_plan_updated = false;
UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row));
+
+ // After a mid-function epilogue we will need to re-insert the original unwind rules
+ // so unwinds work for the remainder of the function. These aren't common with clang/gcc
+ // on x86 but it is possible.
+ bool reinstate_unwind_state = false;
+
while (func.ContainsFileAddress (m_cur_insn))
{
int insn_len;
@@ -930,10 +944,29 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
offset += insn_len;
m_cur_insn.SetOffset(m_cur_insn.GetOffset() + insn_len);
+ if (reinstate_unwind_state)
+ {
+ // that was the last instruction of this function
+ if (func.ContainsFileAddress (m_cur_insn) == false)
+ continue;
+
+ UnwindPlan::RowSP new_row(new UnwindPlan::Row());
+ *new_row = *original_last_row;
+ new_row->SetOffset (offset);
+ unwind_plan.AppendRow (new_row);
+ row.reset (new UnwindPlan::Row());
+ *row = *new_row;
+ reinstate_unwind_state = false;
+ unwind_plan_updated = true;
+ continue;
+ }
+
// If we already have one row for this instruction, we can continue.
while (row_id < unwind_plan.GetRowCount()
&& unwind_plan.GetRowAtIndex (row_id)->GetOffset() <= offset)
+ {
row_id++;
+ }
UnwindPlan::RowSP original_row = unwind_plan.GetRowAtIndex (row_id - 1);
if (original_row->GetOffset() == offset)
{
@@ -1032,6 +1065,11 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
unwind_plan_updated = true;
continue;
}
+ if (ret_pattern_p ())
+ {
+ reinstate_unwind_state = true;
+ continue;
+ }
}
else if (cfa_reg == m_lldb_fp_regnum)
{
@@ -1053,6 +1091,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
unwind_plan.InsertRow (new_row);
unwind_plan_updated = true;
+ reinstate_unwind_state = true;
continue;
}
}
@@ -1074,6 +1113,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
unwind_plan_source += " plus augmentation from assembly parsing";
unwind_plan.SetSourceName (unwind_plan_source.c_str());
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
}
return true;
}
@@ -1239,17 +1279,130 @@ UnwindAssembly_x86::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, Th
bool
UnwindAssembly_x86::AugmentUnwindPlanFromCallSite (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan)
{
- ExecutionContext exe_ctx (thread.shared_from_this());
- AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
- return asm_parse.augment_unwind_plan_from_call_site (func, unwind_plan);
+ bool do_augment_unwindplan = true;
+
+ UnwindPlan::RowSP first_row = unwind_plan.GetRowForFunctionOffset (0);
+ UnwindPlan::RowSP last_row = unwind_plan.GetRowForFunctionOffset (-1);
+
+ int wordsize = 8;
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ wordsize = process_sp->GetTarget().GetArchitecture().GetAddressByteSize();
+ }
+
+ RegisterNumber sp_regnum (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ RegisterNumber pc_regnum (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+
+ // Does this UnwindPlan describe the prologue? I want to see that the CFA is set
+ // in terms of the stack pointer plus an offset, and I want to see that rip is
+ // retrieved at the CFA-wordsize.
+ // If there is no description of the prologue, don't try to augment this eh_frame
+ // unwinder code, fall back to assembly parsing instead.
+
+ if (first_row->GetCFAType() != UnwindPlan::Row::CFAType::CFAIsRegisterPlusOffset
+ || RegisterNumber (thread, unwind_plan.GetRegisterKind(), first_row->GetCFARegister()) != sp_regnum
+ || first_row->GetCFAOffset() != wordsize)
+ {
+ return false;
+ }
+ UnwindPlan::Row::RegisterLocation first_row_pc_loc;
+ if (first_row->GetRegisterInfo (pc_regnum.GetAsKind (unwind_plan.GetRegisterKind()), first_row_pc_loc) == false
+ || first_row_pc_loc.IsAtCFAPlusOffset() == false
+ || first_row_pc_loc.GetOffset() != -wordsize)
+ {
+ return false;
+ }
+
+
+ // It looks like the prologue is described.
+ // Is the epilogue described? If it is, no need to do any augmentation.
+
+ if (first_row != last_row && first_row->GetOffset() != last_row->GetOffset())
+ {
+ // The first & last row have the same CFA register
+ // and the same CFA offset value
+ // and the CFA register is esp/rsp (the stack pointer).
+
+ // We're checking that both of them have an unwind rule like "CFA=esp+4" or CFA+rsp+8".
+
+ if (first_row->GetCFAType() == last_row->GetCFAType()
+ && first_row->GetCFARegister() == last_row->GetCFARegister()
+ && first_row->GetCFAOffset() == last_row->GetCFAOffset())
+ {
+ // Get the register locations for eip/rip from the first & last rows.
+ // Are they both CFA plus an offset? Is it the same offset?
+
+ UnwindPlan::Row::RegisterLocation last_row_pc_loc;
+ if (last_row->GetRegisterInfo (pc_regnum.GetAsKind (unwind_plan.GetRegisterKind()), last_row_pc_loc))
+ {
+ if (last_row_pc_loc.IsAtCFAPlusOffset()
+ && first_row_pc_loc.GetOffset() == last_row_pc_loc.GetOffset())
+ {
+
+ // One last sanity check: Is the unwind rule for getting the caller pc value
+ // "deref the CFA-4" or "deref the CFA-8"?
+
+ // If so, we have an UnwindPlan that already describes the epilogue and we don't need
+ // to modify it at all.
+
+ if (first_row_pc_loc.GetOffset() == -wordsize)
+ {
+ do_augment_unwindplan = false;
+ }
+ }
+ }
+ }
+ }
+
+ if (do_augment_unwindplan)
+ {
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
+ return asm_parse.augment_unwind_plan_from_call_site (func, unwind_plan);
+ }
+
+ return false;
}
bool
UnwindAssembly_x86::GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan)
{
- ExecutionContext exe_ctx (thread.shared_from_this());
- AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
- return asm_parse.get_fast_unwind_plan (func, unwind_plan);
+ // if prologue is
+ // 55 pushl %ebp
+ // 89 e5 movl %esp, %ebp
+ // or
+ // 55 pushq %rbp
+ // 48 89 e5 movq %rsp, %rbp
+
+ // We should pull in the ABI architecture default unwind plan and return that
+
+ llvm::SmallVector <uint8_t, 4> opcode_data;
+
+ ProcessSP process_sp = thread.GetProcess();
+ if (process_sp)
+ {
+ Target &target (process_sp->GetTarget());
+ const bool prefer_file_cache = true;
+ Error error;
+ if (target.ReadMemory (func.GetBaseAddress (), prefer_file_cache, opcode_data.data(),
+ 4, error) == 4)
+ {
+ uint8_t i386_push_mov[] = {0x55, 0x89, 0xe5};
+ uint8_t x86_64_push_mov[] = {0x55, 0x48, 0x89, 0xe5};
+
+ if (memcmp (opcode_data.data(), i386_push_mov, sizeof (i386_push_mov)) == 0
+ || memcmp (opcode_data.data(), x86_64_push_mov, sizeof (x86_64_push_mov)) == 0)
+ {
+ ABISP abi_sp = process_sp->GetABI();
+ if (abi_sp)
+ {
+ return abi_sp->CreateDefaultUnwindPlan (unwind_plan);
+ }
+ }
+ }
+ }
+ return false;
}
bool