#define _POSIX_C_SOURCE 200112L #include #include #include #include #include #include #include #include #include #include #include "elf.h" void *libelf_map(char *path, size_t *fsize); int libelf_iself(void *elf); char *libelf_soname(void *elf); int libelf_type(void *elf); Elf64_Ehdr *libelf_header(void *elf) { return elf; } Elf64_Shdr *libelf_shdr(void *elf, int n) { return (Elf64_Shdr*)(char *)elf + n; } Elf64_Shdr *libelf_sht_strtab(void *elf) { int i; Elf64_Ehdr *hdr; Elf64_Shdr *shdr; hdr = libelf_header(elf); for (i = 0; i < hdr->e_shnum; i++) { shdr = (Elf64_Shdr *)((char *)elf + hdr->e_shoff + i * hdr->e_shentsize); if (shdr->sh_type == SHT_STRTAB && i == hdr->e_shstrndx) { return shdr; } } return 0; } char *libelf_sectionname(Elf64_Shdr *section, Elf64_Shdr *strtab) { return (char *)strtab + section->sh_name; } Elf64_Shdr *libelf_section_n(void *elf, int n) { Elf64_Ehdr *hdr; hdr = libelf_header(elf); if (n > hdr->e_shnum) { return 0; } return (Elf64_Shdr *)((char *)elf + hdr->e_shoff + n * hdr->e_shentsize); } Elf64_Shdr *libelf_section(void *elf, unsigned int type) { int i; Elf64_Ehdr *hdr; Elf64_Shdr *shdr; hdr = libelf_header(elf); for (i = 0; i < hdr->e_shnum; i++) { shdr = (Elf64_Shdr *)((char *)elf + hdr->e_shoff + i * hdr->e_shentsize); if (shdr->sh_type == type) { return shdr; } } return 0; } int libelf_type(void *elf) { return ((Elf64_Ehdr *)elf)->e_type; } int libelf_iself(void *elf) { Elf64_Ehdr *hdr; hdr = elf; if (hdr->e_ident[EI_MAG0] != ELFMAG0 || hdr->e_ident[EI_MAG1] != ELFMAG1 || hdr->e_ident[EI_MAG2] != ELFMAG2 || hdr->e_ident[EI_MAG3] != ELFMAG3 ) { return 0; } return 1; } void *libelf_map(char *path, size_t *fsize) { int elffd; struct stat sbuf; void *elfbase; errno = 0; elffd = open(path, O_RDONLY); if (elffd == -1) { perror("open"); return NULL; } if (fstat(elffd, &sbuf) == -1) { close(elffd); return NULL; } /* not a regular file? */ if (!S_ISREG(sbuf.st_mode)) { close(elffd); return NULL; } /* not at least the size of the elf header? */ if ((size_t)sbuf.st_size < sizeof(Elf64_Ehdr)) { close(elffd); return NULL; } elfbase = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, elffd, 0); close(elffd); if (!elfbase) { return NULL; } if (!libelf_iself(elfbase)) { munmap(elfbase, sbuf.st_size); return NULL; } *fsize = sbuf.st_size; return elfbase; } int main(int ac, char **av) { void *elf; size_t fsize; int i; Elf64_Ehdr *hdr; char *strtab; Elf64_Phdr *phdr; Elf64_Dyn *dyn = 0; int opt, flags = 0; while ((opt = getopt(ac, av, "e")) != -1) { flags = 1; } elf = libelf_map(av[optind], &fsize); if (!elf) { exit(1); } /* only dynamic files will have an soname */ if (libelf_type(elf) != ET_DYN && libelf_type(elf) != ET_EXEC) { exit(4); } hdr = libelf_header(elf); switch (hdr->e_ident[EI_CLASS]) { case ELFCLASS64: case ELFCLASS32: case ELFCLASSNONE: break; default: exit(5); } /* check endian ness */ switch (hdr->e_ident[EI_DATA]) { case ELFDATA2LSB: break; case ELFDATA2MSB: break; default: exit(6); } Elf64_Shdr *dsect = 0; /* find program header table */ for (i = 0; i < hdr->e_phnum; i++) { phdr = (Elf64_Phdr *)((char *)elf + hdr->e_phoff + i * hdr->e_phentsize); if (phdr->p_type == PT_DYNAMIC) { dsect = (Elf64_Shdr *)((char *)elf + phdr->p_offset); } } if (!dsect) { /* no dsect, statically linked? */ exit(7); } dyn = (Elf64_Dyn *)((char *)elf + dsect->sh_offset); if (!dyn) { exit(9); } dyn = (Elf64_Dyn *)dsect; dsect = libelf_section(elf, SHT_DYNAMIC); Elf64_Shdr *strsect; strsect = libelf_section_n(elf, dsect->sh_link); strtab = (char *)elf + strsect->sh_offset; while (dyn->d_tag != DT_NULL) { if (dyn->d_tag == DT_NEEDED) { if (flags) { printf("%s ", av[optind]); } printf("%s\n", strtab + dyn->d_un.d_val); } dyn++; } return 0; }