LLDB  mainline
NativeProcessELF.cpp
Go to the documentation of this file.
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 
12 
13 namespace lldb_private {
14 
15 llvm::Optional<uint64_t>
17  if (m_aux_vector == nullptr) {
18  auto buffer_or_error = GetAuxvData();
19  if (!buffer_or_error)
20  return llvm::None;
21  DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(),
22  buffer_or_error.get()->getBufferSize(),
24  m_aux_vector = std::make_unique<AuxVector>(auxv_data);
25  }
26 
27  return m_aux_vector->GetAuxValue(type);
28 }
29 
31  if (!m_shared_library_info_addr.hasValue()) {
32  if (GetAddressByteSize() == 8)
34  GetELFImageInfoAddress<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr,
35  llvm::ELF::Elf64_Dyn>();
36  else
38  GetELFImageInfoAddress<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr,
39  llvm::ELF::Elf32_Dyn>();
40  }
41 
42  return m_shared_library_info_addr.getValue();
43 }
44 
45 template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN>
47  llvm::Optional<uint64_t> maybe_phdr_addr =
49  llvm::Optional<uint64_t> maybe_phdr_entry_size =
51  llvm::Optional<uint64_t> maybe_phdr_num_entries =
53  if (!maybe_phdr_addr || !maybe_phdr_entry_size || !maybe_phdr_num_entries)
54  return LLDB_INVALID_ADDRESS;
55  lldb::addr_t phdr_addr = *maybe_phdr_addr;
56  size_t phdr_entry_size = *maybe_phdr_entry_size;
57  size_t phdr_num_entries = *maybe_phdr_num_entries;
58 
59  // Find the PT_DYNAMIC segment (.dynamic section) in the program header and
60  // what the load bias by calculating the difference of the program header
61  // load address and its virtual address.
62  lldb::offset_t load_bias;
63  bool found_load_bias = false;
64  lldb::addr_t dynamic_section_addr = 0;
65  uint64_t dynamic_section_size = 0;
66  bool found_dynamic_section = false;
67  ELF_PHDR phdr_entry;
68  for (size_t i = 0; i < phdr_num_entries; i++) {
69  size_t bytes_read;
70  auto error = ReadMemory(phdr_addr + i * phdr_entry_size, &phdr_entry,
71  sizeof(phdr_entry), bytes_read);
72  if (!error.Success())
73  return LLDB_INVALID_ADDRESS;
74  if (phdr_entry.p_type == llvm::ELF::PT_PHDR) {
75  load_bias = phdr_addr - phdr_entry.p_vaddr;
76  found_load_bias = true;
77  }
78 
79  if (phdr_entry.p_type == llvm::ELF::PT_DYNAMIC) {
80  dynamic_section_addr = phdr_entry.p_vaddr;
81  dynamic_section_size = phdr_entry.p_memsz;
82  found_dynamic_section = true;
83  }
84  }
85 
86  if (!found_load_bias || !found_dynamic_section)
87  return LLDB_INVALID_ADDRESS;
88 
89  // Find the DT_DEBUG entry in the .dynamic section
90  dynamic_section_addr += load_bias;
91  ELF_DYN dynamic_entry;
92  size_t dynamic_num_entries = dynamic_section_size / sizeof(dynamic_entry);
93  for (size_t i = 0; i < dynamic_num_entries; i++) {
94  size_t bytes_read;
95  auto error = ReadMemory(dynamic_section_addr + i * sizeof(dynamic_entry),
96  &dynamic_entry, sizeof(dynamic_entry), bytes_read);
97  if (!error.Success())
98  return LLDB_INVALID_ADDRESS;
99  // Return the &DT_DEBUG->d_ptr which points to r_debug which contains the
100  // link_map.
101  if (dynamic_entry.d_tag == llvm::ELF::DT_DEBUG) {
102  return dynamic_section_addr + i * sizeof(dynamic_entry) +
103  sizeof(dynamic_entry.d_tag);
104  }
105  }
106 
107  return LLDB_INVALID_ADDRESS;
108 }
109 
111  llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>();
113  llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Phdr, llvm::ELF::Elf64_Dyn>();
114 
115 template <typename T>
116 llvm::Expected<SVR4LibraryInfo>
118  ELFLinkMap<T> link_map;
119  size_t bytes_read;
120  auto error =
121  ReadMemory(link_map_addr, &link_map, sizeof(link_map), bytes_read);
122  if (!error.Success())
123  return error.ToError();
124 
125  char name_buffer[PATH_MAX];
126  llvm::Expected<llvm::StringRef> string_or_error = ReadCStringFromMemory(
127  link_map.l_name, &name_buffer[0], sizeof(name_buffer), bytes_read);
128  if (!string_or_error)
129  return string_or_error.takeError();
130 
131  SVR4LibraryInfo info;
132  info.name = string_or_error->str();
133  info.link_map = link_map_addr;
134  info.base_addr = link_map.l_addr;
135  info.ld_addr = link_map.l_ld;
136  info.next = link_map.l_next;
137 
138  return info;
139 }
140 
141 llvm::Expected<std::vector<SVR4LibraryInfo>>
143  // Address of DT_DEBUG.d_ptr which points to r_debug
144  lldb::addr_t info_address = GetSharedLibraryInfoAddress();
145  if (info_address == LLDB_INVALID_ADDRESS)
146  return llvm::createStringError(llvm::inconvertibleErrorCode(),
147  "Invalid shared library info address");
148  // Address of r_debug
149  lldb::addr_t address = 0;
150  size_t bytes_read;
151  auto status =
152  ReadMemory(info_address, &address, GetAddressByteSize(), bytes_read);
153  if (!status.Success())
154  return status.ToError();
155  if (address == 0)
156  return llvm::createStringError(llvm::inconvertibleErrorCode(),
157  "Invalid r_debug address");
158  // Read r_debug.r_map
159  lldb::addr_t link_map = 0;
160  status = ReadMemory(address + GetAddressByteSize(), &link_map,
161  GetAddressByteSize(), bytes_read);
162  if (!status.Success())
163  return status.ToError();
164  if (address == 0)
165  return llvm::createStringError(llvm::inconvertibleErrorCode(),
166  "Invalid link_map address");
167 
168  std::vector<SVR4LibraryInfo> library_list;
169  while (link_map) {
170  llvm::Expected<SVR4LibraryInfo> info =
171  GetAddressByteSize() == 8 ? ReadSVR4LibraryInfo<uint64_t>(link_map)
172  : ReadSVR4LibraryInfo<uint32_t>(link_map);
173  if (!info)
174  return info.takeError();
175  if (!info->name.empty() && info->base_addr != 0)
176  library_list.push_back(*info);
177  link_map = info->next;
178  }
179 
180  return library_list;
181 }
182 
183 } // namespace lldb_private
AuxVector::AUXV_AT_PHDR
@ AUXV_AT_PHDR
Program headers.
Definition: AuxVector.h:29
lldb_private::SVR4LibraryInfo::ld_addr
lldb::addr_t ld_addr
Definition: NativeProcessProtocol.h:42
lldb_private::NativeProcessProtocol::ReadCStringFromMemory
llvm::Expected< llvm::StringRef > ReadCStringFromMemory(lldb::addr_t addr, char *buffer, size_t max_size, size_t &total_bytes_read)
Reads a null terminated string from memory.
Definition: NativeProcessProtocol.cpp:642
AuxVector::AUXV_AT_PHNUM
@ AUXV_AT_PHNUM
Number of program headers.
Definition: AuxVector.h:31
AuxVector::AUXV_AT_PHENT
@ AUXV_AT_PHENT
Size of program header.
Definition: AuxVector.h:30
lldb_private::NativeProcessProtocol::GetAuxvData
virtual llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > GetAuxvData() const =0
lldb::offset_t
uint64_t offset_t
Definition: lldb-types.h:87
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::NativeProcessELF::GetSharedLibraryInfoAddress
lldb::addr_t GetSharedLibraryInfoAddress() override
Definition: NativeProcessELF.cpp:30
lldb_private::NativeProcessELF::ELFLinkMap::l_name
T l_name
Definition: NativeProcessELF.h:30
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::SVR4LibraryInfo::next
lldb::addr_t next
Definition: NativeProcessProtocol.h:43
lldb_private::DataExtractor
Definition: DataExtractor.h:48
NativeProcessELF.h
lldb_private::NativeProcessELF::GetLoadedSVR4Libraries
llvm::Expected< std::vector< SVR4LibraryInfo > > GetLoadedSVR4Libraries() override
Definition: NativeProcessELF.cpp:142
lldb_private::SVR4LibraryInfo::name
std::string name
Definition: NativeProcessProtocol.h:39
lldb_private::NativeProcessELF::ELFLinkMap::l_next
T l_next
Definition: NativeProcessELF.h:32
AuxVector::EntryType
EntryType
Constants describing the type of entry.
Definition: AuxVector.h:25
lldb_private::NativeProcessELF::GetELFImageInfoAddress
lldb::addr_t GetELFImageInfoAddress()
Definition: NativeProcessELF.cpp:46
lldb_private::SVR4LibraryInfo::base_addr
lldb::addr_t base_addr
Definition: NativeProcessProtocol.h:41
lldb_private::SVR4LibraryInfo::link_map
lldb::addr_t link_map
Definition: NativeProcessProtocol.h:40
lldb_private::NativeProcessELF::GetAuxValue
llvm::Optional< uint64_t > GetAuxValue(enum AuxVector::EntryType type)
Definition: NativeProcessELF.cpp:16
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:86
DataExtractor.h
lldb_private::NativeProcessProtocol::GetByteOrder
lldb::ByteOrder GetByteOrder() const
Definition: NativeProcessProtocol.h:184
lldb_private::NativeProcessELF::ELFLinkMap::l_ld
T l_ld
Definition: NativeProcessELF.h:31
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::NativeProcessELF::ELFLinkMap::l_addr
T l_addr
Definition: NativeProcessELF.h:29
lldb_private::SVR4LibraryInfo
Definition: NativeProcessProtocol.h:38
lldb_private::NativeProcessELF::ReadSVR4LibraryInfo
llvm::Expected< SVR4LibraryInfo > ReadSVR4LibraryInfo(lldb::addr_t link_map_addr)
Definition: NativeProcessELF.cpp:117
lldb_private::NativeProcessProtocol::GetAddressByteSize
uint32_t GetAddressByteSize() const
Definition: NativeProcessProtocol.h:188
PATH_MAX
#define PATH_MAX
Definition: windows/PosixApi.h:25
lldb_private::NativeProcessELF::m_aux_vector
std::unique_ptr< AuxVector > m_aux_vector
Definition: NativeProcessELF.h:48
lldb_private::NativeProcessProtocol::ReadMemory
virtual Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)=0
lldb_private::NativeProcessELF::m_shared_library_info_addr
llvm::Optional< lldb::addr_t > m_shared_library_info_addr
Definition: NativeProcessELF.h:49
lldb_private::NativeProcessELF::ELFLinkMap
Definition: NativeProcessELF.h:28