Skip to content

Commit ccde823

Browse files
authored
Read and store gnu build id from loaded core file (#92492)
As we have debuginfod as symbol locator available in lldb now, we want to make full use of it. In case of post mortem debugging, we don't always have the main executable available. However, the .note.gnu.build-id of the main executable(some other modules too), should be available in the core file, as those binaries are loaded in memory and dumped in the core file. We try to iterate through the NT_FILE entries, read and store the gnu build id if possible. This will be very useful as this id is the unique key which is needed for querying the debuginfod server. Test: Build and run lldb. Breakpoint set to https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp#L147 Verified after this commit, module_uuid is the correct gnu build id of the main executable which caused the crash(first in the NT_FILE entry) Previous PR: #92078 was mistakenly merged. This PR is re-opening the commit.
1 parent 4658803 commit ccde823

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

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

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ Status ProcessElfCore::DoLoadCore() {
250250
}
251251
}
252252

253+
// Try to find gnu build id before we load the executable.
254+
UpdateBuildIdForNTFileEntries();
255+
253256
// Core files are useless without the main executable. See if we can locate
254257
// the main executable using data we found in the core file notes.
255258
lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
@@ -258,6 +261,7 @@ Status ProcessElfCore::DoLoadCore() {
258261
if (!m_nt_file_entries.empty()) {
259262
ModuleSpec exe_module_spec;
260263
exe_module_spec.GetArchitecture() = arch;
264+
exe_module_spec.GetUUID() = m_nt_file_entries[0].uuid;
261265
exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path,
262266
FileSpec::Style::native);
263267
if (exe_module_spec.GetFileSpec()) {
@@ -271,6 +275,12 @@ Status ProcessElfCore::DoLoadCore() {
271275
return error;
272276
}
273277

278+
void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
279+
for (NT_FILE_Entry &entry : m_nt_file_entries) {
280+
entry.uuid = FindBuidIdInCoreMemory(entry.start);
281+
}
282+
}
283+
274284
lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
275285
if (m_dyld_up.get() == nullptr)
276286
m_dyld_up.reset(DynamicLoader::FindPlugin(
@@ -983,6 +993,67 @@ llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
983993
}
984994
}
985995

996+
UUID ProcessElfCore::FindBuidIdInCoreMemory(lldb::addr_t address) {
997+
UUID invalid_uuid;
998+
const uint32_t addr_size = GetAddressByteSize();
999+
const size_t elf_header_size = addr_size == 4 ? sizeof(llvm::ELF::Elf32_Ehdr)
1000+
: sizeof(llvm::ELF::Elf64_Ehdr);
1001+
1002+
std::vector<uint8_t> elf_header_bytes;
1003+
elf_header_bytes.resize(elf_header_size);
1004+
Status error;
1005+
size_t byte_read =
1006+
ReadMemory(address, elf_header_bytes.data(), elf_header_size, error);
1007+
if (byte_read != elf_header_size ||
1008+
!elf::ELFHeader::MagicBytesMatch(elf_header_bytes.data()))
1009+
return invalid_uuid;
1010+
DataExtractor elf_header_data(elf_header_bytes.data(), elf_header_size,
1011+
GetByteOrder(), addr_size);
1012+
lldb::offset_t offset = 0;
1013+
1014+
elf::ELFHeader elf_header;
1015+
elf_header.Parse(elf_header_data, &offset);
1016+
1017+
const lldb::addr_t ph_addr = address + elf_header.e_phoff;
1018+
1019+
std::vector<uint8_t> ph_bytes;
1020+
ph_bytes.resize(elf_header.e_phentsize);
1021+
for (unsigned int i = 0; i < elf_header.e_phnum; ++i) {
1022+
byte_read = ReadMemory(ph_addr + i * elf_header.e_phentsize,
1023+
ph_bytes.data(), elf_header.e_phentsize, error);
1024+
if (byte_read != elf_header.e_phentsize)
1025+
break;
1026+
DataExtractor program_header_data(ph_bytes.data(), elf_header.e_phentsize,
1027+
GetByteOrder(), addr_size);
1028+
offset = 0;
1029+
elf::ELFProgramHeader program_header;
1030+
program_header.Parse(program_header_data, &offset);
1031+
if (program_header.p_type != llvm::ELF::PT_NOTE)
1032+
continue;
1033+
1034+
std::vector<uint8_t> note_bytes;
1035+
note_bytes.resize(program_header.p_memsz);
1036+
1037+
byte_read = ReadMemory(program_header.p_vaddr, note_bytes.data(),
1038+
program_header.p_memsz, error);
1039+
if (byte_read != program_header.p_memsz)
1040+
continue;
1041+
DataExtractor segment_data(note_bytes.data(), note_bytes.size(),
1042+
GetByteOrder(), addr_size);
1043+
auto notes_or_error = parseSegment(segment_data);
1044+
if (!notes_or_error)
1045+
return invalid_uuid;
1046+
for (const CoreNote &note : *notes_or_error) {
1047+
if (note.info.n_namesz == 4 &&
1048+
note.info.n_type == llvm::ELF::NT_GNU_BUILD_ID &&
1049+
"GNU" == note.info.n_name &&
1050+
note.data.ValidOffsetForDataOfSize(0, note.info.n_descsz))
1051+
return UUID(note.data.GetData().take_front(note.info.n_descsz));
1052+
}
1053+
}
1054+
return invalid_uuid;
1055+
}
1056+
9861057
uint32_t ProcessElfCore::GetNumThreadContexts() {
9871058
if (!m_thread_data_valid)
9881059
DoLoadCore();

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ class ProcessElfCore : public lldb_private::PostMortemProcess {
117117
lldb::addr_t end;
118118
lldb::addr_t file_ofs;
119119
std::string path;
120+
// Add a UUID member for convenient access. The UUID value is not in the
121+
// NT_FILE entries, we will find it in core memory and store it here for
122+
// easy access.
123+
lldb_private::UUID uuid;
120124
};
121125

122126
// For ProcessElfCore only
@@ -158,6 +162,12 @@ class ProcessElfCore : public lldb_private::PostMortemProcess {
158162
// Returns number of thread contexts stored in the core file
159163
uint32_t GetNumThreadContexts();
160164

165+
// Populate gnu uuid for each NT_FILE entry
166+
void UpdateBuildIdForNTFileEntries();
167+
168+
// Returns the value of certain type of note of a given start address
169+
lldb_private::UUID FindBuidIdInCoreMemory(lldb::addr_t address);
170+
161171
// Parse a contiguous address range of the process from LOAD segment
162172
lldb::addr_t
163173
AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader &header);

0 commit comments

Comments
 (0)