[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Fri May 24 00:14:52 PDT 2024


================
@@ -983,6 +994,67 @@ llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+UUID ProcessElfCore::FindBuidIdInCoreMemory(lldb::addr_t address) {
+  UUID invalid_uuid;
+  const uint32_t addr_size = GetAddressByteSize();
+  const size_t elf_header_size = addr_size == 4 ? sizeof(llvm::ELF::Elf32_Ehdr)
+                                                : sizeof(llvm::ELF::Elf64_Ehdr);
+
+  // 80 bytes buffer is larger enough for the ELF header or program headers
+  unsigned char buf[80];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  if (byte_read != elf_header_size || !elf::ELFHeader::MagicBytesMatch(buf))
+    return invalid_uuid;
+  assert(sizeof(buf) >= elf_header_size);
+  DataExtractor elf_header_data(buf, elf_header_size, GetByteOrder(),
+                                addr_size);
+  lldb::offset_t offset = 0;
+
+  elf::ELFHeader elf_header;
+  elf_header.Parse(elf_header_data, &offset);
+
+  const lldb::addr_t ph_addr = address + elf_header.e_phoff;
+
+  for (unsigned int i = 0; i < elf_header.e_phnum; ++i) {
+    byte_read = ReadMemory(ph_addr + i * elf_header.e_phentsize, buf,
+                           elf_header.e_phentsize, error);
+    if (byte_read != elf_header.e_phentsize)
+      break;
+    assert(sizeof(buf) >= elf_header.e_phentsize);
+    DataExtractor program_header_data(buf, elf_header.e_phentsize,
+                                      GetByteOrder(), addr_size);
+    offset = 0;
+    elf::ELFProgramHeader program_header;
+    program_header.Parse(program_header_data, &offset);
+    if (program_header.p_type != llvm::ELF::PT_NOTE)
+      continue;
+
+    std::vector<uint8_t> note_bytes;
+    note_bytes.resize(program_header.p_memsz);
+
+    byte_read = ReadMemory(program_header.p_vaddr, note_bytes.data(),
+                           program_header.p_memsz, error);
+    if (byte_read != program_header.p_memsz)
+      continue;
+    assert(sizeof(buf) >= program_header.p_memsz);
+    DataExtractor segment_data(note_bytes.data(), note_bytes.size(),
+                               GetByteOrder(), addr_size);
+    auto notes_or_error = parseSegment(segment_data);
+    if (!notes_or_error)
+      return invalid_uuid;
+    for (const CoreNote &note : *notes_or_error) {
+      if (note.info.n_namesz == 4 &&
+          note.info.n_type == llvm::ELF::NT_GNU_BUILD_ID) {
+        if ("GNU" == note.info.n_name)
+          return UUID(llvm::ArrayRef<uint8_t>(
+              note.data.GetDataStart(), note.info.n_descsz /*byte size*/));
----------------
labath wrote:

In case of a corrupted core file, `note.data` can contain less than `n_descsz` bytes, and this will create a invalid ArrayRef (and possibly crash lldb). Writing this like `return UUID(note.data.GetData())` will ensure that does not happen, although it could return a truncated UUID in that case. If you want to check that case explicitly, then I'd recommend something like:
```
if(note.data.ValidOffsetForDataOfSize(0, note.info.n_descsz))
  return UUID(note.data.GetData().take_front(note.info.n_descsz);
```

https://github.com/llvm/llvm-project/pull/92492


More information about the lldb-commits mailing list