labath created this revision.
We've had a single function responsible for splitting a core segment
into notes, and parsing the notes themselves, bearing in mind variations
between 4 supported OS types. This commit splits that code into 5
pieces:
- (os-independent) code for splitting a segment into individual notes
- per-os function for parsing the notes into thread information
https://reviews.llvm.org/D40311
Files:
source/Plugins/Process/elf-core/ProcessElfCore.cpp
source/Plugins/Process/elf-core/ProcessElfCore.h
source/Plugins/Process/elf-core/ThreadElfCore.cpp
source/Plugins/Process/elf-core/ThreadElfCore.h
source/Plugins/Process/elf-core/elf-core-enums.h
Index: source/Plugins/Process/elf-core/elf-core-enums.h
===================================================================
--- source/Plugins/Process/elf-core/elf-core-enums.h
+++ source/Plugins/Process/elf-core/elf-core-enums.h
@@ -10,6 +10,10 @@
#ifndef LLDB_ELF_CORE_ENUMS_H
#define LLDB_ELF_CORE_ENUMS_H
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+#include "lldb/Utility/DataExtractor.h"
+
+namespace lldb_private {
/// Core files PT_NOTE segment descriptor types
namespace FREEBSD {
@@ -52,4 +56,11 @@
};
}
+struct CoreNote {
+ ELFNote info;
+ DataExtractor data;
+};
+
+} // namespace lldb_private
+
#endif // #ifndef LLDB_ELF_CORE_ENUMS_H
Index: source/Plugins/Process/elf-core/ThreadElfCore.h
===================================================================
--- source/Plugins/Process/elf-core/ThreadElfCore.h
+++ source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -58,15 +58,15 @@
ELFLinuxPrStatus();
- lldb_private::Status Parse(lldb_private::DataExtractor &data,
- lldb_private::ArchSpec &arch);
+ lldb_private::Status Parse(const lldb_private::DataExtractor &data,
+ const lldb_private::ArchSpec &arch);
// Return the bytesize of the structure
// 64 bit - just sizeof
// 32 bit - hardcoded because we are reusing the struct, but some of the
// members are smaller -
// so the layout is not the same
- static size_t GetSize(lldb_private::ArchSpec &arch);
+ static size_t GetSize(const lldb_private::ArchSpec &arch);
};
static_assert(sizeof(ELFLinuxPrStatus) == 112,
@@ -79,7 +79,7 @@
ELFLinuxSigInfo();
- lldb_private::Status Parse(lldb_private::DataExtractor &data,
+ lldb_private::Status Parse(const lldb_private::DataExtractor &data,
const lldb_private::ArchSpec &arch);
// Return the bytesize of the structure
@@ -114,15 +114,15 @@
ELFLinuxPrPsInfo();
- lldb_private::Status Parse(lldb_private::DataExtractor &data,
- lldb_private::ArchSpec &arch);
+ lldb_private::Status Parse(const lldb_private::DataExtractor &data,
+ const lldb_private::ArchSpec &arch);
// Return the bytesize of the structure
// 64 bit - just sizeof
// 32 bit - hardcoded because we are reusing the struct, but some of the
// members are smaller -
// so the layout is not the same
- static size_t GetSize(lldb_private::ArchSpec &arch);
+ static size_t GetSize(const lldb_private::ArchSpec &arch);
};
static_assert(sizeof(ELFLinuxPrPsInfo) == 136,
Index: source/Plugins/Process/elf-core/ThreadElfCore.cpp
===================================================================
--- source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -259,7 +259,7 @@
memset(this, 0, sizeof(ELFLinuxPrStatus));
}
-size_t ELFLinuxPrStatus::GetSize(lldb_private::ArchSpec &arch) {
+size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) {
constexpr size_t mips_linux_pr_status_size_o32 = 96;
constexpr size_t mips_linux_pr_status_size_n32 = 72;
if (arch.IsMIPS()) {
@@ -285,7 +285,8 @@
}
}
-Status ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) {
+Status ELFLinuxPrStatus::Parse(const DataExtractor &data,
+ const ArchSpec &arch) {
Status error;
if (GetSize(arch) > data.GetByteSize()) {
error.SetErrorStringWithFormat(
@@ -334,7 +335,7 @@
memset(this, 0, sizeof(ELFLinuxPrPsInfo));
}
-size_t ELFLinuxPrPsInfo::GetSize(lldb_private::ArchSpec &arch) {
+size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128;
if (arch.IsMIPS()) {
uint8_t address_byte_size = arch.GetAddressByteSize();
@@ -355,7 +356,8 @@
}
}
-Status ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) {
+Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
+ const ArchSpec &arch) {
Status error;
ByteOrder byteorder = data.GetByteOrder();
if (GetSize(arch) > data.GetByteSize()) {
@@ -424,7 +426,7 @@
}
}
-Status ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) {
+Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
Status error;
if (GetSize(arch) > data.GetByteSize()) {
error.SetErrorStringWithFormat(
Index: source/Plugins/Process/elf-core/ProcessElfCore.h
===================================================================
--- source/Plugins/Process/elf-core/ProcessElfCore.h
+++ source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -29,6 +29,8 @@
#include "lldb/Utility/Status.h"
#include "Plugins/ObjectFile/ELF/ELFHeader.h"
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+#include "Plugins/Process/elf-core/elf-core-enums.h"
struct ThreadData;
@@ -149,10 +151,8 @@
std::string m_dyld_plugin_name;
DISALLOW_COPY_AND_ASSIGN(ProcessElfCore);
- llvm::Triple::OSType m_os;
-
// True if m_thread_contexts contains valid entries
- bool m_thread_data_valid;
+ bool m_thread_data_valid = false;
// Contain thread data read from NOTE segments
std::vector<ThreadData> m_thread_data;
@@ -170,7 +170,7 @@
std::vector<NT_FILE_Entry> m_nt_file_entries;
// Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment
- lldb_private::Status ParseThreadContextsFromNoteSegment(
+ llvm::Error ParseThreadContextsFromNoteSegment(
const elf::ELFProgramHeader *segment_header,
lldb_private::DataExtractor segment_data);
@@ -180,6 +180,13 @@
// Parse a contiguous address range of the process from LOAD segment
lldb::addr_t
AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header);
+
+ std::vector<lldb_private::CoreNote>
+ parseSegment(const lldb_private::DataExtractor &segment);
+ llvm::Error parseFreeBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
+ llvm::Error parseNetBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
+ llvm::Error parseOpenBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
+ llvm::Error parseLinuxNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
};
#endif // liblldb_ProcessElfCore_h_
Index: source/Plugins/Process/elf-core/ProcessElfCore.cpp
===================================================================
--- source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -31,7 +31,6 @@
#include "llvm/Support/Threading.h"
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
-#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
// Project includes
#include "ProcessElfCore.h"
@@ -102,10 +101,7 @@
ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp,
lldb::ListenerSP listener_sp,
const FileSpec &core_file)
- : Process(target_sp, listener_sp), 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() {}
+ : Process(target_sp, listener_sp), m_core_file(core_file) {}
//----------------------------------------------------------------------
// Destructor
@@ -194,9 +190,8 @@
// Parse thread contexts and auxv structure
if (header->p_type == llvm::ELF::PT_NOTE) {
- error = ParseThreadContextsFromNoteSegment(header, data);
- if (error.Fail())
- return error;
+ if (llvm::Error error = ParseThreadContextsFromNoteSegment(header, data))
+ return Status(std::move(error));
}
// PT_LOAD segments contains address map
if (header->p_type == llvm::ELF::PT_LOAD) {
@@ -405,7 +400,6 @@
void ProcessElfCore::Clear() {
m_thread_list.Clear();
- m_os = llvm::Triple::UnknownOS;
SetUnixSignals(std::make_shared<UnixSignals>());
}
@@ -429,8 +423,9 @@
}
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
-static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
- ArchSpec &arch) {
+static void ParseFreeBSDPrStatus(ThreadData &thread_data,
+ const DataExtractor &data,
+ const ArchSpec &arch) {
lldb::offset_t offset = 0;
bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 ||
arch.GetMachine() == llvm::Triple::mips64 ||
@@ -459,12 +454,8 @@
thread_data.gpregset = DataExtractor(data, offset, len);
}
-static void ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) {
- lldb::offset_t offset = 0;
- thread_data.name = data.GetCStr(&offset, 20);
-}
-
-static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) {
+static void ParseNetBSDProcInfo(ThreadData &thread_data,
+ const DataExtractor &data) {
lldb::offset_t offset = 0;
int version = data.GetU32(&offset);
@@ -475,7 +466,8 @@
thread_data.signo = data.GetU32(&offset);
}
-static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) {
+static void ParseOpenBSDProcInfo(ThreadData &thread_data,
+ const DataExtractor &data) {
lldb::offset_t offset = 0;
int version = data.GetU32(&offset);
@@ -486,6 +478,252 @@
thread_data.signo = data.GetU32(&offset);
}
+std::vector<CoreNote>
+ProcessElfCore::parseSegment(const DataExtractor &segment) {
+ lldb::offset_t offset = 0;
+ std::vector<CoreNote> result;
+
+ while (offset < segment.GetByteSize()) {
+ ELFNote note = ELFNote();
+ note.Parse(segment, &offset);
+
+ size_t note_start = offset;
+ size_t note_size = llvm::alignTo(note.n_descsz, 4);
+ DataExtractor note_data(segment, note_start, note_size);
+
+ result.push_back({note, note_data});
+ offset += note_size;
+ }
+
+ return result;
+}
+
+llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
+ bool have_prstatus = false;
+ bool have_prpsinfo = false;
+ ThreadData thread_data;
+ for (const auto ¬e : notes) {
+ if (note.info.n_name != "FreeBSD")
+ continue;
+
+ if ((note.info.n_type == FREEBSD::NT_PRSTATUS && have_prstatus) ||
+ (note.info.n_type == FREEBSD::NT_PRPSINFO && have_prpsinfo)) {
+ assert(thread_data.gpregset.GetByteSize() > 0);
+ // Add the new thread to thread list
+ m_thread_data.push_back(thread_data);
+ thread_data = ThreadData();
+ have_prstatus = false;
+ have_prpsinfo = false;
+ }
+
+ switch (note.info.n_type) {
+ case FREEBSD::NT_PRSTATUS:
+ have_prstatus = true;
+ ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture());
+ break;
+ case FREEBSD::NT_FPREGSET:
+ thread_data.fpregset = note.data;
+ break;
+ case FREEBSD::NT_PPC_VMX:
+ thread_data.vregset = note.data;
+ break;
+ case FREEBSD::NT_PRPSINFO:
+ have_prpsinfo = true;
+ break;
+ case FREEBSD::NT_THRMISC: {
+ lldb::offset_t offset = 0;
+ thread_data.name = note.data.GetCStr(&offset, 20);
+ break;
+ }
+ case FREEBSD::NT_PROCSTAT_AUXV:
+ // FIXME: FreeBSD sticks an int at the beginning of the note
+ m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4);
+ break;
+ default:
+ break;
+ }
+ }
+ if (!have_prstatus) {
+ return llvm::make_error<llvm::StringError>(
+ "Could not find NT_PRSTATUS note in core file.",
+ llvm::inconvertibleErrorCode());
+ }
+ m_thread_data.push_back(thread_data);
+ return llvm::Error::success();
+}
+
+llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {
+ ThreadData thread_data;
+ for (const auto ¬e : notes) {
+ // NetBSD per-thread information is stored in notes named
+ // "NetBSD-CORE@nnn" so match on the initial part of the string.
+ if (!llvm::StringRef(note.info.n_name).startswith("NetBSD-CORE"))
+ continue;
+
+ if (note.info.n_type == NETBSD::NT_PROCINFO) {
+ ParseNetBSDProcInfo(thread_data, note.data);
+ continue;
+ }
+ if (note.info.n_type == NETBSD::NT_AUXV) {
+ m_auxv = note.data;
+ continue;
+ }
+
+ if (GetArchitecture().GetMachine() == llvm::Triple::x86_64) {
+ switch (note.info.n_type) {
+ case NETBSD::NT_AMD64_REGS:
+ thread_data.gpregset = note.data;
+ break;
+ case NETBSD::NT_AMD64_FPREGS:
+ thread_data.fpregset = note.data;
+ break;
+ }
+ }
+ }
+ if (thread_data.gpregset.GetByteSize() == 0) {
+ return llvm::make_error<llvm::StringError>(
+ "Could not find general purpose registers note in core file.",
+ llvm::inconvertibleErrorCode());
+ }
+ m_thread_data.push_back(thread_data);
+ return llvm::Error::success();
+}
+
+llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) {
+ ThreadData thread_data;
+ for (const auto ¬e : notes) {
+ // OpenBSD per-thread information is stored in notes named
+ // "OpenBSD@nnn" so match on the initial part of the string.
+ if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD"))
+ continue;
+
+ switch (note.info.n_type) {
+ case OPENBSD::NT_PROCINFO:
+ ParseOpenBSDProcInfo(thread_data, note.data);
+ break;
+ case OPENBSD::NT_AUXV:
+ m_auxv = note.data;
+ break;
+ case OPENBSD::NT_REGS:
+ thread_data.gpregset = note.data;
+ break;
+ case OPENBSD::NT_FPREGS:
+ thread_data.fpregset = note.data;
+ break;
+ }
+ }
+ if (thread_data.gpregset.GetByteSize() == 0) {
+ return llvm::make_error<llvm::StringError>(
+ "Could not find general purpose registers note in core file.",
+ llvm::inconvertibleErrorCode());
+ }
+ m_thread_data.push_back(thread_data);
+ return llvm::Error::success();
+}
+
+llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
+ const ArchSpec &arch = GetArchitecture();
+ bool have_prstatus = false;
+ bool have_prpsinfo = false;
+ ThreadData thread_data;
+ for (const auto ¬e : notes) {
+ if (note.info.n_name != "CORE" && note.info.n_name != "LINUX")
+ continue;
+
+ if ((note.info.n_type == LINUX::NT_PRSTATUS && have_prstatus) ||
+ (note.info.n_type == LINUX::NT_PRPSINFO && have_prpsinfo)) {
+ assert(thread_data.gpregset.GetByteSize() > 0);
+ // Add the new thread to thread list
+ m_thread_data.push_back(thread_data);
+ thread_data = ThreadData();
+ have_prstatus = false;
+ have_prpsinfo = false;
+ }
+
+ switch (note.info.n_type) {
+ case LINUX::NT_PRSTATUS: {
+ have_prstatus = true;
+ ELFLinuxPrStatus prstatus;
+ Status status = prstatus.Parse(note.data, arch);
+ if (status.Fail())
+ return status.ToError();
+ thread_data.prstatus_sig = prstatus.pr_cursig;
+ thread_data.tid = prstatus.pr_pid;
+ uint32_t header_size = ELFLinuxPrStatus::GetSize(arch);
+ size_t len = note.data.GetByteSize() - header_size;
+ thread_data.gpregset = DataExtractor(note.data, header_size, len);
+ if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic)
+ thread_data.regsets.try_emplace(note.info.n_type, thread_data.gpregset);
+ break;
+ }
+ case LINUX::NT_PRPSINFO: {
+ have_prpsinfo = true;
+ ELFLinuxPrPsInfo prpsinfo;
+ Status status = prpsinfo.Parse(note.data, arch);
+ if (status.Fail())
+ return status.ToError();
+ thread_data.name = prpsinfo.pr_fname;
+ SetID(prpsinfo.pr_pid);
+ break;
+ }
+ case LINUX::NT_SIGINFO: {
+ ELFLinuxSigInfo siginfo;
+ Status status = siginfo.Parse(note.data, arch);
+ if (status.Fail())
+ return status.ToError();
+ thread_data.signo = siginfo.si_signo;
+ break;
+ }
+ case LINUX::NT_FILE: {
+ m_nt_file_entries.clear();
+ lldb::offset_t offset = 0;
+ const uint64_t count = note.data.GetAddress(&offset);
+ note.data.GetAddress(&offset); // Skip page size
+ for (uint64_t i = 0; i < count; ++i) {
+ NT_FILE_Entry entry;
+ entry.start = note.data.GetAddress(&offset);
+ entry.end = note.data.GetAddress(&offset);
+ entry.file_ofs = note.data.GetAddress(&offset);
+ m_nt_file_entries.push_back(entry);
+ }
+ for (uint64_t i = 0; i < count; ++i) {
+ const char *path = note.data.GetCStr(&offset);
+ if (path && path[0])
+ m_nt_file_entries[i].path.SetCString(path);
+ }
+ break;
+ }
+ case LINUX::NT_AUXV:
+ m_auxv = note.data;
+ break;
+ case LINUX::NT_FPREGSET:
+ // 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 || arch.IsMIPS())
+ thread_data.fpregset = note.data;
+ else if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic) {
+ thread_data.regsets.insert(std::make_pair(note.info.n_type, note.data));
+ }
+ break;
+ case LINUX::NT_PPC_VMX:
+ case LINUX::NT_PPC_VSX:
+ if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic)
+ thread_data.regsets.insert(std::make_pair(note.info.n_type, note.data));
+ break;
+ case LINUX::NT_PRXFPREG:
+ thread_data.fpregset = note.data;
+ break;
+ }
+ }
+ // Add last entry in the note section
+ if (have_prstatus)
+ m_thread_data.push_back(thread_data);
+ return llvm::Error::success();
+}
+
/// 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.
@@ -507,196 +745,25 @@
/// 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).
-Status ProcessElfCore::ParseThreadContextsFromNoteSegment(
+llvm::Error 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;
- std::unique_ptr<ThreadData> thread_data(new ThreadData);
- bool have_prstatus = false;
- bool have_prpsinfo = false;
-
- ArchSpec arch = GetArchitecture();
- ELFLinuxPrPsInfo prpsinfo;
- ELFLinuxPrStatus prstatus;
- ELFLinuxSigInfo siginfo;
- size_t header_size;
- size_t len;
- Status error;
-
- // Loop through the NOTE entires in the segment
- while (offset < segment_header->p_filesz) {
- ELFNote note = ELFNote();
- note.Parse(segment_data, &offset);
-
- // Beginning of new thread
- if (((note.n_type == LINUX::NT_PRSTATUS ||
- note.n_type == FREEBSD::NT_PRSTATUS) &&
- have_prstatus) ||
- ((note.n_type == LINUX::NT_PRPSINFO ||
- note.n_type == FREEBSD::NT_PRPSINFO) &&
- have_prpsinfo)) {
- assert(thread_data->gpregset.GetByteSize() > 0);
- // Add the new thread to thread list
- m_thread_data.push_back(*thread_data);
- *thread_data = ThreadData();
- have_prstatus = false;
- have_prpsinfo = false;
- }
-
- size_t note_start, note_size;
- note_start = offset;
- note_size = llvm::alignTo(note.n_descsz, 4);
-
- // Store the NOTE information in the current thread
- DataExtractor note_data(segment_data, note_start, note_size);
- note_data.SetAddressByteSize(
- m_core_module_sp->GetArchitecture().GetAddressByteSize());
- if (note.n_name == "FreeBSD") {
- m_os = llvm::Triple::FreeBSD;
- switch (note.n_type) {
- case FREEBSD::NT_PRSTATUS:
- have_prstatus = true;
- ParseFreeBSDPrStatus(*thread_data, note_data, arch);
- break;
- case FREEBSD::NT_FPREGSET:
- thread_data->fpregset = note_data;
- break;
- case FREEBSD::NT_PRPSINFO:
- have_prpsinfo = true;
- break;
- case FREEBSD::NT_THRMISC:
- ParseFreeBSDThrMisc(*thread_data, note_data);
- break;
- 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;
- case FREEBSD::NT_PPC_VMX:
- thread_data->vregset = note_data;
- break;
- default:
- break;
- }
- } else if (note.n_name.substr(0, 11) == "NetBSD-CORE") {
- // NetBSD per-thread information is stored in notes named
- // "NetBSD-CORE@nnn" so match on the initial part of the string.
- m_os = llvm::Triple::NetBSD;
- if (note.n_type == NETBSD::NT_PROCINFO) {
- ParseNetBSDProcInfo(*thread_data, note_data);
- } else if (note.n_type == NETBSD::NT_AUXV) {
- m_auxv = DataExtractor(note_data);
- } else if (arch.GetMachine() == llvm::Triple::x86_64 &&
- note.n_type == NETBSD::NT_AMD64_REGS) {
- thread_data->gpregset = note_data;
- } else if (arch.GetMachine() == llvm::Triple::x86_64 &&
- note.n_type == NETBSD::NT_AMD64_FPREGS) {
- thread_data->fpregset = note_data;
- }
- } else if (note.n_name.substr(0, 7) == "OpenBSD") {
- // OpenBSD per-thread information is stored in notes named
- // "OpenBSD@nnn" so match on the initial part of the string.
- m_os = llvm::Triple::OpenBSD;
- switch (note.n_type) {
- case OPENBSD::NT_PROCINFO:
- ParseOpenBSDProcInfo(*thread_data, note_data);
- break;
- case OPENBSD::NT_AUXV:
- m_auxv = DataExtractor(note_data);
- break;
- case OPENBSD::NT_REGS:
- thread_data->gpregset = note_data;
- break;
- case OPENBSD::NT_FPREGS:
- thread_data->fpregset = note_data;
- break;
- }
- } else if (note.n_name == "CORE") {
- switch (note.n_type) {
- case LINUX::NT_PRSTATUS:
- have_prstatus = true;
- error = prstatus.Parse(note_data, arch);
- if (error.Fail())
- return error;
- thread_data->prstatus_sig = prstatus.pr_cursig;
- thread_data->tid = prstatus.pr_pid;
- header_size = ELFLinuxPrStatus::GetSize(arch);
- len = note_data.GetByteSize() - header_size;
- thread_data->gpregset = DataExtractor(note_data, header_size, len);
-
- if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic)
- thread_data->regsets.insert(
- std::make_pair(note.n_type, thread_data->gpregset));
- break;
- case LINUX::NT_FPREGSET:
- // 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 || arch.IsMIPS())
- thread_data->fpregset = note_data;
- else if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic) {
- thread_data->regsets.insert(std::make_pair(note.n_type, note_data));
- }
- break;
- case LINUX::NT_PRPSINFO:
- have_prpsinfo = true;
- error = prpsinfo.Parse(note_data, arch);
- if (error.Fail())
- return error;
- thread_data->name = prpsinfo.pr_fname;
- SetID(prpsinfo.pr_pid);
- break;
- case LINUX::NT_AUXV:
- m_auxv = DataExtractor(note_data);
- break;
- case LINUX::NT_FILE: {
- m_nt_file_entries.clear();
- lldb::offset_t offset = 0;
- const uint64_t count = note_data.GetAddress(&offset);
- note_data.GetAddress(&offset); // Skip page size
- for (uint64_t i = 0; i < count; ++i) {
- NT_FILE_Entry entry;
- entry.start = note_data.GetAddress(&offset);
- entry.end = note_data.GetAddress(&offset);
- entry.file_ofs = note_data.GetAddress(&offset);
- m_nt_file_entries.push_back(entry);
- }
- for (uint64_t i = 0; i < count; ++i) {
- const char *path = note_data.GetCStr(&offset);
- if (path && path[0])
- m_nt_file_entries[i].path.SetCString(path);
- }
- } break;
- case LINUX::NT_SIGINFO: {
- error = siginfo.Parse(note_data, arch);
- if (error.Fail())
- return error;
- thread_data->signo = siginfo.si_signo;
- } break;
- default:
- break;
- }
- } else if (note.n_name == "LINUX") {
- switch (note.n_type) {
- case LINUX::NT_PRXFPREG:
- thread_data->fpregset = note_data;
- break;
- case LINUX::NT_PPC_VMX:
- case LINUX::NT_PPC_VSX:
- if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic)
- thread_data->regsets.insert(std::make_pair(note.n_type, note_data));
- break;
- }
- }
-
- offset += note_size;
- }
- // Add last entry in the note section
- if (thread_data && thread_data->gpregset.GetByteSize() > 0) {
- m_thread_data.push_back(*thread_data);
+ auto notes = parseSegment(segment_data);
+ switch (GetArchitecture().GetTriple().getOS()) {
+ case llvm::Triple::FreeBSD:
+ return parseFreeBSDNotes(notes);
+ case llvm::Triple::Linux:
+ return parseLinuxNotes(notes);
+ case llvm::Triple::NetBSD:
+ return parseNetBSDNotes(notes);
+ case llvm::Triple::OpenBSD:
+ return parseOpenBSDNotes(notes);
+ default:
+ return llvm::make_error<llvm::StringError>(
+ "Don't know how to parse core file. Unsupported OS.",
+ llvm::inconvertibleErrorCode());
}
-
- return error;
}
uint32_t ProcessElfCore::GetNumThreadContexts() {
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits