ltrace-elf.c revision 0b55b5852b9fe2ed6cceada004db303fe6efe6ce
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 <inttypes.h> 9#include <stdint.h> 10#include <stdlib.h> 11#include <string.h> 12#include <unistd.h> 13#include <assert.h> 14 15#include "common.h" 16#include "proc.h" 17#include "library.h" 18 19#ifdef PLT_REINITALISATION_BP 20extern char *PLTs_initialized_by_here; 21#endif 22 23#ifndef DT_PPC_GOT 24# define DT_PPC_GOT (DT_LOPROC + 0) 25#endif 26 27 28#ifndef ARCH_HAVE_LTELF_DATA 29int 30arch_elf_init(struct ltelf *lte) 31{ 32 return 0; 33} 34 35void 36arch_elf_destroy(struct ltelf *lte) 37{ 38} 39#endif 40 41int 42default_elf_add_plt_entry(struct Process *proc, struct ltelf *lte, 43 const char *a_name, GElf_Rela *rela, size_t ndx, 44 struct library_symbol **ret) 45{ 46 char *name = strdup(a_name); 47 if (name == NULL) { 48 fail: 49 free(name); 50 return -1; 51 } 52 53 enum toplt pltt = PLTS_ARE_EXECUTABLE(lte) 54 ? LS_TOPLT_EXEC : LS_TOPLT_POINT; 55 GElf_Addr addr = arch_plt_sym_val(lte, ndx, rela); 56 57 struct library_symbol *libsym = malloc(sizeof(*libsym)); 58 if (libsym == NULL) 59 goto fail; 60 61 target_address_t taddr = (target_address_t)(addr + lte->bias); 62 63 /* The logic behind this conditional translation is as 64 * follows. PLT entries do not typically need custom TOC 65 * pointer, and therefore aren't redirected via OPD. POINT 66 * PLT, on the other hand, most likely contains addresses of 67 * target functions, not PLT entries themselves, and would 68 * need the OPD redirection. */ 69 if (pltt == LS_TOPLT_POINT 70 && arch_translate_address(proc, taddr, &taddr) < 0) { 71 free(libsym); 72 goto fail; 73 } 74 75 library_symbol_init(libsym, taddr, name, 1, pltt); 76 *ret = libsym; 77 return 0; 78} 79 80#ifndef ARCH_HAVE_ADD_PLT_ENTRY 81enum plt_status 82arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte, 83 const char *a_name, GElf_Rela *rela, size_t ndx, 84 struct library_symbol **ret) 85{ 86 return plt_default; 87} 88#endif 89 90Elf_Data * 91elf_loaddata(Elf_Scn *scn, GElf_Shdr *shdr) 92{ 93 Elf_Data *data = elf_getdata(scn, NULL); 94 if (data == NULL || elf_getdata(scn, data) != NULL 95 || data->d_off || data->d_size != shdr->sh_size) 96 return NULL; 97 return data; 98} 99 100static int 101elf_get_section_if(struct ltelf *lte, Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr, 102 int (*predicate)(Elf_Scn *, GElf_Shdr *, void *data), 103 void *data) 104{ 105 int i; 106 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 107 Elf_Scn *scn; 108 GElf_Shdr shdr; 109 110 scn = elf_getscn(lte->elf, i); 111 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) { 112 debug(1, "Couldn't read section or header."); 113 return -1; 114 } 115 if (predicate(scn, &shdr, data)) { 116 *tgt_sec = scn; 117 *tgt_shdr = shdr; 118 return 0; 119 } 120 } 121 return -1; 122 123} 124 125static int 126inside_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data) 127{ 128 GElf_Addr addr = *(GElf_Addr *)data; 129 return addr >= shdr->sh_addr 130 && addr < shdr->sh_addr + shdr->sh_size; 131} 132 133int 134elf_get_section_covering(struct ltelf *lte, GElf_Addr addr, 135 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr) 136{ 137 return elf_get_section_if(lte, tgt_sec, tgt_shdr, 138 &inside_p, &addr); 139} 140 141static int 142type_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data) 143{ 144 GElf_Word type = *(GElf_Word *)data; 145 return shdr->sh_type == type; 146} 147 148int 149elf_get_section_type(struct ltelf *lte, GElf_Word type, 150 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr) 151{ 152 return elf_get_section_if(lte, tgt_sec, tgt_shdr, 153 &type_p, &type); 154} 155 156static int 157need_data(Elf_Data *data, size_t offset, size_t size) 158{ 159 assert(data != NULL); 160 if (data->d_size < size || offset > data->d_size - size) { 161 debug(1, "Not enough data to read %zd-byte value" 162 " at offset %zd.", size, offset); 163 return -1; 164 } 165 return 0; 166} 167 168#define DEF_READER(NAME, SIZE) \ 169 int \ 170 NAME(Elf_Data *data, size_t offset, uint##SIZE##_t *retp) \ 171 { \ 172 if (!need_data(data, offset, SIZE / 8) < 0) \ 173 return -1; \ 174 \ 175 if (data->d_buf == NULL) /* NODATA section */ { \ 176 *retp = 0; \ 177 return 0; \ 178 } \ 179 \ 180 union { \ 181 uint##SIZE##_t dst; \ 182 char buf[0]; \ 183 } u; \ 184 memcpy(u.buf, data->d_buf + offset, sizeof(u.dst)); \ 185 *retp = u.dst; \ 186 return 0; \ 187 } 188 189DEF_READER(elf_read_u16, 16) 190DEF_READER(elf_read_u32, 32) 191DEF_READER(elf_read_u64, 64) 192 193#undef DEF_READER 194 195int 196open_elf(struct ltelf *lte, const char *filename) 197{ 198 lte->fd = open(filename, O_RDONLY); 199 if (lte->fd == -1) 200 return 1; 201 202 elf_version(EV_CURRENT); 203 204#ifdef HAVE_ELF_C_READ_MMAP 205 lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL); 206#else 207 lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL); 208#endif 209 210 if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF) 211 error(EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename); 212 213 if (gelf_getehdr(lte->elf, <e->ehdr) == NULL) 214 error(EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"", 215 filename); 216 217 if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN) 218 error(EXIT_FAILURE, 0, 219 "\"%s\" is not an ELF executable nor shared library", 220 filename); 221 222 if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS 223 || lte->ehdr.e_machine != LT_ELF_MACHINE) 224#ifdef LT_ELF_MACHINE2 225 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2 226 || lte->ehdr.e_machine != LT_ELF_MACHINE2) 227#endif 228#ifdef LT_ELF_MACHINE3 229 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3 230 || lte->ehdr.e_machine != LT_ELF_MACHINE3) 231#endif 232 ) 233 error(EXIT_FAILURE, 0, 234 "\"%s\" is ELF from incompatible architecture", filename); 235 236 return 0; 237} 238 239static int 240do_init_elf(struct ltelf *lte, const char *filename, GElf_Addr bias) 241{ 242 int i; 243 GElf_Addr relplt_addr = 0; 244 GElf_Addr soname_offset = 0; 245 246 debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename); 247 debug(1, "Reading ELF from %s...", filename); 248 249 if (open_elf(lte, filename) < 0) 250 return -1; 251 252 /* Find out the base address. */ 253 { 254 GElf_Phdr phdr; 255 for (i = 0; gelf_getphdr (lte->elf, i, &phdr) != NULL; ++i) { 256 if (phdr.p_type == PT_LOAD) { 257 lte->base_addr = phdr.p_vaddr - bias; 258 fprintf(stderr, 259 " + vaddr=%#lx, bias=%#lx, base=%#lx\n", 260 phdr.p_vaddr, bias, lte->base_addr); 261 break; 262 } 263 } 264 } 265 266 if (lte->base_addr == 0) { 267 fprintf(stderr, "Couldn't determine base address of %s\n", 268 filename); 269 return -1; 270 } 271 272 lte->bias = bias; 273 lte->entry_addr = lte->ehdr.e_entry + lte->bias; 274 275 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 276 Elf_Scn *scn; 277 GElf_Shdr shdr; 278 const char *name; 279 280 scn = elf_getscn(lte->elf, i); 281 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 282 error(EXIT_FAILURE, 0, 283 "Couldn't get section header from \"%s\"", 284 filename); 285 286 name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name); 287 if (name == NULL) 288 error(EXIT_FAILURE, 0, 289 "Couldn't get section header from \"%s\"", 290 filename); 291 292 if (shdr.sh_type == SHT_SYMTAB) { 293 Elf_Data *data; 294 295 lte->symtab = elf_getdata(scn, NULL); 296 lte->symtab_count = shdr.sh_size / shdr.sh_entsize; 297 if ((lte->symtab == NULL 298 || elf_getdata(scn, lte->symtab) != NULL) 299 && opt_x != NULL) 300 error(EXIT_FAILURE, 0, 301 "Couldn't get .symtab data from \"%s\"", 302 filename); 303 304 scn = elf_getscn(lte->elf, shdr.sh_link); 305 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 306 error(EXIT_FAILURE, 0, 307 "Couldn't get section header from \"%s\"", 308 filename); 309 310 data = elf_getdata(scn, NULL); 311 if (data == NULL || elf_getdata(scn, data) != NULL 312 || shdr.sh_size != data->d_size || data->d_off) 313 error(EXIT_FAILURE, 0, 314 "Couldn't get .strtab data from \"%s\"", 315 filename); 316 317 lte->strtab = data->d_buf; 318 } else if (shdr.sh_type == SHT_DYNSYM) { 319 Elf_Data *data; 320 321 lte->dynsym = elf_getdata(scn, NULL); 322 lte->dynsym_count = shdr.sh_size / shdr.sh_entsize; 323 if (lte->dynsym == NULL 324 || elf_getdata(scn, lte->dynsym) != NULL) 325 error(EXIT_FAILURE, 0, 326 "Couldn't get .dynsym data from \"%s\"", 327 filename); 328 329 scn = elf_getscn(lte->elf, shdr.sh_link); 330 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 331 error(EXIT_FAILURE, 0, 332 "Couldn't get section header from \"%s\"", 333 filename); 334 335 data = elf_getdata(scn, NULL); 336 if (data == NULL || elf_getdata(scn, data) != NULL 337 || shdr.sh_size != data->d_size || data->d_off) 338 error(EXIT_FAILURE, 0, 339 "Couldn't get .dynstr data from \"%s\"", 340 filename); 341 342 lte->dynstr = data->d_buf; 343 } else if (shdr.sh_type == SHT_DYNAMIC) { 344 Elf_Data *data; 345 size_t j; 346 347 lte->dyn_addr = shdr.sh_addr; 348 fprintf(stderr, "dyn_addr = %#lx\n", lte->dyn_addr); 349 lte->dyn_sz = shdr.sh_size; 350 351 data = elf_getdata(scn, NULL); 352 if (data == NULL || elf_getdata(scn, data) != NULL) 353 error(EXIT_FAILURE, 0, 354 "Couldn't get .dynamic data from \"%s\"", 355 filename); 356 357 for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) { 358 GElf_Dyn dyn; 359 360 if (gelf_getdyn(data, j, &dyn) == NULL) 361 error(EXIT_FAILURE, 0, 362 "Couldn't get .dynamic data from \"%s\"", 363 filename); 364 if (dyn.d_tag == DT_JMPREL) 365 relplt_addr = dyn.d_un.d_ptr; 366 else if (dyn.d_tag == DT_PLTRELSZ) 367 lte->relplt_size = dyn.d_un.d_val; 368 else if (dyn.d_tag == DT_SONAME) 369 soname_offset = dyn.d_un.d_val; 370 } 371 } else if (shdr.sh_type == SHT_PROGBITS 372 || shdr.sh_type == SHT_NOBITS) { 373 if (strcmp(name, ".plt") == 0) { 374 lte->plt_addr = shdr.sh_addr; 375 lte->plt_size = shdr.sh_size; 376 lte->plt_data = elf_loaddata(scn, &shdr); 377 if (lte->plt_data == NULL) 378 fprintf(stderr, 379 "Can't load .plt data\n"); 380 if (shdr.sh_flags & SHF_EXECINSTR) 381 lte->lte_flags |= LTE_PLT_EXECUTABLE; 382 } 383#ifdef ARCH_SUPPORTS_OPD 384 else if (strcmp(name, ".opd") == 0) { 385 lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr; 386 lte->opd_size = shdr.sh_size; 387 lte->opd = elf_rawdata(scn, NULL); 388 } 389#endif 390 } 391 } 392 393 if (lte->dynsym == NULL || lte->dynstr == NULL) 394 error(EXIT_FAILURE, 0, 395 "Couldn't find .dynsym or .dynstr in \"%s\"", filename); 396 397 if (!relplt_addr || !lte->plt_addr) { 398 debug(1, "%s has no PLT relocations", filename); 399 lte->relplt = NULL; 400 lte->relplt_count = 0; 401 } else if (lte->relplt_size == 0) { 402 debug(1, "%s has unknown PLT size", filename); 403 lte->relplt = NULL; 404 lte->relplt_count = 0; 405 } else { 406 407 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 408 Elf_Scn *scn; 409 GElf_Shdr shdr; 410 411 scn = elf_getscn(lte->elf, i); 412 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 413 error(EXIT_FAILURE, 0, 414 "Couldn't get section header from \"%s\"", 415 filename); 416 if (shdr.sh_addr == relplt_addr 417 && shdr.sh_size == lte->relplt_size) { 418 lte->relplt = elf_getdata(scn, NULL); 419 lte->relplt_count = 420 shdr.sh_size / shdr.sh_entsize; 421 if (lte->relplt == NULL 422 || elf_getdata(scn, lte->relplt) != NULL) 423 error(EXIT_FAILURE, 0, 424 "Couldn't get .rel*.plt data from \"%s\"", 425 filename); 426 break; 427 } 428 } 429 430 if (i == lte->ehdr.e_shnum) 431 error(EXIT_FAILURE, 0, 432 "Couldn't find .rel*.plt section in \"%s\"", 433 filename); 434 435 debug(1, "%s %zd PLT relocations", filename, lte->relplt_count); 436 } 437 438 if (soname_offset != 0) 439 lte->soname = lte->dynstr + soname_offset; 440 441 if (arch_elf_init(lte) < 0) { 442 fprintf(stderr, "Backend initialization failed.\n"); 443 return -1; 444 } 445 446 return 0; 447} 448 449/* XXX temporarily non-static */ 450void 451do_close_elf(struct ltelf *lte) { 452 debug(DEBUG_FUNCTION, "do_close_elf()"); 453 arch_elf_destroy(lte); 454 elf_end(lte->elf); 455 close(lte->fd); 456} 457 458struct library * 459ltelf_read_library(struct Process *proc, const char *filename, GElf_Addr bias) 460{ 461 // XXX we leak LTE contents 462 struct ltelf lte = {}; 463 if (do_init_elf(<e, filename, bias) < 0) 464 return NULL; 465 proc->e_machine = lte.ehdr.e_machine; 466 467 struct library *lib = malloc(sizeof(*lib)); 468 char *soname = NULL; 469 if (lib == NULL) { 470 fail: 471 free(soname); 472 library_destroy(lib); 473 free(lib); 474 lib = NULL; 475 goto done; 476 } 477 478 int own_soname; 479 if (lte.soname != NULL) { 480 soname = strdup(lte.soname); 481 own_soname = 1; 482 } else { 483 soname = rindex(filename, '/') + 1; 484 own_soname = 0; 485 } 486 if (soname == NULL) 487 goto fail; 488 489 target_address_t entry = (target_address_t)lte.entry_addr; 490 if (arch_translate_address(proc, entry + lte.bias, &entry) < 0) 491 goto fail; 492 493 library_init(lib); 494 library_set_soname(lib, soname, own_soname); 495 library_set_pathname(lib, filename, 1); 496 lib->base = (target_address_t)lte.base_addr; 497 lib->entry = entry; 498 lib->dyn_addr = (target_address_t)lte.dyn_addr; 499 500 size_t i; 501 for (i = 0; i < lte.relplt_count; ++i) { 502 GElf_Rel rel; 503 GElf_Rela rela; 504 GElf_Sym sym; 505 void *ret; 506 507 if (lte.relplt->d_type == ELF_T_REL) { 508 ret = gelf_getrel(lte.relplt, i, &rel); 509 rela.r_offset = rel.r_offset; 510 rela.r_info = rel.r_info; 511 rela.r_addend = 0; 512 } else { 513 ret = gelf_getrela(lte.relplt, i, &rela); 514 } 515 516 if (ret == NULL 517 || ELF64_R_SYM(rela.r_info) >= lte.dynsym_count 518 || gelf_getsym(lte.dynsym, ELF64_R_SYM(rela.r_info), 519 &sym) == NULL) 520 error(EXIT_FAILURE, 0, 521 "Couldn't get relocation from \"%s\"", 522 filename); 523 524 char const *name = lte.dynstr + sym.st_name; 525 struct library_symbol *libsym; 526 switch (arch_elf_add_plt_entry(proc, <e, name, 527 &rela, i, &libsym)) { 528 case plt_default: 529 if (default_elf_add_plt_entry(proc, <e, name, 530 &rela, i, &libsym) < 0) 531 case plt_fail: 532 goto fail; 533 case plt_ok: 534 if (libsym != NULL) 535 library_add_symbol(lib, libsym); 536 } 537 } 538 539done: 540 do_close_elf(<e); 541 return lib; 542} 543 544struct library * 545ltelf_read_main_binary(struct Process *proc, const char *path) 546{ 547 fprintf(stderr, "ltelf_read_main_binary %d %s\n", proc->pid, path); 548 char *fname = pid2name(proc->pid); 549 struct library *lib = ltelf_read_library(proc, fname, 0); 550 if (lib != NULL) { 551 library_set_pathname(lib, path, 0); 552 library_set_soname(lib, rindex(path, '/') + 1, 0); 553 } 554 return lib; 555} 556