]> pd.if.org Git - zpackage/blob - elf/soname.c
exit with failure status if soname not found
[zpackage] / elf / soname.c
1 #define _POSIX_C_SOURCE 200112L
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <sys/mman.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <limits.h>
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "elf.h"
14
15 int main(int ac, char **av) {
16         void *elfbase;
17         int elffd, i;
18         struct stat sbuf;
19         Elf64_Ehdr *hdr;
20         Elf64_Shdr *shdr;
21         Elf64_Shdr *dynsect = 0;
22         Elf64_Shdr *strtab = 0, *dyntab = 0;
23         char *name, *dynname;
24         Elf64_Dyn *dent;
25
26         if (ac < 2) {
27                 fprintf(stderr, "usage: soname <file>\n");
28                 exit(EXIT_FAILURE);
29         }
30
31         if (lstat(av[1], &sbuf) == -1) {
32                 exit(1);
33         }
34         if (!S_ISREG(sbuf.st_mode)) {
35                 exit(1);
36         }
37
38         elffd = open(av[1], O_RDONLY);
39         if (elffd == -1) {
40                 exit(1);
41         }
42         if (fstat(elffd, &sbuf) == -1) {
43                 exit(1);
44         }
45         /* not a regular file? */
46         if (!S_ISREG(sbuf.st_mode)) {
47                 exit(1);
48         }
49         /* not at least the size of the elf header? */
50         if ((size_t)sbuf.st_size < sizeof(Elf64_Ehdr)) {
51                 exit(1);
52         }
53
54         elfbase = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, elffd, 0);
55         if (!elfbase) {
56                 exit(2);
57         }
58
59         hdr = elfbase;
60         if (hdr->e_ident[EI_MAG0] != ELFMAG0
61                         || hdr->e_ident[EI_MAG1] != ELFMAG1
62                         || hdr->e_ident[EI_MAG2] != ELFMAG2
63                         || hdr->e_ident[EI_MAG3] != ELFMAG3
64            ) {
65                 exit(3);
66         }
67
68         /* only dynamic files will have an soname */
69         if (hdr->e_type != ET_DYN) {
70                 exit(4);
71         }
72         
73         switch (hdr->e_ident[EI_CLASS]) {
74                 case ELFCLASS64:
75                 case ELFCLASS32:
76                 case ELFCLASSNONE:
77                         break;
78                 default:
79                         exit(5);
80         }
81
82         /* check endian ness */
83         switch (hdr->e_ident[EI_DATA]) {
84                 case ELFDATA2LSB: break;
85                 case ELFDATA2MSB: break;
86                 default:
87                         exit(6);
88         }
89
90         /* find the section header table */
91         for (i = 0; i < hdr->e_shnum; i++) {
92                 shdr = (Elf64_Shdr *)((char *)elfbase + hdr->e_shoff + i * hdr->e_shentsize);
93                 if (shdr->sh_type == SHT_DYNAMIC) {
94                         dynsect = shdr;
95                 } else if (shdr->sh_type == SHT_STRTAB && i == hdr->e_shstrndx) {
96                         strtab = shdr;
97                 }
98         }
99         if (!strtab) {
100                 exit(8);
101         }
102         if (!dynsect) {
103                 exit(9);
104         }
105
106         name = (char *) elfbase + strtab->sh_offset;
107         for (i = 0; i < hdr->e_shnum; i++) {
108                 shdr = (Elf64_Shdr *)((char *)elfbase + hdr->e_shoff + i * hdr->e_shentsize);
109                 if (shdr->sh_type == SHT_STRTAB && !strcmp(".dynstr", name+shdr->sh_name)) {
110                         dyntab = shdr;
111                 }
112         }
113         if (!dyntab) {
114                 exit(10);
115         }
116
117         dynname = (char *) elfbase + dyntab->sh_offset;
118         for (dent = (Elf64_Dyn *)((char *)elfbase + dynsect->sh_offset); dent->d_tag != DT_NULL; dent++) {
119                 if (dent->d_tag == DT_SONAME) {
120                         printf("%s\n", dynname + dent->d_un.d_val);
121                         /* TODO can there be more than one? */
122                         exit(0);
123                 }
124         }
125
126         return 11;
127 }