--- /dev/null
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <elf.h>
+
+int main(int ac, char **av) {
+ void *elfbase;
+ int elffd, i;
+ struct stat sbuf;
+ Elf64_Ehdr *hdr;
+ Elf64_Shdr *shdr;
+ Elf64_Shdr *dynsect = 0;
+ Elf64_Shdr *strtab = 0, *dyntab = 0;
+ char *name, *dynname;
+ Elf64_Dyn *dent;
+
+ elffd = open(av[1], O_RDONLY);
+ if (elffd == -1) {
+ exit(1);
+ }
+ if (fstat(elffd, &sbuf) == -1) {
+ exit(1);
+ }
+
+ elfbase = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, elffd, 0);
+ if (!elfbase) {
+ exit(2);
+ }
+
+ hdr = elfbase;
+ 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
+ ) {
+ exit(3);
+ }
+
+ /* only dynamic files will have an soname */
+ if (hdr->e_type != ET_DYN) {
+ exit(4);
+ }
+
+ 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);
+ }
+
+ /* find the section header table */
+ for (i = 0; i < hdr->e_shnum; i++) {
+ shdr = (Elf64_Shdr *)((char *)elfbase + hdr->e_shoff + i * hdr->e_shentsize);
+ if (shdr->sh_type == SHT_DYNAMIC) {
+ dynsect = shdr;
+ } else if (shdr->sh_type == SHT_STRTAB && i == hdr->e_shstrndx) {
+ strtab = shdr;
+ }
+ }
+ if (!strtab) {
+ exit(8);
+ }
+ if (!dynsect) {
+ exit(9);
+ }
+
+ name = (char *) elfbase + strtab->sh_offset;
+ for (i = 0; i < hdr->e_shnum; i++) {
+ shdr = (Elf64_Shdr *)((char *)elfbase + hdr->e_shoff + i * hdr->e_shentsize);
+ if (shdr->sh_type == SHT_STRTAB && !strcmp(".dynstr", name+shdr->sh_name)) {
+ dyntab = shdr;
+ }
+ }
+ if (!dyntab) {
+ exit(10);
+ }
+
+ dynname = (char *) elfbase + dyntab->sh_offset;
+ for (dent = (Elf64_Dyn *)((char *)elfbase + dynsect->sh_offset); dent->d_tag != DT_NULL; dent++) {
+ if (dent->d_tag == DT_SONAME) {
+ printf("%s\n", dynname + dent->d_un.d_val);
+ break;
+ }
+ }
+
+ return 0;
+}