18 #include "absl/debugging/internal/elf_mem_image.h"
20 #ifdef ABSL_HAVE_ELF_MEM_IMAGE // defined in elf_mem_image.h
25 #include "absl/base/config.h"
26 #include "absl/base/internal/raw_logging.h"
39 #define VERSYM_VERSION 0x7fff
43 namespace debugging_internal {
47 #if __SIZEOF_POINTER__ == 4
49 int ElfBind(
const ElfW(Sym) *symbol) {
return ELF32_ST_BIND(symbol->st_info); }
50 int ElfType(
const ElfW(Sym) *symbol) {
return ELF32_ST_TYPE(symbol->st_info); }
51 #elif __SIZEOF_POINTER__ == 8
53 int ElfBind(
const ElfW(Sym) *symbol) {
return ELF64_ST_BIND(symbol->st_info); }
54 int ElfType(
const ElfW(Sym) *symbol) {
return ELF64_ST_TYPE(symbol->st_info); }
56 const int kElfClass = -1;
57 int ElfBind(
const ElfW(Sym) *) {
61 int ElfType(
const ElfW(Sym) *) {
71 const T *GetTableElement(
const ElfW(Ehdr) * ehdr, ElfW(Off) table_offset,
72 ElfW(Word) element_size,
size_t index) {
73 return reinterpret_cast<const T*
>(
reinterpret_cast<const char *
>(ehdr)
75 +
index * element_size);
82 const int ElfMemImage::kInvalidBaseSentinel = 0;
84 ElfMemImage::ElfMemImage(
const void *
base) {
89 int ElfMemImage::GetNumSymbols()
const {
97 const ElfW(Sym) *ElfMemImage::GetDynsym(
int index)
const {
99 return dynsym_ +
index;
102 const ElfW(Versym) *ElfMemImage::GetVersym(
int index)
const {
104 return versym_ +
index;
107 const ElfW(Phdr) *ElfMemImage::GetPhdr(
int index)
const {
109 return GetTableElement<ElfW(Phdr)>(ehdr_,
115 const char *ElfMemImage::GetDynstr(ElfW(Word)
offset)
const {
120 const void *ElfMemImage::GetSymAddr(
const ElfW(Sym) *sym)
const {
123 return reinterpret_cast<const void *
>(sym->st_value);
125 ABSL_RAW_CHECK(link_base_ < sym->st_value,
"symbol out of range");
126 return GetTableElement<char>(ehdr_, 0, 1, sym->st_value - link_base_);
129 const ElfW(Verdef) *ElfMemImage::GetVerdef(
int index)
const {
131 "index out of range");
132 const ElfW(Verdef) *version_definition = verdef_;
133 while (version_definition->vd_ndx <
index && version_definition->vd_next) {
134 const char *
const version_definition_as_char =
135 reinterpret_cast<const char *
>(version_definition);
137 reinterpret_cast<const ElfW(Verdef) *
>(version_definition_as_char +
138 version_definition->vd_next);
140 return version_definition->vd_ndx ==
index ? version_definition :
nullptr;
143 const ElfW(Verdaux) *ElfMemImage::GetVerdefAux(
144 const ElfW(Verdef) *verdef)
const {
145 return reinterpret_cast<const ElfW(Verdaux) *
>(verdef+1);
148 const char *ElfMemImage::GetVerstr(ElfW(Word)
offset)
const {
166 const char *
const base_as_char =
reinterpret_cast<const char *
>(
base);
172 int elf_class = base_as_char[
EI_CLASS];
173 if (elf_class != kElfClass) {
177 switch (base_as_char[
EI_DATA]) {
179 #ifndef ABSL_IS_LITTLE_ENDIAN
186 #ifndef ABSL_IS_BIG_ENDIAN
198 ehdr_ =
reinterpret_cast<const ElfW(Ehdr) *
>(
base);
199 const ElfW(Phdr) *dynamic_program_header =
nullptr;
200 for (
int i = 0;
i < ehdr_->e_phnum; ++
i) {
201 const ElfW(Phdr) *
const program_header = GetPhdr(i);
202 switch (program_header->p_type) {
205 link_base_ = program_header->p_vaddr;
209 dynamic_program_header = program_header;
213 if (!~link_base_ || !dynamic_program_header) {
219 ptrdiff_t relocation =
220 base_as_char -
reinterpret_cast<const char *
>(link_base_);
221 ElfW(Dyn) *dynamic_entry =
222 reinterpret_cast<ElfW(Dyn) *
>(dynamic_program_header->p_vaddr +
224 for (; dynamic_entry->d_tag !=
DT_NULL; ++dynamic_entry) {
225 const auto value = dynamic_entry->d_un.d_val + relocation;
226 switch (dynamic_entry->d_tag) {
228 hash_ =
reinterpret_cast<ElfW(Word) *
>(
value);
231 dynsym_ =
reinterpret_cast<ElfW(Sym) *
>(
value);
234 dynstr_ =
reinterpret_cast<const char *
>(
value);
237 versym_ =
reinterpret_cast<ElfW(Versym) *
>(
value);
240 verdef_ =
reinterpret_cast<ElfW(Verdef) *
>(
value);
243 verdefnum_ = dynamic_entry->d_un.d_val;
246 strsize_ = dynamic_entry->d_un.d_val;
253 if (!hash_ || !dynsym_ || !dynstr_ || !versym_ ||
254 !verdef_ || !verdefnum_ || !strsize_) {
262 bool ElfMemImage::LookupSymbol(
const char *
name,
265 SymbolInfo *info_out)
const {
266 for (
const SymbolInfo& info : *
this) {
267 if (strcmp(info.name,
name) == 0 && strcmp(info.version,
version) == 0 &&
268 ElfType(info.symbol) ==
type) {
278 bool ElfMemImage::LookupSymbolByAddress(
const void *address,
279 SymbolInfo *info_out)
const {
280 for (
const SymbolInfo& info : *
this) {
281 const char *
const symbol_start =
282 reinterpret_cast<const char *
>(info.address);
283 const char *
const symbol_end = symbol_start + info.symbol->st_size;
284 if (symbol_start <= address && address < symbol_end) {
304 ElfMemImage::SymbolIterator::SymbolIterator(
const void *
const image,
int index)
308 const ElfMemImage::SymbolInfo *ElfMemImage::SymbolIterator::operator->()
const {
317 return this->image_ == rhs.image_ && this->
index_ == rhs.index_;
321 return !(*
this == rhs);
330 SymbolIterator
it(
this, 0);
336 return SymbolIterator(
this, GetNumSymbols());
340 const ElfMemImage *
image =
reinterpret_cast<const ElfMemImage *
>(image_);
342 if (!
image->IsPresent()) {
350 const ElfW(Sym) *symbol =
image->GetDynsym(
index_);
351 const ElfW(Versym) *version_symbol =
image->GetVersym(
index_);
353 const char *
const symbol_name =
image->GetDynstr(symbol->st_name);
354 #if defined(__NetBSD__)
355 const int version_index = version_symbol->vs_vers &
VERSYM_VERSION;
357 const ElfW(Versym) version_index = version_symbol[0] &
VERSYM_VERSION;
359 const ElfW(Verdef) *version_definition =
nullptr;
360 const char *version_name =
"";
366 version_definition =
image->GetVerdef(version_index);
368 if (version_definition) {
372 version_definition->vd_cnt == 1 || version_definition->vd_cnt == 2,
373 "wrong number of entries");
374 const ElfW(Verdaux) *version_aux =
image->GetVerdefAux(version_definition);
375 version_name =
image->GetVerstr(version_aux->vda_name);
377 info_.name = symbol_name;
378 info_.version = version_name;
380 info_.symbol = symbol;
387 #endif // ABSL_HAVE_ELF_MEM_IMAGE