From: Nathan Wagner Date: Thu, 17 Nov 2016 09:11:19 +0000 (+0000) Subject: add zpm-soneed X-Git-Tag: v0.1.6~155 X-Git-Url: https://pd.if.org/git/?p=zpackage;a=commitdiff_plain;h=6067372b564a72a21ac424d74d6a914aae928f16 add zpm-soneed --- diff --git a/.gitignore b/.gitignore index 520cb5e..6d799aa 100644 --- a/.gitignore +++ b/.gitignore @@ -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 index 0000000..477344f --- /dev/null +++ b/elf/libelf.c @@ -0,0 +1,135 @@ +#define _POSIX_C_SOURCE 200112L +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 index 0000000..f4edd3d --- /dev/null +++ b/elf/needed.c @@ -0,0 +1,211 @@ +#define _POSIX_C_SOURCE 200112L +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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; +}