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

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

  ViewVC Help
Powered by ViewVC 1.1.20