summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins
diff options
context:
space:
mode:
authorDimitar Vlahovski <dvlahovski@gmail.com>2016-11-20 21:24:49 +0000
committerDimitar Vlahovski <dvlahovski@gmail.com>2016-11-20 21:24:49 +0000
commita228c46c2a1ec209ec1cc67ba2a58f8df4150668 (patch)
tree65560d3f28b49c26357511992747c671b23526da /lldb/source/Plugins
parent1dcb9110612abc47405be50a0fc20661cef2f926 (diff)
downloadbcm5719-llvm-a228c46c2a1ec209ec1cc67ba2a58f8df4150668.tar.gz
bcm5719-llvm-a228c46c2a1ec209ec1cc67ba2a58f8df4150668.zip
ELF core: Adding parsing of the floating-point and SSE registers on x86 32/64 bit elf core files
Summary: The floating-point and SSE registers could be present in the elf-core file in the note NT_FPREGSET for 64 bit ones, and in the note NT_PRXFPREG for 32 bit ones. The entire note is a binary blob matching the layout of the x87 save area that gets generated by the FXSAVE instruction (see Intel developers manual for more information). This CL mainly modifies the RegisterRead function in RegisterContextPOSIXCore_x86_64 for it to return the correct data both for GPR and FPR/SSE registers, and return false (meaning "this register is not available") for other registers. I added a test to TestElfCore.py that tests reading FPR/SSE registers both from a 32 and 64 bit elf-core file and I have inluded the source which I used to generate the core files. I tried to also add support for the AVX registers, because this info could also be present in the elf-core file (note NT_X86_XSTATE - that is the result of the newer XSAVE instruction). Parsing the contents from the file is easy. The problem is that the ymm registers are split into two halves and they are in different places in the note. For making this work one would either make a "hacky" approach, because there won't be any other way with the current state of the register contexts - they assume that "this register is of size N and at offset M" and don't have the notion of discontinuos registers. Reviewers: labath Subscribers: emaste, lldb-commits Differential Revision: https://reviews.llvm.org/D26300 llvm-svn: 287506
Diffstat (limited to 'lldb/source/Plugins')
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp4
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp5
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp4
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h2
-rw-r--r--lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp14
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp53
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h5
10 files changed, 72 insertions, 21 deletions
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
index 6563796db12..2eebaddcecc 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
@@ -111,6 +111,10 @@ RegisterContextLinux_i386::RegisterContextLinux_i386(
size_t RegisterContextLinux_i386::GetGPRSize() const { return sizeof(GPR); }
+size_t RegisterContextLinux_i386::GetFXSAVEOffset() const {
+ return (LLVM_EXTENSION offsetof(UserArea, i387));
+}
+
const RegisterInfo *RegisterContextLinux_i386::GetRegisterInfo() const {
switch (m_target_arch.GetMachine()) {
case llvm::Triple::x86:
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
index fbf803789cc..bb6707b0ed7 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
@@ -18,6 +18,8 @@ public:
size_t GetGPRSize() const override;
+ size_t GetFXSAVEOffset() const override;
+
const lldb_private::RegisterInfo *GetRegisterInfo() const override;
uint32_t GetRegisterCount() const override;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
index 526b3eca81a..6f4bb800c4d 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
@@ -179,6 +179,11 @@ RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(
size_t RegisterContextLinux_x86_64::GetGPRSize() const { return sizeof(GPR); }
+size_t RegisterContextLinux_x86_64::GetFXSAVEOffset() const {
+ return (LLVM_EXTENSION offsetof(UserArea, fpr) +
+ LLVM_EXTENSION offsetof(FPR, xstate));
+}
+
const std::vector<lldb_private::RegisterInfo> *
RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const {
return &d_register_infos;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
index 99a4cb73679..e9e3e8bffde 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
@@ -18,6 +18,8 @@ public:
size_t GetGPRSize() const override;
+ size_t GetFXSAVEOffset() const override;
+
const lldb_private::RegisterInfo *GetRegisterInfo() const override;
uint32_t GetRegisterCount() const override;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
index 77f3fcb0e9c..d6f67cbc0bd 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
@@ -419,6 +419,10 @@ size_t RegisterContextPOSIX_x86::GetGPRSize() {
return m_register_info_ap->GetGPRSize();
}
+size_t RegisterContextPOSIX_x86::GetFXSAVEOffset() {
+ return m_register_info_ap->GetFXSAVEOffset();
+}
+
const RegisterInfo *RegisterContextPOSIX_x86::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
// specialized.
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
index 22f3493b4ee..c5afe089e47 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
@@ -38,6 +38,8 @@ public:
virtual size_t GetGPRSize();
+ virtual size_t GetFXSAVEOffset();
+
virtual unsigned GetRegisterSize(unsigned reg);
virtual unsigned GetRegisterOffset(unsigned reg);
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h b/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
index 12db366d7a5..a0776407908 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
@@ -29,6 +29,8 @@ public:
virtual size_t GetGPRSize() const = 0;
+ virtual size_t GetFXSAVEOffset() const { return 0; }
+
virtual const lldb_private::RegisterInfo *GetRegisterInfo() const = 0;
// Returns the number of registers including the user registers and the
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 840a79279f5..f03f8db3387 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -400,7 +400,8 @@ enum {
NT_TASKSTRUCT,
NT_PLATFORM,
NT_AUXV,
- NT_FILE = 0x46494c45
+ NT_FILE = 0x46494c45,
+ NT_PRXFPREG = 0x46e62b7f,
};
namespace FREEBSD {
@@ -552,7 +553,11 @@ Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
thread_data->gpregset = DataExtractor(note_data, header_size, len);
break;
case NT_FPREGSET:
- thread_data->fpregset = note_data;
+ // In a i386 core file NT_FPREGSET is present, but it's not the result
+ // of the FXSAVE instruction like in 64 bit files.
+ // The result from FXSAVE is in NT_PRXFPREG for i386 core files
+ if (arch.GetCore() == ArchSpec::eCore_x86_64_x86_64)
+ thread_data->fpregset = note_data;
break;
case NT_PRPSINFO:
have_prpsinfo = true;
@@ -586,6 +591,11 @@ Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
default:
break;
}
+ } else if (note.n_name == "LINUX") {
+ switch (note.n_type) {
+ case NT_PRXFPREG:
+ thread_data->fpregset = note_data;
+ }
}
offset += note_size;
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
index 8157401b54e..b0148c28ea0 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -21,18 +21,27 @@ RegisterContextCorePOSIX_x86_64::RegisterContextCorePOSIX_x86_64(
size_t size, len;
size = GetGPRSize();
- m_gpregset = new uint8_t[size];
- len = gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset);
- assert(len == size);
-}
+ m_gpregset.reset(new uint8_t[size]);
+ len =
+ gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset.get());
+ if (len != size)
+ m_gpregset.reset();
-RegisterContextCorePOSIX_x86_64::~RegisterContextCorePOSIX_x86_64() {
- delete[] m_gpregset;
+ size = sizeof(FXSAVE);
+ m_fpregset.reset(new uint8_t[size]);
+ len =
+ fpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_fpregset.get());
+ if (len != size)
+ m_fpregset.reset();
}
-bool RegisterContextCorePOSIX_x86_64::ReadGPR() { return m_gpregset != NULL; }
+bool RegisterContextCorePOSIX_x86_64::ReadGPR() {
+ return m_gpregset != nullptr;
+}
-bool RegisterContextCorePOSIX_x86_64::ReadFPR() { return false; }
+bool RegisterContextCorePOSIX_x86_64::ReadFPR() {
+ return m_fpregset != nullptr;
+}
bool RegisterContextCorePOSIX_x86_64::WriteGPR() {
assert(0);
@@ -46,15 +55,27 @@ bool RegisterContextCorePOSIX_x86_64::WriteFPR() {
bool RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info,
RegisterValue &value) {
- switch (reg_info->byte_size) {
- case 4:
- value = *(uint32_t *)(m_gpregset + reg_info->byte_offset);
- return true;
- case 8:
- value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
- return true;
+ const uint8_t *src;
+ size_t offset;
+ const size_t fxsave_offset = reg_info->byte_offset - GetFXSAVEOffset();
+ // make the offset relative to the beginning of the FXSAVE structure
+ // because this is the data that we have (not the entire UserArea)
+
+ if (m_gpregset && reg_info->byte_offset < GetGPRSize()) {
+ src = m_gpregset.get();
+ offset = reg_info->byte_offset;
+ } else if (m_fpregset && fxsave_offset < sizeof(FXSAVE)) {
+ src = m_fpregset.get();
+ offset = fxsave_offset;
+ } else {
+ return false;
}
- return false;
+
+ Error error;
+ value.SetFromMemoryData(reg_info, src + offset, reg_info->byte_size,
+ lldb::eByteOrderLittle, error);
+
+ return error.Success();
}
bool RegisterContextCorePOSIX_x86_64::ReadAllRegisterValues(
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
index eeb36b68de0..c27e09132bb 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
@@ -24,8 +24,6 @@ public:
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
- ~RegisterContextCorePOSIX_x86_64() override;
-
bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value) override;
@@ -48,7 +46,8 @@ protected:
bool WriteFPR() override;
private:
- uint8_t *m_gpregset;
+ std::unique_ptr<uint8_t[]> m_gpregset;
+ std::unique_ptr<uint8_t[]> m_fpregset;
};
#endif // liblldb_RegisterContextCorePOSIX_x86_64_h_
OpenPOWER on IntegriCloud