summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/POSIX
diff options
context:
space:
mode:
authorAntonio Afonso <antonio.afonso@gmail.com>2019-06-14 21:15:08 +0000
committerAntonio Afonso <antonio.afonso@gmail.com>2019-06-14 21:15:08 +0000
commitf4335b8e3c6a787e3616f3b0ccdfd64409eaf149 (patch)
tree7fbcb3e390df5c927ba9738f46368d251af2928d /lldb/source/Plugins/Process/POSIX
parent2de984cd3046de0ec6b9557721a08688beadf7e2 (diff)
downloadbcm5719-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.txt2
-rw-r--r--lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp110
-rw-r--r--lldb/source/Plugins/Process/POSIX/NativeProcessELF.h46
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
OpenPOWER on IntegriCloud