+#define _POSIX_C_SOURCE 200112L
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 0;
+}
+
+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, 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 (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;
+
+ 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;
+ /* 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);
+ }
+ }
+ 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;
+}