From c05ae522a7efbfbc1eb55e36cfd3cdb56a3abc8a Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Tue, 23 Jul 2013 18:30:49 +0000 Subject: [PATCH] elf-core: Improve FreeBSD support and move data extraction to parse time Extracting thread data at parse time simplifies multi-platform support. This change adds FreeBSD thread names and auxv info. Thanks to Samuel Jacob for review, testing, and improvements. llvm-svn: 186975 --- .../Plugins/Process/elf-core/ProcessElfCore.cpp | 43 ++++++++++++++++++---- .../Plugins/Process/elf-core/ProcessElfCore.h | 11 +----- .../Plugins/Process/elf-core/ThreadElfCore.cpp | 32 ++++++---------- .../Plugins/Process/elf-core/ThreadElfCore.h | 18 ++++++--- 4 files changed, 60 insertions(+), 44 deletions(-) diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index b70ffc1..b507e98 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -231,8 +231,7 @@ ProcessElfCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_t for (lldb::tid_t tid = 0; tid < num_threads; ++tid) { const ThreadData &td = m_thread_data[tid]; - lldb::ThreadSP thread_sp(new ThreadElfCore (*this, tid, td.prstatus, - td.prpsinfo, td.fpregset)); + lldb::ThreadSP thread_sp(new ThreadElfCore (*this, tid, td)); new_thread_list.AddThread (thread_sp); } return new_thread_list.GetSize(false) > 0; @@ -436,6 +435,13 @@ struct ELFNote } }; +static void +ParseFreeBSDThrMisc(ThreadData *thread_data, DataExtractor &data) +{ + lldb::offset_t offset = 0; + thread_data->name = data.GetCStr(&offset, 20); +} + /// Parse Thread context from PT_NOTE segment and store it in the thread list /// Notes: /// 1) A PT_NOTE segment is composed of one or more NOTE entries. @@ -465,6 +471,12 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * bool have_prstatus = false; bool have_prpsinfo = false; + ArchSpec arch = GetArchitecture(); + ELFPrPsInfo prpsinfo; + ELFPrStatus prstatus; + size_t header_size; + size_t len; + // Loop through the NOTE entires in the segment while (offset < segment_header->p_filesz) { @@ -475,7 +487,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * if ((note.n_type == NT_PRSTATUS && have_prstatus) || (note.n_type == NT_PRPSINFO && have_prpsinfo)) { - assert(thread_data->prstatus.GetByteSize() > 0); + assert(thread_data->gpregset.GetByteSize() > 0); // Add the new thread to thread list m_thread_data.push_back(*thread_data); thread_data = new ThreadData(); @@ -495,14 +507,24 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * { case NT_FREEBSD_PRSTATUS: have_prstatus = true; - thread_data->prstatus = note_data; + prstatus.Parse(note_data, arch); + thread_data->signo = prstatus.pr_cursig; + header_size = ELFPrStatus::GetSize(arch); + len = note_data.GetByteSize() - header_size; + thread_data->gpregset = DataExtractor(note_data, header_size, len); break; case NT_FREEBSD_FPREGSET: thread_data->fpregset = note_data; break; case NT_FREEBSD_PRPSINFO: have_prpsinfo = true; - thread_data->prpsinfo = note_data; + break; + case NT_FREEBSD_THRMISC: + ParseFreeBSDThrMisc(thread_data, note_data); + break; + case NT_FREEBSD_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; default: break; @@ -514,14 +536,19 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * { case NT_PRSTATUS: have_prstatus = true; - thread_data->prstatus = note_data; + prstatus.Parse(note_data, arch); + thread_data->signo = prstatus.pr_cursig; + header_size = ELFPrStatus::GetSize(arch); + len = note_data.GetByteSize() - header_size; + thread_data->gpregset = DataExtractor(note_data, header_size, len); break; case NT_FPREGSET: thread_data->fpregset = note_data; break; case NT_PRPSINFO: have_prpsinfo = true; - thread_data->prpsinfo = note_data; + prpsinfo.Parse(note_data, arch); + thread_data->name = prpsinfo.pr_fname; break; case NT_AUXV: m_auxv = DataExtractor(note_data); @@ -534,7 +561,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * offset += note_size; } // Add last entry in the note section - if (thread_data && thread_data->prstatus.GetByteSize() > 0) + if (thread_data && thread_data->gpregset.GetByteSize() > 0) { m_thread_data.push_back(*thread_data); } diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h index 34ac05c..1c1ed98 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -28,6 +28,8 @@ #include "Plugins/ObjectFile/ELF/ELFHeader.h" +struct ThreadData; + class ProcessElfCore : public lldb_private::Process { public: @@ -135,15 +137,6 @@ private: typedef lldb_private::Range FileRange; typedef lldb_private::RangeDataArray VMRangeToFileOffset; - // In ELF core file thread context is described mainly by 3 Note entries - // The following structure holds pointers to those note entries. - struct ThreadData - { - lldb_private::DataExtractor prstatus; - lldb_private::DataExtractor fpregset; - lldb_private::DataExtractor prpsinfo; - }; - lldb::ModuleSP m_core_module_sp; lldb_private::FileSpec m_core_file; std::string m_dyld_plugin_name; diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 7d0397e..a6963f8b 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -23,24 +23,17 @@ using namespace lldb; using namespace lldb_private; //---------------------------------------------------------------------- -// Construct a Thread object with given PRSTATUS, PRPSINFO and FPREGSET +// Construct a Thread object with given data //---------------------------------------------------------------------- -ThreadElfCore::ThreadElfCore (Process &process, tid_t tid, DataExtractor prstatus, - DataExtractor prpsinfo, DataExtractor fpregset) : +ThreadElfCore::ThreadElfCore (Process &process, tid_t tid, + const ThreadData &td) : Thread(process, tid), - m_thread_reg_ctx_sp () + m_thread_name(td.name), + m_thread_reg_ctx_sp (), + m_signo(td.signo), + m_gpregset_data(td.gpregset), + m_fpregset_data(td.fpregset) { - ProcessElfCore *pr = static_cast(GetProcess().get()); - ArchSpec arch = pr->GetArchitecture(); - - /* Parse the datastructures from the file */ - m_prstatus.Parse(prstatus, arch); - m_prpsinfo.Parse(prpsinfo, arch); - - m_prstatus_data = prstatus; - m_fpregset_data = fpregset; - - m_thread_name = std::string(m_prpsinfo.pr_fname); } ThreadElfCore::~ThreadElfCore () @@ -89,19 +82,16 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) ProcessElfCore *process = static_cast(GetProcess().get()); ArchSpec arch = process->GetArchitecture(); - size_t header_size = ELFPrStatus::GetSize(arch); - size_t len = m_prstatus_data.GetByteSize() - header_size; - DataExtractor gpregset_data = DataExtractor(m_prstatus_data, header_size, len); switch (arch.GetMachine()) { case llvm::Triple::x86_64: switch (arch.GetTriple().getOS()) { case llvm::Triple::FreeBSD: - m_thread_reg_ctx_sp.reset(new RegisterContextCoreFreeBSD_x86_64 (*this, gpregset_data, m_fpregset_data)); + m_thread_reg_ctx_sp.reset(new RegisterContextCoreFreeBSD_x86_64 (*this, m_gpregset_data, m_fpregset_data)); break; case llvm::Triple::Linux: - m_thread_reg_ctx_sp.reset(new RegisterContextCoreLinux_x86_64 (*this, gpregset_data, m_fpregset_data)); + m_thread_reg_ctx_sp.reset(new RegisterContextCoreLinux_x86_64 (*this, m_gpregset_data, m_fpregset_data)); break; default: if (log) @@ -132,7 +122,7 @@ ThreadElfCore::CalculateStopInfo () ProcessSP process_sp (GetProcess()); if (process_sp) { - SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, m_prstatus.pr_cursig)); + SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, m_signo)); return true; } return false; diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h index ad0f67a..c61f449 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -125,13 +125,19 @@ struct ELFPrPsInfo }; +struct ThreadData +{ + lldb_private::DataExtractor gpregset; + lldb_private::DataExtractor fpregset; + int signo; + std::string name; +}; + class ThreadElfCore : public lldb_private::Thread { public: ThreadElfCore (lldb_private::Process &process, lldb::tid_t tid, - lldb_private::DataExtractor prstatus, - lldb_private::DataExtractor prpsinfo, - lldb_private::DataExtractor fpregset); + const ThreadData &td); virtual ~ThreadElfCore (); @@ -178,9 +184,9 @@ protected: std::string m_thread_name; lldb::RegisterContextSP m_thread_reg_ctx_sp; - ELFPrStatus m_prstatus; - ELFPrPsInfo m_prpsinfo; - lldb_private::DataExtractor m_prstatus_data; + int m_signo; + + lldb_private::DataExtractor m_gpregset_data; lldb_private::DataExtractor m_fpregset_data; virtual bool CalculateStopInfo(); -- 2.7.4