Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp
39644 views
//===-- NativeProcessELF.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "NativeProcessELF.h"910#include "lldb/Utility/DataExtractor.h"11#include <optional>1213namespace lldb_private {1415std::optional<uint64_t>16NativeProcessELF::GetAuxValue(enum AuxVector::EntryType type) {17if (m_aux_vector == nullptr) {18auto buffer_or_error = GetAuxvData();19if (!buffer_or_error)20return std::nullopt;21DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(),22buffer_or_error.get()->getBufferSize(),23GetByteOrder(), GetAddressByteSize());24m_aux_vector = std::make_unique<AuxVector>(auxv_data);25}2627return m_aux_vector->GetAuxValue(type);28}2930lldb::addr_t NativeProcessELF::GetSharedLibraryInfoAddress() {31if (!m_shared_library_info_addr) {32if (GetAddressByteSize() == 8)33m_shared_library_info_addr =34GetELFImageInfoAddress<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr,35llvm::ELF::Elf64_Dyn>();36else37m_shared_library_info_addr =38GetELFImageInfoAddress<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr,39llvm::ELF::Elf32_Dyn>();40}4142return *m_shared_library_info_addr;43}4445template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN>46lldb::addr_t NativeProcessELF::GetELFImageInfoAddress() {47std::optional<uint64_t> maybe_phdr_addr =48GetAuxValue(AuxVector::AUXV_AT_PHDR);49std::optional<uint64_t> maybe_phdr_entry_size =50GetAuxValue(AuxVector::AUXV_AT_PHENT);51std::optional<uint64_t> maybe_phdr_num_entries =52GetAuxValue(AuxVector::AUXV_AT_PHNUM);53if (!maybe_phdr_addr || !maybe_phdr_entry_size || !maybe_phdr_num_entries)54return LLDB_INVALID_ADDRESS;55lldb::addr_t phdr_addr = *maybe_phdr_addr;56size_t phdr_entry_size = *maybe_phdr_entry_size;57size_t phdr_num_entries = *maybe_phdr_num_entries;5859// Find the PT_DYNAMIC segment (.dynamic section) in the program header and60// what the load bias by calculating the difference of the program header61// load address and its virtual address.62lldb::offset_t load_bias;63bool found_load_bias = false;64lldb::addr_t dynamic_section_addr = 0;65uint64_t dynamic_section_size = 0;66bool found_dynamic_section = false;67ELF_PHDR phdr_entry;68for (size_t i = 0; i < phdr_num_entries; i++) {69size_t bytes_read;70auto error = ReadMemory(phdr_addr + i * phdr_entry_size, &phdr_entry,71sizeof(phdr_entry), bytes_read);72if (!error.Success())73return LLDB_INVALID_ADDRESS;74if (phdr_entry.p_type == llvm::ELF::PT_PHDR) {75load_bias = phdr_addr - phdr_entry.p_vaddr;76found_load_bias = true;77}7879if (phdr_entry.p_type == llvm::ELF::PT_DYNAMIC) {80dynamic_section_addr = phdr_entry.p_vaddr;81dynamic_section_size = phdr_entry.p_memsz;82found_dynamic_section = true;83}84}8586if (!found_load_bias || !found_dynamic_section)87return LLDB_INVALID_ADDRESS;8889// Find the DT_DEBUG entry in the .dynamic section90dynamic_section_addr += load_bias;91ELF_DYN dynamic_entry;92size_t dynamic_num_entries = dynamic_section_size / sizeof(dynamic_entry);93for (size_t i = 0; i < dynamic_num_entries; i++) {94size_t bytes_read;95auto error = ReadMemory(dynamic_section_addr + i * sizeof(dynamic_entry),96&dynamic_entry, sizeof(dynamic_entry), bytes_read);97if (!error.Success())98return LLDB_INVALID_ADDRESS;99// Return the &DT_DEBUG->d_ptr which points to r_debug which contains the100// link_map.101if (dynamic_entry.d_tag == llvm::ELF::DT_DEBUG) {102return dynamic_section_addr + i * sizeof(dynamic_entry) +103sizeof(dynamic_entry.d_tag);104}105}106107return LLDB_INVALID_ADDRESS;108}109110template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress<111llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>();112template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress<113llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr, llvm::ELF::Elf64_Dyn>();114115template <typename T>116llvm::Expected<SVR4LibraryInfo>117NativeProcessELF::ReadSVR4LibraryInfo(lldb::addr_t link_map_addr) {118ELFLinkMap<T> link_map;119size_t bytes_read;120auto error =121ReadMemory(link_map_addr, &link_map, sizeof(link_map), bytes_read);122if (!error.Success())123return error.ToError();124125char name_buffer[PATH_MAX];126llvm::Expected<llvm::StringRef> string_or_error = ReadCStringFromMemory(127link_map.l_name, &name_buffer[0], sizeof(name_buffer), bytes_read);128if (!string_or_error)129return string_or_error.takeError();130131SVR4LibraryInfo info;132info.name = string_or_error->str();133info.link_map = link_map_addr;134info.base_addr = link_map.l_addr;135info.ld_addr = link_map.l_ld;136info.next = link_map.l_next;137138return info;139}140141llvm::Expected<std::vector<SVR4LibraryInfo>>142NativeProcessELF::GetLoadedSVR4Libraries() {143// Address of DT_DEBUG.d_ptr which points to r_debug144lldb::addr_t info_address = GetSharedLibraryInfoAddress();145if (info_address == LLDB_INVALID_ADDRESS)146return llvm::createStringError(llvm::inconvertibleErrorCode(),147"Invalid shared library info address");148// Address of r_debug149lldb::addr_t address = 0;150size_t bytes_read;151auto status =152ReadMemory(info_address, &address, GetAddressByteSize(), bytes_read);153if (!status.Success())154return status.ToError();155if (address == 0)156return llvm::createStringError(llvm::inconvertibleErrorCode(),157"Invalid r_debug address");158// Read r_debug.r_map159lldb::addr_t link_map = 0;160status = ReadMemory(address + GetAddressByteSize(), &link_map,161GetAddressByteSize(), bytes_read);162if (!status.Success())163return status.ToError();164if (link_map == 0)165return llvm::createStringError(llvm::inconvertibleErrorCode(),166"Invalid link_map address");167168std::vector<SVR4LibraryInfo> library_list;169while (link_map) {170llvm::Expected<SVR4LibraryInfo> info =171GetAddressByteSize() == 8 ? ReadSVR4LibraryInfo<uint64_t>(link_map)172: ReadSVR4LibraryInfo<uint32_t>(link_map);173if (!info)174return info.takeError();175if (!info->name.empty() && info->base_addr != 0)176library_list.push_back(*info);177link_map = info->next;178}179180return library_list;181}182183void NativeProcessELF::NotifyDidExec() {184NativeProcessProtocol::NotifyDidExec();185m_shared_library_info_addr.reset();186}187188} // namespace lldb_private189190191