diff options
| author | Antonio Afonso <antonio.afonso@gmail.com> | 2019-06-14 21:15:08 +0000 |
|---|---|---|
| committer | Antonio Afonso <antonio.afonso@gmail.com> | 2019-06-14 21:15:08 +0000 |
| commit | f4335b8e3c6a787e3616f3b0ccdfd64409eaf149 (patch) | |
| tree | 7fbcb3e390df5c927ba9738f46368d251af2928d /lldb/source/Plugins/Process/POSIX | |
| parent | 2de984cd3046de0ec6b9557721a08688beadf7e2 (diff) | |
| download | bcm5719-llvm-f4335b8e3c6a787e3616f3b0ccdfd64409eaf149.tar.gz bcm5719-llvm-f4335b8e3c6a787e3616f3b0ccdfd64409eaf149.zip | |
Implement GetSharedLibraryInfoAddress
Summary:
This is the third patch to improve module loading in a series that started here (where I explain the motivation and solution): 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.
Reviewers: clayborg, xiaobai, labath
Reviewed By: clayborg, labath
Subscribers: emaste, krytarowski, mgorny, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D62501
llvm-svn: 363458
Diffstat (limited to 'lldb/source/Plugins/Process/POSIX')
| -rw-r--r-- | lldb/source/Plugins/Process/POSIX/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp | 110 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/POSIX/NativeProcessELF.h | 46 |
3 files changed, 158 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/POSIX/CMakeLists.txt b/lldb/source/Plugins/Process/POSIX/CMakeLists.txt index c0f6d5a1750..fd74f816d1a 100644 --- a/lldb/source/Plugins/Process/POSIX/CMakeLists.txt +++ b/lldb/source/Plugins/Process/POSIX/CMakeLists.txt @@ -1,9 +1,11 @@ add_lldb_library(lldbPluginProcessPOSIX PLUGIN CrashReason.cpp + NativeProcessELF.cpp ProcessMessage.cpp ProcessPOSIXLog.cpp LINK_LIBS + lldbPluginProcessUtility lldbUtility LINK_COMPONENTS Support diff --git a/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp b/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp new file mode 100644 index 00000000000..559b16c8fd6 --- /dev/null +++ b/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp @@ -0,0 +1,110 @@ +//===-- NativeProcessELF.cpp ---------------------------------- -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "NativeProcessELF.h" + +#include "lldb/Utility/DataExtractor.h" + +namespace lldb_private { + +llvm::Optional<uint64_t> +NativeProcessELF::GetAuxValue(enum AuxVector::EntryType type) { + if (m_aux_vector == nullptr) { + auto buffer_or_error = GetAuxvData(); + if (!buffer_or_error) + return llvm::None; + DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(), + buffer_or_error.get()->getBufferSize(), + GetByteOrder(), GetAddressByteSize()); + m_aux_vector = llvm::make_unique<AuxVector>(auxv_data); + } + + return m_aux_vector->GetAuxValue(type); +} + +lldb::addr_t NativeProcessELF::GetSharedLibraryInfoAddress() { + if (!m_shared_library_info_addr.hasValue()) { + if (GetAddressByteSize() == 8) + m_shared_library_info_addr = + GetELFImageInfoAddress<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr, + llvm::ELF::Elf64_Dyn>(); + else + m_shared_library_info_addr = + GetELFImageInfoAddress<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, + llvm::ELF::Elf32_Dyn>(); + } + + return m_shared_library_info_addr.getValue(); +} + +template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN> +lldb::addr_t NativeProcessELF::GetELFImageInfoAddress() { + llvm::Optional<uint64_t> maybe_phdr_addr = + GetAuxValue(AuxVector::AUXV_AT_PHDR); + llvm::Optional<uint64_t> maybe_phdr_entry_size = + GetAuxValue(AuxVector::AUXV_AT_PHENT); + llvm::Optional<uint64_t> maybe_phdr_num_entries = + GetAuxValue(AuxVector::AUXV_AT_PHNUM); + if (!maybe_phdr_addr || !maybe_phdr_entry_size || !maybe_phdr_num_entries) + return LLDB_INVALID_ADDRESS; + lldb::addr_t phdr_addr = *maybe_phdr_addr; + size_t phdr_entry_size = *maybe_phdr_entry_size; + size_t phdr_num_entries = *maybe_phdr_num_entries; + + // Find the PT_DYNAMIC segment (.dynamic section) in the program header and + // what the load bias by calculating the difference of the program header + // load address and its virtual address. + lldb::offset_t load_bias; + bool found_load_bias = 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 (phdr_entry.p_type == llvm::ELF::PT_PHDR) { + load_bias = phdr_addr - phdr_entry.p_vaddr; + found_load_bias = 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_load_bias || !found_dynamic_section) + return LLDB_INVALID_ADDRESS; + + // Find the DT_DEBUG entry in the .dynamic section + dynamic_section_addr += load_bias; + 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) { + return dynamic_section_addr + i * sizeof(dynamic_entry) + + sizeof(dynamic_entry.d_tag); + } + } + + return LLDB_INVALID_ADDRESS; +} + +} // namespace lldb_private
\ No newline at end of file diff --git a/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h b/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h new file mode 100644 index 00000000000..84dc8d08a34 --- /dev/null +++ b/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h @@ -0,0 +1,46 @@ +//===-- NativeProcessELF.h ------------------------------------ -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_NativeProcessELF_H_ +#define liblldb_NativeProcessELF_H_ + +#include "Plugins/Process/Utility/AuxVector.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "llvm/BinaryFormat/ELF.h" + +namespace lldb_private { + +/// \class NativeProcessELF +/// Abstract class that extends \a NativeProcessProtocol with ELF specific +/// logic. Meant to be subclassed by ELF based NativeProcess* implementations. +class NativeProcessELF : public NativeProcessProtocol { + using NativeProcessProtocol::NativeProcessProtocol; + +protected: + template <typename T> struct ELFLinkMap { + T l_addr; + T l_name; + T l_ld; + T l_next; + T l_prev; + }; + + llvm::Optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type); + + lldb::addr_t GetSharedLibraryInfoAddress() override; + + template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN> + lldb::addr_t GetELFImageInfoAddress(); + + std::unique_ptr<AuxVector> m_aux_vector; + llvm::Optional<lldb::addr_t> m_shared_library_info_addr; +}; + +} // namespace lldb_private + +#endif
\ No newline at end of file |

