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