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