diff options
Diffstat (limited to 'source/Plugins/Process/elf-core/ProcessElfCore.cpp')
-rw-r--r-- | source/Plugins/Process/elf-core/ProcessElfCore.cpp | 71 |
1 files changed, 58 insertions, 13 deletions
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 7ea5c89..5668167 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -17,12 +17,17 @@ #include "lldb/Core/Section.h" #include "lldb/Core/State.h" #include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Log.h" #include "lldb/Target/Target.h" #include "lldb/Target/DynamicLoader.h" -#include "ProcessPOSIXLog.h" +#include "lldb/Target/UnixSignals.h" + +#include "llvm/Support/ELF.h" #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" +#include "Plugins/Process/Utility/FreeBSDSignals.h" +#include "Plugins/Process/Utility/LinuxSignals.h" // Project includes #include "ProcessElfCore.h" @@ -54,8 +59,25 @@ lldb::ProcessSP ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file) { lldb::ProcessSP process_sp; - if (crash_file) - process_sp.reset(new ProcessElfCore (target, listener, *crash_file)); + if (crash_file) + { + // Read enough data for a ELF32 header or ELF64 header + const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr); + + lldb::DataBufferSP data_sp (crash_file->ReadFileContents(0, header_size)); + if (data_sp && data_sp->GetByteSize() == header_size && + elf::ELFHeader::MagicBytesMatch (data_sp->GetBytes())) + { + elf::ELFHeader elf_header; + DataExtractor data(data_sp, lldb::eByteOrderLittle, 4); + lldb::offset_t data_offset = 0; + if (elf_header.Parse(data, &data_offset)) + { + if (elf_header.e_type == llvm::ELF::ET_CORE) + process_sp.reset(new ProcessElfCore (target, listener, *crash_file)); + } + } + } return process_sp; } @@ -66,7 +88,7 @@ ProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name) if (!m_core_module_sp && m_core_file.Exists()) { ModuleSpec core_module_spec(m_core_file, target.GetArchitecture()); - Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp, + Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp, NULL, NULL, NULL)); if (m_core_module_sp) { @@ -87,6 +109,7 @@ ProcessElfCore::ProcessElfCore(Target& target, Listener &listener, m_core_module_sp (), m_core_file (core_file), m_dyld_plugin_name (), + m_os(llvm::Triple::UnknownOS), m_thread_data_valid(false), m_thread_data(), m_core_aranges () @@ -154,21 +177,21 @@ ProcessElfCore::DoLoadCore () Error error; if (!m_core_module_sp) { - error.SetErrorString ("invalid core module"); + error.SetErrorString ("invalid core module"); return error; } ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); if (core == NULL) { - error.SetErrorString ("invalid core object file"); + error.SetErrorString ("invalid core object file"); return error; } const uint32_t num_segments = core->GetProgramHeaderCount(); if (num_segments == 0) { - error.SetErrorString ("core file has no sections"); + error.SetErrorString ("core file has no sections"); return error; } @@ -209,7 +232,25 @@ ProcessElfCore::DoLoadCore () // it to match the core file which is always single arch. ArchSpec arch (m_core_module_sp->GetArchitecture()); if (arch.IsValid()) - m_target.SetArchitecture(arch); + m_target.SetArchitecture(arch); + + switch (m_os) + { + case llvm::Triple::FreeBSD: + { + static UnixSignalsSP s_freebsd_signals_sp(new FreeBSDSignals ()); + SetUnixSignals(s_freebsd_signals_sp); + break; + } + case llvm::Triple::Linux: + { + static UnixSignalsSP s_linux_signals_sp(new process_linux::LinuxSignals ()); + SetUnixSignals(s_linux_signals_sp); + break; + } + default: + break; + } return error; } @@ -324,13 +365,17 @@ void ProcessElfCore::Clear() { m_thread_list.Clear(); + m_os = llvm::Triple::UnknownOS; + + static UnixSignalsSP s_default_unix_signals_sp(new UnixSignals()); + SetUnixSignals(s_default_unix_signals_sp); } void ProcessElfCore::Initialize() { static bool g_initialized = false; - + if (g_initialized == false) { g_initialized = true; @@ -378,7 +423,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, arch.GetMachine() == llvm::Triple::x86_64); int pr_version = data.GetU32(&offset); - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); + Log *log (GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { if (pr_version > 1) @@ -395,7 +440,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, offset += 4; // pr_pid if (lp64) offset += 4; - + size_t len = data.GetByteSize() - offset; thread_data.gpregset = DataExtractor(data, offset, len); } @@ -421,7 +466,7 @@ ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) /// a) Each thread context(2 or more NOTE entries) contained in its own segment (PT_NOTE) /// b) All thread context is stored in a single segment(PT_NOTE). /// This case is little tricker since while parsing we have to find where the -/// new thread starts. The current implementation marks beginning of +/// new thread starts. The current implementation marks beginning of /// new thread when it finds NT_PRSTATUS or NT_PRPSINFO NOTE entry. /// 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). @@ -468,6 +513,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * DataExtractor note_data (segment_data, note_start, note_size); if (note.n_name == "FreeBSD") { + m_os = llvm::Triple::FreeBSD; switch (note.n_type) { case NT_FREEBSD_PRSTATUS: @@ -553,4 +599,3 @@ ProcessElfCore::GetAuxvData() lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len)); return buffer; } - |