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