+
+char *libelf_soname(void *elfbase) {
+ Elf64_Ehdr *hdr;
+ int i;
+ Elf64_Shdr *shdr;
+ Elf64_Shdr *dynsect = 0;
+ Elf64_Shdr *strtab = 0, *dyntab = 0;
+ char *name, *dynname;
+ Elf64_Dyn *dent;
+
+ if (!libelf_iself(elfbase)) {
+ return 0;
+ }
+ hdr = libelf_header(elfbase);
+
+ /* only dynamic files will have an soname */
+ if (hdr->e_type != ET_DYN) {
+ return 0;
+ }
+
+ switch (hdr->e_ident[EI_CLASS]) {
+ case ELFCLASS64:
+ case ELFCLASS32:
+ case ELFCLASSNONE:
+ break;
+ default: return 0; break;
+ }
+
+ /* check endian ness */
+ switch (hdr->e_ident[EI_DATA]) {
+ case ELFDATA2LSB: break;
+ case ELFDATA2MSB: break;
+ default: return 0; break;
+ }
+
+ /* 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) {
+ return 0;
+ }
+ if (!dynsect) {
+ return 0;
+ }
+
+ 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) {
+ return 0;
+ }
+
+ 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) {
+ return dynname + dent->d_un.d_val;
+ }
+ }
+
+ return 0;
+}