static int elf_reloc_x86_64(struct elf_binary *elf, int type, uint64_t addr, uint64_t value) { void *ptr = elf_get_ptr(elf, addr); uint64_t *u64; uint32_t *u32; int32_t *s32; switch ( type ) { case 1 /* R_X86_64_64 */ : u64 = ptr; value += elf->reloc_offset; *u64 = value; break; case 2 /* R_X86_64_PC32 */ : u32 = ptr; *u32 = value - addr; if ( *u32 != (uint32_t)(value - addr) ) { elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32 " != 0x%" PRIx32 "\n", *u32, (uint32_t) (value - addr)); return -1; } break; case 10 /* R_X86_64_32 */ : u32 = ptr; value += elf->reloc_offset; *u32 = value; if ( *u32 != value ) { elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32 " != 0x%" PRIx64 "\n", *u32, value); return -1; } break; case 11 /* R_X86_64_32S */ : s32 = ptr; value += elf->reloc_offset; *s32 = value; if ( *s32 != (int64_t) value ) { elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32 " != 0x%" PRIx64 "\n", *s32, (int64_t) value); return -1; } break; default: return -1; } return 0; }
static int dump_dynamic(struct file_state *f, Elf_Scn *scn, GElf_Shdr *shdr) { struct dyn_state d; GElf_Dyn needed_dyn; char *needed_name; int i; d.f = f; d.dyn_data = elf_getdata(scn, NULL); if (!d.dyn_data) { elf_err("elf_getdata failed"); return -1; } d.count = shdr->sh_size / shdr->sh_entsize; for (i = 0; i < d.count; i++) { if (!gelf_getdyn(d.dyn_data, i, &needed_dyn)) continue; if (needed_dyn.d_tag != DT_NEEDED) continue; needed_name = (char *)f->strtab_data->d_buf + needed_dyn.d_un.d_val; dump_needed(f->t, needed_name); } return 0; }
static int dump_file(struct tree_state *t, char *name, char *file) { struct file_state f; int fd; Elf_Scn *scn; GElf_Shdr shdr; if ((dup_mode == HIDE_DUPS) && seen(t, name)) return 0; indent(t); printf("%s", name); if ((dup_mode == PRUNE_DUPS) && seen(t, name)) { printf("...\n"); return 0; } else { printf(":\n"); } see(t, name); f.t = t; fd = open(file, O_RDONLY); if (fd < 0) { unix_err("open(%s) failed", file); return -1; } f.e = elf_begin(fd, ELF_C_READ, NULL); if (!f.e) { elf_err("elf_begin failed on %s", file); return -1; } scn = find_scn(&f, SHT_STRTAB, NULL, &shdr); f.strtab_data = elf_getdata(scn, NULL); if (!f.strtab_data) { app_err("%s has no strtab section", file); return -1; } scn = NULL; while ((scn = find_scn(&f, SHT_DYNAMIC, scn, &shdr))) { dump_dynamic(&f, scn, &shdr); } elf_end(f.e); close(fd); return 0; }
int main(int argc, char *argv[]) { struct tree_state t; if (argc < 2 || parse_args(argc, argv)) { usage(); exit(EXIT_FAILURE); } if (elf_version(EV_CURRENT) == EV_NONE) { elf_err("version mismatch"); exit(EXIT_FAILURE); } t.level = 0; t.seen = NULL; add_search_dirs(); dump_file(&t, root_name, root_name); return 0; }