/* Find the index in MOD->reloc_info.refs containing *ADDR. */ static int find_section (Dwfl_Module *mod, Dwarf_Addr *addr) { if (unlikely (mod->reloc_info == NULL) && cache_sections (mod) < 0) return -1; struct dwfl_relocation *sections = mod->reloc_info; /* The sections are sorted by address, so we can use binary search. */ size_t l = 0, u = sections->count; while (l < u) { size_t idx = (l + u) / 2; if (*addr < sections->refs[idx].start) u = idx; else if (*addr > sections->refs[idx].end) l = idx + 1; else { /* Consider the limit of a section to be inside it, unless it's inside the next one. A section limit address can appear in line records. */ if (*addr == sections->refs[idx].end && idx < sections->count && *addr == sections->refs[idx + 1].start) ++idx; *addr -= sections->refs[idx].start; return idx; } } __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_NO_MATCH)); return -1; }
int dwfl_module_relocations (Dwfl_Module *mod) { if (mod == NULL) return -1; if (mod->reloc_info != NULL) return mod->reloc_info->count; switch (mod->e_type) { case ET_REL: return cache_sections (mod); case ET_DYN: return 1; case ET_EXEC: assert (mod->main.bias == 0); assert (mod->debug.bias == 0); break; } return 0; }
int dwfl_module_relocations (Dwfl_Module *mod) { if (mod == NULL) return -1; switch (mod->e_type) { case ET_REL: return cache_sections (mod); case ET_DYN: return 1; case ET_EXEC: assert (mod->main.vaddr == mod->low_addr); break; } return 0; }
const char * dwfl_module_relocation_info (Dwfl_Module *mod, unsigned int idx, Elf32_Word *shndxp) { if (mod == NULL) return NULL; switch (mod->e_type) { case ET_REL: break; case ET_DYN: if (idx != 0) return NULL; if (shndxp) *shndxp = SHN_ABS; return ""; default: return NULL; } if (unlikely (mod->reloc_info == NULL) && cache_sections (mod) < 0) return NULL; struct dwfl_relocation *sections = mod->reloc_info; if (idx >= sections->count) return NULL; if (shndxp) *shndxp = elf_ndxscn (sections->refs[idx].scn); return sections->refs[idx].name; }