/[gentoo-projects]/pax-utils/scanelf.c
Gentoo

Diff of /pax-utils/scanelf.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.13 Revision 1.32
1/* 1/*
2 * Copyright 2003 Ned Ludd <solar@gentoo.org> 2 * Copyright 2003 Ned Ludd <solar@gentoo.org>
3 * Copyright 1999-2005 Gentoo Foundation 3 * Copyright 1999-2005 Gentoo Foundation
4 * Distributed under the terms of the GNU General Public License v2 4 * Distributed under the terms of the GNU General Public License v2
5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.13 2005/03/31 18:34:01 solar Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.32 2005/04/07 00:01:40 vapier Exp $
6 * 6 *
7 ******************************************************************** 7 ********************************************************************
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the 10 * published by the Free Software Foundation; either version 2 of the
22 */ 22 */
23 23
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <sys/types.h> 26#include <sys/types.h>
27#define __USE_GNU
27#include <string.h> 28#include <string.h>
28#include <errno.h> 29#include <errno.h>
29#include <unistd.h> 30#include <unistd.h>
30#include <sys/stat.h> 31#include <sys/stat.h>
31#include <dirent.h> 32#include <dirent.h>
32#include <getopt.h> 33#include <getopt.h>
34#include <assert.h>
33 35
34#include "paxelf.h" 36#include "paxelf.h"
35 37
36static const char *rcsid = "$Id: scanelf.c,v 1.13 2005/03/31 18:34:01 solar Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.32 2005/04/07 00:01:40 vapier Exp $";
37 39
38 40
39/* helper functions for showing errors */ 41/* helper functions for showing errors */
40#define argv0 "scanelf\0" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/ 42#define argv0 "scanelf" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/
41#define warn(fmt, args...) \ 43#define warn(fmt, args...) \
42 fprintf(stderr, "%s: " fmt "\n", argv0, ## args) 44 fprintf(stderr, "%s: " fmt "\n", argv0, ## args)
43#define warnf(fmt, args...) warn("%s(): " fmt, __FUNCTION__, ## args) 45#define warnf(fmt, args...) warn("%s(): " fmt, __FUNCTION__, ## args)
44#define err(fmt, args...) \ 46#define err(fmt, args...) \
45 do { \ 47 do { \
59 61
60/* variables to control behavior */ 62/* variables to control behavior */
61static char scan_ldpath = 0; 63static char scan_ldpath = 0;
62static char scan_envpath = 0; 64static char scan_envpath = 0;
63static char dir_recurse = 0; 65static char dir_recurse = 0;
66static char dir_crossmount = 1;
64static char show_pax = 0; 67static char show_pax = 0;
65static char show_stack = 0; 68static char show_stack = 0;
66static char show_textrel = 0; 69static char show_textrel = 0;
67static char show_rpath = 0; 70static char show_rpath = 0;
71static char show_needed = 0;
68static char show_header = 1; 72static char show_banner = 1;
69static char be_quiet = 0; 73static char be_quiet = 0;
74static char be_verbose = 0;
75static char *find_sym = NULL;
70 76
71 77
72 78
73/* scan an elf file and show all the fun stuff */ 79/* scan an elf file and show all the fun stuff */
74static void scanelf_file(const char *filename) 80static void scanelf_file(const char *filename)
75{ 81{
76 int i; 82 int i;
77 char found_stack, found_relro, found_textrel, found_rpath; 83 char found_pax, found_stack, found_relro, found_textrel,
78 Elf_Dyn *dyn; 84 found_rpath, found_needed, found_sym;
79 elfobj *elf = NULL; 85 elfobj *elf;
80 86
81 found_stack = found_relro = found_textrel = found_rpath = 0; 87 found_pax = found_stack = found_relro = found_textrel = \
88 found_rpath = found_needed = found_sym = 0;
82 89
83 /* verify this is real ELF */ 90 /* verify this is real ELF */
84 if ((elf = readelf(filename)) == NULL) 91 if ((elf = readelf(filename)) == NULL) {
92 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
85 return; 93 return;
86 if (check_elf_header(elf->ehdr) || !IS_ELF(elf)) 94 }
87 goto bail; 95
96 if (be_verbose > 1)
97 printf("%s: {%s,%s} scanning file\n", filename,
98 get_elfeitype(elf, EI_CLASS, elf->elf_class),
99 get_elfeitype(elf, EI_DATA, elf->data[EI_DATA]));
100 else if (be_verbose)
101 printf("%s: scanning file\n", filename);
88 102
89 /* show the header */ 103 /* show the header */
90 if (!be_quiet && show_header) { 104 if (!be_quiet && show_banner) {
91 fputs(" TYPE ", stderr); 105 printf(" TYPE ");
92 if (show_pax) fputs(" PAX ", stderr); 106 if (show_pax) printf(" PAX ");
93 if (show_stack) fputs(" STACK/RELRO ", stderr); 107 if (show_stack) printf("STK/REL ");
94 if (show_textrel) fputs(" TEXTREL ", stderr); 108 if (show_textrel) printf("TEXTREL ");
95 if (show_rpath) fputs(" RPATH ", stderr); 109 if (show_rpath) printf("RPATH ");
96 fputs(" FILE\n", stderr); 110 if (show_needed) printf("NEEDED ");
111 printf(" FILE\n");
97 show_header = 0; 112 show_banner = 0;
98 } 113 }
99 114
100 /* dump all the good stuff */ 115 /* dump all the good stuff */
101 if (!be_quiet) 116 if (!be_quiet)
102 printf("%-7s ", get_elfetype(elf->ehdr->e_type)); 117 printf("%-7s ", get_elfetype(elf));
103 118
104 if (show_pax) 119 if (show_pax) {
120 char *paxflags = pax_short_hf_flags(PAX_FLAGS(elf));
121 if (!be_quiet || (be_quiet && strncmp(paxflags, "PeMRxS", 6))) {
122 found_pax = 1;
105 printf("%s ", pax_short_hf_flags(PAX_FLAGS(elf))); 123 printf("%s ", pax_short_hf_flags(PAX_FLAGS(elf)));
124 }
125 }
106 126
107 /* stack fun */ 127 /* stack fun */
108 if (show_stack) { 128 if (show_stack) {
129#define SHOW_STACK(B) \
130 if (elf->elf_class == ELFCLASS ## B) { \
131 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
132 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
109 for (i = 0; i < elf->ehdr->e_phnum; i++) { 133 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
110 if (elf->phdr[i].p_type != PT_GNU_STACK && \ 134 if (EGET(phdr[i].p_type) != PT_GNU_STACK && \
111 elf->phdr[i].p_type != PT_GNU_RELRO) continue; 135 EGET(phdr[i].p_type) != PT_GNU_RELRO) continue; \
112
113 if (be_quiet && !(elf->phdr[i].p_flags & PF_X)) 136 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \
114 continue; 137 continue; \
115
116 if (elf->phdr[i].p_type == PT_GNU_STACK) 138 if (EGET(phdr[i].p_type) == PT_GNU_STACK) \
117 found_stack = 1; 139 found_stack = 1; \
118 if (elf->phdr[i].p_type == PT_GNU_RELRO) 140 if (EGET(phdr[i].p_type) == PT_GNU_RELRO) \
119 found_relro = 1; 141 found_relro = 1; \
120
121 printf("%s ", gnu_short_stack_flags(elf->phdr[i].p_flags)); 142 printf("%s ", gnu_short_stack_flags(EGET(phdr[i].p_flags))); \
122 } 143 } \
144 }
145 SHOW_STACK(32)
146 SHOW_STACK(64)
123 if (!be_quiet && !found_stack) fputs("--- ", stdout); 147 if (!be_quiet && !found_stack) printf("--- ");
124 if (!be_quiet && !found_relro) fputs("--- ", stdout); 148 if (!be_quiet && !found_relro) printf("--- ");
125 } 149 }
126 150
127 /* textrel fun */ 151 /* textrel fun */
128 if (show_textrel) { 152 if (show_textrel) {
153#define SHOW_TEXTREL(B) \
154 if (elf->elf_class == ELFCLASS ## B) { \
155 Elf ## B ## _Dyn *dyn; \
156 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
157 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
129 for (i = 0; i < elf->ehdr->e_phnum; i++) { 158 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
130 if (elf->phdr[i].p_type != PT_DYNAMIC) continue; 159 if (phdr[i].p_type != PT_DYNAMIC) continue; \
131 160 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
132 dyn = (Elf_Dyn *)(elf->data + elf->phdr[i].p_offset);
133 while (dyn->d_tag != DT_NULL) { 161 while (EGET(dyn->d_tag) != DT_NULL) { \
134 if (dyn->d_tag == DT_TEXTREL) { //dyn->d_tag != DT_FLAGS) 162 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
135 found_textrel = 1; 163 found_textrel = 1; \
136// if (dyn->d_un.d_val & DF_TEXTREL) 164 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
137 fputs("TEXTREL ", stdout); 165 printf("TEXTREL "); \
138 } 166 } \
139 ++dyn; 167 ++dyn; \
140 } 168 } \
141 } 169 } }
170 SHOW_TEXTREL(32)
171 SHOW_TEXTREL(64)
142 if (!be_quiet && !found_textrel) fputs("------- ", stdout); 172 if (!be_quiet && !found_textrel) printf("------- ");
143 } 173 }
144 174
145 /* rpath fun */ 175 /* rpath fun */
146 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */ 176 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */
147 if (show_rpath) { 177 if (show_rpath) {
178 char *rpath, *runpath;
148 Elf_Shdr *strtbl = elf_findsecbyname(elf, ".dynstr"); 179 void *strtbl_void = elf_findsecbyname(elf, ".dynstr");
180 rpath = runpath = NULL;
149 181
150 if (strtbl) 182 if (strtbl_void) {
183#define SHOW_RPATH(B) \
184 if (elf->elf_class == ELFCLASS ## B) { \
185 Elf ## B ## _Dyn *dyn; \
186 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
187 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
188 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
151 for (i = 0; i < elf->ehdr->e_phnum; i++) { 189 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
152 if (elf->phdr[i].p_type != PT_DYNAMIC) continue; 190 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
153 191 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
154 dyn = (Elf_Dyn *)(elf->data + elf->phdr[i].p_offset);
155 while (dyn->d_tag != DT_NULL) { 192 while (EGET(dyn->d_tag) != DT_NULL) { \
156 if (dyn->d_tag == DT_RPATH) { //|| dyn->d_tag != DT_RUNPATH) 193 if (EGET(dyn->d_tag) == DT_RPATH) { \
157 char *rpath = elf->data + strtbl->sh_offset + dyn->d_un.d_ptr; 194 rpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
158 found_rpath = 1; 195 found_rpath = 1; \
159 printf("%s ", rpath); 196 } else if (EGET(dyn->d_tag) == DT_RUNPATH) { \
197 runpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
198 found_rpath = 1; \
160 } 199 } \
161 ++dyn; 200 ++dyn; \
201 } \
202 } }
203 SHOW_RPATH(32)
204 SHOW_RPATH(64)
205 }
206 if (rpath && runpath) {
207 if (!strcmp(rpath, runpath))
208 printf("%-5s ", runpath);
209 else {
210 fprintf(stderr, "%s's RPATH [%s] != RUNPATH [%s]\n", filename, rpath, runpath);
211 printf("{%s,%s} ", rpath, runpath);
162 } 212 }
213 } else if (rpath || runpath)
214 printf("%-5s ", (runpath ? runpath : rpath));
215 else if (!be_quiet && !found_rpath)
216 printf(" - ");
163 } 217 }
164 if (!be_quiet && !found_rpath) fputs("- ", stdout); 218
219 /* print out all the NEEDED entries */
220 if (show_needed) {
221 char *needed;
222 void *strtbl_void = elf_findsecbyname(elf, ".dynstr");
223
224 if (strtbl_void) {
225#define SHOW_NEEDED(B) \
226 if (elf->elf_class == ELFCLASS ## B) { \
227 Elf ## B ## _Dyn *dyn; \
228 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
229 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
230 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
231 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
232 if (be_verbose && EGET(phdr[i].p_type) == PT_INTERP) { \
233 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
234 printf("%s\n", elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr)); \
235 exit(0); \
236 } \
237 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
238 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
239 while (EGET(dyn->d_tag) != DT_NULL) { \
240 if (EGET(dyn->d_tag) == DT_NEEDED) { \
241 needed = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
242 if (found_needed) printf(","); \
243 printf("%s", needed); \
244 found_needed = 1; \
245 } \
246 ++dyn; \
247 } \
248 } }
249 SHOW_NEEDED(32)
250 SHOW_NEEDED(64)
165 } 251 }
252 if (!be_quiet && !found_needed)
253 printf(" - ");
254 else if (found_needed)
255 printf(" ");
256 }
166 257
258 /* search the symbol table for a specified symbol */
259 if (find_sym) {
260 void *symtab_void, *strtab_void;
261 char *versioned_symname;
262 size_t len;
263
264 len = strlen(find_sym) + 1;
265 versioned_symname = (char *)malloc(sizeof(char) * (len+1));
266 if (!versioned_symname) {
267 warnf("Could not malloc() mem for sym scan");
268 return;
269 }
270 sprintf(versioned_symname, "%s@", find_sym);
271
272 symtab_void = elf_findsecbyname(elf, ".symtab");
273 strtab_void = elf_findsecbyname(elf, ".strtab");
274
275 if (symtab_void && strtab_void) {
276#define FIND_SYM(B) \
277 if (elf->elf_class == ELFCLASS ## B) { \
278 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
279 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
280 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
281 int cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \
282 char *symname; \
283 for (i = 0; i < cnt; ++i) { \
284 if (sym->st_name) { \
285 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
286 if (*find_sym == '*') { \
287 printf("%s(%s) %5lX %15s %s\n", \
288 ((found_sym == 0) ? "\n\t" : "\t"), \
289 (char *)basename(filename), \
290 (long)sym->st_size, \
291 (char *)get_elfstttype(sym->st_info), \
292 symname); \
293 found_sym = 1; \
294 } else if ((strcmp(find_sym, symname) == 0) || \
295 (strncmp(symname, versioned_symname, len) == 0)) \
296 found_sym++; \
297 } \
298 ++sym; \
299 } }
300 FIND_SYM(32)
301 FIND_SYM(64)
302 }
303 free(versioned_symname);
304 if (*find_sym != '*') {
305 if (found_sym)
306 printf(" %s ", find_sym);
307 else if (!be_quiet)
308 printf(" - ");
309 }
310 }
311
167 if (!be_quiet || show_pax || found_stack || found_textrel || found_rpath) 312 if (!be_quiet || found_pax || found_stack || found_textrel || \
168 puts(filename); 313 found_rpath || found_needed || found_sym)
314 printf("%s\n", filename);
169 315
170bail:
171 unreadelf(elf); 316 unreadelf(elf);
172} 317}
173 318
174/* scan a directory for ET_EXEC files and print when we find one */ 319/* scan a directory for ET_EXEC files and print when we find one */
175static void scanelf_dir(const char *path) 320static void scanelf_dir(const char *path)
176{ 321{
177 register DIR *dir; 322 register DIR *dir;
178 register struct dirent *dentry; 323 register struct dirent *dentry;
179 struct stat st; 324 struct stat st_top, st;
180 char *p; 325 char buf[_POSIX_PATH_MAX];
181 int len = 0; 326 size_t pathlen = 0, len = 0;
182 327
183 /* make sure path exists */ 328 /* make sure path exists */
184 if (lstat(path, &st) == -1) 329 if (lstat(path, &st_top) == -1)
185 return; 330 return;
186 331
187 /* ok, if it isn't a directory, assume we can open it */ 332 /* ok, if it isn't a directory, assume we can open it */
188 if (!S_ISDIR(st.st_mode)) { 333 if (!S_ISDIR(st_top.st_mode)) {
189 scanelf_file(path); 334 scanelf_file(path);
190 return; 335 return;
191 } 336 }
192 337
193 /* now scan the dir looking for fun stuff */ 338 /* now scan the dir looking for fun stuff */
194 if ((dir = opendir(path)) == NULL) { 339 if ((dir = opendir(path)) == NULL) {
195 warnf("could not opendir %s: %s", path, strerror(errno)); 340 warnf("could not opendir %s: %s", path, strerror(errno));
196 return; 341 return;
197 } 342 }
343 if (be_verbose) printf("%s: scanning dir\n", path);
198 344
345 pathlen = strlen(path);
199 while ((dentry = readdir(dir))) { 346 while ((dentry = readdir(dir))) {
200 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) 347 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
201 continue; 348 continue;
202 len = (strlen(path) + 2 + strlen(dentry->d_name)); 349 len = (pathlen + 1 + strlen(dentry->d_name) + 1);
203 p = malloc(len); 350 if (len >= sizeof(buf)) {
204 if (!p) 351 warnf("Skipping '%s': len > sizeof(buf); %d > %d\n", path, (int)len, (int)sizeof(buf));
205 err("scanelf_dir(): Could not malloc: %s", strerror(errno)); 352 continue;
206 strncpy(p, path, len); 353 }
207 strncat(p, "/", len); 354 sprintf(buf, "%s/%s", path, dentry->d_name);
208 strncat(p, dentry->d_name, len);
209 if (lstat(p, &st) != -1) { 355 if (lstat(buf, &st) != -1) {
210 if (S_ISREG(st.st_mode)) 356 if (S_ISREG(st.st_mode))
211 scanelf_file(p); 357 scanelf_file(buf);
212 else if (dir_recurse && S_ISDIR(st.st_mode)) { 358 else if (dir_recurse && S_ISDIR(st.st_mode)) {
359 if (dir_crossmount || (st_top.st_dev == st.st_dev))
213 scanelf_dir(p); 360 scanelf_dir(buf);
214 } 361 }
215 } 362 }
216 free(p);
217 } 363 }
218 closedir(dir); 364 closedir(dir);
219} 365}
220 366
221/* scan /etc/ld.so.conf for paths */ 367/* scan /etc/ld.so.conf for paths */
222static void scanelf_ldpath() 368static void scanelf_ldpath()
223{ 369{
370 char scan_l, scan_ul, scan_ull;
224 char *path, *p; 371 char *path, *p;
225 FILE *fp; 372 FILE *fp;
226 373
227 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 374 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
228 err("Unable to open ld.so.conf: %s", strerror(errno)); 375 err("Unable to open ld.so.conf: %s", strerror(errno));
229 376
377 scan_l = scan_ul = scan_ull = 0;
378
230 path = malloc(_POSIX_PATH_MAX); 379 if ((path = malloc(_POSIX_PATH_MAX)) == NULL) {
380 warn("Can not malloc() memory for ldpath scanning");
381 return;
382 }
231 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) 383 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
232 if (*path == '/') { 384 if (*path == '/') {
233 if ((p = strrchr(path, '\r')) != NULL) 385 if ((p = strrchr(path, '\r')) != NULL)
234 *p = 0; 386 *p = 0;
235 if ((p = strrchr(path, '\n')) != NULL) 387 if ((p = strrchr(path, '\n')) != NULL)
236 *p = 0; 388 *p = 0;
389 if (!scan_l && !strcmp(path, "/lib")) scan_l = 1;
390 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1;
391 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1;
237 scanelf_dir(path); 392 scanelf_dir(path);
238 } 393 }
239 free(path); 394 free(path);
240
241 fclose(fp); 395 fclose(fp);
396
397 if (!scan_l) scanelf_dir("/lib");
398 if (!scan_ul) scanelf_dir("/usr/lib");
399 if (!scan_ull) scanelf_dir("/usr/local/lib");
242} 400}
243 401
244/* scan env PATH for paths */ 402/* scan env PATH for paths */
245static void scanelf_envpath() 403static void scanelf_envpath()
246{ 404{
249 path = getenv("PATH"); 407 path = getenv("PATH");
250 if (!path) 408 if (!path)
251 err("PATH is not set in your env !"); 409 err("PATH is not set in your env !");
252 410
253 if ((path = strdup(path)) == NULL) 411 if ((path = strdup(path)) == NULL)
254 err("stdup failed: %s", strerror(errno)); 412 err("strdup failed: %s", strerror(errno));
255 413
256 while ((p = strrchr(path, ':')) != NULL) { 414 while ((p = strrchr(path, ':')) != NULL) {
257 scanelf_dir(p + 1); 415 scanelf_dir(p + 1);
258 *p = 0; 416 *p = 0;
259 } 417 }
418
260 free(path); 419 free(path);
261} 420}
262 421
263 422
264 423
265/* usage / invocation handling functions */ 424/* usage / invocation handling functions */
266#define PARSE_FLAGS "plRxstraqhV" 425#define PARSE_FLAGS "plRmxetrns:aqvo:BhV"
426#define a_argument required_argument
267static struct option const long_opts[] = { 427static struct option const long_opts[] = {
268 {"path", no_argument, NULL, 'p'}, 428 {"path", no_argument, NULL, 'p'},
269 {"ldpath", no_argument, NULL, 'l'}, 429 {"ldpath", no_argument, NULL, 'l'},
270 {"recursive", no_argument, NULL, 'R'}, 430 {"recursive", no_argument, NULL, 'R'},
431 {"mount", no_argument, NULL, 'm'},
271 {"pax", no_argument, NULL, 'x'}, 432 {"pax", no_argument, NULL, 'x'},
272 {"stack", no_argument, NULL, 's'}, 433 {"header", no_argument, NULL, 'e'},
273 {"textrel", no_argument, NULL, 't'}, 434 {"textrel", no_argument, NULL, 't'},
274 {"rpath", no_argument, NULL, 'r'}, 435 {"rpath", no_argument, NULL, 'r'},
436 {"needed", no_argument, NULL, 'n'},
437 {"symbol", a_argument, NULL, 's'},
275 {"all", no_argument, NULL, 'a'}, 438 {"all", no_argument, NULL, 'a'},
276 {"quiet", no_argument, NULL, 'q'}, 439 {"quiet", no_argument, NULL, 'q'},
277/* {"vebose", no_argument, NULL, 'v'},*/ 440 {"verbose", no_argument, NULL, 'v'},
441 {"file", a_argument, NULL, 'o'},
442 {"nobanner", no_argument, NULL, 'B'},
278 {"help", no_argument, NULL, 'h'}, 443 {"help", no_argument, NULL, 'h'},
279 {"version", no_argument, NULL, 'V'}, 444 {"version", no_argument, NULL, 'V'},
280 {NULL, no_argument, NULL, 0x0} 445 {NULL, no_argument, NULL, 0x0}
281}; 446};
282static char *opts_help[] = { 447static char *opts_help[] = {
283 "Scan all directories in PATH environment", 448 "Scan all directories in PATH environment",
284 "Scan all directories in /etc/ld.so.conf", 449 "Scan all directories in /etc/ld.so.conf",
285 "Scan directories recursively\n", 450 "Scan directories recursively",
451 "Don't recursively cross mount points\n",
286 "Print PaX markings", 452 "Print PaX markings",
287 "Print GNU_STACK markings", 453 "Print GNU_STACK markings",
288 "Print TEXTREL information", 454 "Print TEXTREL information",
289 "Print RPATH information", 455 "Print RPATH information",
456 "Print NEEDED information",
457 "Find a specified symbol",
290 "Print all scanned info", 458 "Print all scanned info (-x -e -t -r)\n",
291 "Only output 'bad' things\n", 459 "Only output 'bad' things",
292/* "Be verbose !",*/ 460 "Be verbose (can be specified more than once)",
461 "Write output stream to a filename",
462 "Don't display the header",
293 "Print this help and exit", 463 "Print this help and exit",
294 "Print version and exit", 464 "Print version and exit",
295 NULL 465 NULL
296}; 466};
297 467
298/* display usage and exit */ 468/* display usage and exit */
299static void usage(int status) 469static void usage(int status)
300{ 470{
301 int i; 471 int i;
302 printf(" Scan ELF binaries for stuff\n\n" 472 printf(" Scan ELF binaries for stuff\n"
303 "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0); 473 "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0);
304 fputs("Options:\n", stdout); 474 printf("Options:\n");
305 for (i = 0; long_opts[i].name; ++i) 475 for (i = 0; long_opts[i].name; ++i)
476 if (long_opts[i].has_arg == no_argument)
306 printf(" -%c, --%-12s %s\n", long_opts[i].val, 477 printf(" -%c, --%-13s %s\n", long_opts[i].val,
307 long_opts[i].name, opts_help[i]); 478 long_opts[i].name, opts_help[i]);
479 else
480 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val,
481 long_opts[i].name, opts_help[i]);
308 exit(status); 482 exit(status);
309} 483}
310 484
311/* parse command line arguments and preform needed actions */ 485/* parse command line arguments and preform needed actions */
312static void parseargs(int argc, char *argv[]) 486static void parseargs(int argc, char *argv[])
316 opterr = 0; 490 opterr = 0;
317 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) { 491 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
318 switch (flag) { 492 switch (flag) {
319 493
320 case 'V': /* version info */ 494 case 'V': /* version info */
321 printf("%s compiled %s\n" 495 printf("%s compiled %s\n%s\n"
322 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n" 496 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n",
323 "%s\n",
324 __FILE__, __DATE__, argv0, rcsid); 497 __FILE__, __DATE__, rcsid, argv0);
325 exit(EXIT_SUCCESS); 498 exit(EXIT_SUCCESS);
326 break; 499 break;
327 case 'h': usage(EXIT_SUCCESS); break; 500 case 'h': usage(EXIT_SUCCESS); break;
328 501
502 case 'o': {
503 FILE *fp = NULL;
504 fp = freopen(optarg, "w", stdout);
505 if (fp == NULL)
506 err("Could not open output stream '%s': %s", optarg, strerror(errno));
507 stdout = fp;
508 break;
509 }
510
511 case 's': find_sym = strdup(optarg); break;
512
513 case 'B': show_banner = 0; break;
329 case 'l': scan_ldpath = 1; break; 514 case 'l': scan_ldpath = 1; break;
330 case 'p': scan_envpath = 1; break; 515 case 'p': scan_envpath = 1; break;
331 case 'R': dir_recurse = 1; break; 516 case 'R': dir_recurse = 1; break;
517 case 'm': dir_crossmount = 0; break;
332 case 'x': show_pax = 1; break; 518 case 'x': show_pax = 1; break;
333 case 's': show_stack = 1; break; 519 case 'e': show_stack = 1; break;
334 case 't': show_textrel = 1; break; 520 case 't': show_textrel = 1; break;
335 case 'r': show_rpath = 1; break; 521 case 'r': show_rpath = 1; break;
522 case 'n': show_needed = 1; break;
336 case 'q': be_quiet = 1; break; 523 case 'q': be_quiet = 1; break;
524 case 'v': be_verbose = (be_verbose % 20) + 1; break;
337 case 'a': show_pax = show_stack = show_textrel = show_rpath = 1; break; 525 case 'a': show_pax = show_stack = show_textrel = show_needed = show_rpath = 1; break;
338 526
339 case ':': 527 case ':':
340 warn("Option missing parameter"); 528 warn("Option missing parameter");
341 usage(EXIT_FAILURE); 529 usage(EXIT_FAILURE);
342 break; 530 break;
348 err("Unhandled option '%c'", flag); 536 err("Unhandled option '%c'", flag);
349 break; 537 break;
350 } 538 }
351 } 539 }
352 540
541 if (be_quiet && be_verbose)
542 err("You can be quiet or you can be verbose, not both, stupid");
543
353 if (scan_ldpath) scanelf_ldpath(); 544 if (scan_ldpath) scanelf_ldpath();
354 if (scan_envpath) scanelf_envpath(); 545 if (scan_envpath) scanelf_envpath();
546 if (optind == argc && !scan_ldpath && !scan_envpath)
547 err("Nothing to scan !?");
355 while (optind < argc) 548 while (optind < argc)
356 scanelf_dir(argv[optind++]); 549 scanelf_dir(argv[optind++]);
550
551 if (find_sym) free(find_sym);
357} 552}
358 553
359 554
360 555
361int main(int argc, char *argv[]) 556int main(int argc, char *argv[])
362{ 557{
363 if (argc < 2) 558 if (argc < 2)
364 usage(EXIT_FAILURE); 559 usage(EXIT_FAILURE);
365 parseargs(argc, argv); 560 parseargs(argc, argv);
561 fclose(stdout);
366 return EXIT_SUCCESS; 562 return EXIT_SUCCESS;
367} 563}

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.32

  ViewVC Help
Powered by ViewVC 1.1.20