1*f4335b8eSAntonio Afonso //===-- NativeProcessELF.cpp ---------------------------------- -*- C++ -*-===// 2*f4335b8eSAntonio Afonso // 3*f4335b8eSAntonio Afonso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*f4335b8eSAntonio Afonso // See https://llvm.org/LICENSE.txt for license information. 5*f4335b8eSAntonio Afonso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*f4335b8eSAntonio Afonso // 7*f4335b8eSAntonio Afonso //===----------------------------------------------------------------------===// 8*f4335b8eSAntonio Afonso 9*f4335b8eSAntonio Afonso #include "NativeProcessELF.h" 10*f4335b8eSAntonio Afonso 11*f4335b8eSAntonio Afonso #include "lldb/Utility/DataExtractor.h" 12*f4335b8eSAntonio Afonso 13*f4335b8eSAntonio Afonso namespace lldb_private { 14*f4335b8eSAntonio Afonso 15*f4335b8eSAntonio Afonso llvm::Optional<uint64_t> 16*f4335b8eSAntonio Afonso NativeProcessELF::GetAuxValue(enum AuxVector::EntryType type) { 17*f4335b8eSAntonio Afonso if (m_aux_vector == nullptr) { 18*f4335b8eSAntonio Afonso auto buffer_or_error = GetAuxvData(); 19*f4335b8eSAntonio Afonso if (!buffer_or_error) 20*f4335b8eSAntonio Afonso return llvm::None; 21*f4335b8eSAntonio Afonso DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(), 22*f4335b8eSAntonio Afonso buffer_or_error.get()->getBufferSize(), 23*f4335b8eSAntonio Afonso GetByteOrder(), GetAddressByteSize()); 24*f4335b8eSAntonio Afonso m_aux_vector = llvm::make_unique<AuxVector>(auxv_data); 25*f4335b8eSAntonio Afonso } 26*f4335b8eSAntonio Afonso 27*f4335b8eSAntonio Afonso return m_aux_vector->GetAuxValue(type); 28*f4335b8eSAntonio Afonso } 29*f4335b8eSAntonio Afonso 30*f4335b8eSAntonio Afonso lldb::addr_t NativeProcessELF::GetSharedLibraryInfoAddress() { 31*f4335b8eSAntonio Afonso if (!m_shared_library_info_addr.hasValue()) { 32*f4335b8eSAntonio Afonso if (GetAddressByteSize() == 8) 33*f4335b8eSAntonio Afonso m_shared_library_info_addr = 34*f4335b8eSAntonio Afonso GetELFImageInfoAddress<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr, 35*f4335b8eSAntonio Afonso llvm::ELF::Elf64_Dyn>(); 36*f4335b8eSAntonio Afonso else 37*f4335b8eSAntonio Afonso m_shared_library_info_addr = 38*f4335b8eSAntonio Afonso GetELFImageInfoAddress<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, 39*f4335b8eSAntonio Afonso llvm::ELF::Elf32_Dyn>(); 40*f4335b8eSAntonio Afonso } 41*f4335b8eSAntonio Afonso 42*f4335b8eSAntonio Afonso return m_shared_library_info_addr.getValue(); 43*f4335b8eSAntonio Afonso } 44*f4335b8eSAntonio Afonso 45*f4335b8eSAntonio Afonso template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN> 46*f4335b8eSAntonio Afonso lldb::addr_t NativeProcessELF::GetELFImageInfoAddress() { 47*f4335b8eSAntonio Afonso llvm::Optional<uint64_t> maybe_phdr_addr = 48*f4335b8eSAntonio Afonso GetAuxValue(AuxVector::AUXV_AT_PHDR); 49*f4335b8eSAntonio Afonso llvm::Optional<uint64_t> maybe_phdr_entry_size = 50*f4335b8eSAntonio Afonso GetAuxValue(AuxVector::AUXV_AT_PHENT); 51*f4335b8eSAntonio Afonso llvm::Optional<uint64_t> maybe_phdr_num_entries = 52*f4335b8eSAntonio Afonso GetAuxValue(AuxVector::AUXV_AT_PHNUM); 53*f4335b8eSAntonio Afonso if (!maybe_phdr_addr || !maybe_phdr_entry_size || !maybe_phdr_num_entries) 54*f4335b8eSAntonio Afonso return LLDB_INVALID_ADDRESS; 55*f4335b8eSAntonio Afonso lldb::addr_t phdr_addr = *maybe_phdr_addr; 56*f4335b8eSAntonio Afonso size_t phdr_entry_size = *maybe_phdr_entry_size; 57*f4335b8eSAntonio Afonso size_t phdr_num_entries = *maybe_phdr_num_entries; 58*f4335b8eSAntonio Afonso 59*f4335b8eSAntonio Afonso // Find the PT_DYNAMIC segment (.dynamic section) in the program header and 60*f4335b8eSAntonio Afonso // what the load bias by calculating the difference of the program header 61*f4335b8eSAntonio Afonso // load address and its virtual address. 62*f4335b8eSAntonio Afonso lldb::offset_t load_bias; 63*f4335b8eSAntonio Afonso bool found_load_bias = false; 64*f4335b8eSAntonio Afonso lldb::addr_t dynamic_section_addr = 0; 65*f4335b8eSAntonio Afonso uint64_t dynamic_section_size = 0; 66*f4335b8eSAntonio Afonso bool found_dynamic_section = false; 67*f4335b8eSAntonio Afonso ELF_PHDR phdr_entry; 68*f4335b8eSAntonio Afonso for (size_t i = 0; i < phdr_num_entries; i++) { 69*f4335b8eSAntonio Afonso size_t bytes_read; 70*f4335b8eSAntonio Afonso auto error = ReadMemory(phdr_addr + i * phdr_entry_size, &phdr_entry, 71*f4335b8eSAntonio Afonso sizeof(phdr_entry), bytes_read); 72*f4335b8eSAntonio Afonso if (!error.Success()) 73*f4335b8eSAntonio Afonso return LLDB_INVALID_ADDRESS; 74*f4335b8eSAntonio Afonso if (phdr_entry.p_type == llvm::ELF::PT_PHDR) { 75*f4335b8eSAntonio Afonso load_bias = phdr_addr - phdr_entry.p_vaddr; 76*f4335b8eSAntonio Afonso found_load_bias = true; 77*f4335b8eSAntonio Afonso } 78*f4335b8eSAntonio Afonso 79*f4335b8eSAntonio Afonso if (phdr_entry.p_type == llvm::ELF::PT_DYNAMIC) { 80*f4335b8eSAntonio Afonso dynamic_section_addr = phdr_entry.p_vaddr; 81*f4335b8eSAntonio Afonso dynamic_section_size = phdr_entry.p_memsz; 82*f4335b8eSAntonio Afonso found_dynamic_section = true; 83*f4335b8eSAntonio Afonso } 84*f4335b8eSAntonio Afonso } 85*f4335b8eSAntonio Afonso 86*f4335b8eSAntonio Afonso if (!found_load_bias || !found_dynamic_section) 87*f4335b8eSAntonio Afonso return LLDB_INVALID_ADDRESS; 88*f4335b8eSAntonio Afonso 89*f4335b8eSAntonio Afonso // Find the DT_DEBUG entry in the .dynamic section 90*f4335b8eSAntonio Afonso dynamic_section_addr += load_bias; 91*f4335b8eSAntonio Afonso ELF_DYN dynamic_entry; 92*f4335b8eSAntonio Afonso size_t dynamic_num_entries = dynamic_section_size / sizeof(dynamic_entry); 93*f4335b8eSAntonio Afonso for (size_t i = 0; i < dynamic_num_entries; i++) { 94*f4335b8eSAntonio Afonso size_t bytes_read; 95*f4335b8eSAntonio Afonso auto error = ReadMemory(dynamic_section_addr + i * sizeof(dynamic_entry), 96*f4335b8eSAntonio Afonso &dynamic_entry, sizeof(dynamic_entry), bytes_read); 97*f4335b8eSAntonio Afonso if (!error.Success()) 98*f4335b8eSAntonio Afonso return LLDB_INVALID_ADDRESS; 99*f4335b8eSAntonio Afonso // Return the &DT_DEBUG->d_ptr which points to r_debug which contains the 100*f4335b8eSAntonio Afonso // link_map. 101*f4335b8eSAntonio Afonso if (dynamic_entry.d_tag == llvm::ELF::DT_DEBUG) { 102*f4335b8eSAntonio Afonso return dynamic_section_addr + i * sizeof(dynamic_entry) + 103*f4335b8eSAntonio Afonso sizeof(dynamic_entry.d_tag); 104*f4335b8eSAntonio Afonso } 105*f4335b8eSAntonio Afonso } 106*f4335b8eSAntonio Afonso 107*f4335b8eSAntonio Afonso return LLDB_INVALID_ADDRESS; 108*f4335b8eSAntonio Afonso } 109*f4335b8eSAntonio Afonso 110*f4335b8eSAntonio Afonso } // namespace lldb_private