#define _POSIX_C_SOURCE 200112L #include #include #include #include #include #include #include #include #include #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; if (ac < 2) { fprintf(stderr, "usage: soname \n"); exit(EXIT_FAILURE); } if (lstat(av[1], &sbuf) == -1) { exit(1); } if (!S_ISREG(sbuf.st_mode)) { exit(1); } elffd = open(av[1], O_RDONLY); if (elffd == -1) { exit(1); } if (fstat(elffd, &sbuf) == -1) { exit(1); } /* not a regular file? */ if (!S_ISREG(sbuf.st_mode)) { exit(1); } /* not at least the size of the elf header? */ if ((size_t)sbuf.st_size < sizeof(Elf64_Ehdr)) { 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); /* TODO can there be more than one? */ exit(0); } } return 11; }