1 /* Relocate debug information. 2 Copyright (C) 2005-2011, 2014 Red Hat, Inc. 3 This file is part of elfutils. 4 5 This file is free software; you can redistribute it and/or modify 6 it under the terms of either 7 8 * the GNU Lesser General Public License as published by the Free 9 Software Foundation; either version 3 of the License, or (at 10 your option) any later version 11 12 or 13 14 * the GNU General Public License as published by the Free 15 Software Foundation; either version 2 of the License, or (at 16 your option) any later version 17 18 or both in parallel, as here. 19 20 elfutils is distributed in the hope that it will be useful, but 21 WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 General Public License for more details. 24 25 You should have received copies of the GNU General Public License and 26 the GNU Lesser General Public License along with this program. If 27 not, see <http://www.gnu.org/licenses/>. */ 28 29 #include "libdwflP.h" 30 31 typedef uint8_t GElf_Byte; 32 33 /* Adjust *VALUE to add the load address of the SHNDX section. 34 We update the section header in place to cache the result. */ 35 36 Dwfl_Error 37 internal_function 38 __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx, 39 Elf32_Word shndx, GElf_Addr *value) 40 { 41 /* No adjustment needed for section zero, it is never loaded. 42 Handle it first, just in case the ELF file has strange section 43 zero flags set. */ 44 if (shndx == 0) 45 return DWFL_E_NOERROR; 46 47 Elf_Scn *refscn = elf_getscn (elf, shndx); 48 GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem); 49 if (refshdr == NULL) 50 return DWFL_E_LIBELF; 51 52 if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC)) 53 { 54 /* This is a loaded section. Find its actual 55 address and update the section header. */ 56 57 if (*shstrndx == SHN_UNDEF 58 && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0)) 59 return DWFL_E_LIBELF; 60 61 const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name); 62 if (unlikely (name == NULL)) 63 return DWFL_E_LIBELF; 64 65 if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod), 66 name, shndx, refshdr, 67 &refshdr->sh_addr)) 68 return CBFAIL; 69 70 if (refshdr->sh_addr == (Dwarf_Addr) -1l) 71 /* The callback indicated this section wasn't really loaded but we 72 don't really care. */ 73 refshdr->sh_addr = 0; /* Make no adjustment below. */ 74 75 /* Update the in-core file's section header to show the final 76 load address (or unloadedness). This serves as a cache, 77 so we won't get here again for the same section. */ 78 if (likely (refshdr->sh_addr != 0) 79 && unlikely (! gelf_update_shdr (refscn, refshdr))) 80 return DWFL_E_LIBELF; 81 } 82 83 if (refshdr->sh_flags & SHF_ALLOC) 84 /* Apply the adjustment. */ 85 *value += dwfl_adjusted_address (mod, refshdr->sh_addr); 86 87 return DWFL_E_NOERROR; 88 } 89 90 91 /* Cache used by relocate_getsym. */ 92 struct reloc_symtab_cache 93 { 94 Elf *symelf; 95 Elf_Data *symdata; 96 Elf_Data *symxndxdata; 97 Elf_Data *symstrdata; 98 size_t symshstrndx; 99 size_t strtabndx; 100 }; 101 #define RELOC_SYMTAB_CACHE(cache) \ 102 struct reloc_symtab_cache cache = \ 103 { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF } 104 105 /* This is just doing dwfl_module_getsym, except that we must always use 106 the symbol table in RELOCATED itself when it has one, not MOD->symfile. */ 107 static Dwfl_Error 108 relocate_getsym (Dwfl_Module *mod, 109 Elf *relocated, struct reloc_symtab_cache *cache, 110 int symndx, GElf_Sym *sym, GElf_Word *shndx) 111 { 112 if (cache->symdata == NULL) 113 { 114 if (mod->symfile == NULL || mod->symfile->elf != relocated) 115 { 116 /* We have to look up the symbol table in the file we are 117 relocating, if it has its own. These reloc sections refer to 118 the symbol table in this file, and a symbol table in the main 119 file might not match. However, some tools did produce ET_REL 120 .debug files with relocs but no symtab of their own. */ 121 Elf_Scn *scn = NULL; 122 while ((scn = elf_nextscn (relocated, scn)) != NULL) 123 { 124 GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem); 125 if (shdr != NULL) 126 switch (shdr->sh_type) 127 { 128 default: 129 continue; 130 case SHT_SYMTAB: 131 cache->symelf = relocated; 132 cache->symdata = elf_getdata (scn, NULL); 133 cache->strtabndx = shdr->sh_link; 134 if (unlikely (cache->symdata == NULL)) 135 return DWFL_E_LIBELF; 136 break; 137 case SHT_SYMTAB_SHNDX: 138 cache->symxndxdata = elf_getdata (scn, NULL); 139 if (unlikely (cache->symxndxdata == NULL)) 140 return DWFL_E_LIBELF; 141 break; 142 } 143 if (cache->symdata != NULL && cache->symxndxdata != NULL) 144 break; 145 } 146 } 147 if (cache->symdata == NULL) 148 { 149 /* We might not have looked for a symbol table file yet, 150 when coming from __libdwfl_relocate_section. */ 151 if (unlikely (mod->symfile == NULL) 152 && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0)) 153 return dwfl_errno (); 154 155 /* The symbol table we have already cached is the one from 156 the file being relocated, so it's what we need. Or else 157 this is an ET_REL .debug file with no .symtab of its own; 158 the symbols refer to the section indices in the main file. */ 159 cache->symelf = mod->symfile->elf; 160 cache->symdata = mod->symdata; 161 cache->symxndxdata = mod->symxndxdata; 162 cache->symstrdata = mod->symstrdata; 163 } 164 } 165 166 if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata, 167 symndx, sym, shndx) == NULL)) 168 return DWFL_E_LIBELF; 169 170 if (sym->st_shndx != SHN_XINDEX) 171 *shndx = sym->st_shndx; 172 173 switch (sym->st_shndx) 174 { 175 case SHN_ABS: 176 case SHN_UNDEF: 177 return DWFL_E_NOERROR; 178 179 case SHN_COMMON: 180 sym->st_value = 0; /* Value is size, not helpful. */ 181 return DWFL_E_NOERROR; 182 } 183 184 return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx, 185 *shndx, &sym->st_value); 186 } 187 188 /* Handle an undefined symbol. We really only support ET_REL for Linux 189 kernel modules, and offline archives. The behavior of the Linux module 190 loader is very simple and easy to mimic. It only matches magically 191 exported symbols, and we match any defined symbols. But we get the same 192 answer except when the module's symbols are undefined and would prevent 193 it from being loaded. */ 194 static Dwfl_Error 195 resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab, 196 GElf_Sym *sym, GElf_Word shndx) 197 { 198 /* First we need its name. */ 199 if (sym->st_name != 0) 200 { 201 if (symtab->symstrdata == NULL) 202 { 203 /* Cache the strtab for this symtab. */ 204 assert (referer->symfile == NULL 205 || referer->symfile->elf != symtab->symelf); 206 symtab->symstrdata = elf_getdata (elf_getscn (symtab->symelf, 207 symtab->strtabndx), 208 NULL); 209 if (unlikely (symtab->symstrdata == NULL 210 || symtab->symstrdata->d_buf == NULL)) 211 return DWFL_E_LIBELF; 212 } 213 if (unlikely (sym->st_name >= symtab->symstrdata->d_size)) 214 return DWFL_E_BADSTROFF; 215 216 const char *name = symtab->symstrdata->d_buf; 217 name += sym->st_name; 218 219 for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next) 220 if (m != referer) 221 { 222 /* Get this module's symtab. 223 If we got a fresh error reading the table, report it. 224 If we just have no symbols in this module, no harm done. */ 225 if (m->symdata == NULL 226 && m->symerr == DWFL_E_NOERROR 227 && INTUSE(dwfl_module_getsymtab) (m) < 0 228 && m->symerr != DWFL_E_NO_SYMTAB) 229 return m->symerr; 230 231 for (size_t ndx = 1; ndx < m->syments; ++ndx) 232 { 233 sym = gelf_getsymshndx (m->symdata, m->symxndxdata, 234 ndx, sym, &shndx); 235 if (unlikely (sym == NULL)) 236 return DWFL_E_LIBELF; 237 if (sym->st_shndx != SHN_XINDEX) 238 shndx = sym->st_shndx; 239 240 /* We are looking for a defined global symbol with a name. */ 241 if (shndx == SHN_UNDEF || shndx == SHN_COMMON 242 || GELF_ST_BIND (sym->st_info) == STB_LOCAL 243 || sym->st_name == 0) 244 continue; 245 246 /* Get this candidate symbol's name. */ 247 if (unlikely (sym->st_name >= m->symstrdata->d_size)) 248 return DWFL_E_BADSTROFF; 249 const char *n = m->symstrdata->d_buf; 250 n += sym->st_name; 251 252 /* Does the name match? */ 253 if (strcmp (name, n)) 254 continue; 255 256 /* We found it! */ 257 if (shndx == SHN_ABS) /* XXX maybe should apply bias? */ 258 return DWFL_E_NOERROR; 259 260 if (m->e_type != ET_REL) 261 { 262 sym->st_value = dwfl_adjusted_st_value (m, m->symfile->elf, 263 sym->st_value); 264 return DWFL_E_NOERROR; 265 } 266 267 /* In an ET_REL file, the symbol table values are relative 268 to the section, not to the module's load base. */ 269 size_t symshstrndx = SHN_UNDEF; 270 return __libdwfl_relocate_value (m, m->symfile->elf, 271 &symshstrndx, 272 shndx, &sym->st_value); 273 } 274 } 275 } 276 277 return DWFL_E_RELUNDEF; 278 } 279 280 static Dwfl_Error 281 relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, 282 size_t shstrndx, struct reloc_symtab_cache *reloc_symtab, 283 Elf_Scn *scn, GElf_Shdr *shdr, 284 Elf_Scn *tscn, bool debugscn, bool partial) 285 { 286 /* First, fetch the name of the section these relocations apply to. */ 287 GElf_Shdr tshdr_mem; 288 GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem); 289 const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name); 290 if (tname == NULL) 291 return DWFL_E_LIBELF; 292 293 if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0)) 294 /* No contents to relocate. */ 295 return DWFL_E_NOERROR; 296 297 if (debugscn && ! ebl_debugscn_p (mod->ebl, tname)) 298 /* This relocation section is not for a debugging section. 299 Nothing to do here. */ 300 return DWFL_E_NOERROR; 301 302 /* Fetch the section data that needs the relocations applied. */ 303 Elf_Data *tdata = elf_rawdata (tscn, NULL); 304 if (tdata == NULL) 305 return DWFL_E_LIBELF; 306 307 /* If either the section that needs the relocation applied, or the 308 section that the relocations come from overlap one of the ehdrs, 309 shdrs or phdrs data then we refuse to do the relocations. It 310 isn't illegal for ELF section data to overlap the header data, 311 but updating the (relocation) data might corrupt the in-memory 312 libelf headers causing strange corruptions or errors. */ 313 size_t ehsize = gelf_fsize (relocated, ELF_T_EHDR, 1, EV_CURRENT); 314 if (unlikely (shdr->sh_offset < ehsize 315 || tshdr->sh_offset < ehsize)) 316 return DWFL_E_BADELF; 317 318 GElf_Off shdrs_start = ehdr->e_shoff; 319 size_t shnums; 320 if (elf_getshdrnum (relocated, &shnums) < 0) 321 return DWFL_E_LIBELF; 322 /* Overflows will have been checked by elf_getshdrnum/get|rawdata. */ 323 size_t shentsize = gelf_fsize (relocated, ELF_T_SHDR, 1, EV_CURRENT); 324 GElf_Off shdrs_end = shdrs_start + shnums * shentsize; 325 if (unlikely ((shdrs_start < shdr->sh_offset + shdr->sh_size 326 && shdr->sh_offset < shdrs_end) 327 || (shdrs_start < tshdr->sh_offset + tshdr->sh_size 328 && tshdr->sh_offset < shdrs_end))) 329 return DWFL_E_BADELF; 330 331 GElf_Off phdrs_start = ehdr->e_phoff; 332 size_t phnums; 333 if (elf_getphdrnum (relocated, &phnums) < 0) 334 return DWFL_E_LIBELF; 335 if (phdrs_start != 0 && phnums != 0) 336 { 337 /* Overflows will have been checked by elf_getphdrnum/get|rawdata. */ 338 size_t phentsize = gelf_fsize (relocated, ELF_T_PHDR, 1, EV_CURRENT); 339 GElf_Off phdrs_end = phdrs_start + phnums * phentsize; 340 if (unlikely ((phdrs_start < shdr->sh_offset + shdr->sh_size 341 && shdr->sh_offset < phdrs_end) 342 || (phdrs_start < tshdr->sh_offset + tshdr->sh_size 343 && tshdr->sh_offset < phdrs_end))) 344 return DWFL_E_BADELF; 345 } 346 347 /* Apply one relocation. Returns true for any invalid data. */ 348 Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend, 349 int rtype, int symndx) 350 { 351 /* First see if this is a reloc we can handle. 352 If we are skipping it, don't bother resolving the symbol. */ 353 354 if (unlikely (rtype == 0)) 355 /* In some odd situations, the linker can leave R_*_NONE relocs 356 behind. This is probably bogus ld -r behavior, but the only 357 cases it's known to appear in are harmless: DWARF data 358 referring to addresses in a section that has been discarded. 359 So we just pretend it's OK without further relocation. */ 360 return DWFL_E_NOERROR; 361 362 Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype); 363 if (unlikely (type == ELF_T_NUM)) 364 return DWFL_E_BADRELTYPE; 365 366 /* First, resolve the symbol to an absolute value. */ 367 GElf_Addr value; 368 369 if (symndx == STN_UNDEF) 370 /* When strip removes a section symbol referring to a 371 section moved into the debuginfo file, it replaces 372 that symbol index in relocs with STN_UNDEF. We 373 don't actually need the symbol, because those relocs 374 are always references relative to the nonallocated 375 debugging sections, which start at zero. */ 376 value = 0; 377 else 378 { 379 GElf_Sym sym; 380 GElf_Word shndx; 381 Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab, 382 symndx, &sym, &shndx); 383 if (unlikely (error != DWFL_E_NOERROR)) 384 return error; 385 386 if (shndx == SHN_UNDEF || shndx == SHN_COMMON) 387 { 388 /* Maybe we can figure it out anyway. */ 389 error = resolve_symbol (mod, reloc_symtab, &sym, shndx); 390 if (error != DWFL_E_NOERROR 391 && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON)) 392 return error; 393 } 394 395 value = sym.st_value; 396 } 397 398 /* These are the types we can relocate. */ 399 #define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \ 400 DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \ 401 DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword) 402 size_t size; 403 switch (type) 404 { 405 #define DO_TYPE(NAME, Name) \ 406 case ELF_T_##NAME: \ 407 size = sizeof (GElf_##Name); \ 408 break 409 TYPES; 410 #undef DO_TYPE 411 default: 412 return DWFL_E_BADRELTYPE; 413 } 414 415 if (offset > tdata->d_size || tdata->d_size - offset < size) 416 return DWFL_E_BADRELOFF; 417 418 #define DO_TYPE(NAME, Name) GElf_##Name Name; 419 union { TYPES; } tmpbuf; 420 #undef DO_TYPE 421 Elf_Data tmpdata = 422 { 423 .d_type = type, 424 .d_buf = &tmpbuf, 425 .d_size = size, 426 .d_version = EV_CURRENT, 427 }; 428 Elf_Data rdata = 429 { 430 .d_type = type, 431 .d_buf = tdata->d_buf + offset, 432 .d_size = size, 433 .d_version = EV_CURRENT, 434 }; 435 436 /* XXX check for overflow? */ 437 if (addend) 438 { 439 /* For the addend form, we have the value already. */ 440 value += *addend; 441 switch (type) 442 { 443 #define DO_TYPE(NAME, Name) \ 444 case ELF_T_##NAME: \ 445 tmpbuf.Name = value; \ 446 break 447 TYPES; 448 #undef DO_TYPE 449 default: 450 abort (); 451 } 452 } 453 else 454 { 455 /* Extract the original value and apply the reloc. */ 456 Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata, 457 ehdr->e_ident[EI_DATA]); 458 if (d == NULL) 459 return DWFL_E_LIBELF; 460 assert (d == &tmpdata); 461 switch (type) 462 { 463 #define DO_TYPE(NAME, Name) \ 464 case ELF_T_##NAME: \ 465 tmpbuf.Name += (GElf_##Name) value; \ 466 break 467 TYPES; 468 #undef DO_TYPE 469 default: 470 abort (); 471 } 472 } 473 474 /* Now convert the relocated datum back to the target 475 format. This will write into rdata.d_buf, which 476 points into the raw section data being relocated. */ 477 Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata, 478 ehdr->e_ident[EI_DATA]); 479 if (s == NULL) 480 return DWFL_E_LIBELF; 481 assert (s == &rdata); 482 483 /* We have applied this relocation! */ 484 return DWFL_E_NOERROR; 485 } 486 487 /* Fetch the relocation section and apply each reloc in it. */ 488 Elf_Data *reldata = elf_getdata (scn, NULL); 489 if (reldata == NULL) 490 return DWFL_E_LIBELF; 491 492 Dwfl_Error result = DWFL_E_NOERROR; 493 bool first_badreltype = true; 494 inline void check_badreltype (void) 495 { 496 if (first_badreltype) 497 { 498 first_badreltype = false; 499 if (ebl_get_elfmachine (mod->ebl) == EM_NONE) 500 /* This might be because ebl_openbackend failed to find 501 any libebl_CPU.so library. Diagnose that clearly. */ 502 result = DWFL_E_UNKNOWN_MACHINE; 503 } 504 } 505 506 size_t sh_entsize 507 = gelf_fsize (relocated, shdr->sh_type == SHT_REL ? ELF_T_REL : ELF_T_RELA, 508 1, EV_CURRENT); 509 size_t nrels = shdr->sh_size / sh_entsize; 510 size_t complete = 0; 511 if (shdr->sh_type == SHT_REL) 512 for (size_t relidx = 0; !result && relidx < nrels; ++relidx) 513 { 514 GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem); 515 if (r == NULL) 516 return DWFL_E_LIBELF; 517 result = relocate (r->r_offset, NULL, 518 GELF_R_TYPE (r->r_info), 519 GELF_R_SYM (r->r_info)); 520 check_badreltype (); 521 if (partial) 522 switch (result) 523 { 524 case DWFL_E_NOERROR: 525 /* We applied the relocation. Elide it. */ 526 memset (&rel_mem, 0, sizeof rel_mem); 527 gelf_update_rel (reldata, relidx, &rel_mem); 528 ++complete; 529 break; 530 case DWFL_E_BADRELTYPE: 531 case DWFL_E_RELUNDEF: 532 /* We couldn't handle this relocation. Skip it. */ 533 result = DWFL_E_NOERROR; 534 break; 535 default: 536 break; 537 } 538 } 539 else 540 for (size_t relidx = 0; !result && relidx < nrels; ++relidx) 541 { 542 GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx, 543 &rela_mem); 544 if (r == NULL) 545 return DWFL_E_LIBELF; 546 result = relocate (r->r_offset, &r->r_addend, 547 GELF_R_TYPE (r->r_info), 548 GELF_R_SYM (r->r_info)); 549 check_badreltype (); 550 if (partial) 551 switch (result) 552 { 553 case DWFL_E_NOERROR: 554 /* We applied the relocation. Elide it. */ 555 memset (&rela_mem, 0, sizeof rela_mem); 556 gelf_update_rela (reldata, relidx, &rela_mem); 557 ++complete; 558 break; 559 case DWFL_E_BADRELTYPE: 560 case DWFL_E_RELUNDEF: 561 /* We couldn't handle this relocation. Skip it. */ 562 result = DWFL_E_NOERROR; 563 break; 564 default: 565 break; 566 } 567 } 568 569 if (likely (result == DWFL_E_NOERROR)) 570 { 571 if (!partial || complete == nrels) 572 /* Mark this relocation section as being empty now that we have 573 done its work. This affects unstrip -R, so e.g. it emits an 574 empty .rela.debug_info along with a .debug_info that has 575 already been fully relocated. */ 576 nrels = 0; 577 else if (complete != 0) 578 { 579 /* We handled some of the relocations but not all. 580 We've zeroed out the ones we processed. 581 Now remove them from the section. */ 582 583 size_t next = 0; 584 if (shdr->sh_type == SHT_REL) 585 for (size_t relidx = 0; relidx < nrels; ++relidx) 586 { 587 GElf_Rel rel_mem; 588 GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem); 589 if (r->r_info != 0 || r->r_offset != 0) 590 { 591 if (next != relidx) 592 gelf_update_rel (reldata, next, r); 593 ++next; 594 } 595 } 596 else 597 for (size_t relidx = 0; relidx < nrels; ++relidx) 598 { 599 GElf_Rela rela_mem; 600 GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem); 601 if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0) 602 { 603 if (next != relidx) 604 gelf_update_rela (reldata, next, r); 605 ++next; 606 } 607 } 608 nrels = next; 609 } 610 611 shdr->sh_size = reldata->d_size = nrels * sh_entsize; 612 gelf_update_shdr (scn, shdr); 613 } 614 615 return result; 616 } 617 618 Dwfl_Error 619 internal_function 620 __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug) 621 { 622 assert (mod->e_type == ET_REL); 623 624 GElf_Ehdr ehdr_mem; 625 const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem); 626 if (ehdr == NULL) 627 return DWFL_E_LIBELF; 628 629 size_t d_shstrndx; 630 if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0) 631 return DWFL_E_LIBELF; 632 633 RELOC_SYMTAB_CACHE (reloc_symtab); 634 635 /* Look at each section in the debuginfo file, and process the 636 relocation sections for debugging sections. */ 637 Dwfl_Error result = DWFL_E_NOERROR; 638 Elf_Scn *scn = NULL; 639 while (result == DWFL_E_NOERROR 640 && (scn = elf_nextscn (debugfile, scn)) != NULL) 641 { 642 GElf_Shdr shdr_mem; 643 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 644 645 if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) 646 && shdr->sh_size != 0) 647 { 648 /* It's a relocation section. */ 649 650 Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info); 651 if (unlikely (tscn == NULL)) 652 result = DWFL_E_LIBELF; 653 else 654 result = relocate_section (mod, debugfile, ehdr, d_shstrndx, 655 &reloc_symtab, scn, shdr, tscn, 656 debug, !debug); 657 } 658 } 659 660 return result; 661 } 662 663 Dwfl_Error 664 internal_function 665 __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated, 666 Elf_Scn *relocscn, Elf_Scn *tscn, bool partial) 667 { 668 GElf_Ehdr ehdr_mem; 669 GElf_Shdr shdr_mem; 670 671 RELOC_SYMTAB_CACHE (reloc_symtab); 672 673 size_t shstrndx; 674 if (elf_getshdrstrndx (relocated, &shstrndx) < 0) 675 return DWFL_E_LIBELF; 676 677 return (__libdwfl_module_getebl (mod) 678 ?: relocate_section (mod, relocated, 679 gelf_getehdr (relocated, &ehdr_mem), shstrndx, 680 &reloc_symtab, 681 relocscn, gelf_getshdr (relocscn, &shdr_mem), 682 tscn, false, partial)); 683 } 684