[Lldb-commits] [lldb] [LLDB] Impove ObjectFileELF's .dynamic parsing and usage. (PR #101237)

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed Jul 31 05:04:31 PDT 2024


================
@@ -3704,3 +3790,83 @@ ObjectFileELF::MapFileDataWritable(const FileSpec &file, uint64_t Size,
   return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size,
                                                          Offset);
 }
+
+std::optional<DataExtractor> ObjectFileELF::GetDynstrData() {
+
+  SectionList *section_list = GetSectionList();
+  if (section_list) {
+    // Find the SHT_DYNAMIC section.
+    Section *dynamic =
+        section_list->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true)
+            .get();
+    if (dynamic) {
+      assert(dynamic->GetObjectFile() == this);
+      const ELFSectionHeaderInfo *header =
+          GetSectionHeaderByIndex(dynamic->GetID());
+      if (header) {
+        // sh_link: section header index of string table used by entries in
+        // the section.
+        Section *dynstr = section_list->FindSectionByID(header->sh_link).get();
+        DataExtractor data;
+        if (dynstr && ReadSectionData(dynstr, data))
+          return data;
+      }
+    }
+  }
+
+  // Every ELF file which represents an executable or shared library has
+  // mandatory .dynamic entries. Two of these values are DT_STRTAB and DT_STRSZ
+  // and represent the dynamic symbol tables's string table. These are needed
+  // by the dynamic loader and we can read them from a process' address space.
+  //
+  // When loading and ELF file from memory, only the program headers end up
+  // being mapped into memory, and we can find these values in the PT_DYNAMIC
+  // segment.
+  if (!IsInMemory())
+    return std::nullopt;
+  ProcessSP process_sp(m_process_wp.lock());
+  if (!process_sp)
+    return std::nullopt;
+
+  const ELFDynamic *strtab = FindDynamicSymbol(DT_STRTAB);
+  const ELFDynamic *strsz = FindDynamicSymbol(DT_STRSZ);
+  if (strtab == nullptr || strsz == nullptr)
+    return std::nullopt;
+
+  DataBufferSP data_sp = ReadMemory(process_sp, strtab->d_ptr, strsz->d_val);
----------------
labath wrote:

This is the tricky part. This line assumes that the DT_STRTAB entry has been relocated by the dynamic linker. This will be true for an in-memory elf file (*), but not for an on-disk file, where it should be an unrelocated file (virtual) address (@MaskRay, is that guaranteed?) If we add a fallback for treating this as a file address for on-disk files, then we should be able to run this code on files as well -- which will make testing a lot easier.

(*) it's only true for if the dynamic linker has had a chance to do it's job (i.e., we don't run this too early). This should be mostly fine because the way we normally learn about shared libraries is through linker notifications, but I could imagine some sort of a file-addr fallback for in-memory files as well.

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


More information about the lldb-commits mailing list