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

Legend:
Removed from v.1.22  
changed lines
  Added in v.1.35

  ViewVC Help
Powered by ViewVC 1.1.20