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

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

  ViewVC Help
Powered by ViewVC 1.1.20