brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.7 KiB · 23e94a5 Raw
190 lines · cpp
1//===-- NativeProcessELF.cpp ----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "NativeProcessELF.h"10 11#include "lldb/Utility/DataExtractor.h"12#include <optional>13 14namespace lldb_private {15 16std::optional<uint64_t>17NativeProcessELF::GetAuxValue(enum AuxVector::EntryType type) {18  if (m_aux_vector == nullptr) {19    auto buffer_or_error = GetAuxvData();20    if (!buffer_or_error)21      return std::nullopt;22    DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(),23                            buffer_or_error.get()->getBufferSize(),24                            GetByteOrder(), GetAddressByteSize());25    m_aux_vector = std::make_unique<AuxVector>(auxv_data);26  }27 28  return m_aux_vector->GetAuxValue(type);29}30 31lldb::addr_t NativeProcessELF::GetSharedLibraryInfoAddress() {32  if (!m_shared_library_info_addr) {33    if (GetAddressByteSize() == 8)34      m_shared_library_info_addr =35          GetELFImageInfoAddress<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr,36                                 llvm::ELF::Elf64_Dyn>();37    else38      m_shared_library_info_addr =39          GetELFImageInfoAddress<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr,40                                 llvm::ELF::Elf32_Dyn>();41  }42 43  return *m_shared_library_info_addr;44}45 46template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN>47lldb::addr_t NativeProcessELF::GetELFImageInfoAddress() {48  std::optional<uint64_t> maybe_phdr_addr =49      GetAuxValue(AuxVector::AUXV_AT_PHDR);50  std::optional<uint64_t> maybe_phdr_entry_size =51      GetAuxValue(AuxVector::AUXV_AT_PHENT);52  std::optional<uint64_t> maybe_phdr_num_entries =53      GetAuxValue(AuxVector::AUXV_AT_PHNUM);54  if (!maybe_phdr_addr || !maybe_phdr_entry_size || !maybe_phdr_num_entries)55    return LLDB_INVALID_ADDRESS;56  lldb::addr_t phdr_addr = *maybe_phdr_addr;57  size_t phdr_entry_size = *maybe_phdr_entry_size;58  size_t phdr_num_entries = *maybe_phdr_num_entries;59 60  // Find the PT_DYNAMIC segment (.dynamic section) in the program header and61  // what the load bias by calculating the difference of the program header62  // load address and its virtual address.63  lldb::offset_t load_bias;64  bool found_load_bias = false;65  lldb::addr_t dynamic_section_addr = 0;66  uint64_t dynamic_section_size = 0;67  bool found_dynamic_section = false;68  ELF_PHDR phdr_entry;69  for (size_t i = 0; i < phdr_num_entries; i++) {70    size_t bytes_read;71    auto error = ReadMemory(phdr_addr + i * phdr_entry_size, &phdr_entry,72                            sizeof(phdr_entry), bytes_read);73    if (!error.Success())74      return LLDB_INVALID_ADDRESS;75    if (phdr_entry.p_type == llvm::ELF::PT_PHDR) {76      load_bias = phdr_addr - phdr_entry.p_vaddr;77      found_load_bias = true;78    }79 80    if (phdr_entry.p_type == llvm::ELF::PT_DYNAMIC) {81      dynamic_section_addr = phdr_entry.p_vaddr;82      dynamic_section_size = phdr_entry.p_memsz;83      found_dynamic_section = true;84    }85  }86 87  if (!found_load_bias || !found_dynamic_section)88    return LLDB_INVALID_ADDRESS;89 90  // Find the DT_DEBUG entry in the .dynamic section91  dynamic_section_addr += load_bias;92  ELF_DYN dynamic_entry;93  size_t dynamic_num_entries = dynamic_section_size / sizeof(dynamic_entry);94  for (size_t i = 0; i < dynamic_num_entries; i++) {95    size_t bytes_read;96    auto error = ReadMemory(dynamic_section_addr + i * sizeof(dynamic_entry),97                            &dynamic_entry, sizeof(dynamic_entry), bytes_read);98    if (!error.Success())99      return LLDB_INVALID_ADDRESS;100    // Return the &DT_DEBUG->d_ptr which points to r_debug which contains the101    // link_map.102    if (dynamic_entry.d_tag == llvm::ELF::DT_DEBUG) {103      return dynamic_section_addr + i * sizeof(dynamic_entry) +104             sizeof(dynamic_entry.d_tag);105    }106  }107 108  return LLDB_INVALID_ADDRESS;109}110 111template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress<112    llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>();113template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress<114    llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr, llvm::ELF::Elf64_Dyn>();115 116template <typename T>117llvm::Expected<SVR4LibraryInfo>118NativeProcessELF::ReadSVR4LibraryInfo(lldb::addr_t link_map_addr) {119  ELFLinkMap<T> link_map;120  size_t bytes_read;121  auto error =122      ReadMemory(link_map_addr, &link_map, sizeof(link_map), bytes_read);123  if (!error.Success())124    return error.ToError();125 126  char name_buffer[PATH_MAX];127  llvm::Expected<llvm::StringRef> string_or_error = ReadCStringFromMemory(128      link_map.l_name, &name_buffer[0], sizeof(name_buffer), bytes_read);129  if (!string_or_error)130    return string_or_error.takeError();131 132  SVR4LibraryInfo info;133  info.name = string_or_error->str();134  info.link_map = link_map_addr;135  info.base_addr = link_map.l_addr;136  info.ld_addr = link_map.l_ld;137  info.next = link_map.l_next;138 139  return info;140}141 142llvm::Expected<std::vector<SVR4LibraryInfo>>143NativeProcessELF::GetLoadedSVR4Libraries() {144  // Address of DT_DEBUG.d_ptr which points to r_debug145  lldb::addr_t info_address = GetSharedLibraryInfoAddress();146  if (info_address == LLDB_INVALID_ADDRESS)147    return llvm::createStringError(llvm::inconvertibleErrorCode(),148                                   "Invalid shared library info address");149  // Address of r_debug150  lldb::addr_t address = 0;151  size_t bytes_read;152  auto status =153      ReadMemory(info_address, &address, GetAddressByteSize(), bytes_read);154  if (!status.Success())155    return status.ToError();156  if (address == 0)157    return llvm::createStringError(llvm::inconvertibleErrorCode(),158                                   "Invalid r_debug address");159  // Read r_debug.r_map160  lldb::addr_t link_map = 0;161  status = ReadMemory(address + GetAddressByteSize(), &link_map,162                      GetAddressByteSize(), bytes_read);163  if (!status.Success())164    return status.ToError();165  if (link_map == 0)166    return llvm::createStringError(llvm::inconvertibleErrorCode(),167                                   "Invalid link_map address");168 169  std::vector<SVR4LibraryInfo> library_list;170  while (link_map) {171    llvm::Expected<SVR4LibraryInfo> info =172        GetAddressByteSize() == 8 ? ReadSVR4LibraryInfo<uint64_t>(link_map)173                                  : ReadSVR4LibraryInfo<uint32_t>(link_map);174    if (!info)175      return info.takeError();176    if (!info->name.empty() && info->base_addr != 0)177      library_list.push_back(*info);178    link_map = info->next;179  }180 181  return library_list;182}183 184void NativeProcessELF::NotifyDidExec() {185  NativeProcessProtocol::NotifyDidExec();186  m_shared_library_info_addr.reset();187}188 189} // namespace lldb_private190