]> pd.if.org Git - zpackage/commitdiff
add zpm-soneed
authorNathan Wagner <nw@hydaspes.if.org>
Thu, 17 Nov 2016 09:11:19 +0000 (09:11 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Tue, 21 Feb 2017 08:14:04 +0000 (08:14 +0000)
.gitignore
elf/libelf.c [new file with mode: 0644]
elf/needed.c [new file with mode: 0644]

index 520cb5e33e884b728d6baaafd46be40fb794041d..6d799aa67140a5adc77231bad3d4c9912abb154c 100644 (file)
@@ -1,11 +1,13 @@
 elftype
 *.o
 *.a
+uncompress
 zpm-addfile
+zpm-vercmp
 zpm-extract
 zpm-init
+zpm-soneed
 zpm-hash
-uncompress
 *.zpm
 *.db
 soname
diff --git a/elf/libelf.c b/elf/libelf.c
new file mode 100644 (file)
index 0000000..477344f
--- /dev/null
@@ -0,0 +1,135 @@
+#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;
+}
diff --git a/elf/needed.c b/elf/needed.c
new file mode 100644 (file)
index 0000000..f4edd3d
--- /dev/null
@@ -0,0 +1,211 @@
+#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;
+}