aadsm created this revision.
aadsm added reviewers: clayborg, xiaobai.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
aadsm added a parent revision: D62500: Add support to read aux vector values.
This is the third patch to improve module loading in a series that started here
(where I explain the motivation and solution): D62499
<https://reviews.llvm.org/D62499>
Add functions to read the r_debug location to know where the linked list of
loaded libraries are so I can generate the `xfer:libraries-svr4` packet.
I'm also using this function to implement `GetSharedLibraryInfoAddress` that
was "not implemented" for linux.
Most of this code was inspired by the current ds2 implementation here:
https://github.com/facebook/ds2/blob/master/Sources/Target/POSIX/ELFProcess.cpp.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D62501
Files:
lldb/include/lldb/Host/common/NativeProcessProtocol.h
lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -130,11 +130,14 @@
protected:
llvm::Expected<llvm::ArrayRef<uint8_t>>
GetSoftwareBreakpointTrapOpcode(size_t size_hint) override;
+ template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN>
+ lldb::addr_t GetELFImageInfoAddress();
private:
MainLoop::SignalHandleUP m_sigchld_handle;
ArchSpec m_arch;
std::unique_ptr<ELFAuxVector> m_aux_vector;
+ lldb::addr_t m_elf_image_info_addr = LLDB_INVALID_ADDRESS;
LazyBool m_supports_mem_region = eLazyBoolCalculate;
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -38,6 +38,7 @@
#include "lldb/Utility/State.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StringExtractor.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Threading.h"
@@ -1390,8 +1391,12 @@
}
lldb::addr_t NativeProcessLinux::GetSharedLibraryInfoAddress() {
- // punt on this for now
- return LLDB_INVALID_ADDRESS;
+ if (GetAddressByteSize() == 8)
+ return GetELFImageInfoAddress<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr,
+ llvm::ELF::Elf64_Dyn>();
+ else
+ return GetELFImageInfoAddress<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr,
+ llvm::ELF::Elf32_Dyn>();
}
size_t NativeProcessLinux::UpdateThreads() {
@@ -2096,3 +2101,71 @@
return m_aux_vector->GetAuxValue(type);
}
+
+template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN>
+lldb::addr_t NativeProcessLinux::GetELFImageInfoAddress() {
+ if (m_elf_image_info_addr != LLDB_INVALID_ADDRESS)
+ return m_elf_image_info_addr;
+
+ lldb::addr_t phdr_addr = GetAuxValue(ELFAuxVector::AUXV_AT_PHDR);
+ size_t phdr_entry_size = GetAuxValue(ELFAuxVector::AUXV_AT_PHENT);
+ size_t phdr_num_entries = GetAuxValue(ELFAuxVector::AUXV_AT_PHNUM);
+ lldb::addr_t load_base = phdr_addr - sizeof(ELF_EHDR);
+ if (phdr_addr == 0 || phdr_entry_size == 0 || phdr_num_entries == 0)
+ return LLDB_INVALID_ADDRESS;
+
+ // Find the PT_DYNAMIC segment (.dynamic section) in the program header and
+ // what the ELF believes to be the load base.
+ lldb::addr_t elf_load_base = 0;
+ bool found_elf_load_base = false;
+ lldb::addr_t dynamic_section_addr = 0;
+ uint64_t dynamic_section_size = 0;
+ bool found_dynamic_section = false;
+ ELF_PHDR phdr_entry;
+ for (size_t i = 0; i < phdr_num_entries; i++) {
+ size_t bytes_read;
+ auto error = ReadMemory(phdr_addr + i * phdr_entry_size, &phdr_entry,
+ sizeof(phdr_entry), bytes_read);
+ if (!error.Success())
+ return LLDB_INVALID_ADDRESS;
+
+ if ((!found_elf_load_base || phdr_entry.p_vaddr < elf_load_base) &&
+ phdr_entry.p_type == llvm::ELF::PT_LOAD) {
+ elf_load_base = phdr_entry.p_vaddr;
+ found_elf_load_base = true;
+ }
+
+ if (phdr_entry.p_type == llvm::ELF::PT_DYNAMIC) {
+ dynamic_section_addr = phdr_entry.p_vaddr;
+ dynamic_section_size = phdr_entry.p_memsz;
+ found_dynamic_section = true;
+ }
+ }
+
+ if (!found_elf_load_base || !found_dynamic_section)
+ return LLDB_INVALID_ADDRESS;
+
+ // Find the DT_DEBUG entry in the .dynamic section
+ // The load base we got from the auxiliary vector is the source of truth. If
+ // we got a different load base from the ELF then we need to correct the
+ // .dynamic section address with the difference we found.
+ dynamic_section_addr += (load_base - elf_load_base);
+ ELF_DYN dynamic_entry;
+ size_t dynamic_num_entries = dynamic_section_size / sizeof(dynamic_entry);
+ for (size_t i = 0; i < dynamic_num_entries; i++) {
+ size_t bytes_read;
+ auto error = ReadMemory(dynamic_section_addr + i * sizeof(dynamic_entry),
+ &dynamic_entry, sizeof(dynamic_entry), bytes_read);
+ if (!error.Success())
+ return LLDB_INVALID_ADDRESS;
+ // Return the &DT_DEBUG->d_ptr which points to r_debug which contains the
+ // link_map.
+ if (dynamic_entry.d_tag == llvm::ELF::DT_DEBUG) {
+ m_elf_image_info_addr = dynamic_section_addr + i * sizeof(dynamic_entry) +
+ sizeof(dynamic_entry.d_tag);
+ return m_elf_image_info_addr;
+ }
+ }
+
+ return LLDB_INVALID_ADDRESS;
+}
Index: lldb/include/lldb/Host/common/NativeProcessProtocol.h
===================================================================
--- lldb/include/lldb/Host/common/NativeProcessProtocol.h
+++ lldb/include/lldb/Host/common/NativeProcessProtocol.h
@@ -427,6 +427,8 @@
NativeThreadProtocol *GetThreadByIDUnlocked(lldb::tid_t tid);
+ lldb::addr_t GetELFImageInfoAddress();
+
private:
void SynchronouslyNotifyProcessStateChanged(lldb::StateType state);
llvm::Expected<SoftwareBreakpoint>
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits