1f4335b8eSAntonio Afonso //===-- NativeProcessELF.cpp ---------------------------------- -*- C++ -*-===// 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()); 24f4335b8eSAntonio Afonso m_aux_vector = llvm::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 110*05e32badSAntonio Afonso template <typename T> 111*05e32badSAntonio Afonso llvm::Expected<SVR4LibraryInfo> 112*05e32badSAntonio Afonso NativeProcessELF::ReadSVR4LibraryInfo(lldb::addr_t link_map_addr) { 113*05e32badSAntonio Afonso ELFLinkMap<T> link_map; 114*05e32badSAntonio Afonso size_t bytes_read; 115*05e32badSAntonio Afonso auto error = 116*05e32badSAntonio Afonso ReadMemory(link_map_addr, &link_map, sizeof(link_map), bytes_read); 117*05e32badSAntonio Afonso if (!error.Success()) 118*05e32badSAntonio Afonso return error.ToError(); 119*05e32badSAntonio Afonso 120*05e32badSAntonio Afonso char name_buffer[PATH_MAX]; 121*05e32badSAntonio Afonso error = ReadMemory(link_map.l_name, &name_buffer, sizeof(name_buffer), 122*05e32badSAntonio Afonso bytes_read); 123*05e32badSAntonio Afonso if (bytes_read == 0) 124*05e32badSAntonio Afonso return error.ToError(); 125*05e32badSAntonio Afonso name_buffer[PATH_MAX - 1] = '\0'; 126*05e32badSAntonio Afonso 127*05e32badSAntonio Afonso SVR4LibraryInfo info; 128*05e32badSAntonio Afonso info.name = std::string(name_buffer); 129*05e32badSAntonio Afonso info.link_map = link_map_addr; 130*05e32badSAntonio Afonso info.base_addr = link_map.l_addr; 131*05e32badSAntonio Afonso info.ld_addr = link_map.l_ld; 132*05e32badSAntonio Afonso info.next = link_map.l_next; 133*05e32badSAntonio Afonso 134*05e32badSAntonio Afonso return info; 135*05e32badSAntonio Afonso } 136*05e32badSAntonio Afonso 137*05e32badSAntonio Afonso llvm::Expected<std::vector<SVR4LibraryInfo>> 138*05e32badSAntonio Afonso NativeProcessELF::GetLoadedSVR4Libraries() { 139*05e32badSAntonio Afonso // Address of DT_DEBUG.d_ptr which points to r_debug 140*05e32badSAntonio Afonso lldb::addr_t info_address = GetSharedLibraryInfoAddress(); 141*05e32badSAntonio Afonso if (info_address == LLDB_INVALID_ADDRESS) 142*05e32badSAntonio Afonso return llvm::createStringError(llvm::inconvertibleErrorCode(), 143*05e32badSAntonio Afonso "Invalid shared library info address"); 144*05e32badSAntonio Afonso // Address of r_debug 145*05e32badSAntonio Afonso lldb::addr_t address = 0; 146*05e32badSAntonio Afonso size_t bytes_read; 147*05e32badSAntonio Afonso auto status = 148*05e32badSAntonio Afonso ReadMemory(info_address, &address, GetAddressByteSize(), bytes_read); 149*05e32badSAntonio Afonso if (!status.Success()) 150*05e32badSAntonio Afonso return status.ToError(); 151*05e32badSAntonio Afonso if (address == 0) 152*05e32badSAntonio Afonso return llvm::createStringError(llvm::inconvertibleErrorCode(), 153*05e32badSAntonio Afonso "Invalid r_debug address"); 154*05e32badSAntonio Afonso // Read r_debug.r_map 155*05e32badSAntonio Afonso lldb::addr_t link_map = 0; 156*05e32badSAntonio Afonso status = ReadMemory(address + GetAddressByteSize(), &link_map, 157*05e32badSAntonio Afonso GetAddressByteSize(), bytes_read); 158*05e32badSAntonio Afonso if (!status.Success()) 159*05e32badSAntonio Afonso return status.ToError(); 160*05e32badSAntonio Afonso if (address == 0) 161*05e32badSAntonio Afonso return llvm::createStringError(llvm::inconvertibleErrorCode(), 162*05e32badSAntonio Afonso "Invalid link_map address"); 163*05e32badSAntonio Afonso 164*05e32badSAntonio Afonso std::vector<SVR4LibraryInfo> library_list; 165*05e32badSAntonio Afonso while (link_map) { 166*05e32badSAntonio Afonso llvm::Expected<SVR4LibraryInfo> info = 167*05e32badSAntonio Afonso GetAddressByteSize() == 8 ? ReadSVR4LibraryInfo<uint64_t>(link_map) 168*05e32badSAntonio Afonso : ReadSVR4LibraryInfo<uint32_t>(link_map); 169*05e32badSAntonio Afonso if (!info) 170*05e32badSAntonio Afonso return info.takeError(); 171*05e32badSAntonio Afonso if (!info->name.empty() && info->base_addr != 0) 172*05e32badSAntonio Afonso library_list.push_back(*info); 173*05e32badSAntonio Afonso link_map = info->next; 174*05e32badSAntonio Afonso } 175*05e32badSAntonio Afonso 176*05e32badSAntonio Afonso return library_list; 177*05e32badSAntonio Afonso } 178*05e32badSAntonio Afonso 179f4335b8eSAntonio Afonso } // namespace lldb_private 180