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