/[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.16 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.16 2005/04/01 20:44:11 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.16 2005/04/01 20:44:11 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 { \
64static char dir_crossmount = 1; 66static char dir_crossmount = 1;
65static char show_pax = 0; 67static char show_pax = 0;
66static char show_stack = 0; 68static char show_stack = 0;
67static char show_textrel = 0; 69static char show_textrel = 0;
68static char show_rpath = 0; 70static char show_rpath = 0;
71static char show_needed = 0;
69static char show_banner = 1; 72static char show_banner = 1;
70static char be_quiet = 0; 73static char be_quiet = 0;
71static char be_verbose = 0; 74static char be_verbose = 0;
75static char *find_sym = NULL;
72 76
73 77
74 78
75/* scan an elf file and show all the fun stuff */ 79/* scan an elf file and show all the fun stuff */
76static void scanelf_file(const char *filename) 80static void scanelf_file(const char *filename)
77{ 81{
78 int i; 82 int i;
79 char found_pax, found_stack, found_relro, found_textrel, found_rpath; 83 char found_pax, found_stack, found_relro, found_textrel,
80 Elf_Dyn *dyn; 84 found_rpath, found_needed, found_sym;
81 elfobj *elf = NULL; 85 elfobj *elf;
82 86
83 found_pax = 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;
84 89
85 /* verify this is real ELF */ 90 /* verify this is real ELF */
86 if ((elf = readelf(filename)) == NULL) { 91 if ((elf = readelf(filename)) == NULL) {
87 if (be_verbose > 1) printf("%s: not an ELF\n", filename); 92 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
88 return; 93 return;
89 } 94 }
90 if (check_elf_header(elf->ehdr) || !IS_ELF(elf)) {
91 if (be_verbose > 1) printf("%s: cannot handle ELF :(\n", filename);
92 goto bail;
93 }
94 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)
95 if (be_verbose) printf("%s: scanning file\n", filename); 101 printf("%s: scanning file\n", filename);
96 102
97 /* show the header */ 103 /* show the header */
98 if (!be_quiet && show_banner) { 104 if (!be_quiet && show_banner) {
99 fputs(" TYPE ", stdout); 105 printf(" TYPE ");
100 if (show_pax) fputs(" PAX ", stdout); 106 if (show_pax) printf(" PAX ");
101 if (show_stack) fputs(" STK/REL ", stdout); 107 if (show_stack) printf("STK/REL ");
102 if (show_textrel) fputs("TEXTREL ", stdout); 108 if (show_textrel) printf("TEXTREL ");
103 if (show_rpath) fputs("RPATH ", stdout); 109 if (show_rpath) printf("RPATH ");
104 fputs(" FILE\n", stdout); 110 if (show_needed) printf("NEEDED ");
111 printf(" FILE\n");
105 show_banner = 0; 112 show_banner = 0;
106 } 113 }
107 114
108 /* dump all the good stuff */ 115 /* dump all the good stuff */
109 if (!be_quiet) 116 if (!be_quiet)
110 printf("%-7s ", get_elfetype(elf->ehdr->e_type)); 117 printf("%-7s ", get_elfetype(elf));
111 118
112 if (show_pax) { 119 if (show_pax) {
113 char *paxflags = pax_short_hf_flags(PAX_FLAGS(elf)); 120 char *paxflags = pax_short_hf_flags(PAX_FLAGS(elf));
114 if (!be_quiet || (be_quiet && strncmp(paxflags, "PeMRxS", 6))) { 121 if (!be_quiet || (be_quiet && strncmp(paxflags, "PeMRxS", 6))) {
115 found_pax = 1; 122 found_pax = 1;
117 } 124 }
118 } 125 }
119 126
120 /* stack fun */ 127 /* stack fun */
121 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); \
122 for (i = 0; i < elf->ehdr->e_phnum; i++) { 133 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
123 if (elf->phdr[i].p_type != PT_GNU_STACK && \ 134 if (EGET(phdr[i].p_type) != PT_GNU_STACK && \
124 elf->phdr[i].p_type != PT_GNU_RELRO) continue; 135 EGET(phdr[i].p_type) != PT_GNU_RELRO) continue; \
125
126 if (be_quiet && !(elf->phdr[i].p_flags & PF_X)) 136 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \
127 continue; 137 continue; \
128
129 if (elf->phdr[i].p_type == PT_GNU_STACK) 138 if (EGET(phdr[i].p_type) == PT_GNU_STACK) \
130 found_stack = 1; 139 found_stack = 1; \
131 if (elf->phdr[i].p_type == PT_GNU_RELRO) 140 if (EGET(phdr[i].p_type) == PT_GNU_RELRO) \
132 found_relro = 1; 141 found_relro = 1; \
133
134 printf("%s ", gnu_short_stack_flags(elf->phdr[i].p_flags)); 142 printf("%s ", gnu_short_stack_flags(EGET(phdr[i].p_flags))); \
135 } 143 } \
144 }
145 SHOW_STACK(32)
146 SHOW_STACK(64)
136 if (!be_quiet && !found_stack) fputs("--- ", stdout); 147 if (!be_quiet && !found_stack) printf("--- ");
137 if (!be_quiet && !found_relro) fputs("--- ", stdout); 148 if (!be_quiet && !found_relro) printf("--- ");
138 } 149 }
139 150
140 /* textrel fun */ 151 /* textrel fun */
141 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); \
142 for (i = 0; i < elf->ehdr->e_phnum; i++) { 158 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
143 if (elf->phdr[i].p_type != PT_DYNAMIC) continue; 159 if (phdr[i].p_type != PT_DYNAMIC) continue; \
144 160 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
145 dyn = (Elf_Dyn *)(elf->data + elf->phdr[i].p_offset);
146 while (dyn->d_tag != DT_NULL) { 161 while (EGET(dyn->d_tag) != DT_NULL) { \
147 if (dyn->d_tag == DT_TEXTREL) { //dyn->d_tag != DT_FLAGS) 162 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
148 found_textrel = 1; 163 found_textrel = 1; \
149// if (dyn->d_un.d_val & DF_TEXTREL) 164 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
150 fputs("TEXTREL ", stdout); 165 printf("TEXTREL "); \
151 } 166 } \
152 ++dyn; 167 ++dyn; \
153 } 168 } \
154 } 169 } }
170 SHOW_TEXTREL(32)
171 SHOW_TEXTREL(64)
155 if (!be_quiet && !found_textrel) fputs("------- ", stdout); 172 if (!be_quiet && !found_textrel) printf("------- ");
156 } 173 }
157 174
158 /* rpath fun */ 175 /* rpath fun */
159 /* 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 */
160 if (show_rpath) { 177 if (show_rpath) {
178 char *rpath, *runpath;
161 Elf_Shdr *strtbl = elf_findsecbyname(elf, ".dynstr"); 179 void *strtbl_void = elf_findsecbyname(elf, ".dynstr");
180 rpath = runpath = NULL;
162 181
163 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); \
164 for (i = 0; i < elf->ehdr->e_phnum; i++) { 189 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
165 if (elf->phdr[i].p_type != PT_DYNAMIC) continue; 190 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
166 191 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
167 dyn = (Elf_Dyn *)(elf->data + elf->phdr[i].p_offset);
168 while (dyn->d_tag != DT_NULL) { 192 while (EGET(dyn->d_tag) != DT_NULL) { \
169 if (dyn->d_tag == DT_RPATH) { //|| dyn->d_tag != DT_RUNPATH) 193 if (EGET(dyn->d_tag) == DT_RPATH) { \
170 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); \
171 found_rpath = 1; 195 found_rpath = 1; \
172 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; \
173 } 199 } \
174 ++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);
175 } 212 }
213 } else if (rpath || runpath)
214 printf("%-5s ", (runpath ? runpath : rpath));
215 else if (!be_quiet && !found_rpath)
216 printf(" - ");
176 } 217 }
177 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)
178 } 251 }
252 if (!be_quiet && !found_needed)
253 printf(" - ");
254 else if (found_needed)
255 printf(" ");
256 }
179 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
180 if (!be_quiet || found_pax || found_stack || found_textrel || found_rpath) 312 if (!be_quiet || found_pax || found_stack || found_textrel || \
181 puts(filename); 313 found_rpath || found_needed || found_sym)
314 printf("%s\n", filename);
182 315
183bail:
184 unreadelf(elf); 316 unreadelf(elf);
185} 317}
186 318
187/* 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 */
188static void scanelf_dir(const char *path) 320static void scanelf_dir(const char *path)
189{ 321{
190 register DIR *dir; 322 register DIR *dir;
191 register struct dirent *dentry; 323 register struct dirent *dentry;
192 struct stat st_top, st; 324 struct stat st_top, st;
193 char *p; 325 char buf[_POSIX_PATH_MAX];
194 int len = 0; 326 size_t pathlen = 0, len = 0;
195 327
196 /* make sure path exists */ 328 /* make sure path exists */
197 if (lstat(path, &st_top) == -1) 329 if (lstat(path, &st_top) == -1)
198 return; 330 return;
199 331
208 warnf("could not opendir %s: %s", path, strerror(errno)); 340 warnf("could not opendir %s: %s", path, strerror(errno));
209 return; 341 return;
210 } 342 }
211 if (be_verbose) printf("%s: scanning dir\n", path); 343 if (be_verbose) printf("%s: scanning dir\n", path);
212 344
345 pathlen = strlen(path);
213 while ((dentry = readdir(dir))) { 346 while ((dentry = readdir(dir))) {
214 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) 347 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
215 continue; 348 continue;
216 len = (strlen(path) + 2 + strlen(dentry->d_name)); 349 len = (pathlen + 1 + strlen(dentry->d_name) + 1);
217 p = malloc(len); 350 if (len >= sizeof(buf)) {
218 if (!p) 351 warnf("Skipping '%s': len > sizeof(buf); %d > %d\n", path, (int)len, (int)sizeof(buf));
219 err("scanelf_dir(): Could not malloc: %s", strerror(errno)); 352 continue;
220 strncpy(p, path, len); 353 }
221 strncat(p, "/", len); 354 sprintf(buf, "%s/%s", path, dentry->d_name);
222 strncat(p, dentry->d_name, len);
223 if (lstat(p, &st) != -1) { 355 if (lstat(buf, &st) != -1) {
224 if (S_ISREG(st.st_mode)) 356 if (S_ISREG(st.st_mode))
225 scanelf_file(p); 357 scanelf_file(buf);
226 else if (dir_recurse && S_ISDIR(st.st_mode)) { 358 else if (dir_recurse && S_ISDIR(st.st_mode)) {
227 if (dir_crossmount || (st_top.st_dev == st.st_dev)) 359 if (dir_crossmount || (st_top.st_dev == st.st_dev))
228 scanelf_dir(p); 360 scanelf_dir(buf);
229 } 361 }
230 } 362 }
231 free(p);
232 } 363 }
233 closedir(dir); 364 closedir(dir);
234} 365}
235 366
236/* scan /etc/ld.so.conf for paths */ 367/* scan /etc/ld.so.conf for paths */
237static void scanelf_ldpath() 368static void scanelf_ldpath()
238{ 369{
370 char scan_l, scan_ul, scan_ull;
239 char *path, *p; 371 char *path, *p;
240 FILE *fp; 372 FILE *fp;
241 373
242 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 374 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
243 err("Unable to open ld.so.conf: %s", strerror(errno)); 375 err("Unable to open ld.so.conf: %s", strerror(errno));
244 376
377 scan_l = scan_ul = scan_ull = 0;
378
245 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 }
246 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) 383 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
247 if (*path == '/') { 384 if (*path == '/') {
248 if ((p = strrchr(path, '\r')) != NULL) 385 if ((p = strrchr(path, '\r')) != NULL)
249 *p = 0; 386 *p = 0;
250 if ((p = strrchr(path, '\n')) != NULL) 387 if ((p = strrchr(path, '\n')) != NULL)
251 *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;
252 scanelf_dir(path); 392 scanelf_dir(path);
253 } 393 }
254 free(path); 394 free(path);
255
256 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");
257} 400}
258 401
259/* scan env PATH for paths */ 402/* scan env PATH for paths */
260static void scanelf_envpath() 403static void scanelf_envpath()
261{ 404{
264 path = getenv("PATH"); 407 path = getenv("PATH");
265 if (!path) 408 if (!path)
266 err("PATH is not set in your env !"); 409 err("PATH is not set in your env !");
267 410
268 if ((path = strdup(path)) == NULL) 411 if ((path = strdup(path)) == NULL)
269 err("stdup failed: %s", strerror(errno)); 412 err("strdup failed: %s", strerror(errno));
270 413
271 while ((p = strrchr(path, ':')) != NULL) { 414 while ((p = strrchr(path, ':')) != NULL) {
272 scanelf_dir(p + 1); 415 scanelf_dir(p + 1);
273 *p = 0; 416 *p = 0;
274 } 417 }
418
275 free(path); 419 free(path);
276} 420}
277 421
278 422
279 423
280/* usage / invocation handling functions */ 424/* usage / invocation handling functions */
281#define PARSE_FLAGS "plRmxetraqvBhV" 425#define PARSE_FLAGS "plRmxetrns:aqvo:BhV"
426#define a_argument required_argument
282static struct option const long_opts[] = { 427static struct option const long_opts[] = {
283 {"path", no_argument, NULL, 'p'}, 428 {"path", no_argument, NULL, 'p'},
284 {"ldpath", no_argument, NULL, 'l'}, 429 {"ldpath", no_argument, NULL, 'l'},
285 {"recursive", no_argument, NULL, 'R'}, 430 {"recursive", no_argument, NULL, 'R'},
286 {"mount", no_argument, NULL, 'm'}, 431 {"mount", no_argument, NULL, 'm'},
287 {"pax", no_argument, NULL, 'x'}, 432 {"pax", no_argument, NULL, 'x'},
288 {"header", no_argument, NULL, 'e'}, 433 {"header", no_argument, NULL, 'e'},
289 {"textrel", no_argument, NULL, 't'}, 434 {"textrel", no_argument, NULL, 't'},
290 {"rpath", no_argument, NULL, 'r'}, 435 {"rpath", no_argument, NULL, 'r'},
436 {"needed", no_argument, NULL, 'n'},
437 {"symbol", a_argument, NULL, 's'},
291 {"all", no_argument, NULL, 'a'}, 438 {"all", no_argument, NULL, 'a'},
292 {"quiet", no_argument, NULL, 'q'}, 439 {"quiet", no_argument, NULL, 'q'},
293 {"verbose", no_argument, NULL, 'v'}, 440 {"verbose", no_argument, NULL, 'v'},
441 {"file", a_argument, NULL, 'o'},
294 {"nobanner", no_argument, NULL, 'B'}, 442 {"nobanner", no_argument, NULL, 'B'},
295 {"help", no_argument, NULL, 'h'}, 443 {"help", no_argument, NULL, 'h'},
296 {"version", no_argument, NULL, 'V'}, 444 {"version", no_argument, NULL, 'V'},
297 {NULL, no_argument, NULL, 0x0} 445 {NULL, no_argument, NULL, 0x0}
298}; 446};
303 "Don't recursively cross mount points\n", 451 "Don't recursively cross mount points\n",
304 "Print PaX markings", 452 "Print PaX markings",
305 "Print GNU_STACK markings", 453 "Print GNU_STACK markings",
306 "Print TEXTREL information", 454 "Print TEXTREL information",
307 "Print RPATH information", 455 "Print RPATH information",
456 "Print NEEDED information",
457 "Find a specified symbol",
308 "Print all scanned info (-x -e -t -r)\n", 458 "Print all scanned info (-x -e -t -r)\n",
309 "Only output 'bad' things", 459 "Only output 'bad' things",
310 "Be verbose (can be specified more than once)", 460 "Be verbose (can be specified more than once)",
461 "Write output stream to a filename",
311 "Don't display the header", 462 "Don't display the header",
312 "Print this help and exit", 463 "Print this help and exit",
313 "Print version and exit", 464 "Print version and exit",
314 NULL 465 NULL
315}; 466};
316 467
317/* display usage and exit */ 468/* display usage and exit */
318static void usage(int status) 469static void usage(int status)
319{ 470{
320 int i; 471 int i;
321 printf(" Scan ELF binaries for stuff\n\n" 472 printf(" Scan ELF binaries for stuff\n"
322 "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0); 473 "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0);
323 fputs("Options:\n", stdout); 474 printf("Options:\n");
324 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)
325 printf(" -%c, --%-12s %s\n", long_opts[i].val, 477 printf(" -%c, --%-13s %s\n", long_opts[i].val,
326 long_opts[i].name, opts_help[i]); 478 long_opts[i].name, opts_help[i]);
327#ifdef MANLYPAGE 479 else
328 for (i = 0; long_opts[i].name; ++i) 480 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val,
329 printf(".TP\n\\fB\\-%c, \\-\\-%s\\fR\n%s\n", long_opts[i].val,
330 long_opts[i].name, opts_help[i]); 481 long_opts[i].name, opts_help[i]);
331#endif
332 exit(status); 482 exit(status);
333} 483}
334 484
335/* parse command line arguments and preform needed actions */ 485/* parse command line arguments and preform needed actions */
336static void parseargs(int argc, char *argv[]) 486static void parseargs(int argc, char *argv[])
340 opterr = 0; 490 opterr = 0;
341 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) {
342 switch (flag) { 492 switch (flag) {
343 493
344 case 'V': /* version info */ 494 case 'V': /* version info */
345 printf("%s compiled %s\n" 495 printf("%s compiled %s\n%s\n"
346 "%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",
347 "%s\n",
348 __FILE__, __DATE__, argv0, rcsid); 497 __FILE__, __DATE__, rcsid, argv0);
349 exit(EXIT_SUCCESS); 498 exit(EXIT_SUCCESS);
350 break; 499 break;
351 case 's': /* reserved for -s, --symbol= */
352 case 'h': usage(EXIT_SUCCESS); break; 500 case 'h': usage(EXIT_SUCCESS); break;
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;
353 512
354 case 'B': show_banner = 0; break; 513 case 'B': show_banner = 0; break;
355 case 'l': scan_ldpath = 1; break; 514 case 'l': scan_ldpath = 1; break;
356 case 'p': scan_envpath = 1; break; 515 case 'p': scan_envpath = 1; break;
357 case 'R': dir_recurse = 1; break; 516 case 'R': dir_recurse = 1; break;
358 case 'm': dir_crossmount = 0; break; 517 case 'm': dir_crossmount = 0; break;
359 case 'x': show_pax = 1; break; 518 case 'x': show_pax = 1; break;
360 case 'e': show_stack = 1; break; 519 case 'e': show_stack = 1; break;
361 case 't': show_textrel = 1; break; 520 case 't': show_textrel = 1; break;
362 case 'r': show_rpath = 1; break; 521 case 'r': show_rpath = 1; break;
522 case 'n': show_needed = 1; break;
363 case 'q': be_quiet = 1; break; 523 case 'q': be_quiet = 1; break;
364 case 'v': be_verbose = (be_verbose % 20) + 1; break; 524 case 'v': be_verbose = (be_verbose % 20) + 1; break;
365 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;
366 526
367 case ':': 527 case ':':
368 warn("Option missing parameter"); 528 warn("Option missing parameter");
369 usage(EXIT_FAILURE); 529 usage(EXIT_FAILURE);
370 break; 530 break;
381 if (be_quiet && be_verbose) 541 if (be_quiet && be_verbose)
382 err("You can be quiet or you can be verbose, not both, stupid"); 542 err("You can be quiet or you can be verbose, not both, stupid");
383 543
384 if (scan_ldpath) scanelf_ldpath(); 544 if (scan_ldpath) scanelf_ldpath();
385 if (scan_envpath) scanelf_envpath(); 545 if (scan_envpath) scanelf_envpath();
546 if (optind == argc && !scan_ldpath && !scan_envpath)
547 err("Nothing to scan !?");
386 while (optind < argc) 548 while (optind < argc)
387 scanelf_dir(argv[optind++]); 549 scanelf_dir(argv[optind++]);
550
551 if (find_sym) free(find_sym);
388} 552}
389 553
390 554
391 555
392int main(int argc, char *argv[]) 556int main(int argc, char *argv[])
393{ 557{
394 if (argc < 2) 558 if (argc < 2)
395 usage(EXIT_FAILURE); 559 usage(EXIT_FAILURE);
396 parseargs(argc, argv); 560 parseargs(argc, argv);
561 fclose(stdout);
397 return EXIT_SUCCESS; 562 return EXIT_SUCCESS;
398} 563}

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

  ViewVC Help
Powered by ViewVC 1.1.20