summaryrefslogtreecommitdiff
path: root/source/Plugins/Process/elf-core
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2014-02-18 16:23:10 +0000
committerEd Maste <emaste@FreeBSD.org>2014-02-18 16:23:10 +0000
commit866dcdacfe59f5f448e008fe2c4cb9dfcf72b2ec (patch)
tree95cb16075f0af1b3a05b9b84eb18dda8e6c903e9 /source/Plugins/Process/elf-core
parentde889deb2c386f2a7831befaf226e5c86685fa53 (diff)
Diffstat (limited to 'source/Plugins/Process/elf-core')
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp46
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp12
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.cpp70
3 files changed, 83 insertions, 45 deletions
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 93641ede1bc78..7ea5c89e7df4f 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -131,7 +131,8 @@ ProcessElfCore::AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *head
VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
if (last_entry &&
last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
- last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
+ last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&
+ last_entry->GetByteSize() == last_entry->data.GetByteSize())
{
last_entry->SetRangeEnd (range_entry.GetRangeEnd());
last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
@@ -294,9 +295,13 @@ ProcessElfCore::DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &
size_t zero_fill_size = 0; // Padding
lldb::addr_t bytes_left = 0; // Number of bytes available in the core file from the given address
- if (file_end > offset)
- bytes_left = file_end - offset;
+ // Figure out how many on-disk bytes remain in this segment
+ // starting at the given offset
+ if (file_end > file_start + offset)
+ bytes_left = file_end - (file_start + offset);
+ // Figure out how many bytes we need to zero-fill if we are
+ // reading more bytes than available in the on-disk segment
if (bytes_to_read > bytes_left)
{
zero_fill_size = bytes_to_read - bytes_left;
@@ -365,12 +370,12 @@ enum {
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
static void
-ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data,
+ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
ArchSpec &arch)
{
lldb::offset_t offset = 0;
- bool have_padding = (arch.GetMachine() == llvm::Triple::mips64 ||
- arch.GetMachine() == llvm::Triple::x86_64);
+ bool lp64 = (arch.GetMachine() == llvm::Triple::mips64 ||
+ arch.GetMachine() == llvm::Triple::x86_64);
int pr_version = data.GetU32(&offset);
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
@@ -380,23 +385,26 @@ ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data,
log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version);
}
- if (have_padding)
- offset += 4;
- offset += 28; // pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
- thread_data->signo = data.GetU32(&offset); // pr_cursig
+ // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
+ if (lp64)
+ offset += 32;
+ else
+ offset += 16;
+
+ thread_data.signo = data.GetU32(&offset); // pr_cursig
offset += 4; // pr_pid
- if (have_padding)
+ if (lp64)
offset += 4;
size_t len = data.GetByteSize() - offset;
- thread_data->gpregset = DataExtractor(data, offset, len);
+ thread_data.gpregset = DataExtractor(data, offset, len);
}
static void
-ParseFreeBSDThrMisc(ThreadData *thread_data, DataExtractor &data)
+ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data)
{
lldb::offset_t offset = 0;
- thread_data->name = data.GetCStr(&offset, 20);
+ thread_data.name = data.GetCStr(&offset, 20);
}
/// Parse Thread context from PT_NOTE segment and store it in the thread list
@@ -418,13 +426,13 @@ ParseFreeBSDThrMisc(ThreadData *thread_data, DataExtractor &data)
/// For case (b) there may be either one NT_PRPSINFO per thread, or a single
/// one that applies to all threads (depending on the platform type).
void
-ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *segment_header,
+ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *segment_header,
DataExtractor segment_data)
{
assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
lldb::offset_t offset = 0;
- ThreadData *thread_data = new ThreadData();
+ std::unique_ptr<ThreadData> thread_data(new ThreadData);
bool have_prstatus = false;
bool have_prpsinfo = false;
@@ -447,7 +455,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
assert(thread_data->gpregset.GetByteSize() > 0);
// Add the new thread to thread list
m_thread_data.push_back(*thread_data);
- thread_data = new ThreadData();
+ *thread_data = ThreadData();
have_prstatus = false;
have_prpsinfo = false;
}
@@ -464,7 +472,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
{
case NT_FREEBSD_PRSTATUS:
have_prstatus = true;
- ParseFreeBSDPrStatus(thread_data, note_data, arch);
+ ParseFreeBSDPrStatus(*thread_data, note_data, arch);
break;
case NT_FREEBSD_FPREGSET:
thread_data->fpregset = note_data;
@@ -473,7 +481,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
have_prpsinfo = true;
break;
case NT_FREEBSD_THRMISC:
- ParseFreeBSDThrMisc(thread_data, note_data);
+ ParseFreeBSDThrMisc(*thread_data, note_data);
break;
case NT_FREEBSD_PROCSTAT_AUXV:
// FIXME: FreeBSD sticks an int at the beginning of the note
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
index 610506c20a0bd..3e09c7bc20322 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -63,8 +63,16 @@ RegisterContextCorePOSIX_x86_64::WriteFPR()
bool
RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
{
- value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
- return true;
+ 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;
+ }
+ return false;
}
bool
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index 3bda86dc0f739..cadcf53ca5431 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -17,6 +17,7 @@
#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 "RegisterContextPOSIXCore_mips64.h"
@@ -85,45 +86,66 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
ArchSpec arch = process->GetArchitecture();
- switch (arch.GetMachine())
+ RegisterInfoInterface *reg_interface = NULL;
+
+ switch (arch.GetTriple().getOS())
{
- case llvm::Triple::mips64:
- switch (arch.GetTriple().getOS())
+ case llvm::Triple::FreeBSD:
+ {
+ switch (arch.GetMachine())
{
- case llvm::Triple::FreeBSD:
- m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, new RegisterContextFreeBSD_mips64(arch), m_gpregset_data, m_fpregset_data));
+ case llvm::Triple::mips64:
+ reg_interface = new RegisterContextFreeBSD_mips64(arch);
+ break;
+ case llvm::Triple::x86:
+ reg_interface = new RegisterContextFreeBSD_i386(arch);
+ break;
+ case llvm::Triple::x86_64:
+ reg_interface = new RegisterContextFreeBSD_x86_64(arch);
break;
default:
- if (log)
- log->Printf ("elf-core::%s:: OS(%d) not supported",
- __FUNCTION__, arch.GetTriple().getOS());
- assert (false && "OS not supported");
break;
}
break;
- case llvm::Triple::x86_64:
- switch (arch.GetTriple().getOS())
+ }
+
+ case llvm::Triple::Linux:
+ {
+ switch (arch.GetMachine())
{
- case llvm::Triple::FreeBSD:
- m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, new RegisterContextFreeBSD_x86_64(arch), m_gpregset_data, m_fpregset_data));
- break;
- case llvm::Triple::Linux:
- m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, new RegisterContextLinux_x86_64(arch), m_gpregset_data, m_fpregset_data));
+ case llvm::Triple::x86_64:
+ reg_interface = new RegisterContextLinux_x86_64(arch);
break;
default:
- if (log)
- log->Printf ("elf-core::%s:: OS(%d) not supported",
- __FUNCTION__, arch.GetTriple().getOS());
- assert (false && "OS not supported");
break;
}
break;
+ }
+
+ default:
+ break;
+ }
+
+ if (!reg_interface) {
+ if (log)
+ log->Printf ("elf-core::%s:: Architecture(%d) or OS(%d) not supported",
+ __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
+ assert (false && "Architecture or OS not supported");
+ }
+
+ switch (arch.GetMachine())
+ {
+ 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::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));
+ break;
default:
- if (log)
- log->Printf ("elf-core::%s:: Architecture(%d) not supported",
- __FUNCTION__, arch.GetMachine());
- assert (false && "Architecture not supported");
+ break;
}
+
reg_ctx_sp = m_thread_reg_ctx_sp;
}
else if (m_unwinder_ap.get())