]> pd.if.org Git - zpackage/blobdiff - elf/libelf.c
add libelf_soneed function
[zpackage] / elf / libelf.c
index 477344fa76729b0e6bdad1750df2733a470fcd74..063eefa74a9f9256897931ec0d4fae2603f87bea 100644 (file)
@@ -22,9 +22,11 @@ Elf64_Ehdr *libelf_header(void *elf) {
        return elf;
 }
 
+#if 0
 Elf64_Shdr *libelf_shdr(void *elf, int n) {
        return 0;
 }
+#endif
 
 Elf64_Shdr *libelf_sht_strtab(void *elf) {
        int i;
@@ -58,7 +60,7 @@ Elf64_Shdr *libelf_section_n(void *elf, int n) {
        return (Elf64_Shdr *)((char *)elf + hdr->e_shoff + n * hdr->e_shentsize);
 }
 
-Elf64_Shdr *libelf_section(void *elf, int type) {
+Elf64_Shdr *libelf_section(void *elf, unsigned int type) {
        int i;
        Elf64_Ehdr *hdr;
        Elf64_Shdr *shdr;
@@ -75,7 +77,7 @@ Elf64_Shdr *libelf_section(void *elf, int type) {
 }
 
 int libelf_type(void *elf) {
-       return ((Elf64_Ehdr *)elf)->e_type;
+       return libelf_iself(elf) ? libelf_header(elf)->e_type : 0;
 }
 
 int libelf_iself(void *elf) {
@@ -113,7 +115,7 @@ void *libelf_map(char *path, size_t *fsize) {
                return NULL;
        }
        /* not at least the size of the elf header? */
-       if (sbuf.st_size < sizeof(Elf64_Ehdr)) {
+       if ((size_t)sbuf.st_size < sizeof(Elf64_Ehdr)) {
                close(elffd);
                return NULL;
        }
@@ -133,3 +135,74 @@ void *libelf_map(char *path, size_t *fsize) {
 
        return elfbase;
 }
+
+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;
+}