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