/[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.43 Revision 1.48
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.43 2005/05/06 02:55:27 vapier Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.48 2005/05/18 02:51:02 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
33#include <getopt.h> 33#include <getopt.h>
34#include <assert.h> 34#include <assert.h>
35 35
36#include "paxelf.h" 36#include "paxelf.h"
37 37
38static const char *rcsid = "$Id: scanelf.c,v 1.43 2005/05/06 02:55:27 vapier Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.48 2005/05/18 02:51:02 vapier Exp $";
39#define argv0 "scanelf" 39#define argv0 "scanelf"
40 40
41 41
42 42
43/* prototypes */ 43/* prototypes */
52static void xstrcat(char **dst, const char *src, size_t *curr_len); 52static void xstrcat(char **dst, const char *src, size_t *curr_len);
53static inline void xchrcat(char **dst, const char append, size_t *curr_len); 53static inline void xchrcat(char **dst, const char append, size_t *curr_len);
54static int xemptybuffer(const char *buff); 54static int xemptybuffer(const char *buff);
55 55
56/* variables to control behavior */ 56/* variables to control behavior */
57static char *ldpaths[256];
57static char scan_ldpath = 0; 58static char scan_ldpath = 0;
58static char scan_envpath = 0; 59static char scan_envpath = 0;
59static char scan_symlink = 1; 60static char scan_symlink = 1;
60static char dir_recurse = 0; 61static char dir_recurse = 0;
61static char dir_crossmount = 1; 62static char dir_crossmount = 1;
90} 91}
91static char *scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro) 92static char *scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro)
92{ 93{
93 static char ret[8]; 94 static char ret[8];
94 char *found; 95 char *found;
95 int i, off, shown; 96 unsigned long i, off, shown;
96 97
97 if (!show_stack) return NULL; 98 if (!show_stack) return NULL;
98 99
99 shown = 0; 100 shown = 0;
100 strcpy(ret, "--- ---"); 101 strcpy(ret, "--- ---");
102
103 if (elf->phdr) {
101#define SHOW_STACK(B) \ 104#define SHOW_STACK(B) \
102 if (elf->elf_class == ELFCLASS ## B) { \ 105 if (elf->elf_class == ELFCLASS ## B) { \
103 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 106 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
104 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 107 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
105 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 108 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
118 ++shown; \ 121 ++shown; \
119 } \ 122 } \
120 } 123 }
121 SHOW_STACK(32) 124 SHOW_STACK(32)
122 SHOW_STACK(64) 125 SHOW_STACK(64)
126 }
127
123 if (be_quiet && !shown) 128 if (be_quiet && !shown)
124 return NULL; 129 return NULL;
125 else 130 else
126 return ret; 131 return ret;
127} 132}
128static char *scanelf_file_textrel(elfobj *elf, char *found_textrel) 133static char *scanelf_file_textrel(elfobj *elf, char *found_textrel)
129{ 134{
130 static char *ret = "TEXTREL"; 135 static char *ret = "TEXTREL";
131 int i; 136 unsigned long i;
132 137
133 if (!show_textrel) return NULL; 138 if (!show_textrel) return NULL;
134 139
140 if (elf->phdr) {
135#define SHOW_TEXTREL(B) \ 141#define SHOW_TEXTREL(B) \
136 if (elf->elf_class == ELFCLASS ## B) { \ 142 if (elf->elf_class == ELFCLASS ## B) { \
137 Elf ## B ## _Dyn *dyn; \ 143 Elf ## B ## _Dyn *dyn; \
138 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 144 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
139 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 145 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
146 Elf ## B ## _Off offset; \
140 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 147 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
141 if (phdr[i].p_type != PT_DYNAMIC) continue; \ 148 if (phdr[i].p_type != PT_DYNAMIC) continue; \
149 offset = EGET(phdr[i].p_offset); \
150 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
142 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 151 dyn = DYN ## B (elf->data + offset); \
143 while (EGET(dyn->d_tag) != DT_NULL) { \ 152 while (EGET(dyn->d_tag) != DT_NULL) { \
144 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \ 153 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
145 *found_textrel = 1; \ 154 *found_textrel = 1; \
146 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \ 155 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
147 return ret; \ 156 return ret; \
149 ++dyn; \ 158 ++dyn; \
150 } \ 159 } \
151 } } 160 } }
152 SHOW_TEXTREL(32) 161 SHOW_TEXTREL(32)
153 SHOW_TEXTREL(64) 162 SHOW_TEXTREL(64)
163 }
164
154 if (be_quiet) 165 if (be_quiet)
155 return NULL; 166 return NULL;
156 else 167 else
157 return " - "; 168 return " - ";
158} 169}
159static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len) 170static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len)
160{ 171{
161 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */ 172 /* TODO: when checking RPATH entries, check each subpath (between :) in ld.so.conf */
162 int i; 173 unsigned long i, s;
163 char *rpath, *runpath; 174 char *rpath, *runpath, **r;
164 void *strtbl_void; 175 void *strtbl_void;
165 176
166 if (!show_rpath) return; 177 if (!show_rpath) return;
167 178
168 strtbl_void = elf_findsecbyname(elf, ".dynstr"); 179 strtbl_void = elf_findsecbyname(elf, ".dynstr");
169 rpath = runpath = NULL; 180 rpath = runpath = NULL;
170 181
171 if (strtbl_void) { 182 if (elf->phdr && strtbl_void) {
172#define SHOW_RPATH(B) \ 183#define SHOW_RPATH(B) \
173 if (elf->elf_class == ELFCLASS ## B) { \ 184 if (elf->elf_class == ELFCLASS ## B) { \
174 Elf ## B ## _Dyn *dyn; \ 185 Elf ## B ## _Dyn *dyn; \
175 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 186 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
176 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 187 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
177 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 188 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
189 Elf ## B ## _Off offset; \
190 Elf ## B ## _Sxword word; \
191 /* Scan all the program headers */ \
178 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 192 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
193 /* Just scan dynamic headers */ \
179 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 194 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
195 offset = EGET(phdr[i].p_offset); \
196 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
197 /* Just scan dynamic RPATH/RUNPATH headers */ \
180 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 198 dyn = DYN ## B (elf->data + offset); \
181 while (EGET(dyn->d_tag) != DT_NULL) { \ 199 while ((word=EGET(dyn->d_tag)) != DT_NULL) { \
182 if (EGET(dyn->d_tag) == DT_RPATH) { \ 200 if (word == DT_RPATH) { \
183 if (rpath) warn("ELF has multiple DT_RPATH's !?"); \ 201 r = &rpath; \
202 } else if (word == DT_RUNPATH) { \
203 r = &runpath; \
204 } else { \
205 ++dyn; \
206 continue; \
207 } \
208 /* Verify the memory is somewhat sane */ \
184 rpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 209 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
210 if (offset < elf->len) { \
211 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \
212 *r = (char*)(elf->data + offset); \
213 /* If quiet, don't output paths in ld.so.conf */ \
214 if (be_quiet) \
215 for (s = 0; ldpaths[s]; ++s) \
216 if (!strcmp(ldpaths[s], *r)) { \
217 *r = NULL; \
218 break; \
219 } \
185 *found_rpath = 1; \ 220 if (*r) *found_rpath = 1; \
186 } else if (EGET(dyn->d_tag) == DT_RUNPATH) { \
187 if (runpath) warn("ELF has multiple DT_RUNPATH's !?"); \
188 runpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
189 *found_rpath = 1; \
190 } \ 221 } \
191 ++dyn; \ 222 ++dyn; \
192 } \ 223 } \
193 } } 224 } }
194 SHOW_RPATH(32) 225 SHOW_RPATH(32)
211 else if (!be_quiet) 242 else if (!be_quiet)
212 xstrcat(ret, " - ", ret_len); 243 xstrcat(ret, " - ", ret_len);
213} 244}
214static void scanelf_file_needed(elfobj *elf, char *found_needed, char **ret, size_t *ret_len) 245static void scanelf_file_needed(elfobj *elf, char *found_needed, char **ret, size_t *ret_len)
215{ 246{
216 int i; 247 unsigned long i;
217 char *needed; 248 char *needed;
218 void *strtbl_void; 249 void *strtbl_void;
219 250
220 if (!show_needed) return; 251 if (!show_needed) return;
221 252
222 strtbl_void = elf_findsecbyname(elf, ".dynstr"); 253 strtbl_void = elf_findsecbyname(elf, ".dynstr");
223 254
224 if (strtbl_void) { 255 if (elf->phdr && strtbl_void) {
225#define SHOW_NEEDED(B) \ 256#define SHOW_NEEDED(B) \
226 if (elf->elf_class == ELFCLASS ## B) { \ 257 if (elf->elf_class == ELFCLASS ## B) { \
227 Elf ## B ## _Dyn *dyn; \ 258 Elf ## B ## _Dyn *dyn; \
228 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 259 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
229 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 260 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
230 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 261 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
262 Elf ## B ## _Off offset; \
231 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 263 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
232 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 264 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
265 offset = EGET(phdr[i].p_offset); \
266 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
233 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 267 dyn = DYN ## B (elf->data + offset); \
234 while (EGET(dyn->d_tag) != DT_NULL) { \ 268 while (EGET(dyn->d_tag) != DT_NULL) { \
235 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 269 if (EGET(dyn->d_tag) == DT_NEEDED) { \
236 needed = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 270 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
271 if (offset >= elf->len) continue; \
272 needed = (char*)(elf->data + offset); \
237 if (*found_needed) xchrcat(ret, ',', ret_len); \ 273 if (*found_needed) xchrcat(ret, ',', ret_len); \
238 xstrcat(ret, needed, ret_len); \ 274 xstrcat(ret, needed, ret_len); \
239 *found_needed = 1; \ 275 *found_needed = 1; \
240 } \ 276 } \
241 ++dyn; \ 277 ++dyn; \
265 } 301 }
266 return NULL; 302 return NULL;
267} 303}
268static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename) 304static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename)
269{ 305{
270 int i; 306 unsigned long i;
271 void *symtab_void, *strtab_void; 307 void *symtab_void, *strtab_void;
272 308
273 if (!find_sym) return NULL; 309 if (!find_sym) return NULL;
274 310
275 symtab_void = elf_findsecbyname(elf, ".symtab"); 311 symtab_void = elf_findsecbyname(elf, ".symtab");
279#define FIND_SYM(B) \ 315#define FIND_SYM(B) \
280 if (elf->elf_class == ELFCLASS ## B) { \ 316 if (elf->elf_class == ELFCLASS ## B) { \
281 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 317 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
282 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 318 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
283 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 319 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
284 int cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \ 320 unsigned long cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \
285 char *symname; \ 321 char *symname; \
286 for (i = 0; i < cnt; ++i) { \ 322 for (i = 0; i < cnt; ++i) { \
287 if (sym->st_name) { \ 323 if (sym->st_name) { \
288 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 324 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
289 if (*find_sym == '*') { \ 325 if (*find_sym == '*') { \
312} 348}
313/* scan an elf file and show all the fun stuff */ 349/* scan an elf file and show all the fun stuff */
314#define prints(str) fputs(str, stdout) 350#define prints(str) fputs(str, stdout)
315static void scanelf_file(const char *filename) 351static void scanelf_file(const char *filename)
316{ 352{
317 int i; 353 unsigned long i;
318 char found_pax, found_stack, found_relro, found_textrel, 354 char found_pax, found_stack, found_relro, found_textrel,
319 found_rpath, found_needed, found_interp, found_sym, 355 found_rpath, found_needed, found_interp, found_sym,
320 found_file; 356 found_file;
321 elfobj *elf; 357 elfobj *elf;
322 struct stat st; 358 struct stat st;
468 } 504 }
469 } 505 }
470 closedir(dir); 506 closedir(dir);
471} 507}
472 508
509static int scanelf_from_file(char *filename)
510{
511 FILE *fp = NULL;
512 char *p;
513 char path[_POSIX_PATH_MAX];
514
515 if (((strcmp(filename, "-")) == 0) && (ttyname(0) == NULL))
516 fp = stdin;
517 else if ((fp = fopen(filename, "r")) == NULL)
518 return 1;
519
520 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) {
521 if ((p = strchr(path, '\n')) != NULL)
522 *p = 0;
523 scanelf_dir(path);
524 }
525 if (fp != stdin)
526 fclose(fp);
527 return 0;
528}
529
530static void load_ld_so_conf()
531{
532 FILE *fp = NULL;
533 char *p;
534 char path[_POSIX_PATH_MAX];
535 int i = 0;
536
537 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
538 return;
539
540 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) {
541 if (*path != '/')
542 continue;
543
544 if ((p = strrchr(path, '\r')) != NULL)
545 *p = 0;
546 if ((p = strchr(path, '\n')) != NULL)
547 *p = 0;
548
549 ldpaths[i++] = xstrdup(path);
550
551 if (i + 1 == sizeof(ldpaths) / sizeof(*ldpaths))
552 break;
553 }
554 ldpaths[i] = NULL;
555
556 fclose(fp);
557}
558
473/* scan /etc/ld.so.conf for paths */ 559/* scan /etc/ld.so.conf for paths */
474static void scanelf_ldpath() 560static void scanelf_ldpath()
475{ 561{
476 char scan_l, scan_ul, scan_ull; 562 char scan_l, scan_ul, scan_ull;
477 char *path, *p; 563 int i = 0;
478 FILE *fp;
479 564
480 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 565 if (!ldpaths[0])
481 err("Unable to open ld.so.conf: %s", strerror(errno)); 566 err("Unable to load any paths from ld.so.conf");
482 567
483 scan_l = scan_ul = scan_ull = 0; 568 scan_l = scan_ul = scan_ull = 0;
484 569
485 path = (char*)xmalloc(_POSIX_PATH_MAX); 570 while (ldpaths[i]) {
486 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
487 if (*path == '/') {
488 if ((p = strrchr(path, '\r')) != NULL)
489 *p = 0;
490 if ((p = strrchr(path, '\n')) != NULL)
491 *p = 0;
492 if (!scan_l && !strcmp(path, "/lib")) scan_l = 1; 571 if (!scan_l && !strcmp(ldpaths[i], "/lib")) scan_l = 1;
493 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1; 572 if (!scan_ul && !strcmp(ldpaths[i], "/usr/lib")) scan_ul = 1;
494 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1; 573 if (!scan_ull && !strcmp(ldpaths[i], "/usr/local/lib")) scan_ull = 1;
495 scanelf_dir(path); 574 scanelf_dir(ldpaths[i]);
575 ++i;
496 } 576 }
497 free(path);
498 fclose(fp);
499 577
500 if (!scan_l) scanelf_dir("/lib"); 578 if (!scan_l) scanelf_dir("/lib");
501 if (!scan_ul) scanelf_dir("/usr/lib"); 579 if (!scan_ul) scanelf_dir("/usr/lib");
502 if (!scan_ull) scanelf_dir("/usr/local/lib"); 580 if (!scan_ull) scanelf_dir("/usr/local/lib");
503} 581}
521} 599}
522 600
523 601
524 602
525/* usage / invocation handling functions */ 603/* usage / invocation handling functions */
526#define PARSE_FLAGS "plRmyxetrnis:aqvF:o:BhV" 604#define PARSE_FLAGS "plRmyxetrnis:aqvF:f:o:BhV"
527#define a_argument required_argument 605#define a_argument required_argument
528static struct option const long_opts[] = { 606static struct option const long_opts[] = {
529 {"path", no_argument, NULL, 'p'}, 607 {"path", no_argument, NULL, 'p'},
530 {"ldpath", no_argument, NULL, 'l'}, 608 {"ldpath", no_argument, NULL, 'l'},
531 {"recursive", no_argument, NULL, 'R'}, 609 {"recursive", no_argument, NULL, 'R'},
540 {"symbol", a_argument, NULL, 's'}, 618 {"symbol", a_argument, NULL, 's'},
541 {"all", no_argument, NULL, 'a'}, 619 {"all", no_argument, NULL, 'a'},
542 {"quiet", no_argument, NULL, 'q'}, 620 {"quiet", no_argument, NULL, 'q'},
543 {"verbose", no_argument, NULL, 'v'}, 621 {"verbose", no_argument, NULL, 'v'},
544 {"format", a_argument, NULL, 'F'}, 622 {"format", a_argument, NULL, 'F'},
623 {"from", a_argument, NULL, 'f'},
545 {"file", a_argument, NULL, 'o'}, 624 {"file", a_argument, NULL, 'o'},
546 {"nobanner", no_argument, NULL, 'B'}, 625 {"nobanner", no_argument, NULL, 'B'},
547 {"help", no_argument, NULL, 'h'}, 626 {"help", no_argument, NULL, 'h'},
548 {"version", no_argument, NULL, 'V'}, 627 {"version", no_argument, NULL, 'V'},
549 {NULL, no_argument, NULL, 0x0} 628 {NULL, no_argument, NULL, 0x0}
559 "Print TEXTREL information", 638 "Print TEXTREL information",
560 "Print RPATH information", 639 "Print RPATH information",
561 "Print NEEDED information", 640 "Print NEEDED information",
562 "Print INTERP information", 641 "Print INTERP information",
563 "Find a specified symbol", 642 "Find a specified symbol",
564 "Print all scanned info (-x -e -t -r)\n", 643 "Print all scanned info (-x -e -t -r -n -i)\n",
565 "Only output 'bad' things", 644 "Only output 'bad' things",
566 "Be verbose (can be specified more than once)", 645 "Be verbose (can be specified more than once)",
567 "Use specified format for output", 646 "Use specified format for output",
647 "Read input stream from a filename",
568 "Write output stream to a filename", 648 "Write output stream to a filename",
569 "Don't display the header", 649 "Don't display the header",
570 "Print this help and exit", 650 "Print this help and exit",
571 "Print version and exit", 651 "Print version and exit",
572 NULL 652 NULL
573}; 653};
574 654
575/* display usage and exit */ 655/* display usage and exit */
576static void usage(int status) 656static void usage(int status)
577{ 657{
578 int i; 658 unsigned long i;
579 printf(" Scan ELF binaries for stuff\n\n" 659 printf(" Scan ELF binaries for stuff\n\n"
580 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0); 660 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0);
581 printf("Options: -[%s]\n", PARSE_FLAGS); 661 printf("Options: -[%s]\n", PARSE_FLAGS);
582 for (i = 0; long_opts[i].name; ++i) 662 for (i = 0; long_opts[i].name; ++i)
583 if (long_opts[i].has_arg == no_argument) 663 if (long_opts[i].has_arg == no_argument)
584 printf(" -%c, --%-13s %s\n", long_opts[i].val, 664 printf(" -%c, --%-13s %s\n", long_opts[i].val,
585 long_opts[i].name, opts_help[i]); 665 long_opts[i].name, opts_help[i]);
586 else 666 else
587 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val, 667 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val,
588 long_opts[i].name, opts_help[i]); 668 long_opts[i].name, opts_help[i]);
669
670 if (status != EXIT_SUCCESS)
671 exit(status);
672
673 puts("\nThe format modifiers for the -F option are:");
674 puts(" %F Filename \t%x PaX Flags \t%e STACK/RELRO");
675 puts(" %t TEXTREL \t%r RPATH \t%n NEEDED");
676 puts(" %i INTERP \t%s symbol");
677
589 exit(status); 678 exit(status);
590} 679}
591 680
592/* parse command line arguments and preform needed actions */ 681/* parse command line arguments and preform needed actions */
593static void parseargs(int argc, char *argv[]) 682static void parseargs(int argc, char *argv[])
594{ 683{
595 int flag; 684 int i;
685 char *from_file = NULL;
596 686
597 opterr = 0; 687 opterr = 0;
598 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) { 688 while ((i=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
599 switch (flag) { 689 switch (i) {
600 690
601 case 'V': 691 case 'V':
602 printf("%s compiled %s\n%s\n" 692 printf("%s compiled %s\n%s\n"
603 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n", 693 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n",
604 __FILE__, __DATE__, rcsid, argv0); 694 __FILE__, __DATE__, rcsid, argv0);
605 exit(EXIT_SUCCESS); 695 exit(EXIT_SUCCESS);
606 break; 696 break;
607 case 'h': usage(EXIT_SUCCESS); break; 697 case 'h': usage(EXIT_SUCCESS); break;
608 698 case 'f':
699 if (from_file == NULL)
700 from_file = xstrdup(optarg);
701 break;
609 case 'o': { 702 case 'o': {
610 FILE *fp = NULL; 703 FILE *fp = NULL;
611 fp = freopen(optarg, "w", stdout); 704 fp = freopen(optarg, "w", stdout);
612 if (fp == NULL) 705 if (fp == NULL)
613 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 706 err("Could not open output stream '%s': %s", optarg, strerror(errno));
623 sprintf(versioned_symname, "%s@", find_sym); 716 sprintf(versioned_symname, "%s@", find_sym);
624 break; 717 break;
625 } 718 }
626 719
627 case 'F': { 720 case 'F': {
628 out_format = strdup(optarg); 721 out_format = xstrdup(optarg);
629 break; 722 break;
630 } 723 }
631 724
632 case 'y': scan_symlink = 0; break; 725 case 'y': scan_symlink = 0; break;
633 case 'B': show_banner = 0; break; 726 case 'B': show_banner = 0; break;
652 case '?': 745 case '?':
653 warn("Unknown option\n"); 746 warn("Unknown option\n");
654 usage(EXIT_FAILURE); 747 usage(EXIT_FAILURE);
655 break; 748 break;
656 default: 749 default:
657 err("Unhandled option '%c'", flag); 750 err("Unhandled option '%c'", i);
658 break; 751 break;
659 } 752 }
660 } 753 }
661 754
662 if (be_quiet && be_verbose) 755 if (be_quiet && be_verbose)
663 err("You can be quiet or you can be verbose, not both, stupid"); 756 err("You can be quiet or you can be verbose, not both, stupid");
664 757
665 /* let the format option override all other options */ 758 /* let the format option override all other options */
666 if (out_format) { 759 if (out_format) {
667 show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 0; 760 show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 0;
668 for (flag=0; out_format[flag]; ++flag) { 761 for (i = 0; out_format[i]; ++i) {
669 if (out_format[flag] != '%') continue; 762 if (out_format[i] != '%') continue;
670 763
671 switch (out_format[++flag]) { 764 switch (out_format[++i]) {
672 case '%': break; 765 case '%': break;
673 case 'F': break; 766 case 'F': break;
674 case 's': break; 767 case 's': break;
675 case 'o': break; 768 case 'o': break;
676 case 'x': show_pax = 1; break; 769 case 'x': show_pax = 1; break;
679 case 'r': show_rpath = 1; break; 772 case 'r': show_rpath = 1; break;
680 case 'n': show_needed = 1; break; 773 case 'n': show_needed = 1; break;
681 case 'i': show_interp = 1; break; 774 case 'i': show_interp = 1; break;
682 default: 775 default:
683 err("Invalid format specifier '%c' (byte %i)", 776 err("Invalid format specifier '%c' (byte %i)",
684 out_format[flag], flag+1); 777 out_format[i], i+1);
685 } 778 }
686 } 779 }
687 780
688 /* construct our default format */ 781 /* construct our default format */
689 } else { 782 } else {
700 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len); 793 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
701 } 794 }
702 if (be_verbose > 2) printf("Format: %s\n", out_format); 795 if (be_verbose > 2) printf("Format: %s\n", out_format);
703 796
704 /* now lets actually do the scanning */ 797 /* now lets actually do the scanning */
798 if (scan_ldpath || (show_rpath && be_quiet))
799 load_ld_so_conf();
705 if (scan_ldpath) scanelf_ldpath(); 800 if (scan_ldpath) scanelf_ldpath();
706 if (scan_envpath) scanelf_envpath(); 801 if (scan_envpath) scanelf_envpath();
802 if (from_file) {
803 scanelf_from_file(from_file);
804 free(from_file);
805 from_file = *argv;
806 }
707 if (optind == argc && !scan_ldpath && !scan_envpath) 807 if (optind == argc && !scan_ldpath && !scan_envpath && !from_file)
708 err("Nothing to scan !?"); 808 err("Nothing to scan !?");
709 while (optind < argc) 809 while (optind < argc)
710 scanelf_dir(argv[optind++]); 810 scanelf_dir(argv[optind++]);
711 811
712 /* clean up */ 812 /* clean up */
713 if (find_sym) { 813 if (find_sym) {
714 free(find_sym); 814 free(find_sym);
715 free(versioned_symname); 815 free(versioned_symname);
716 } 816 }
717 if (out_format) free(out_format); 817 if (out_format) free(out_format);
818 for (i = 0; ldpaths[i]; ++i)
819 free(ldpaths[i]);
718} 820}
719 821
720 822
721 823
722/* utility funcs */ 824/* utility funcs */

Legend:
Removed from v.1.43  
changed lines
  Added in v.1.48

  ViewVC Help
Powered by ViewVC 1.1.20