Skip to content

Commit 11dda0b

Browse files
committed
Read and store gnu build id from loaded core file
1 parent 3ca428c commit 11dda0b

File tree

2 files changed

+94
-4
lines changed

2 files changed

+94
-4
lines changed

lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <memory>
1212
#include <mutex>
1313

14+
#include "Plugins/ObjectFile/ELF/ELFHeader.h"
1415
#include "lldb/Core/Module.h"
1516
#include "lldb/Core/ModuleSpec.h"
1617
#include "lldb/Core/PluginManager.h"
@@ -250,6 +251,9 @@ Status ProcessElfCore::DoLoadCore() {
250251
}
251252
}
252253

254+
// Try to find gnu build id before we load the executable.
255+
UpdateBuildIdForNTFileEntries();
256+
253257
// Core files are useless without the main executable. See if we can locate
254258
// the main executable using data we found in the core file notes.
255259
lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
@@ -258,6 +262,7 @@ Status ProcessElfCore::DoLoadCore() {
258262
if (!m_nt_file_entries.empty()) {
259263
ModuleSpec exe_module_spec;
260264
exe_module_spec.GetArchitecture() = arch;
265+
exe_module_spec.GetUUID() = m_nt_file_entries[0].uuid;
261266
exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path,
262267
FileSpec::Style::native);
263268
if (exe_module_spec.GetFileSpec()) {
@@ -271,6 +276,17 @@ Status ProcessElfCore::DoLoadCore() {
271276
return error;
272277
}
273278

279+
void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
280+
if (!m_nt_file_entries.empty()) {
281+
for (NT_FILE_Entry &entry : m_nt_file_entries) {
282+
std::optional<UUID> uuid =
283+
FindNoteInCoreMemory(entry.start, llvm::ELF::NT_GNU_BUILD_ID);
284+
if (uuid)
285+
entry.uuid = uuid.value();
286+
}
287+
}
288+
}
289+
274290
lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
275291
if (m_dyld_up.get() == nullptr)
276292
m_dyld_up.reset(DynamicLoader::FindPlugin(
@@ -570,11 +586,13 @@ static void ParseOpenBSDProcInfo(ThreadData &thread_data,
570586
}
571587

572588
llvm::Expected<std::vector<CoreNote>>
573-
ProcessElfCore::parseSegment(const DataExtractor &segment) {
589+
ProcessElfCore::parseSegment(const DataExtractor &segment,
590+
unsigned long segment_size) {
574591
lldb::offset_t offset = 0;
575592
std::vector<CoreNote> result;
576-
577-
while (offset < segment.GetByteSize()) {
593+
unsigned long note_size =
594+
segment_size == 0 ? segment.GetByteSize() : segment_size;
595+
while (offset < note_size) {
578596
ELFNote note = ELFNote();
579597
if (!note.Parse(segment, &offset))
580598
return llvm::make_error<llvm::StringError>(
@@ -983,6 +1001,66 @@ llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
9831001
}
9841002
}
9851003

1004+
bool ProcessElfCore::IsElf(lldb::addr_t address) {
1005+
uint8_t buf[4];
1006+
Status error;
1007+
size_t byte_read = ReadMemory(address, buf, 4, error);
1008+
if (byte_read != 4)
1009+
return false;
1010+
return elf::ELFHeader::MagicBytesMatch(buf);
1011+
}
1012+
1013+
std::optional<UUID> ProcessElfCore::FindNoteInCoreMemory(lldb::addr_t address,
1014+
uint32_t type) {
1015+
if (!IsElf(address))
1016+
return std::nullopt;
1017+
const uint32_t addr_size = GetAddressByteSize();
1018+
const size_t elf_header_size = addr_size == 4 ? sizeof(llvm::ELF::Elf32_Ehdr)
1019+
: sizeof(llvm::ELF::Elf64_Ehdr);
1020+
1021+
unsigned char buf[4096];
1022+
Status error;
1023+
size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
1024+
if (byte_read != elf_header_size)
1025+
return std::nullopt;
1026+
DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
1027+
lldb::offset_t offset = 0;
1028+
1029+
elf::ELFHeader elf_header;
1030+
elf_header.Parse(data, &offset);
1031+
1032+
const lldb::addr_t ph_addr = address + elf_header.e_phoff;
1033+
1034+
for (unsigned int i = 0; i < elf_header.e_phnum; ++i) {
1035+
byte_read = ReadMemory(ph_addr + i * elf_header.e_phentsize, buf,
1036+
elf_header.e_phentsize, error);
1037+
if (byte_read != elf_header.e_phentsize)
1038+
break;
1039+
offset = 0;
1040+
elf::ELFProgramHeader program_header;
1041+
program_header.Parse(data, &offset);
1042+
if (program_header.p_type != llvm::ELF::PT_NOTE)
1043+
continue;
1044+
1045+
byte_read =
1046+
ReadMemory(program_header.p_vaddr, buf, program_header.p_memsz, error);
1047+
if (byte_read != program_header.p_memsz)
1048+
continue;
1049+
1050+
auto notes_or_error = parseSegment(data, program_header.p_memsz);
1051+
if (!notes_or_error)
1052+
return std::nullopt;
1053+
for (const CoreNote &note : *notes_or_error) {
1054+
if (note.info.n_namesz == 4 && note.info.n_type == type) {
1055+
if ("GNU" == note.info.n_name)
1056+
return UUID(llvm::ArrayRef<uint8_t>(
1057+
note.data.GetDataStart(), note.info.n_descsz /*byte size*/));
1058+
}
1059+
}
1060+
}
1061+
return std::nullopt;
1062+
}
1063+
9861064
uint32_t ProcessElfCore::GetNumThreadContexts() {
9871065
if (!m_thread_data_valid)
9881066
DoLoadCore();

lldb/source/Plugins/Process/elf-core/ProcessElfCore.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class ProcessElfCore : public lldb_private::PostMortemProcess {
117117
lldb::addr_t end;
118118
lldb::addr_t file_ofs;
119119
std::string path;
120+
lldb_private::UUID uuid; //.note.gnu.build-id
120121
};
121122

122123
// For ProcessElfCore only
@@ -158,6 +159,16 @@ class ProcessElfCore : public lldb_private::PostMortemProcess {
158159
// Returns number of thread contexts stored in the core file
159160
uint32_t GetNumThreadContexts();
160161

162+
// Populate gnu uuid for each NT_FILE entry
163+
void UpdateBuildIdForNTFileEntries();
164+
165+
// Returns the value of certain type of note of a given start address
166+
std::optional<lldb_private::UUID> FindNoteInCoreMemory(lldb::addr_t address,
167+
uint32_t type);
168+
169+
// Returns true if the given address is a start of ELF file
170+
bool IsElf(lldb::addr_t address);
171+
161172
// Parse a contiguous address range of the process from LOAD segment
162173
lldb::addr_t
163174
AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader &header);
@@ -167,7 +178,8 @@ class ProcessElfCore : public lldb_private::PostMortemProcess {
167178
AddAddressRangeFromMemoryTagSegment(const elf::ELFProgramHeader &header);
168179

169180
llvm::Expected<std::vector<lldb_private::CoreNote>>
170-
parseSegment(const lldb_private::DataExtractor &segment);
181+
parseSegment(const lldb_private::DataExtractor &segment,
182+
unsigned long segment_size = 0);
171183
llvm::Error parseFreeBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
172184
llvm::Error parseNetBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
173185
llvm::Error parseOpenBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);

0 commit comments

Comments
 (0)