]> pd.if.org Git - zpackage/blob - elf/needed.c
add zpm-soneed
[zpackage] / elf / needed.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 #include <errno.h>
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "elf.h"
15
16 void *libelf_map(char *path, size_t *fsize);
17 int libelf_iself(void *elf);
18 char *libelf_soname(void *elf);
19 int libelf_type(void *elf);
20
21 Elf64_Ehdr *libelf_header(void *elf) {
22         return elf;
23 }
24
25 Elf64_Shdr *libelf_shdr(void *elf, int n) {
26         return 0;
27 }
28
29 Elf64_Shdr *libelf_sht_strtab(void *elf) {
30         int i;
31         Elf64_Ehdr *hdr;
32         Elf64_Shdr *shdr;
33
34         hdr = libelf_header(elf);
35
36         for (i = 0; i < hdr->e_shnum; i++) {
37                 shdr = (Elf64_Shdr *)((char *)elf + hdr->e_shoff + i * hdr->e_shentsize);
38                 if (shdr->sh_type == SHT_STRTAB && i == hdr->e_shstrndx) {
39                         return shdr;
40                 }
41         }
42         return 0;
43 }
44
45 char *libelf_sectionname(Elf64_Shdr *section, Elf64_Shdr *strtab) {
46         return (char *)strtab + section->sh_name;
47 }
48
49 Elf64_Shdr *libelf_section_n(void *elf, int n) {
50         Elf64_Ehdr *hdr;
51
52         hdr = libelf_header(elf);
53
54         if (n > hdr->e_shnum) {
55                 return 0;
56         }
57
58         return (Elf64_Shdr *)((char *)elf + hdr->e_shoff + n * hdr->e_shentsize);
59 }
60
61 Elf64_Shdr *libelf_section(void *elf, int type) {
62         int i;
63         Elf64_Ehdr *hdr;
64         Elf64_Shdr *shdr;
65
66         hdr = libelf_header(elf);
67
68         for (i = 0; i < hdr->e_shnum; i++) {
69                 shdr = (Elf64_Shdr *)((char *)elf + hdr->e_shoff + i * hdr->e_shentsize);
70                 if (shdr->sh_type == type) {
71                         return shdr;
72                 }
73         }
74         return 0;
75 }
76
77 int libelf_type(void *elf) {
78         return ((Elf64_Ehdr *)elf)->e_type;
79 }
80
81 int libelf_iself(void *elf) {
82         Elf64_Ehdr *hdr;
83         hdr = elf;
84         if (hdr->e_ident[EI_MAG0] != ELFMAG0
85                         || hdr->e_ident[EI_MAG1] != ELFMAG1
86                         || hdr->e_ident[EI_MAG2] != ELFMAG2
87                         || hdr->e_ident[EI_MAG3] != ELFMAG3
88            ) {
89                 return 0;
90         }
91         return 1;
92 }
93
94 void *libelf_map(char *path, size_t *fsize) {
95         int elffd;
96         struct stat sbuf;
97         void *elfbase;
98
99         errno = 0;
100
101         elffd = open(path, O_RDONLY);
102         if (elffd == -1) {
103                 perror("open");
104                 return NULL;
105         }
106         if (fstat(elffd, &sbuf) == -1) {
107                 close(elffd);
108                 return NULL;
109         }
110         /* not a regular file? */
111         if (!S_ISREG(sbuf.st_mode)) {
112                 close(elffd);
113                 return NULL;
114         }
115         /* not at least the size of the elf header? */
116         if (sbuf.st_size < sizeof(Elf64_Ehdr)) {
117                 close(elffd);
118                 return NULL;
119         }
120
121         elfbase = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, elffd, 0);
122         close(elffd);
123         if (!elfbase) {
124                 return NULL;
125         }
126
127         if (!libelf_iself(elfbase)) {
128                 munmap(elfbase, sbuf.st_size);
129                 return NULL;
130         }
131
132         *fsize = sbuf.st_size;
133
134         return elfbase;
135 }
136
137 int main(int ac, char **av) {
138         void *elf;
139         size_t fsize;
140         int i;
141         Elf64_Ehdr *hdr;
142         char *strtab;
143         Elf64_Phdr *phdr;
144         Elf64_Dyn *dyn = 0;
145         int opt, flags;
146
147         while ((opt = getopt(ac, av, "e")) != -1) {
148                 flags = 1;
149         }
150
151         elf = libelf_map(av[optind], &fsize);
152         if (!elf) {
153                 exit(1);
154         }
155
156         /* only dynamic files will have an soname */
157         if (libelf_type(elf) != ET_DYN && libelf_type(elf) != ET_EXEC) {
158                 exit(4);
159         }
160         
161         hdr = libelf_header(elf);
162
163         switch (hdr->e_ident[EI_CLASS]) {
164                 case ELFCLASS64:
165                 case ELFCLASS32:
166                 case ELFCLASSNONE:
167                         break;
168                 default:
169                         exit(5);
170         }
171
172         /* check endian ness */
173         switch (hdr->e_ident[EI_DATA]) {
174                 case ELFDATA2LSB: break;
175                 case ELFDATA2MSB: break;
176                 default:
177                         exit(6);
178         }
179
180         Elf64_Shdr *dsect;
181         /* find program header table */
182         for (i = 0; i < hdr->e_phnum; i++) {
183                 phdr = (Elf64_Phdr *)((char *)elf + hdr->e_phoff + i * hdr->e_phentsize);
184                 if (phdr->p_type == PT_DYNAMIC) {
185                         dsect = (Elf64_Shdr *)((char *)elf + phdr->p_offset);
186                 }
187         }
188         dyn = (Elf64_Dyn *)((char *)elf + dsect->sh_offset);
189         if (!dyn) {
190                 exit(9);
191         }
192         dyn = (Elf64_Dyn *)dsect;
193
194         dsect = libelf_section(elf, SHT_DYNAMIC);
195         Elf64_Shdr *strsect;
196
197         strsect = libelf_section_n(elf, dsect->sh_link);
198         strtab = (char *)elf + strsect->sh_offset;
199
200         while (dyn->d_tag != DT_NULL) {
201                 if (dyn->d_tag == DT_NEEDED) {
202                         if (flags) {
203                                 printf("%s ", av[optind]);
204                         }
205                         printf("%s\n", strtab + dyn->d_un.d_val);
206                 }
207                 dyn++;
208         }
209
210         return 0;
211 }