]> pd.if.org Git - zpackage/blob - elf/elftype.c
change elf.h to use local header
[zpackage] / elf / elftype.c
1 #define _POSIX_C_SOURCE 200112L
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <limits.h>
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "elf.h"
11
12 #define RELOCATABLE 0x1
13 #define EXECUTABLE  0x2
14 #define DYNAMIC     0x4
15 #define CORE        0x8
16 #define SYMLINKS    0x10
17
18 int readline(FILE *f, char *fn);
19 int checkfile(char *fn, unsigned int want, int perr, int quiet);
20
21 int errors = 0;
22 int zeroterm = 0;
23
24 int main(int ac, char **av) {
25         int option;
26         unsigned int want = 0;
27         int quiet = 0;
28         int printtype = 0;
29         int printname = 0;
30         int verbose = 0;
31         int perr = 0;
32         FILE *list = 0;
33         char fn[PATH_MAX];
34         
35         while ((option = getopt(ac, av, "vtnredclaqp0f:")) != -1) {
36                 switch (option) {
37                         case 'r': want |= RELOCATABLE; break;
38                         case 'e': want |= EXECUTABLE; break;
39                         case 'd': want |= DYNAMIC; break;
40                         case 'c': want |= CORE; break;
41                         case 'l': want |= SYMLINKS; break;
42                         case 'a': want = (RELOCATABLE|EXECUTABLE|DYNAMIC|CORE); break;
43                         case 'q': quiet++; break;
44                         case 't': printtype++; break;
45                         case 'n': printname++; break;
46                         case 'v': verbose++; break;
47                         case 'p': perr++; break;
48                         case '0': zeroterm = 1; break;
49                         case 'f':
50                                   if (optarg[0] == '-' && optarg[1] == 0) {
51                                           list = stdin;
52                                   } else {
53                                           list = fopen(optarg, "r");
54                                   }
55                                   break;
56                         default:
57                                   exit(1);
58                                   break;
59                 }
60         }
61
62         if (!want) want = (RELOCATABLE|EXECUTABLE|DYNAMIC|CORE);
63
64         if (list) {
65                 int type;
66                 quiet = 2;
67                 perr = 0;
68                 while (readline(list, fn)) {
69                         if ((type = checkfile(fn, want,perr,quiet)) & want) {
70                                 if (printtype) {
71                                         switch (type) {
72                                                 case RELOCATABLE:
73                                                         printf("relocatable "); break;
74                                                 case EXECUTABLE:
75                                                         printf("executable "); break;
76                                                 case DYNAMIC:
77                                                         printf("dynamic "); break;
78                                                 case CORE:
79                                                         printf("core "); break;
80                                                 default:
81                                                         printf("notelf "); break;
82                                         }
83                                 }
84                                 printf("%s\n", fn);
85                         }
86                 }
87         } else {
88                 int type;
89                 char *fn;
90
91                 fn = av[optind];
92                 if (verbose) fprintf(stderr, "checking %s\n", av[optind]);
93                 type = checkfile(fn,want,perr,quiet);
94
95                 if (printtype) {
96                         switch (type) {
97                                 case RELOCATABLE:
98                                         printf("relocatable"); break;
99                                 case EXECUTABLE:
100                                         printf("executable"); break;
101                                 case DYNAMIC:
102                                         printf("dynamic"); break;
103                                 case CORE:
104                                         printf("core"); break;
105                                 default:
106                                         printf("notelf"); break;
107                         }
108                 }
109
110                 if (printname) {
111                         printf("%s%s", printtype ? " " : "", fn);
112                 }
113                 if (printtype || printname) printf("\n");
114
115                 return type & want ? 0 : 1;
116         }
117         return errors ? 1 : 0;
118 }
119
120 int readline(FILE *f, char *fn) {
121         int ch;
122         int i = 0;
123
124         do {
125                 ch = fgetc(f);
126                 switch (ch) {
127                         case EOF: break;
128                         case 0:
129                                   if (i == 0) continue;
130                                   break;
131                         case '\n':
132                                   if (!zeroterm) {
133                                           if (i == 0) continue;
134                                           break;
135                                   }
136                         default:
137                                   fn[i++] = ch;
138                                   continue;
139                 }
140                 if (i >= PATH_MAX) {
141                         /* TODO print an error */
142                         return 0;
143                 }
144                 fn[i] = 0;
145                 return i;
146         } while (ch != EOF);
147         return 0;
148 }
149
150 int checkfile(char *fn, unsigned int want, int perr, int quiet) {
151         Elf64_Ehdr hdr;
152         int fd, bytes;
153         int endian = 0;
154         struct stat st;
155
156         if (want & SYMLINKS) {
157                 lstat(fn, &st);
158         } else {
159                 stat(fn, &st);
160         }
161         if (!S_ISREG(st.st_mode)) {
162                 return 0;
163         }
164         
165         fd = open(fn, O_RDONLY);
166         if (fd == -1) {
167                 perror("elfcheck");
168                 errors++;
169                 return 0;
170         }
171         bytes = read(fd, &hdr, sizeof hdr);
172         close(fd);
173         if (bytes < sizeof hdr) {
174                 if (perr) fprintf(stderr, "could not read full elf header (wanted %zu got %d bytes)\n", sizeof hdr, bytes);
175                 return 0;
176         }
177         if (hdr.e_ident[EI_MAG0] != ELFMAG0
178                         || hdr.e_ident[EI_MAG1] != ELFMAG1
179                         || hdr.e_ident[EI_MAG2] != ELFMAG2
180                         || hdr.e_ident[EI_MAG3] != ELFMAG3
181            ) {
182                 if (perr) fprintf(stderr, "elf header magic wrong\n");
183                 return 0;
184         }
185         switch (hdr.e_ident[EI_CLASS]) {
186                 case ELFCLASS64:
187                 case ELFCLASS32:
188                 case ELFCLASSNONE:
189                         break;
190                 default:
191                         if (perr) fprintf(stderr, "elf header unknown class\n");
192                         return 0;
193         }
194
195         endian = hdr.e_ident[EI_DATA];
196         switch (endian) {
197                 case ELFDATA2LSB: break;
198                 case ELFDATA2MSB: break;
199                                   /* TODO swap endian if needed */
200                 default:
201                         if (perr) fprintf(stderr, "elf header unknown endian\n");
202                         return 0;
203         }
204
205         switch (hdr.e_type) {
206                 case ET_REL: return RELOCATABLE;
207                 case ET_EXEC: return EXECUTABLE;
208                 case ET_DYN: return DYNAMIC;
209                 case ET_CORE: return CORE;
210                 case ET_NONE:
211                 default:
212                         if (perr) fprintf(stderr, "unknown %s\n", fn);
213                         return 0;
214         }
215
216         return 0;
217 }