1da0c48c4Sopenharmony_ci/* Recover relocatibility for addresses computed from debug information. 2da0c48c4Sopenharmony_ci Copyright (C) 2005-2010, 2013, 2015 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of either 7da0c48c4Sopenharmony_ci 8da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 9da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 10da0c48c4Sopenharmony_ci your option) any later version 11da0c48c4Sopenharmony_ci 12da0c48c4Sopenharmony_ci or 13da0c48c4Sopenharmony_ci 14da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 15da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 16da0c48c4Sopenharmony_ci your option) any later version 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci or both in parallel, as here. 19da0c48c4Sopenharmony_ci 20da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 21da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 22da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23da0c48c4Sopenharmony_ci General Public License for more details. 24da0c48c4Sopenharmony_ci 25da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 26da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 27da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 28da0c48c4Sopenharmony_ci 29da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 30da0c48c4Sopenharmony_ci# include <config.h> 31da0c48c4Sopenharmony_ci#endif 32da0c48c4Sopenharmony_ci 33da0c48c4Sopenharmony_ci#include "libdwflP.h" 34da0c48c4Sopenharmony_ci 35da0c48c4Sopenharmony_cistruct dwfl_relocation 36da0c48c4Sopenharmony_ci{ 37da0c48c4Sopenharmony_ci size_t count; 38da0c48c4Sopenharmony_ci struct 39da0c48c4Sopenharmony_ci { 40da0c48c4Sopenharmony_ci Elf_Scn *scn; 41da0c48c4Sopenharmony_ci Elf_Scn *relocs; 42da0c48c4Sopenharmony_ci const char *name; 43da0c48c4Sopenharmony_ci GElf_Addr start, end; 44da0c48c4Sopenharmony_ci } refs[0]; 45da0c48c4Sopenharmony_ci}; 46da0c48c4Sopenharmony_ci 47da0c48c4Sopenharmony_ci 48da0c48c4Sopenharmony_cistruct secref 49da0c48c4Sopenharmony_ci{ 50da0c48c4Sopenharmony_ci struct secref *next; 51da0c48c4Sopenharmony_ci Elf_Scn *scn; 52da0c48c4Sopenharmony_ci Elf_Scn *relocs; 53da0c48c4Sopenharmony_ci const char *name; 54da0c48c4Sopenharmony_ci GElf_Addr start, end; 55da0c48c4Sopenharmony_ci}; 56da0c48c4Sopenharmony_ci 57da0c48c4Sopenharmony_cistatic int 58da0c48c4Sopenharmony_cicompare_secrefs (const void *a, const void *b) 59da0c48c4Sopenharmony_ci{ 60da0c48c4Sopenharmony_ci struct secref *const *p1 = a; 61da0c48c4Sopenharmony_ci struct secref *const *p2 = b; 62da0c48c4Sopenharmony_ci 63da0c48c4Sopenharmony_ci /* No signed difference calculation is correct here, since the 64da0c48c4Sopenharmony_ci terms are unsigned and could be more than INT64_MAX apart. */ 65da0c48c4Sopenharmony_ci if ((*p1)->start < (*p2)->start) 66da0c48c4Sopenharmony_ci return -1; 67da0c48c4Sopenharmony_ci if ((*p1)->start > (*p2)->start) 68da0c48c4Sopenharmony_ci return 1; 69da0c48c4Sopenharmony_ci 70da0c48c4Sopenharmony_ci if ((*p1)->end < (*p2)->end) 71da0c48c4Sopenharmony_ci return -1; 72da0c48c4Sopenharmony_ci if ((*p1)->end > (*p2)->end) 73da0c48c4Sopenharmony_ci return 1; 74da0c48c4Sopenharmony_ci 75da0c48c4Sopenharmony_ci /* Same start/end, then just compare which section came first. */ 76da0c48c4Sopenharmony_ci return elf_ndxscn ((*p1)->scn) - elf_ndxscn ((*p2)->scn); 77da0c48c4Sopenharmony_ci} 78da0c48c4Sopenharmony_ci 79da0c48c4Sopenharmony_cistatic int 80da0c48c4Sopenharmony_cicache_sections (Dwfl_Module *mod) 81da0c48c4Sopenharmony_ci{ 82da0c48c4Sopenharmony_ci if (likely (mod->reloc_info != NULL)) 83da0c48c4Sopenharmony_ci return mod->reloc_info->count; 84da0c48c4Sopenharmony_ci 85da0c48c4Sopenharmony_ci struct secref *refs = NULL; 86da0c48c4Sopenharmony_ci size_t nrefs = 0; 87da0c48c4Sopenharmony_ci 88da0c48c4Sopenharmony_ci size_t shstrndx; 89da0c48c4Sopenharmony_ci if (unlikely (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0)) 90da0c48c4Sopenharmony_ci { 91da0c48c4Sopenharmony_ci elf_error: 92da0c48c4Sopenharmony_ci __libdwfl_seterrno (DWFL_E_LIBELF); 93da0c48c4Sopenharmony_ci nrefs = -1; 94da0c48c4Sopenharmony_ci goto free_refs; 95da0c48c4Sopenharmony_ci } 96da0c48c4Sopenharmony_ci 97da0c48c4Sopenharmony_ci bool check_reloc_sections = false; 98da0c48c4Sopenharmony_ci Elf_Scn *scn = NULL; 99da0c48c4Sopenharmony_ci while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL) 100da0c48c4Sopenharmony_ci { 101da0c48c4Sopenharmony_ci GElf_Shdr shdr_mem; 102da0c48c4Sopenharmony_ci GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 103da0c48c4Sopenharmony_ci if (shdr == NULL) 104da0c48c4Sopenharmony_ci goto elf_error; 105da0c48c4Sopenharmony_ci 106da0c48c4Sopenharmony_ci if ((shdr->sh_flags & SHF_ALLOC) && shdr->sh_addr == 0 107da0c48c4Sopenharmony_ci && mod->e_type == ET_REL) 108da0c48c4Sopenharmony_ci { 109da0c48c4Sopenharmony_ci /* This section might not yet have been looked at. */ 110da0c48c4Sopenharmony_ci if (__libdwfl_relocate_value (mod, mod->main.elf, &shstrndx, 111da0c48c4Sopenharmony_ci elf_ndxscn (scn), 112da0c48c4Sopenharmony_ci &shdr->sh_addr) != DWFL_E_NOERROR) 113da0c48c4Sopenharmony_ci continue; 114da0c48c4Sopenharmony_ci shdr = gelf_getshdr (scn, &shdr_mem); 115da0c48c4Sopenharmony_ci if (unlikely (shdr == NULL)) 116da0c48c4Sopenharmony_ci goto elf_error; 117da0c48c4Sopenharmony_ci } 118da0c48c4Sopenharmony_ci 119da0c48c4Sopenharmony_ci if (shdr->sh_flags & SHF_ALLOC) 120da0c48c4Sopenharmony_ci { 121da0c48c4Sopenharmony_ci const char *name = elf_strptr (mod->main.elf, shstrndx, 122da0c48c4Sopenharmony_ci shdr->sh_name); 123da0c48c4Sopenharmony_ci if (unlikely (name == NULL)) 124da0c48c4Sopenharmony_ci goto elf_error; 125da0c48c4Sopenharmony_ci 126da0c48c4Sopenharmony_ci struct secref *newref = malloc (sizeof *newref); 127da0c48c4Sopenharmony_ci if (unlikely (newref == NULL)) 128da0c48c4Sopenharmony_ci { 129da0c48c4Sopenharmony_ci nomem: 130da0c48c4Sopenharmony_ci __libdwfl_seterrno (DWFL_E_NOMEM); 131da0c48c4Sopenharmony_ci nrefs = -1; 132da0c48c4Sopenharmony_ci goto free_refs; 133da0c48c4Sopenharmony_ci } 134da0c48c4Sopenharmony_ci 135da0c48c4Sopenharmony_ci newref->scn = scn; 136da0c48c4Sopenharmony_ci newref->relocs = NULL; 137da0c48c4Sopenharmony_ci newref->name = name; 138da0c48c4Sopenharmony_ci newref->start = dwfl_adjusted_address (mod, shdr->sh_addr); 139da0c48c4Sopenharmony_ci newref->end = newref->start + shdr->sh_size; 140da0c48c4Sopenharmony_ci newref->next = refs; 141da0c48c4Sopenharmony_ci refs = newref; 142da0c48c4Sopenharmony_ci ++nrefs; 143da0c48c4Sopenharmony_ci } 144da0c48c4Sopenharmony_ci 145da0c48c4Sopenharmony_ci if (mod->e_type == ET_REL 146da0c48c4Sopenharmony_ci && shdr->sh_size != 0 147da0c48c4Sopenharmony_ci && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) 148da0c48c4Sopenharmony_ci && mod->dwfl->callbacks->section_address != NULL) 149da0c48c4Sopenharmony_ci { 150da0c48c4Sopenharmony_ci if (shdr->sh_info < elf_ndxscn (scn)) 151da0c48c4Sopenharmony_ci { 152da0c48c4Sopenharmony_ci /* We've already looked at the section these relocs apply to. */ 153da0c48c4Sopenharmony_ci Elf_Scn *tscn = elf_getscn (mod->main.elf, shdr->sh_info); 154da0c48c4Sopenharmony_ci if (likely (tscn != NULL)) 155da0c48c4Sopenharmony_ci for (struct secref *sec = refs; sec != NULL; sec = sec->next) 156da0c48c4Sopenharmony_ci if (sec->scn == tscn) 157da0c48c4Sopenharmony_ci { 158da0c48c4Sopenharmony_ci sec->relocs = scn; 159da0c48c4Sopenharmony_ci break; 160da0c48c4Sopenharmony_ci } 161da0c48c4Sopenharmony_ci } 162da0c48c4Sopenharmony_ci else 163da0c48c4Sopenharmony_ci /* We'll have to do a second pass. */ 164da0c48c4Sopenharmony_ci check_reloc_sections = true; 165da0c48c4Sopenharmony_ci } 166da0c48c4Sopenharmony_ci } 167da0c48c4Sopenharmony_ci 168da0c48c4Sopenharmony_ci mod->reloc_info = malloc (offsetof (struct dwfl_relocation, refs[nrefs])); 169da0c48c4Sopenharmony_ci if (unlikely (mod->reloc_info == NULL)) 170da0c48c4Sopenharmony_ci goto nomem; 171da0c48c4Sopenharmony_ci 172da0c48c4Sopenharmony_ci struct secref **sortrefs = malloc (nrefs * sizeof sortrefs[0]); 173da0c48c4Sopenharmony_ci if (unlikely (sortrefs == NULL)) 174da0c48c4Sopenharmony_ci goto nomem; 175da0c48c4Sopenharmony_ci 176da0c48c4Sopenharmony_ci for (size_t i = nrefs; i-- > 0; refs = refs->next) 177da0c48c4Sopenharmony_ci sortrefs[i] = refs; 178da0c48c4Sopenharmony_ci assert (refs == NULL); 179da0c48c4Sopenharmony_ci 180da0c48c4Sopenharmony_ci qsort (sortrefs, nrefs, sizeof sortrefs[0], &compare_secrefs); 181da0c48c4Sopenharmony_ci 182da0c48c4Sopenharmony_ci mod->reloc_info->count = nrefs; 183da0c48c4Sopenharmony_ci for (size_t i = 0; i < nrefs; ++i) 184da0c48c4Sopenharmony_ci { 185da0c48c4Sopenharmony_ci mod->reloc_info->refs[i].name = sortrefs[i]->name; 186da0c48c4Sopenharmony_ci mod->reloc_info->refs[i].scn = sortrefs[i]->scn; 187da0c48c4Sopenharmony_ci mod->reloc_info->refs[i].relocs = sortrefs[i]->relocs; 188da0c48c4Sopenharmony_ci mod->reloc_info->refs[i].start = sortrefs[i]->start; 189da0c48c4Sopenharmony_ci mod->reloc_info->refs[i].end = sortrefs[i]->end; 190da0c48c4Sopenharmony_ci free (sortrefs[i]); 191da0c48c4Sopenharmony_ci } 192da0c48c4Sopenharmony_ci 193da0c48c4Sopenharmony_ci free (sortrefs); 194da0c48c4Sopenharmony_ci 195da0c48c4Sopenharmony_ci if (unlikely (check_reloc_sections)) 196da0c48c4Sopenharmony_ci { 197da0c48c4Sopenharmony_ci /* There was a reloc section that preceded its target section. 198da0c48c4Sopenharmony_ci So we have to scan again now that we have cached all the 199da0c48c4Sopenharmony_ci possible target sections we care about. */ 200da0c48c4Sopenharmony_ci 201da0c48c4Sopenharmony_ci scn = NULL; 202da0c48c4Sopenharmony_ci while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL) 203da0c48c4Sopenharmony_ci { 204da0c48c4Sopenharmony_ci GElf_Shdr shdr_mem; 205da0c48c4Sopenharmony_ci GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 206da0c48c4Sopenharmony_ci if (shdr == NULL) 207da0c48c4Sopenharmony_ci goto elf_error; 208da0c48c4Sopenharmony_ci 209da0c48c4Sopenharmony_ci if (shdr->sh_size != 0 210da0c48c4Sopenharmony_ci && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)) 211da0c48c4Sopenharmony_ci { 212da0c48c4Sopenharmony_ci Elf_Scn *tscn = elf_getscn (mod->main.elf, shdr->sh_info); 213da0c48c4Sopenharmony_ci if (likely (tscn != NULL)) 214da0c48c4Sopenharmony_ci for (size_t i = 0; i < nrefs; ++i) 215da0c48c4Sopenharmony_ci if (mod->reloc_info->refs[i].scn == tscn) 216da0c48c4Sopenharmony_ci { 217da0c48c4Sopenharmony_ci mod->reloc_info->refs[i].relocs = scn; 218da0c48c4Sopenharmony_ci break; 219da0c48c4Sopenharmony_ci } 220da0c48c4Sopenharmony_ci } 221da0c48c4Sopenharmony_ci } 222da0c48c4Sopenharmony_ci } 223da0c48c4Sopenharmony_ci 224da0c48c4Sopenharmony_cifree_refs: 225da0c48c4Sopenharmony_ci while (refs != NULL) 226da0c48c4Sopenharmony_ci { 227da0c48c4Sopenharmony_ci struct secref *ref = refs; 228da0c48c4Sopenharmony_ci refs = ref->next; 229da0c48c4Sopenharmony_ci free (ref); 230da0c48c4Sopenharmony_ci } 231da0c48c4Sopenharmony_ci 232da0c48c4Sopenharmony_ci return nrefs; 233da0c48c4Sopenharmony_ci} 234da0c48c4Sopenharmony_ci 235da0c48c4Sopenharmony_ci 236da0c48c4Sopenharmony_ciint 237da0c48c4Sopenharmony_cidwfl_module_relocations (Dwfl_Module *mod) 238da0c48c4Sopenharmony_ci{ 239da0c48c4Sopenharmony_ci if (mod == NULL) 240da0c48c4Sopenharmony_ci return -1; 241da0c48c4Sopenharmony_ci 242da0c48c4Sopenharmony_ci switch (mod->e_type) 243da0c48c4Sopenharmony_ci { 244da0c48c4Sopenharmony_ci case ET_REL: 245da0c48c4Sopenharmony_ci return cache_sections (mod); 246da0c48c4Sopenharmony_ci 247da0c48c4Sopenharmony_ci case ET_DYN: 248da0c48c4Sopenharmony_ci return 1; 249da0c48c4Sopenharmony_ci 250da0c48c4Sopenharmony_ci case ET_EXEC: 251da0c48c4Sopenharmony_ci assert (mod->main.vaddr == mod->low_addr); 252da0c48c4Sopenharmony_ci break; 253da0c48c4Sopenharmony_ci } 254da0c48c4Sopenharmony_ci 255da0c48c4Sopenharmony_ci return 0; 256da0c48c4Sopenharmony_ci} 257da0c48c4Sopenharmony_ci 258da0c48c4Sopenharmony_ciconst char * 259da0c48c4Sopenharmony_cidwfl_module_relocation_info (Dwfl_Module *mod, unsigned int idx, 260da0c48c4Sopenharmony_ci Elf32_Word *shndxp) 261da0c48c4Sopenharmony_ci{ 262da0c48c4Sopenharmony_ci if (mod == NULL) 263da0c48c4Sopenharmony_ci return NULL; 264da0c48c4Sopenharmony_ci 265da0c48c4Sopenharmony_ci switch (mod->e_type) 266da0c48c4Sopenharmony_ci { 267da0c48c4Sopenharmony_ci case ET_REL: 268da0c48c4Sopenharmony_ci break; 269da0c48c4Sopenharmony_ci 270da0c48c4Sopenharmony_ci case ET_DYN: 271da0c48c4Sopenharmony_ci if (idx != 0) 272da0c48c4Sopenharmony_ci return NULL; 273da0c48c4Sopenharmony_ci if (shndxp) 274da0c48c4Sopenharmony_ci *shndxp = SHN_ABS; 275da0c48c4Sopenharmony_ci return ""; 276da0c48c4Sopenharmony_ci 277da0c48c4Sopenharmony_ci default: 278da0c48c4Sopenharmony_ci return NULL; 279da0c48c4Sopenharmony_ci } 280da0c48c4Sopenharmony_ci 281da0c48c4Sopenharmony_ci if (cache_sections (mod) < 0) 282da0c48c4Sopenharmony_ci return NULL; 283da0c48c4Sopenharmony_ci 284da0c48c4Sopenharmony_ci struct dwfl_relocation *sections = mod->reloc_info; 285da0c48c4Sopenharmony_ci 286da0c48c4Sopenharmony_ci if (idx >= sections->count) 287da0c48c4Sopenharmony_ci return NULL; 288da0c48c4Sopenharmony_ci 289da0c48c4Sopenharmony_ci if (shndxp) 290da0c48c4Sopenharmony_ci *shndxp = elf_ndxscn (sections->refs[idx].scn); 291da0c48c4Sopenharmony_ci 292da0c48c4Sopenharmony_ci return sections->refs[idx].name; 293da0c48c4Sopenharmony_ci} 294da0c48c4Sopenharmony_ci 295da0c48c4Sopenharmony_ci/* Check that MOD is valid and make sure its relocation has been done. */ 296da0c48c4Sopenharmony_cistatic bool 297da0c48c4Sopenharmony_cicheck_module (Dwfl_Module *mod) 298da0c48c4Sopenharmony_ci{ 299da0c48c4Sopenharmony_ci if (mod == NULL) 300da0c48c4Sopenharmony_ci return true; 301da0c48c4Sopenharmony_ci 302da0c48c4Sopenharmony_ci if (INTUSE(dwfl_module_getsymtab) (mod) < 0) 303da0c48c4Sopenharmony_ci { 304da0c48c4Sopenharmony_ci Dwfl_Error error = dwfl_errno (); 305da0c48c4Sopenharmony_ci if (error != DWFL_E_NO_SYMTAB) 306da0c48c4Sopenharmony_ci { 307da0c48c4Sopenharmony_ci __libdwfl_seterrno (error); 308da0c48c4Sopenharmony_ci return true; 309da0c48c4Sopenharmony_ci } 310da0c48c4Sopenharmony_ci } 311da0c48c4Sopenharmony_ci 312da0c48c4Sopenharmony_ci if (mod->dw == NULL) 313da0c48c4Sopenharmony_ci { 314da0c48c4Sopenharmony_ci Dwarf_Addr bias; 315da0c48c4Sopenharmony_ci if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL) 316da0c48c4Sopenharmony_ci { 317da0c48c4Sopenharmony_ci Dwfl_Error error = dwfl_errno (); 318da0c48c4Sopenharmony_ci if (error != DWFL_E_NO_DWARF) 319da0c48c4Sopenharmony_ci { 320da0c48c4Sopenharmony_ci __libdwfl_seterrno (error); 321da0c48c4Sopenharmony_ci return true; 322da0c48c4Sopenharmony_ci } 323da0c48c4Sopenharmony_ci } 324da0c48c4Sopenharmony_ci } 325da0c48c4Sopenharmony_ci 326da0c48c4Sopenharmony_ci return false; 327da0c48c4Sopenharmony_ci} 328da0c48c4Sopenharmony_ci 329da0c48c4Sopenharmony_ci/* Find the index in MOD->reloc_info.refs containing *ADDR. */ 330da0c48c4Sopenharmony_cistatic int 331da0c48c4Sopenharmony_cifind_section (Dwfl_Module *mod, Dwarf_Addr *addr) 332da0c48c4Sopenharmony_ci{ 333da0c48c4Sopenharmony_ci if (cache_sections (mod) < 0) 334da0c48c4Sopenharmony_ci return -1; 335da0c48c4Sopenharmony_ci 336da0c48c4Sopenharmony_ci struct dwfl_relocation *sections = mod->reloc_info; 337da0c48c4Sopenharmony_ci 338da0c48c4Sopenharmony_ci /* The sections are sorted by address, so we can use binary search. */ 339da0c48c4Sopenharmony_ci size_t l = 0, u = sections->count; 340da0c48c4Sopenharmony_ci while (l < u) 341da0c48c4Sopenharmony_ci { 342da0c48c4Sopenharmony_ci size_t idx = (l + u) / 2; 343da0c48c4Sopenharmony_ci if (*addr < sections->refs[idx].start) 344da0c48c4Sopenharmony_ci u = idx; 345da0c48c4Sopenharmony_ci else if (*addr > sections->refs[idx].end) 346da0c48c4Sopenharmony_ci l = idx + 1; 347da0c48c4Sopenharmony_ci else 348da0c48c4Sopenharmony_ci { 349da0c48c4Sopenharmony_ci /* Consider the limit of a section to be inside it, unless it's 350da0c48c4Sopenharmony_ci inside the next one. A section limit address can appear in 351da0c48c4Sopenharmony_ci line records. */ 352da0c48c4Sopenharmony_ci if (*addr == sections->refs[idx].end 353da0c48c4Sopenharmony_ci && idx + 1 < sections->count 354da0c48c4Sopenharmony_ci && *addr == sections->refs[idx + 1].start) 355da0c48c4Sopenharmony_ci ++idx; 356da0c48c4Sopenharmony_ci 357da0c48c4Sopenharmony_ci *addr -= sections->refs[idx].start; 358da0c48c4Sopenharmony_ci return idx; 359da0c48c4Sopenharmony_ci } 360da0c48c4Sopenharmony_ci } 361da0c48c4Sopenharmony_ci 362da0c48c4Sopenharmony_ci __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_NO_MATCH)); 363da0c48c4Sopenharmony_ci return -1; 364da0c48c4Sopenharmony_ci} 365da0c48c4Sopenharmony_ci 366da0c48c4Sopenharmony_cisize_t 367da0c48c4Sopenharmony_ciinternal_function 368da0c48c4Sopenharmony_ci__libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr) 369da0c48c4Sopenharmony_ci{ 370da0c48c4Sopenharmony_ci int idx = find_section (mod, addr); 371da0c48c4Sopenharmony_ci if (unlikely (idx == -1)) 372da0c48c4Sopenharmony_ci return SHN_UNDEF; 373da0c48c4Sopenharmony_ci 374da0c48c4Sopenharmony_ci return elf_ndxscn (mod->reloc_info->refs[idx].scn); 375da0c48c4Sopenharmony_ci} 376da0c48c4Sopenharmony_ci 377da0c48c4Sopenharmony_ciint 378da0c48c4Sopenharmony_cidwfl_module_relocate_address (Dwfl_Module *mod, Dwarf_Addr *addr) 379da0c48c4Sopenharmony_ci{ 380da0c48c4Sopenharmony_ci if (unlikely (check_module (mod))) 381da0c48c4Sopenharmony_ci return -1; 382da0c48c4Sopenharmony_ci 383da0c48c4Sopenharmony_ci switch (mod->e_type) 384da0c48c4Sopenharmony_ci { 385da0c48c4Sopenharmony_ci case ET_REL: 386da0c48c4Sopenharmony_ci return find_section (mod, addr); 387da0c48c4Sopenharmony_ci 388da0c48c4Sopenharmony_ci case ET_DYN: 389da0c48c4Sopenharmony_ci /* All relative to first and only relocation base: module start. */ 390da0c48c4Sopenharmony_ci *addr -= mod->low_addr; 391da0c48c4Sopenharmony_ci break; 392da0c48c4Sopenharmony_ci 393da0c48c4Sopenharmony_ci default: 394da0c48c4Sopenharmony_ci /* Already absolute, dwfl_module_relocations returned zero. We 395da0c48c4Sopenharmony_ci shouldn't really have been called, but it's a harmless no-op. */ 396da0c48c4Sopenharmony_ci break; 397da0c48c4Sopenharmony_ci } 398da0c48c4Sopenharmony_ci 399da0c48c4Sopenharmony_ci return 0; 400da0c48c4Sopenharmony_ci} 401da0c48c4Sopenharmony_ciINTDEF (dwfl_module_relocate_address) 402da0c48c4Sopenharmony_ci 403da0c48c4Sopenharmony_ciElf_Scn * 404da0c48c4Sopenharmony_cidwfl_module_address_section (Dwfl_Module *mod, Dwarf_Addr *address, 405da0c48c4Sopenharmony_ci Dwarf_Addr *bias) 406da0c48c4Sopenharmony_ci{ 407da0c48c4Sopenharmony_ci if (check_module (mod)) 408da0c48c4Sopenharmony_ci return NULL; 409da0c48c4Sopenharmony_ci 410da0c48c4Sopenharmony_ci int idx = find_section (mod, address); 411da0c48c4Sopenharmony_ci if (idx < 0) 412da0c48c4Sopenharmony_ci return NULL; 413da0c48c4Sopenharmony_ci 414da0c48c4Sopenharmony_ci if (mod->reloc_info->refs[idx].relocs != NULL) 415da0c48c4Sopenharmony_ci { 416da0c48c4Sopenharmony_ci assert (mod->e_type == ET_REL); 417da0c48c4Sopenharmony_ci 418da0c48c4Sopenharmony_ci Elf_Scn *tscn = mod->reloc_info->refs[idx].scn; 419da0c48c4Sopenharmony_ci Elf_Scn *relocscn = mod->reloc_info->refs[idx].relocs; 420da0c48c4Sopenharmony_ci Dwfl_Error result = __libdwfl_relocate_section (mod, mod->main.elf, 421da0c48c4Sopenharmony_ci relocscn, tscn, true); 422da0c48c4Sopenharmony_ci if (likely (result == DWFL_E_NOERROR)) 423da0c48c4Sopenharmony_ci mod->reloc_info->refs[idx].relocs = NULL; 424da0c48c4Sopenharmony_ci else 425da0c48c4Sopenharmony_ci { 426da0c48c4Sopenharmony_ci __libdwfl_seterrno (result); 427da0c48c4Sopenharmony_ci return NULL; 428da0c48c4Sopenharmony_ci } 429da0c48c4Sopenharmony_ci } 430da0c48c4Sopenharmony_ci 431da0c48c4Sopenharmony_ci *bias = dwfl_adjusted_address (mod, 0); 432da0c48c4Sopenharmony_ci return mod->reloc_info->refs[idx].scn; 433da0c48c4Sopenharmony_ci} 434da0c48c4Sopenharmony_ciINTDEF (dwfl_module_address_section) 435