486 changes: 276 additions & 210 deletions lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,7 @@ bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp,
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
Expand Down Expand Up @@ -194,9 +191,8 @@ Status ProcessElfCore::DoLoadCore() {

// 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) {
Expand Down Expand Up @@ -405,7 +401,6 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,

void ProcessElfCore::Clear() {
m_thread_list.Clear();
m_os = llvm::Triple::UnknownOS;

SetUnixSignals(std::make_shared<UnixSignals>());
}
Expand All @@ -429,8 +424,9 @@ lldb::addr_t ProcessElfCore::GetImageInfoAddress() {
}

// 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 ||
Expand Down Expand Up @@ -459,12 +455,8 @@ static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
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);
Expand All @@ -475,7 +467,8 @@ static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) {
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);
Expand All @@ -486,217 +479,290 @@ static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) {
thread_data.signo = data.GetU32(&offset);
}

/// 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.
/// 2) NOTE Entry contains a standard header followed by variable size data.
/// (see ELFNote structure)
/// 3) A Thread Context in a core file usually described by 3 NOTE entries.
/// a) NT_PRSTATUS - Register context
/// b) NT_PRPSINFO - Process info(pid..)
/// c) NT_FPREGSET - Floating point registers
/// 4) The NOTE entries can be in any order
/// 5) If a core file contains multiple thread contexts then there is two data
/// forms
/// 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 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(
const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) {
assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);

llvm::Expected<std::vector<CoreNote>>
ProcessElfCore::parseSegment(const DataExtractor &segment) {
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;
std::vector<CoreNote> result;

// Loop through the NOTE entires in the segment
while (offset < segment_header->p_filesz) {
while (offset < segment.GetByteSize()) {
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);
if (!note.Parse(segment, &offset))
return llvm::make_error<llvm::StringError>(
"Unable to parse note segment", llvm::inconvertibleErrorCode());

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 std::move(result);
}

llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
bool have_prstatus = false;
bool have_prpsinfo = false;
ThreadData thread_data;
for (const auto &note : 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();
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;
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 &note : 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;
default:
case NETBSD::NT_AMD64_FPREGS:
thread_data.fpregset = note.data;
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;
}
}
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 &note : 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();
}

/// A description of a linux process usually contains the following NOTE
/// entries:
/// - NT_PRPSINFO - General process information like pid, uid, name, ...
/// - NT_SIGINFO - Information about the signal that terminated the process
/// - NT_AUXV - Process auxiliary vector
/// - NT_FILE - Files mapped into memory
///
/// Additionally, for each thread in the process the core file will contain at
/// least the NT_PRSTATUS note, containing the thread id and general purpose
/// registers. It may include additional notes for other register sets (floating
/// point and vector registers, ...). The tricky part here is that some of these
/// notes have "CORE" in their owner fields, while other set it to "LINUX".
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 &note : 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);
}
} 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;
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);
}
} 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;
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;
}

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);
}
if (have_prstatus)
m_thread_data.push_back(thread_data);
return llvm::Error::success();
}

return error;
/// Parse Thread context from PT_NOTE segment and store it in the thread list
/// A note segment consists of one or more NOTE entries, but their types and
/// meaning differ depending on the OS.
llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) {
assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);

auto notes_or_error = parseSegment(segment_data);
if(!notes_or_error)
return notes_or_error.takeError();
switch (GetArchitecture().GetTriple().getOS()) {
case llvm::Triple::FreeBSD:
return parseFreeBSDNotes(*notes_or_error);
case llvm::Triple::Linux:
return parseLinuxNotes(*notes_or_error);
case llvm::Triple::NetBSD:
return parseNetBSDNotes(*notes_or_error);
case llvm::Triple::OpenBSD:
return parseOpenBSDNotes(*notes_or_error);
default:
return llvm::make_error<llvm::StringError>(
"Don't know how to parse core file. Unsupported OS.",
llvm::inconvertibleErrorCode());
}
}

uint32_t ProcessElfCore::GetNumThreadContexts() {
Expand Down
14 changes: 10 additions & 4 deletions lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "lldb/Utility/Status.h"

#include "Plugins/ObjectFile/ELF/ELFHeader.h"
#include "Plugins/Process/elf-core/elf-core-enums.h"

struct ThreadData;

Expand Down Expand Up @@ -149,10 +150,8 @@ class ProcessElfCore : public lldb_private::Process {
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;
Expand All @@ -170,7 +169,7 @@ class ProcessElfCore : public lldb_private::Process {
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);

Expand All @@ -180,6 +179,13 @@ class ProcessElfCore : public lldb_private::Process {
// Parse a contiguous address range of the process from LOAD segment
lldb::addr_t
AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header);

llvm::Expected<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_
12 changes: 7 additions & 5 deletions lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ ELFLinuxPrStatus::ELFLinuxPrStatus() {
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()) {
Expand All @@ -285,7 +285,8 @@ size_t ELFLinuxPrStatus::GetSize(lldb_private::ArchSpec &arch) {
}
}

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(
Expand Down Expand Up @@ -334,7 +335,7 @@ ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
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();
Expand All @@ -355,7 +356,8 @@ size_t ELFLinuxPrPsInfo::GetSize(lldb_private::ArchSpec &arch) {
}
}

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()) {
Expand Down Expand Up @@ -424,7 +426,7 @@ size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
}
}

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(
Expand Down
14 changes: 7 additions & 7 deletions lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ struct ELFLinuxPrStatus {

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,
Expand All @@ -79,7 +79,7 @@ struct ELFLinuxSigInfo {

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
Expand Down Expand Up @@ -114,15 +114,15 @@ struct ELFLinuxPrPsInfo {

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,
Expand Down
11 changes: 11 additions & 0 deletions lldb/source/Plugins/Process/elf-core/elf-core-enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -52,4 +56,11 @@ enum {
};
}

struct CoreNote {
ELFNote info;
DataExtractor data;
};

} // namespace lldb_private

#endif // #ifndef LLDB_ELF_CORE_ENUMS_H