180814287SRaphael Isemann //===-- NativeProcessELF.cpp ----------------------------------------------===// 2f4335b8eSAntonio Afonso // 3f4335b8eSAntonio Afonso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f4335b8eSAntonio Afonso // See https://llvm.org/LICENSE.txt for license information. 5f4335b8eSAntonio Afonso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f4335b8eSAntonio Afonso // 7f4335b8eSAntonio Afonso //===----------------------------------------------------------------------===// 8f4335b8eSAntonio Afonso 9f4335b8eSAntonio Afonso #include "NativeProcessELF.h" 10f4335b8eSAntonio Afonso 11f4335b8eSAntonio Afonso #include "lldb/Utility/DataExtractor.h" 12f4335b8eSAntonio Afonso 13f4335b8eSAntonio Afonso namespace lldb_private { 14f4335b8eSAntonio Afonso 15f4335b8eSAntonio Afonso llvm::Optional<uint64_t> 16f4335b8eSAntonio Afonso NativeProcessELF::GetAuxValue(enum AuxVector::EntryType type) { 17f4335b8eSAntonio Afonso if (m_aux_vector == nullptr) { 18f4335b8eSAntonio Afonso auto buffer_or_error = GetAuxvData(); 19f4335b8eSAntonio Afonso if (!buffer_or_error) 20f4335b8eSAntonio Afonso return llvm::None; 21f4335b8eSAntonio Afonso DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(), 22f4335b8eSAntonio Afonso buffer_or_error.get()->getBufferSize(), 23f4335b8eSAntonio Afonso GetByteOrder(), GetAddressByteSize()); 24a8f3ae7cSJonas Devlieghere m_aux_vector = std::make_unique<AuxVector>(auxv_data); 25f4335b8eSAntonio Afonso } 26f4335b8eSAntonio Afonso 27f4335b8eSAntonio Afonso return m_aux_vector->GetAuxValue(type); 28f4335b8eSAntonio Afonso } 29f4335b8eSAntonio Afonso 30f4335b8eSAntonio Afonso lldb::addr_t NativeProcessELF::GetSharedLibraryInfoAddress() { 31f4335b8eSAntonio Afonso if (!m_shared_library_info_addr.hasValue()) { 32f4335b8eSAntonio Afonso if (GetAddressByteSize() == 8) 33f4335b8eSAntonio Afonso m_shared_library_info_addr = 34f4335b8eSAntonio Afonso GetELFImageInfoAddress<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr, 35f4335b8eSAntonio Afonso llvm::ELF::Elf64_Dyn>(); 36f4335b8eSAntonio Afonso else 37f4335b8eSAntonio Afonso m_shared_library_info_addr = 38f4335b8eSAntonio Afonso GetELFImageInfoAddress<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, 39f4335b8eSAntonio Afonso llvm::ELF::Elf32_Dyn>(); 40f4335b8eSAntonio Afonso } 41f4335b8eSAntonio Afonso 42f4335b8eSAntonio Afonso return m_shared_library_info_addr.getValue(); 43f4335b8eSAntonio Afonso } 44f4335b8eSAntonio Afonso 45f4335b8eSAntonio Afonso template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN> 46f4335b8eSAntonio Afonso lldb::addr_t NativeProcessELF::GetELFImageInfoAddress() { 47f4335b8eSAntonio Afonso llvm::Optional<uint64_t> maybe_phdr_addr = 48f4335b8eSAntonio Afonso GetAuxValue(AuxVector::AUXV_AT_PHDR); 49f4335b8eSAntonio Afonso llvm::Optional<uint64_t> maybe_phdr_entry_size = 50f4335b8eSAntonio Afonso GetAuxValue(AuxVector::AUXV_AT_PHENT); 51f4335b8eSAntonio Afonso llvm::Optional<uint64_t> maybe_phdr_num_entries = 52f4335b8eSAntonio Afonso GetAuxValue(AuxVector::AUXV_AT_PHNUM); 53f4335b8eSAntonio Afonso if (!maybe_phdr_addr || !maybe_phdr_entry_size || !maybe_phdr_num_entries) 54f4335b8eSAntonio Afonso return LLDB_INVALID_ADDRESS; 55f4335b8eSAntonio Afonso lldb::addr_t phdr_addr = *maybe_phdr_addr; 56f4335b8eSAntonio Afonso size_t phdr_entry_size = *maybe_phdr_entry_size; 57f4335b8eSAntonio Afonso size_t phdr_num_entries = *maybe_phdr_num_entries; 58f4335b8eSAntonio Afonso 59f4335b8eSAntonio Afonso // Find the PT_DYNAMIC segment (.dynamic section) in the program header and 60f4335b8eSAntonio Afonso // what the load bias by calculating the difference of the program header 61f4335b8eSAntonio Afonso // load address and its virtual address. 62f4335b8eSAntonio Afonso lldb::offset_t load_bias; 63f4335b8eSAntonio Afonso bool found_load_bias = false; 64f4335b8eSAntonio Afonso lldb::addr_t dynamic_section_addr = 0; 65f4335b8eSAntonio Afonso uint64_t dynamic_section_size = 0; 66f4335b8eSAntonio Afonso bool found_dynamic_section = false; 67f4335b8eSAntonio Afonso ELF_PHDR phdr_entry; 68f4335b8eSAntonio Afonso for (size_t i = 0; i < phdr_num_entries; i++) { 69f4335b8eSAntonio Afonso size_t bytes_read; 70f4335b8eSAntonio Afonso auto error = ReadMemory(phdr_addr + i * phdr_entry_size, &phdr_entry, 71f4335b8eSAntonio Afonso sizeof(phdr_entry), bytes_read); 72f4335b8eSAntonio Afonso if (!error.Success()) 73f4335b8eSAntonio Afonso return LLDB_INVALID_ADDRESS; 74f4335b8eSAntonio Afonso if (phdr_entry.p_type == llvm::ELF::PT_PHDR) { 75f4335b8eSAntonio Afonso load_bias = phdr_addr - phdr_entry.p_vaddr; 76f4335b8eSAntonio Afonso found_load_bias = true; 77f4335b8eSAntonio Afonso } 78f4335b8eSAntonio Afonso 79f4335b8eSAntonio Afonso if (phdr_entry.p_type == llvm::ELF::PT_DYNAMIC) { 80f4335b8eSAntonio Afonso dynamic_section_addr = phdr_entry.p_vaddr; 81f4335b8eSAntonio Afonso dynamic_section_size = phdr_entry.p_memsz; 82f4335b8eSAntonio Afonso found_dynamic_section = true; 83f4335b8eSAntonio Afonso } 84f4335b8eSAntonio Afonso } 85f4335b8eSAntonio Afonso 86f4335b8eSAntonio Afonso if (!found_load_bias || !found_dynamic_section) 87f4335b8eSAntonio Afonso return LLDB_INVALID_ADDRESS; 88f4335b8eSAntonio Afonso 89f4335b8eSAntonio Afonso // Find the DT_DEBUG entry in the .dynamic section 90f4335b8eSAntonio Afonso dynamic_section_addr += load_bias; 91f4335b8eSAntonio Afonso ELF_DYN dynamic_entry; 92f4335b8eSAntonio Afonso size_t dynamic_num_entries = dynamic_section_size / sizeof(dynamic_entry); 93f4335b8eSAntonio Afonso for (size_t i = 0; i < dynamic_num_entries; i++) { 94f4335b8eSAntonio Afonso size_t bytes_read; 95f4335b8eSAntonio Afonso auto error = ReadMemory(dynamic_section_addr + i * sizeof(dynamic_entry), 96f4335b8eSAntonio Afonso &dynamic_entry, sizeof(dynamic_entry), bytes_read); 97f4335b8eSAntonio Afonso if (!error.Success()) 98f4335b8eSAntonio Afonso return LLDB_INVALID_ADDRESS; 99f4335b8eSAntonio Afonso // Return the &DT_DEBUG->d_ptr which points to r_debug which contains the 100f4335b8eSAntonio Afonso // link_map. 101f4335b8eSAntonio Afonso if (dynamic_entry.d_tag == llvm::ELF::DT_DEBUG) { 102f4335b8eSAntonio Afonso return dynamic_section_addr + i * sizeof(dynamic_entry) + 103f4335b8eSAntonio Afonso sizeof(dynamic_entry.d_tag); 104f4335b8eSAntonio Afonso } 105f4335b8eSAntonio Afonso } 106f4335b8eSAntonio Afonso 107f4335b8eSAntonio Afonso return LLDB_INVALID_ADDRESS; 108f4335b8eSAntonio Afonso } 109f4335b8eSAntonio Afonso 110fbef6c55SJordan Rupprecht template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress< 111fbef6c55SJordan Rupprecht llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>(); 112fbef6c55SJordan Rupprecht template lldb::addr_t NativeProcessELF::GetELFImageInfoAddress< 113fbef6c55SJordan Rupprecht llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr, llvm::ELF::Elf64_Dyn>(); 114fbef6c55SJordan Rupprecht 11505e32badSAntonio Afonso template <typename T> 11605e32badSAntonio Afonso llvm::Expected<SVR4LibraryInfo> 11705e32badSAntonio Afonso NativeProcessELF::ReadSVR4LibraryInfo(lldb::addr_t link_map_addr) { 11805e32badSAntonio Afonso ELFLinkMap<T> link_map; 11905e32badSAntonio Afonso size_t bytes_read; 12005e32badSAntonio Afonso auto error = 12105e32badSAntonio Afonso ReadMemory(link_map_addr, &link_map, sizeof(link_map), bytes_read); 12205e32badSAntonio Afonso if (!error.Success()) 12305e32badSAntonio Afonso return error.ToError(); 12405e32badSAntonio Afonso 12505e32badSAntonio Afonso char name_buffer[PATH_MAX]; 12670795c1eSAntonio Afonso llvm::Expected<llvm::StringRef> string_or_error = ReadCStringFromMemory( 12770795c1eSAntonio Afonso link_map.l_name, &name_buffer[0], sizeof(name_buffer), bytes_read); 12870795c1eSAntonio Afonso if (!string_or_error) 12970795c1eSAntonio Afonso return string_or_error.takeError(); 13005e32badSAntonio Afonso 13105e32badSAntonio Afonso SVR4LibraryInfo info; 13270795c1eSAntonio Afonso info.name = string_or_error->str(); 13305e32badSAntonio Afonso info.link_map = link_map_addr; 13405e32badSAntonio Afonso info.base_addr = link_map.l_addr; 13505e32badSAntonio Afonso info.ld_addr = link_map.l_ld; 13605e32badSAntonio Afonso info.next = link_map.l_next; 13705e32badSAntonio Afonso 13805e32badSAntonio Afonso return info; 13905e32badSAntonio Afonso } 14005e32badSAntonio Afonso 14105e32badSAntonio Afonso llvm::Expected<std::vector<SVR4LibraryInfo>> 14205e32badSAntonio Afonso NativeProcessELF::GetLoadedSVR4Libraries() { 14305e32badSAntonio Afonso // Address of DT_DEBUG.d_ptr which points to r_debug 14405e32badSAntonio Afonso lldb::addr_t info_address = GetSharedLibraryInfoAddress(); 14505e32badSAntonio Afonso if (info_address == LLDB_INVALID_ADDRESS) 14605e32badSAntonio Afonso return llvm::createStringError(llvm::inconvertibleErrorCode(), 14705e32badSAntonio Afonso "Invalid shared library info address"); 14805e32badSAntonio Afonso // Address of r_debug 14905e32badSAntonio Afonso lldb::addr_t address = 0; 15005e32badSAntonio Afonso size_t bytes_read; 15105e32badSAntonio Afonso auto status = 15205e32badSAntonio Afonso ReadMemory(info_address, &address, GetAddressByteSize(), bytes_read); 15305e32badSAntonio Afonso if (!status.Success()) 15405e32badSAntonio Afonso return status.ToError(); 15505e32badSAntonio Afonso if (address == 0) 15605e32badSAntonio Afonso return llvm::createStringError(llvm::inconvertibleErrorCode(), 15705e32badSAntonio Afonso "Invalid r_debug address"); 15805e32badSAntonio Afonso // Read r_debug.r_map 15905e32badSAntonio Afonso lldb::addr_t link_map = 0; 16005e32badSAntonio Afonso status = ReadMemory(address + GetAddressByteSize(), &link_map, 16105e32badSAntonio Afonso GetAddressByteSize(), bytes_read); 16205e32badSAntonio Afonso if (!status.Success()) 16305e32badSAntonio Afonso return status.ToError(); 16405e32badSAntonio Afonso if (address == 0) 16505e32badSAntonio Afonso return llvm::createStringError(llvm::inconvertibleErrorCode(), 16605e32badSAntonio Afonso "Invalid link_map address"); 16705e32badSAntonio Afonso 16805e32badSAntonio Afonso std::vector<SVR4LibraryInfo> library_list; 16905e32badSAntonio Afonso while (link_map) { 17005e32badSAntonio Afonso llvm::Expected<SVR4LibraryInfo> info = 17105e32badSAntonio Afonso GetAddressByteSize() == 8 ? ReadSVR4LibraryInfo<uint64_t>(link_map) 17205e32badSAntonio Afonso : ReadSVR4LibraryInfo<uint32_t>(link_map); 17305e32badSAntonio Afonso if (!info) 17405e32badSAntonio Afonso return info.takeError(); 17505e32badSAntonio Afonso if (!info->name.empty() && info->base_addr != 0) 17605e32badSAntonio Afonso library_list.push_back(*info); 17705e32badSAntonio Afonso link_map = info->next; 17805e32badSAntonio Afonso } 17905e32badSAntonio Afonso 18005e32badSAntonio Afonso return library_list; 18105e32badSAntonio Afonso } 18205e32badSAntonio Afonso 183*cf2c8e41SPavel Labath void NativeProcessELF::NotifyDidExec() { 184*cf2c8e41SPavel Labath NativeProcessProtocol::NotifyDidExec(); 185*cf2c8e41SPavel Labath m_shared_library_info_addr.reset(); 186*cf2c8e41SPavel Labath } 187*cf2c8e41SPavel Labath 188f4335b8eSAntonio Afonso } // namespace lldb_private 189