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 31typedef 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 36Dwfl_Error 37internal_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. */ 92struct 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. */ 107static Dwfl_Error 108relocate_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 { 127 /* We need uncompressed data. */ 128 if ((shdr->sh_type == SHT_SYMTAB 129 || shdr->sh_type == SHT_SYMTAB_SHNDX) 130 && (shdr->sh_flags & SHF_COMPRESSED) != 0) 131 if (elf_compress (scn, 0, 0) < 0) 132 return DWFL_E_LIBELF; 133 134 switch (shdr->sh_type) 135 { 136 default: 137 continue; 138 case SHT_SYMTAB: 139 cache->symelf = relocated; 140 cache->symdata = elf_getdata (scn, NULL); 141 cache->strtabndx = shdr->sh_link; 142 if (unlikely (cache->symdata == NULL)) 143 return DWFL_E_LIBELF; 144 break; 145 case SHT_SYMTAB_SHNDX: 146 cache->symxndxdata = elf_getdata (scn, NULL); 147 if (unlikely (cache->symxndxdata == NULL)) 148 return DWFL_E_LIBELF; 149 break; 150 } 151 } 152 if (cache->symdata != NULL && cache->symxndxdata != NULL) 153 break; 154 } 155 } 156 if (cache->symdata == NULL) 157 { 158 /* We might not have looked for a symbol table file yet, 159 when coming from __libdwfl_relocate_section. */ 160 if (unlikely (mod->symfile == NULL) 161 && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0)) 162 return dwfl_errno (); 163 164 /* The symbol table we have already cached is the one from 165 the file being relocated, so it's what we need. Or else 166 this is an ET_REL .debug file with no .symtab of its own; 167 the symbols refer to the section indices in the main file. */ 168 cache->symelf = mod->symfile->elf; 169 cache->symdata = mod->symdata; 170 cache->symxndxdata = mod->symxndxdata; 171 cache->symstrdata = mod->symstrdata; 172 } 173 } 174 175 if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata, 176 symndx, sym, shndx) == NULL)) 177 return DWFL_E_LIBELF; 178 179 if (sym->st_shndx != SHN_XINDEX) 180 *shndx = sym->st_shndx; 181 182 switch (sym->st_shndx) 183 { 184 case SHN_ABS: 185 case SHN_UNDEF: 186 return DWFL_E_NOERROR; 187 188 case SHN_COMMON: 189 sym->st_value = 0; /* Value is size, not helpful. */ 190 return DWFL_E_NOERROR; 191 } 192 193 return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx, 194 *shndx, &sym->st_value); 195} 196 197/* Handle an undefined symbol. We really only support ET_REL for Linux 198 kernel modules, and offline archives. The behavior of the Linux module 199 loader is very simple and easy to mimic. It only matches magically 200 exported symbols, and we match any defined symbols. But we get the same 201 answer except when the module's symbols are undefined and would prevent 202 it from being loaded. */ 203static Dwfl_Error 204resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab, 205 GElf_Sym *sym, GElf_Word shndx) 206{ 207 /* First we need its name. */ 208 if (sym->st_name != 0) 209 { 210 if (symtab->symstrdata == NULL) 211 { 212 /* Cache the strtab for this symtab. */ 213 assert (referer->symfile == NULL 214 || referer->symfile->elf != symtab->symelf); 215 216 Elf_Scn *scn = elf_getscn (symtab->symelf, symtab->strtabndx); 217 if (scn == NULL) 218 return DWFL_E_LIBELF; 219 220 GElf_Shdr shdr_mem; 221 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 222 if (shdr == NULL) 223 return DWFL_E_LIBELF; 224 225 if (symtab->symshstrndx == SHN_UNDEF 226 && elf_getshdrstrndx (symtab->symelf, &symtab->symshstrndx) < 0) 227 return DWFL_E_LIBELF; 228 229 const char *sname = elf_strptr (symtab->symelf, symtab->symshstrndx, 230 shdr->sh_name); 231 if (sname == NULL) 232 return DWFL_E_LIBELF; 233 234 /* If the section is already decompressed, that isn't an error. */ 235 if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0) 236 elf_compress_gnu (scn, 0, 0); 237 238 if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 239 if (elf_compress (scn, 0, 0) < 0) 240 return DWFL_E_LIBELF; 241 242 symtab->symstrdata = elf_getdata (scn, NULL); 243 if (unlikely (symtab->symstrdata == NULL 244 || symtab->symstrdata->d_buf == NULL)) 245 return DWFL_E_LIBELF; 246 } 247 if (unlikely (sym->st_name >= symtab->symstrdata->d_size)) 248 return DWFL_E_BADSTROFF; 249 250 const char *name = symtab->symstrdata->d_buf; 251 name += sym->st_name; 252 253 for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next) 254 if (m != referer) 255 { 256 /* Get this module's symtab. 257 If we got a fresh error reading the table, report it. 258 If we just have no symbols in this module, no harm done. */ 259 if (m->symdata == NULL 260 && m->symerr == DWFL_E_NOERROR 261 && INTUSE(dwfl_module_getsymtab) (m) < 0 262 && m->symerr != DWFL_E_NO_SYMTAB) 263 return m->symerr; 264 265 for (size_t ndx = 1; ndx < m->syments; ++ndx) 266 { 267 sym = gelf_getsymshndx (m->symdata, m->symxndxdata, 268 ndx, sym, &shndx); 269 if (unlikely (sym == NULL)) 270 return DWFL_E_LIBELF; 271 if (sym->st_shndx != SHN_XINDEX) 272 shndx = sym->st_shndx; 273 274 /* We are looking for a defined global symbol with a name. */ 275 if (shndx == SHN_UNDEF || shndx == SHN_COMMON 276 || GELF_ST_BIND (sym->st_info) == STB_LOCAL 277 || sym->st_name == 0) 278 continue; 279 280 /* Get this candidate symbol's name. */ 281 if (unlikely (sym->st_name >= m->symstrdata->d_size)) 282 return DWFL_E_BADSTROFF; 283 const char *n = m->symstrdata->d_buf; 284 n += sym->st_name; 285 286 /* Does the name match? */ 287 if (strcmp (name, n)) 288 continue; 289 290 /* We found it! */ 291 if (shndx == SHN_ABS) /* XXX maybe should apply bias? */ 292 return DWFL_E_NOERROR; 293 294 if (m->e_type != ET_REL) 295 { 296 sym->st_value = dwfl_adjusted_st_value (m, m->symfile->elf, 297 sym->st_value); 298 return DWFL_E_NOERROR; 299 } 300 301 /* In an ET_REL file, the symbol table values are relative 302 to the section, not to the module's load base. */ 303 size_t symshstrndx = SHN_UNDEF; 304 return __libdwfl_relocate_value (m, m->symfile->elf, 305 &symshstrndx, 306 shndx, &sym->st_value); 307 } 308 } 309 } 310 311 return DWFL_E_RELUNDEF; 312} 313 314/* Apply one relocation. Returns true for any invalid data. */ 315static Dwfl_Error 316relocate (Dwfl_Module * const mod, 317 Elf * const relocated, 318 struct reloc_symtab_cache * const reloc_symtab, 319 Elf_Data * const tdata, 320 const GElf_Ehdr * const ehdr, 321 GElf_Addr offset, 322 const GElf_Sxword *addend, 323 int rtype, 324 int symndx) 325{ 326 /* First see if this is a reloc we can handle. 327 If we are skipping it, don't bother resolving the symbol. */ 328 329 if (unlikely (rtype == 0)) 330 /* In some odd situations, the linker can leave R_*_NONE relocs 331 behind. This is probably bogus ld -r behavior, but the only 332 cases it's known to appear in are harmless: DWARF data 333 referring to addresses in a section that has been discarded. 334 So we just pretend it's OK without further relocation. */ 335 return DWFL_E_NOERROR; 336 337 Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype); 338 if (unlikely (type == ELF_T_NUM)) 339 return DWFL_E_BADRELTYPE; 340 341 /* First, resolve the symbol to an absolute value. */ 342 GElf_Addr value; 343 344 if (symndx == STN_UNDEF) 345 /* When strip removes a section symbol referring to a 346 section moved into the debuginfo file, it replaces 347 that symbol index in relocs with STN_UNDEF. We 348 don't actually need the symbol, because those relocs 349 are always references relative to the nonallocated 350 debugging sections, which start at zero. */ 351 value = 0; 352 else 353 { 354 GElf_Sym sym; 355 GElf_Word shndx; 356 Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab, 357 symndx, &sym, &shndx); 358 if (unlikely (error != DWFL_E_NOERROR)) 359 return error; 360 361 if (shndx == SHN_UNDEF || shndx == SHN_COMMON) 362 { 363 /* Maybe we can figure it out anyway. */ 364 error = resolve_symbol (mod, reloc_symtab, &sym, shndx); 365 if (error != DWFL_E_NOERROR 366 && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON)) 367 return error; 368 } 369 370 value = sym.st_value; 371 } 372 373 /* These are the types we can relocate. */ 374#define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \ 375 DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \ 376 DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword) 377 size_t size; 378 switch (type) 379 { 380#define DO_TYPE(NAME, Name) \ 381 case ELF_T_##NAME: \ 382 size = sizeof (GElf_##Name); \ 383 break 384 TYPES; 385#undef DO_TYPE 386 default: 387 return DWFL_E_BADRELTYPE; 388 } 389 390 if (offset > tdata->d_size || tdata->d_size - offset < size) 391 return DWFL_E_BADRELOFF; 392 393#define DO_TYPE(NAME, Name) GElf_##Name Name; 394 union { TYPES; } tmpbuf; 395#undef DO_TYPE 396 Elf_Data tmpdata = 397 { 398 .d_type = type, 399 .d_buf = &tmpbuf, 400 .d_size = size, 401 .d_version = EV_CURRENT, 402 }; 403 Elf_Data rdata = 404 { 405 .d_type = type, 406 .d_buf = tdata->d_buf + offset, 407 .d_size = size, 408 .d_version = EV_CURRENT, 409 }; 410 411 /* XXX check for overflow? */ 412 if (addend) 413 { 414 /* For the addend form, we have the value already. */ 415 value += *addend; 416 switch (type) 417 { 418#define DO_TYPE(NAME, Name) \ 419 case ELF_T_##NAME: \ 420 tmpbuf.Name = value; \ 421 break 422 TYPES; 423#undef DO_TYPE 424 default: 425 abort (); 426 } 427 } 428 else 429 { 430 /* Extract the original value and apply the reloc. */ 431 Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata, 432 ehdr->e_ident[EI_DATA]); 433 if (d == NULL) 434 return DWFL_E_LIBELF; 435 assert (d == &tmpdata); 436 switch (type) 437 { 438#define DO_TYPE(NAME, Name) \ 439 case ELF_T_##NAME: \ 440 tmpbuf.Name += (GElf_##Name) value; \ 441 break 442 TYPES; 443#undef DO_TYPE 444 default: 445 abort (); 446 } 447 } 448 449 /* Now convert the relocated datum back to the target 450 format. This will write into rdata.d_buf, which 451 points into the raw section data being relocated. */ 452 Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata, 453 ehdr->e_ident[EI_DATA]); 454 if (s == NULL) 455 return DWFL_E_LIBELF; 456 assert (s == &rdata); 457 458 /* We have applied this relocation! */ 459 return DWFL_E_NOERROR; 460} 461 462static inline void 463check_badreltype (bool *first_badreltype, 464 Dwfl_Module *mod, 465 Dwfl_Error *result) 466{ 467 if (*first_badreltype) 468 { 469 *first_badreltype = false; 470 if (ebl_get_elfmachine (mod->ebl) == EM_NONE) 471 /* This might be because ebl_openbackend failed to find 472 any libebl_CPU.so library. Diagnose that clearly. */ 473 *result = DWFL_E_UNKNOWN_MACHINE; 474 } 475} 476 477static Dwfl_Error 478relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, 479 size_t shstrndx, struct reloc_symtab_cache *reloc_symtab, 480 Elf_Scn *scn, GElf_Shdr *shdr, 481 Elf_Scn *tscn, bool debugscn, bool partial) 482{ 483 /* First, fetch the name of the section these relocations apply to. 484 Then try to decompress both relocation and target section. */ 485 GElf_Shdr tshdr_mem; 486 GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem); 487 if (tshdr == NULL) 488 return DWFL_E_LIBELF; 489 490 const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name); 491 if (tname == NULL) 492 return DWFL_E_LIBELF; 493 494 if (debugscn && ! ebl_debugscn_p (mod->ebl, tname)) 495 /* This relocation section is not for a debugging section. 496 Nothing to do here. */ 497 return DWFL_E_NOERROR; 498 499 if (strncmp (tname, ".zdebug", strlen ("zdebug")) == 0) 500 elf_compress_gnu (tscn, 0, 0); 501 502 if ((tshdr->sh_flags & SHF_COMPRESSED) != 0) 503 if (elf_compress (tscn, 0, 0) < 0) 504 return DWFL_E_LIBELF; 505 506 /* Reload Shdr in case section was just decompressed. */ 507 tshdr = gelf_getshdr (tscn, &tshdr_mem); 508 if (tshdr == NULL) 509 return DWFL_E_LIBELF; 510 511 if (unlikely (tshdr->sh_type == SHT_NOBITS) 512 || unlikely (tshdr->sh_size == 0)) 513 /* No contents to relocate. */ 514 return DWFL_E_NOERROR; 515 516 const char *sname = elf_strptr (relocated, shstrndx, shdr->sh_name); 517 if (sname == NULL) 518 return DWFL_E_LIBELF; 519 520 if (strncmp (sname, ".zdebug", strlen ("zdebug")) == 0) 521 elf_compress_gnu (scn, 0, 0); 522 523 if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 524 if (elf_compress (scn, 0, 0) < 0) 525 return DWFL_E_LIBELF; 526 527 /* Reload Shdr in case section was just decompressed. */ 528 GElf_Shdr shdr_mem; 529 shdr = gelf_getshdr (scn, &shdr_mem); 530 if (shdr == NULL) 531 return DWFL_E_LIBELF; 532 533 /* Fetch the section data that needs the relocations applied. */ 534 Elf_Data *tdata = elf_rawdata (tscn, NULL); 535 if (tdata == NULL) 536 return DWFL_E_LIBELF; 537 538 /* If either the section that needs the relocation applied, or the 539 section that the relocations come from overlap one of the ehdrs, 540 shdrs or phdrs data then we refuse to do the relocations. It 541 isn't illegal for ELF section data to overlap the header data, 542 but updating the (relocation) data might corrupt the in-memory 543 libelf headers causing strange corruptions or errors. */ 544 size_t ehsize = gelf_fsize (relocated, ELF_T_EHDR, 1, EV_CURRENT); 545 if (unlikely (shdr->sh_offset < ehsize 546 || tshdr->sh_offset < ehsize)) 547 return DWFL_E_BADELF; 548 549 GElf_Off shdrs_start = ehdr->e_shoff; 550 size_t shnums; 551 if (elf_getshdrnum (relocated, &shnums) < 0) 552 return DWFL_E_LIBELF; 553 /* Overflows will have been checked by elf_getshdrnum/get|rawdata. */ 554 size_t shentsize = gelf_fsize (relocated, ELF_T_SHDR, 1, EV_CURRENT); 555 GElf_Off shdrs_end = shdrs_start + shnums * shentsize; 556 if (unlikely ((shdrs_start < shdr->sh_offset + shdr->sh_size 557 && shdr->sh_offset < shdrs_end) 558 || (shdrs_start < tshdr->sh_offset + tshdr->sh_size 559 && tshdr->sh_offset < shdrs_end))) 560 return DWFL_E_BADELF; 561 562 GElf_Off phdrs_start = ehdr->e_phoff; 563 size_t phnums; 564 if (elf_getphdrnum (relocated, &phnums) < 0) 565 return DWFL_E_LIBELF; 566 if (phdrs_start != 0 && phnums != 0) 567 { 568 /* Overflows will have been checked by elf_getphdrnum/get|rawdata. */ 569 size_t phentsize = gelf_fsize (relocated, ELF_T_PHDR, 1, EV_CURRENT); 570 GElf_Off phdrs_end = phdrs_start + phnums * phentsize; 571 if (unlikely ((phdrs_start < shdr->sh_offset + shdr->sh_size 572 && shdr->sh_offset < phdrs_end) 573 || (phdrs_start < tshdr->sh_offset + tshdr->sh_size 574 && tshdr->sh_offset < phdrs_end))) 575 return DWFL_E_BADELF; 576 } 577 578 /* Fetch the relocation section and apply each reloc in it. */ 579 Elf_Data *reldata = elf_getdata (scn, NULL); 580 if (reldata == NULL) 581 return DWFL_E_LIBELF; 582 583 Dwfl_Error result = DWFL_E_NOERROR; 584 bool first_badreltype = true; 585 586 size_t sh_entsize 587 = gelf_fsize (relocated, shdr->sh_type == SHT_REL ? ELF_T_REL : ELF_T_RELA, 588 1, EV_CURRENT); 589 size_t nrels = shdr->sh_size / sh_entsize; 590 size_t complete = 0; 591 if (shdr->sh_type == SHT_REL) 592 for (size_t relidx = 0; !result && relidx < nrels; ++relidx) 593 { 594 GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem); 595 if (r == NULL) 596 return DWFL_E_LIBELF; 597 result = relocate (mod, relocated, reloc_symtab, tdata, ehdr, 598 r->r_offset, NULL, 599 GELF_R_TYPE (r->r_info), 600 GELF_R_SYM (r->r_info)); 601 check_badreltype (&first_badreltype, mod, &result); 602 if (partial) 603 switch (result) 604 { 605 case DWFL_E_NOERROR: 606 /* We applied the relocation. Elide it. */ 607 memset (&rel_mem, 0, sizeof rel_mem); 608 gelf_update_rel (reldata, relidx, &rel_mem); 609 ++complete; 610 break; 611 case DWFL_E_BADRELTYPE: 612 case DWFL_E_RELUNDEF: 613 /* We couldn't handle this relocation. Skip it. */ 614 result = DWFL_E_NOERROR; 615 break; 616 default: 617 break; 618 } 619 } 620 else 621 for (size_t relidx = 0; !result && relidx < nrels; ++relidx) 622 { 623 GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx, 624 &rela_mem); 625 if (r == NULL) 626 return DWFL_E_LIBELF; 627 result = relocate (mod, relocated, reloc_symtab, tdata, ehdr, 628 r->r_offset, &r->r_addend, 629 GELF_R_TYPE (r->r_info), 630 GELF_R_SYM (r->r_info)); 631 check_badreltype (&first_badreltype, mod, &result); 632 if (partial) 633 switch (result) 634 { 635 case DWFL_E_NOERROR: 636 /* We applied the relocation. Elide it. */ 637 memset (&rela_mem, 0, sizeof rela_mem); 638 gelf_update_rela (reldata, relidx, &rela_mem); 639 ++complete; 640 break; 641 case DWFL_E_BADRELTYPE: 642 case DWFL_E_RELUNDEF: 643 /* We couldn't handle this relocation. Skip it. */ 644 result = DWFL_E_NOERROR; 645 break; 646 default: 647 break; 648 } 649 } 650 651 if (likely (result == DWFL_E_NOERROR)) 652 { 653 if (!partial || complete == nrels) 654 /* Mark this relocation section as being empty now that we have 655 done its work. This affects unstrip -R, so e.g. it emits an 656 empty .rela.debug_info along with a .debug_info that has 657 already been fully relocated. */ 658 nrels = 0; 659 else if (complete != 0) 660 { 661 /* We handled some of the relocations but not all. 662 We've zeroed out the ones we processed. 663 Now remove them from the section. */ 664 665 size_t next = 0; 666 if (shdr->sh_type == SHT_REL) 667 for (size_t relidx = 0; relidx < nrels; ++relidx) 668 { 669 GElf_Rel rel_mem; 670 GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem); 671 if (r->r_info != 0 || r->r_offset != 0) 672 { 673 if (next != relidx) 674 gelf_update_rel (reldata, next, r); 675 ++next; 676 } 677 } 678 else 679 for (size_t relidx = 0; relidx < nrels; ++relidx) 680 { 681 GElf_Rela rela_mem; 682 GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem); 683 if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0) 684 { 685 if (next != relidx) 686 gelf_update_rela (reldata, next, r); 687 ++next; 688 } 689 } 690 nrels = next; 691 } 692 693 shdr->sh_size = reldata->d_size = nrels * sh_entsize; 694 gelf_update_shdr (scn, shdr); 695 } 696 697 return result; 698} 699 700Dwfl_Error 701internal_function 702__libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug) 703{ 704 assert (mod->e_type == ET_REL); 705 706 GElf_Ehdr ehdr_mem; 707 const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem); 708 if (ehdr == NULL) 709 return DWFL_E_LIBELF; 710 711 size_t d_shstrndx; 712 if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0) 713 return DWFL_E_LIBELF; 714 715 RELOC_SYMTAB_CACHE (reloc_symtab); 716 717 /* Look at each section in the debuginfo file, and process the 718 relocation sections for debugging sections. */ 719 Dwfl_Error result = DWFL_E_NOERROR; 720 Elf_Scn *scn = NULL; 721 while (result == DWFL_E_NOERROR 722 && (scn = elf_nextscn (debugfile, scn)) != NULL) 723 { 724 GElf_Shdr shdr_mem; 725 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 726 727 if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) 728 && shdr->sh_size != 0) 729 { 730 /* It's a relocation section. */ 731 732 Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info); 733 if (unlikely (tscn == NULL)) 734 result = DWFL_E_LIBELF; 735 else 736 result = relocate_section (mod, debugfile, ehdr, d_shstrndx, 737 &reloc_symtab, scn, shdr, tscn, 738 debug, !debug); 739 } 740 } 741 742 return result; 743} 744 745Dwfl_Error 746internal_function 747__libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated, 748 Elf_Scn *relocscn, Elf_Scn *tscn, bool partial) 749{ 750 GElf_Ehdr ehdr_mem; 751 GElf_Shdr shdr_mem; 752 753 RELOC_SYMTAB_CACHE (reloc_symtab); 754 755 size_t shstrndx; 756 if (elf_getshdrstrndx (relocated, &shstrndx) < 0) 757 return DWFL_E_LIBELF; 758 759 return (__libdwfl_module_getebl (mod) 760 ?: relocate_section (mod, relocated, 761 gelf_getehdr (relocated, &ehdr_mem), shstrndx, 762 &reloc_symtab, 763 relocscn, gelf_getshdr (relocscn, &shdr_mem), 764 tscn, false, partial)); 765} 766