ltrace-elf.c revision 7a2bdf8e5bf49d2fbb700981efd1d0a8728340ed
1# include "config.h" 2 3#include <endian.h> 4#include <errno.h> 5#include <error.h> 6#include <fcntl.h> 7#include <gelf.h> 8#include <stdint.h> 9#include <stdlib.h> 10#include <string.h> 11#include <unistd.h> 12#include <assert.h> 13 14#include "common.h" 15 16void do_init_elf(struct ltelf *lte, const char *filename); 17void do_close_elf(struct ltelf *lte); 18void add_library_symbol(GElf_Addr addr, const char *name, 19 struct library_symbol **library_symbolspp, 20 enum toplt type_of_plt, int is_weak); 21int in_load_libraries(const char *name, struct ltelf *lte, size_t count, GElf_Sym *sym); 22static GElf_Addr opd2addr(struct ltelf *ltc, GElf_Addr addr); 23 24struct library_symbol *library_symbols = NULL; 25#ifdef PLT_REINITALISATION_BP 26extern char *PLTs_initialized_by_here; 27#endif 28 29#ifndef DT_PPC_GOT 30# define DT_PPC_GOT (DT_LOPROC + 0) 31#endif 32 33#define PPC_PLT_STUB_SIZE 16 34 35static Elf_Data *loaddata(Elf_Scn *scn, GElf_Shdr *shdr) 36{ 37 Elf_Data *data = elf_getdata(scn, NULL); 38 if (data == NULL || elf_getdata(scn, data) != NULL 39 || data->d_off || data->d_size != shdr->sh_size) 40 return NULL; 41 return data; 42} 43 44static int inside(GElf_Addr addr, GElf_Shdr *shdr) 45{ 46 return addr >= shdr->sh_addr 47 && addr < shdr->sh_addr + shdr->sh_size; 48} 49 50static int maybe_pick_section(GElf_Addr addr, 51 Elf_Scn *in_sec, GElf_Shdr *in_shdr, 52 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr) 53{ 54 if (inside (addr, in_shdr)) { 55 *tgt_sec = in_sec; 56 *tgt_shdr = *in_shdr; 57 return 1; 58 } 59 return 0; 60} 61 62static int get_section_covering(struct ltelf *lte, GElf_Addr addr, 63 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr) 64{ 65 int i; 66 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 67 Elf_Scn *scn; 68 GElf_Shdr shdr; 69 70 scn = elf_getscn(lte->elf, i); 71 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) { 72 debug(1, "Couldn't read section or header."); 73 return 0; 74 } 75 76 if (maybe_pick_section(addr, scn, &shdr, tgt_sec, tgt_shdr)) 77 return 1; 78 } 79 80 return 0; 81} 82 83static GElf_Addr read32be(Elf_Data *data, size_t offset) 84{ 85 if (data->d_size < offset + 4) { 86 debug(1, "Not enough data to read 32bit value at offset %zd.", 87 offset); 88 return 0; 89 } 90 91 unsigned char const *buf = data->d_buf + offset; 92 return ((Elf32_Word)buf[0] << 24) 93 | ((Elf32_Word)buf[1] << 16) 94 | ((Elf32_Word)buf[2] << 8) 95 | ((Elf32_Word)buf[3]); 96} 97 98static GElf_Addr get_glink_vma(struct ltelf *lte, GElf_Addr ppcgot, 99 Elf_Data *plt_data) 100{ 101 Elf_Scn *ppcgot_sec = NULL; 102 GElf_Shdr ppcgot_shdr; 103 if (ppcgot != 0 104 && !get_section_covering(lte, ppcgot, &ppcgot_sec, &ppcgot_shdr)) 105 // xxx should be the log out 106 fprintf(stderr, 107 "DT_PPC_GOT=%#lx, but no such section found.\n", 108 ppcgot); 109 110 if (ppcgot_sec != NULL) { 111 Elf_Data *data = loaddata(ppcgot_sec, &ppcgot_shdr); 112 if (data == NULL 113 || data->d_size < 8 ) 114 debug(1, "Couldn't read GOT data."); 115 else { 116 // where PPCGOT begins in .got 117 size_t offset = ppcgot - ppcgot_shdr.sh_addr; 118 GElf_Addr glink_vma = read32be(data, offset + 4); 119 if (glink_vma != 0) { 120 debug(1, "PPC GOT glink_vma address: %#lx", 121 glink_vma); 122 return glink_vma; 123 } 124 } 125 } 126 127 if (plt_data != NULL) { 128 GElf_Addr glink_vma = read32be(plt_data, 0); 129 debug(1, ".plt glink_vma address: %#lx", glink_vma); 130 return glink_vma; 131 } 132 133 return 0; 134} 135 136void 137do_init_elf(struct ltelf *lte, const char *filename) { 138 int i; 139 GElf_Addr relplt_addr = 0; 140 size_t relplt_size = 0; 141 142 debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename); 143 debug(1, "Reading ELF from %s...", filename); 144 145 memset(lte, 0, sizeof(*lte)); 146 lte->fd = open(filename, O_RDONLY); 147 if (lte->fd == -1) 148 error(EXIT_FAILURE, errno, "Can't open \"%s\"", filename); 149 150#ifdef HAVE_ELF_C_READ_MMAP 151 lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL); 152#else 153 lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL); 154#endif 155 156 if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF) 157 error(EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename); 158 159 if (gelf_getehdr(lte->elf, <e->ehdr) == NULL) 160 error(EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"", 161 filename); 162 163 if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN) 164 error(EXIT_FAILURE, 0, 165 "\"%s\" is not an ELF executable nor shared library", 166 filename); 167 168 if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS 169 || lte->ehdr.e_machine != LT_ELF_MACHINE) 170#ifdef LT_ELF_MACHINE2 171 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2 172 || lte->ehdr.e_machine != LT_ELF_MACHINE2) 173#endif 174#ifdef LT_ELF_MACHINE3 175 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3 176 || lte->ehdr.e_machine != LT_ELF_MACHINE3) 177#endif 178 ) 179 error(EXIT_FAILURE, 0, 180 "\"%s\" is ELF from incompatible architecture", filename); 181 182 Elf_Data *plt_data = NULL; 183 GElf_Addr ppcgot = 0; 184 185 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 186 Elf_Scn *scn; 187 GElf_Shdr shdr; 188 const char *name; 189 190 scn = elf_getscn(lte->elf, i); 191 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 192 error(EXIT_FAILURE, 0, 193 "Couldn't get section header from \"%s\"", 194 filename); 195 196 name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name); 197 if (name == NULL) 198 error(EXIT_FAILURE, 0, 199 "Couldn't get section header from \"%s\"", 200 filename); 201 202 if (shdr.sh_type == SHT_SYMTAB) { 203 Elf_Data *data; 204 205 lte->symtab = elf_getdata(scn, NULL); 206 lte->symtab_count = shdr.sh_size / shdr.sh_entsize; 207 if ((lte->symtab == NULL 208 || elf_getdata(scn, lte->symtab) != NULL) 209 && opt_x != NULL) 210 error(EXIT_FAILURE, 0, 211 "Couldn't get .symtab data from \"%s\"", 212 filename); 213 214 scn = elf_getscn(lte->elf, shdr.sh_link); 215 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 216 error(EXIT_FAILURE, 0, 217 "Couldn't get section header from \"%s\"", 218 filename); 219 220 data = elf_getdata(scn, NULL); 221 if (data == NULL || elf_getdata(scn, data) != NULL 222 || shdr.sh_size != data->d_size || data->d_off) 223 error(EXIT_FAILURE, 0, 224 "Couldn't get .strtab data from \"%s\"", 225 filename); 226 227 lte->strtab = data->d_buf; 228 } else if (shdr.sh_type == SHT_DYNSYM) { 229 Elf_Data *data; 230 231 lte->dynsym = elf_getdata(scn, NULL); 232 lte->dynsym_count = shdr.sh_size / shdr.sh_entsize; 233 if (lte->dynsym == NULL 234 || elf_getdata(scn, lte->dynsym) != NULL) 235 error(EXIT_FAILURE, 0, 236 "Couldn't get .dynsym data from \"%s\"", 237 filename); 238 239 scn = elf_getscn(lte->elf, shdr.sh_link); 240 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 241 error(EXIT_FAILURE, 0, 242 "Couldn't get section header from \"%s\"", 243 filename); 244 245 data = elf_getdata(scn, NULL); 246 if (data == NULL || elf_getdata(scn, data) != NULL 247 || shdr.sh_size != data->d_size || data->d_off) 248 error(EXIT_FAILURE, 0, 249 "Couldn't get .dynstr data from \"%s\"", 250 filename); 251 252 lte->dynstr = data->d_buf; 253 } else if (shdr.sh_type == SHT_DYNAMIC) { 254 Elf_Data *data; 255 size_t j; 256 257 lte->dyn_addr = shdr.sh_addr; 258 lte->dyn_sz = shdr.sh_size; 259 260 data = elf_getdata(scn, NULL); 261 if (data == NULL || elf_getdata(scn, data) != NULL) 262 error(EXIT_FAILURE, 0, 263 "Couldn't get .dynamic data from \"%s\"", 264 filename); 265 266 for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) { 267 GElf_Dyn dyn; 268 269 if (gelf_getdyn(data, j, &dyn) == NULL) 270 error(EXIT_FAILURE, 0, 271 "Couldn't get .dynamic data from \"%s\"", 272 filename); 273#ifdef __mips__ 274/** 275 MIPS ABI Supplement: 276 277 DT_PLTGOT This member holds the address of the .got section. 278 279 DT_MIPS_SYMTABNO This member holds the number of entries in the 280 .dynsym section. 281 282 DT_MIPS_LOCAL_GOTNO This member holds the number of local global 283 offset table entries. 284 285 DT_MIPS_GOTSYM This member holds the index of the first dyamic 286 symbol table entry that corresponds to an entry in the gobal offset 287 table. 288 289 */ 290 if(dyn.d_tag==DT_PLTGOT){ 291 lte->pltgot_addr=dyn.d_un.d_ptr; 292 } 293 if(dyn.d_tag==DT_MIPS_LOCAL_GOTNO){ 294 lte->mips_local_gotno=dyn.d_un.d_val; 295 } 296 if(dyn.d_tag==DT_MIPS_GOTSYM){ 297 lte->mips_gotsym=dyn.d_un.d_val; 298 } 299#endif // __mips__ 300 if (dyn.d_tag == DT_JMPREL) 301 relplt_addr = dyn.d_un.d_ptr; 302 else if (dyn.d_tag == DT_PLTRELSZ) 303 relplt_size = dyn.d_un.d_val; 304 else if (dyn.d_tag == DT_PPC_GOT) { 305 ppcgot = dyn.d_un.d_val; 306 debug(1, "ppcgot %#lx", ppcgot); 307 } 308 } 309 } else if (shdr.sh_type == SHT_HASH) { 310 Elf_Data *data; 311 size_t j; 312 313 lte->hash_type = SHT_HASH; 314 315 data = elf_getdata(scn, NULL); 316 if (data == NULL || elf_getdata(scn, data) != NULL 317 || data->d_off || data->d_size != shdr.sh_size) 318 error(EXIT_FAILURE, 0, 319 "Couldn't get .hash data from \"%s\"", 320 filename); 321 322 if (shdr.sh_entsize == 4) { 323 /* Standard conforming ELF. */ 324 if (data->d_type != ELF_T_WORD) 325 error(EXIT_FAILURE, 0, 326 "Couldn't get .hash data from \"%s\"", 327 filename); 328 lte->hash = (Elf32_Word *) data->d_buf; 329 } else if (shdr.sh_entsize == 8) { 330 /* Alpha or s390x. */ 331 Elf32_Word *dst, *src; 332 size_t hash_count = data->d_size / 8; 333 334 lte->hash = (Elf32_Word *) 335 malloc(hash_count * sizeof(Elf32_Word)); 336 if (lte->hash == NULL) 337 error(EXIT_FAILURE, 0, 338 "Couldn't convert .hash section from \"%s\"", 339 filename); 340 lte->lte_flags |= LTE_HASH_MALLOCED; 341 dst = lte->hash; 342 src = (Elf32_Word *) data->d_buf; 343 if ((data->d_type == ELF_T_WORD 344 && __BYTE_ORDER == __BIG_ENDIAN) 345 || (data->d_type == ELF_T_XWORD 346 && lte->ehdr.e_ident[EI_DATA] == 347 ELFDATA2MSB)) 348 ++src; 349 for (j = 0; j < hash_count; ++j, src += 2) 350 *dst++ = *src; 351 } else 352 error(EXIT_FAILURE, 0, 353 "Unknown .hash sh_entsize in \"%s\"", 354 filename); 355 } else if (shdr.sh_type == SHT_GNU_HASH 356 && lte->hash == NULL) { 357 Elf_Data *data; 358 359 lte->hash_type = SHT_GNU_HASH; 360 361 if (shdr.sh_entsize != 0 362 && shdr.sh_entsize != 4) { 363 error(EXIT_FAILURE, 0, 364 ".gnu.hash sh_entsize in \"%s\" should be 4, but is %llu", 365 filename, shdr.sh_entsize); 366 } 367 368 data = loaddata(scn, &shdr); 369 if (data == NULL) 370 error(EXIT_FAILURE, 0, 371 "Couldn't get .gnu.hash data from \"%s\"", 372 filename); 373 374 lte->hash = (Elf32_Word *) data->d_buf; 375 } else if (shdr.sh_type == SHT_PROGBITS 376 || shdr.sh_type == SHT_NOBITS) { 377 if (strcmp(name, ".plt") == 0) { 378 lte->plt_addr = shdr.sh_addr; 379 lte->plt_size = shdr.sh_size; 380 if (shdr.sh_flags & SHF_EXECINSTR) { 381 lte->lte_flags |= LTE_PLT_EXECUTABLE; 382 } 383 if (lte->ehdr.e_machine == EM_PPC) { 384 plt_data = loaddata(scn, &shdr); 385 if (plt_data == NULL) 386 fprintf(stderr, 387 "Can't load .plt data\n"); 388 } 389 } 390#ifdef ARCH_SUPPORTS_OPD 391 else if (strcmp(name, ".opd") == 0) { 392 lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr; 393 lte->opd_size = shdr.sh_size; 394 lte->opd = elf_rawdata(scn, NULL); 395 } 396#endif 397 } 398 } 399 400 if (lte->dynsym == NULL || lte->dynstr == NULL) 401 error(EXIT_FAILURE, 0, 402 "Couldn't find .dynsym or .dynstr in \"%s\"", filename); 403 404 if (!relplt_addr || !lte->plt_addr) { 405 debug(1, "%s has no PLT relocations", filename); 406 lte->relplt = NULL; 407 lte->relplt_count = 0; 408 } else if (relplt_size == 0) { 409 debug(1, "%s has unknown PLT size", filename); 410 lte->relplt = NULL; 411 lte->relplt_count = 0; 412 } else { 413 if (lte->ehdr.e_machine == EM_PPC) { 414 GElf_Addr glink_vma 415 = get_glink_vma(lte, ppcgot, plt_data); 416 417 assert (relplt_size % 12 == 0); 418 size_t count = relplt_size / 12; // size of RELA entry 419 lte->plt_stub_vma = glink_vma 420 - (GElf_Addr)count * PPC_PLT_STUB_SIZE; 421 debug(1, "stub_vma is %#lx", lte->plt_stub_vma); 422 } 423 424 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 425 Elf_Scn *scn; 426 GElf_Shdr shdr; 427 428 scn = elf_getscn(lte->elf, i); 429 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 430 error(EXIT_FAILURE, 0, 431 "Couldn't get section header from \"%s\"", 432 filename); 433 if (shdr.sh_addr == relplt_addr 434 && shdr.sh_size == relplt_size) { 435 lte->relplt = elf_getdata(scn, NULL); 436 lte->relplt_count = 437 shdr.sh_size / shdr.sh_entsize; 438 if (lte->relplt == NULL 439 || elf_getdata(scn, lte->relplt) != NULL) 440 error(EXIT_FAILURE, 0, 441 "Couldn't get .rel*.plt data from \"%s\"", 442 filename); 443 break; 444 } 445 } 446 447 if (i == lte->ehdr.e_shnum) 448 error(EXIT_FAILURE, 0, 449 "Couldn't find .rel*.plt section in \"%s\"", 450 filename); 451 452 debug(1, "%s %zd PLT relocations", filename, lte->relplt_count); 453 } 454} 455 456void 457do_close_elf(struct ltelf *lte) { 458 debug(DEBUG_FUNCTION, "do_close_elf()"); 459 if (lte->lte_flags & LTE_HASH_MALLOCED) 460 free((char *)lte->hash); 461 elf_end(lte->elf); 462 close(lte->fd); 463} 464 465void 466add_library_symbol(GElf_Addr addr, const char *name, 467 struct library_symbol **library_symbolspp, 468 enum toplt type_of_plt, int is_weak) { 469 struct library_symbol *s; 470 471 debug(DEBUG_FUNCTION, "add_library_symbol()"); 472 473 s = malloc(sizeof(struct library_symbol) + strlen(name) + 1); 474 if (s == NULL) 475 error(EXIT_FAILURE, errno, "add_library_symbol failed"); 476 477 s->needs_init = 1; 478 s->is_weak = is_weak; 479 s->plt_type = type_of_plt; 480 s->next = *library_symbolspp; 481 s->enter_addr = (void *)(uintptr_t) addr; 482 s->name = (char *)(s + 1); 483 strcpy(s->name, name); 484 *library_symbolspp = s; 485 486 debug(2, "addr: %p, symbol: \"%s\"", (void *)(uintptr_t) addr, name); 487} 488 489/* stolen from elfutils-0.123 */ 490static unsigned long 491private_elf_gnu_hash(const char *name) { 492 unsigned long h = 5381; 493 const unsigned char *string = (const unsigned char *)name; 494 unsigned char c; 495 for (c = *string; c; c = *++string) 496 h = h * 33 + c; 497 return h & 0xffffffff; 498} 499 500static int 501symbol_matches(struct ltelf *lte, size_t lte_i, GElf_Sym *sym, 502 size_t symidx, const char *name) 503{ 504 GElf_Sym tmp_sym; 505 GElf_Sym *tmp; 506 507 tmp = (sym) ? (sym) : (&tmp_sym); 508 509 if (gelf_getsym(lte[lte_i].dynsym, symidx, tmp) == NULL) 510 error(EXIT_FAILURE, 0, "Couldn't get symbol from .dynsym"); 511 else { 512 tmp->st_value += lte[lte_i].base_addr; 513 debug(2, "symbol found: %s, %zd, %lx", 514 name, lte_i, tmp->st_value); 515 } 516 return tmp->st_value != 0 517 && tmp->st_shndx != SHN_UNDEF 518 && strcmp(name, lte[lte_i].dynstr + tmp->st_name) == 0; 519} 520 521int 522in_load_libraries(const char *name, struct ltelf *lte, size_t count, GElf_Sym *sym) { 523 size_t i; 524 unsigned long hash; 525 unsigned long gnu_hash; 526 527 if (!count) 528 return 1; 529 530 hash = elf_hash((const unsigned char *)name); 531 gnu_hash = private_elf_gnu_hash(name); 532 533 for (i = 0; i < count; ++i) { 534 if (lte[i].hash == NULL) 535 continue; 536 537 if (lte[i].hash_type == SHT_GNU_HASH) { 538 Elf32_Word * hashbase = lte[i].hash; 539 Elf32_Word nbuckets = *hashbase++; 540 Elf32_Word symbias = *hashbase++; 541 Elf32_Word bitmask_nwords = *hashbase++; 542 Elf32_Word * buckets; 543 Elf32_Word * chain_zero; 544 Elf32_Word bucket; 545 546 // +1 for skipped `shift' 547 hashbase += lte[i].ehdr.e_ident[EI_CLASS] * bitmask_nwords + 1; 548 buckets = hashbase; 549 hashbase += nbuckets; 550 chain_zero = hashbase - symbias; 551 bucket = buckets[gnu_hash % nbuckets]; 552 553 if (bucket != 0) { 554 const Elf32_Word *hasharr = &chain_zero[bucket]; 555 do 556 if ((*hasharr & ~1u) == (gnu_hash & ~1u)) { 557 int symidx = hasharr - chain_zero; 558 if (symbol_matches(lte, i, 559 sym, symidx, 560 name)) 561 return 1; 562 } 563 while ((*hasharr++ & 1u) == 0); 564 } 565 } else { 566 Elf32_Word nbuckets, symndx; 567 Elf32_Word *buckets, *chain; 568 nbuckets = lte[i].hash[0]; 569 buckets = <e[i].hash[2]; 570 chain = <e[i].hash[2 + nbuckets]; 571 572 for (symndx = buckets[hash % nbuckets]; 573 symndx != STN_UNDEF; symndx = chain[symndx]) 574 if (symbol_matches(lte, i, sym, symndx, name)) 575 return 1; 576 } 577 } 578 return 0; 579} 580 581static GElf_Addr 582opd2addr(struct ltelf *lte, GElf_Addr addr) { 583#ifdef ARCH_SUPPORTS_OPD 584 unsigned long base, offset; 585 586 if (!lte->opd) 587 return addr; 588 589 base = (unsigned long)lte->opd->d_buf; 590 offset = (unsigned long)addr - (unsigned long)lte->opd_addr; 591 if (offset > lte->opd_size) 592 error(EXIT_FAILURE, 0, "static plt not in .opd"); 593 594 return *(GElf_Addr*)(base + offset); 595#else //!ARCH_SUPPORTS_OPD 596 return addr; 597#endif 598} 599 600struct library_symbol * 601read_elf(Process *proc) { 602 struct ltelf lte[MAX_LIBRARIES + 1]; 603 size_t i; 604 struct opt_x_t *xptr; 605 struct library_symbol **lib_tail = NULL; 606 int exit_out = 0; 607 int count = 0; 608 609 debug(DEBUG_FUNCTION, "read_elf(file=%s)", proc->filename); 610 611 library_symbols = NULL; 612 library_num = 0; 613 elf_version(EV_CURRENT); 614 615 do_init_elf(lte, proc->filename); 616 proc->e_machine = lte->ehdr.e_machine; 617 for (i = 0; i < library_num; ++i) 618 do_init_elf(<e[i + 1], library[i]); 619 620 if (!options.no_plt) { 621#ifdef __mips__ 622 // MIPS doesn't use the PLT and the GOT entries get changed 623 // on startup. 624 proc->need_to_reinitialize_breakpoints = 1; 625 for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){ 626 GElf_Sym sym; 627 const char *name; 628 GElf_Addr addr = arch_plt_sym_val(lte, i, 0); 629 if (gelf_getsym(lte->dynsym, i, &sym) == NULL){ 630 error(EXIT_FAILURE, 0, 631 "Couldn't get relocation from \"%s\"", 632 proc->filename); 633 } 634 name=lte->dynstr+sym.st_name; 635 if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){ 636 debug(2,"sym %s not a function",name); 637 continue; 638 } 639 add_library_symbol(addr, name, &library_symbols, 0, 640 ELF64_ST_BIND(sym.st_info) != 0); 641 if (!lib_tail) 642 lib_tail = &(library_symbols->next); 643 } 644#else 645 for (i = 0; i < lte->relplt_count; ++i) { 646 GElf_Rel rel; 647 GElf_Rela rela; 648 GElf_Sym sym; 649 GElf_Addr addr; 650 void *ret; 651 const char *name; 652 653 if (lte->relplt->d_type == ELF_T_REL) { 654 ret = gelf_getrel(lte->relplt, i, &rel); 655 rela.r_offset = rel.r_offset; 656 rela.r_info = rel.r_info; 657 rela.r_addend = 0; 658 } else 659 ret = gelf_getrela(lte->relplt, i, &rela); 660 661 if (ret == NULL 662 || ELF64_R_SYM(rela.r_info) >= lte->dynsym_count 663 || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info), 664 &sym) == NULL) 665 error(EXIT_FAILURE, 0, 666 "Couldn't get relocation from \"%s\"", 667 proc->filename); 668 669#ifdef PLT_REINITALISATION_BP 670 if (!sym.st_value && PLTs_initialized_by_here) 671 proc->need_to_reinitialize_breakpoints = 1; 672#endif 673 674 name = lte->dynstr + sym.st_name; 675 count = library_num ? library_num+1 : 0; 676 677 if (in_load_libraries(name, lte, count, NULL)) { 678 enum toplt pltt; 679 if (sym.st_value == 0 && lte->plt_stub_vma != 0) { 680 pltt = LS_TOPLT_EXEC; 681 addr = lte->plt_stub_vma + PPC_PLT_STUB_SIZE * i; 682 } 683 else { 684 pltt = PLTS_ARE_EXECUTABLE(lte) 685 ? LS_TOPLT_EXEC : LS_TOPLT_POINT; 686 addr = arch_plt_sym_val(lte, i, &rela); 687 } 688 689 add_library_symbol(addr, name, &library_symbols, pltt, 690 ELF64_ST_BIND(sym.st_info) == STB_WEAK); 691 if (!lib_tail) 692 lib_tail = &(library_symbols->next); 693 } 694 } 695#endif // !__mips__ 696#ifdef PLT_REINITALISATION_BP 697 struct opt_x_t *main_cheat; 698 699 if (proc->need_to_reinitialize_breakpoints) { 700 /* Add "PLTs_initialized_by_here" to opt_x list, if not 701 already there. */ 702 main_cheat = (struct opt_x_t *)malloc(sizeof(struct opt_x_t)); 703 if (main_cheat == NULL) 704 error(EXIT_FAILURE, 0, "Couldn't allocate memory"); 705 main_cheat->next = opt_x; 706 main_cheat->found = 0; 707 main_cheat->name = PLTs_initialized_by_here; 708 709 for (xptr = opt_x; xptr; xptr = xptr->next) 710 if (strcmp(xptr->name, PLTs_initialized_by_here) == 0 711 && main_cheat) { 712 free(main_cheat); 713 main_cheat = NULL; 714 break; 715 } 716 if (main_cheat) 717 opt_x = main_cheat; 718 } 719#endif 720 } else { 721 lib_tail = &library_symbols; 722 } 723 724 for (i = 0; i < lte->symtab_count; ++i) { 725 GElf_Sym sym; 726 GElf_Addr addr; 727 const char *name; 728 729 if (gelf_getsym(lte->symtab, i, &sym) == NULL) 730 error(EXIT_FAILURE, 0, 731 "Couldn't get symbol from \"%s\"", 732 proc->filename); 733 734 name = lte->strtab + sym.st_name; 735 addr = sym.st_value; 736 if (!addr) 737 continue; 738 739 for (xptr = opt_x; xptr; xptr = xptr->next) 740 if (xptr->name && strcmp(xptr->name, name) == 0) { 741 /* FIXME: Should be able to use &library_symbols as above. But 742 when you do, none of the real library symbols cause breaks. */ 743 add_library_symbol(opd2addr(lte, addr), 744 name, lib_tail, LS_TOPLT_NONE, 0); 745 xptr->found = 1; 746 break; 747 } 748 } 749 750 int found_count = 0; 751 752 for (xptr = opt_x; xptr; xptr = xptr->next) { 753 if (xptr->found) 754 continue; 755 756 GElf_Sym sym; 757 GElf_Addr addr; 758 if (in_load_libraries(xptr->name, lte, library_num+1, &sym)) { 759 debug(2, "found symbol %s @ %lx, adding it.", xptr->name, sym.st_value); 760 addr = sym.st_value; 761 if (ELF32_ST_TYPE (sym.st_info) == STT_FUNC) { 762 add_library_symbol(addr, xptr->name, lib_tail, LS_TOPLT_NONE, 0); 763 xptr->found = 1; 764 found_count++; 765 } 766 } 767 if (found_count == opt_x_cnt){ 768 debug(2, "done, found everything: %d\n", found_count); 769 break; 770 } 771 } 772 773 for (xptr = opt_x; xptr; xptr = xptr->next) 774 if ( ! xptr->found) { 775 char *badthing = "WARNING"; 776#ifdef PLT_REINITALISATION_BP 777 if (strcmp(xptr->name, PLTs_initialized_by_here) == 0) { 778 if (lte->ehdr.e_entry) { 779 add_library_symbol ( 780 opd2addr (lte, lte->ehdr.e_entry), 781 PLTs_initialized_by_here, 782 lib_tail, 1, 0); 783 fprintf (stderr, "WARNING: Using e_ent" 784 "ry from elf header (%p) for " 785 "address of \"%s\"\n", (void*) 786 (long) lte->ehdr.e_entry, 787 PLTs_initialized_by_here); 788 continue; 789 } 790 badthing = "ERROR"; 791 exit_out = 1; 792 } 793#endif 794 fprintf (stderr, 795 "%s: Couldn't find symbol \"%s\" in file \"%s" 796 "\"\n", badthing, xptr->name, proc->filename); 797 } 798 if (exit_out) { 799 exit (1); 800 } 801 802 for (i = 0; i < library_num + 1; ++i) 803 do_close_elf(<e[i]); 804 805 return library_symbols; 806} 807