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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "NativeProcessELF.h" 10 11 #include "lldb/Utility/DataExtractor.h" 12 #include <optional> 13 14 namespace lldb_private { 15 16 std::optional<uint64_t> 17 NativeProcessELF::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 31 lldb::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 else 38 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 46 template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN> 47 lldb::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 and 61 // what the load bias by calculating the difference of the program header 62 // 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 section 91 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 the 101 // 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 111 template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress< 112 llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>(); 113 template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress< 114 llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr, llvm::ELF::Elf64_Dyn>(); 115 116 template <typename T> 117 llvm::Expected<SVR4LibraryInfo> 118 NativeProcessELF::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 142 llvm::Expected<std::vector<SVR4LibraryInfo>> 143 NativeProcessELF::GetLoadedSVR4Libraries() { 144 // Address of DT_DEBUG.d_ptr which points to r_debug 145 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_debug 150 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_map 160 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 184 void NativeProcessELF::NotifyDidExec() { 185 NativeProcessProtocol::NotifyDidExec(); 186 m_shared_library_info_addr.reset(); 187 } 188 189 } // namespace lldb_private 190