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