/[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.31 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/scanelf.c,v 1.31 2005/04/06 02:01:52 solar Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/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
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.31 2005/04/06 02:01:52 solar Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.32 2005/04/07 00:01:40 vapier Exp $";
39 39
40 40
41/* helper functions for showing errors */ 41/* helper functions for showing errors */
42#define argv0 "scanelf" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/ 42#define argv0 "scanelf" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/
43#define warn(fmt, args...) \ 43#define warn(fmt, args...) \
66static char dir_crossmount = 1; 66static char dir_crossmount = 1;
67static char show_pax = 0; 67static char show_pax = 0;
68static char show_stack = 0; 68static char show_stack = 0;
69static char show_textrel = 0; 69static char show_textrel = 0;
70static char show_rpath = 0; 70static char show_rpath = 0;
71static char show_needed = 0;
71static char show_banner = 1; 72static char show_banner = 1;
72static char be_quiet = 0; 73static char be_quiet = 0;
73static char be_verbose = 0; 74static char be_verbose = 0;
74static char *find_sym = NULL; 75static char *find_sym = NULL;
75 76
77 78
78/* scan an elf file and show all the fun stuff */ 79/* scan an elf file and show all the fun stuff */
79static void scanelf_file(const char *filename) 80static void scanelf_file(const char *filename)
80{ 81{
81 int i; 82 int i;
82 char found_pax, found_stack, found_relro, found_textrel, found_rpath, found_sym; 83 char found_pax, found_stack, found_relro, found_textrel,
84 found_rpath, found_needed, found_sym;
83 elfobj *elf; 85 elfobj *elf;
84 86
85 found_pax = found_stack = found_relro = found_textrel = found_rpath = found_sym = 0; 87 found_pax = found_stack = found_relro = found_textrel = \
88 found_rpath = found_needed = found_sym = 0;
86 89
87 /* verify this is real ELF */ 90 /* verify this is real ELF */
88 if ((elf = readelf(filename)) == NULL) { 91 if ((elf = readelf(filename)) == NULL) {
89 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 92 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
90 return; 93 return;
97 else if (be_verbose) 100 else if (be_verbose)
98 printf("%s: scanning file\n", filename); 101 printf("%s: scanning file\n", filename);
99 102
100 /* show the header */ 103 /* show the header */
101 if (!be_quiet && show_banner) { 104 if (!be_quiet && show_banner) {
102 printf(" TYPE "); 105 printf(" TYPE ");
103 if (show_pax) printf(" PAX "); 106 if (show_pax) printf(" PAX ");
104 if (show_stack) printf(" STK/REL "); 107 if (show_stack) printf("STK/REL ");
105 if (show_textrel) printf("TEXTREL "); 108 if (show_textrel) printf("TEXTREL ");
106 if (show_rpath) printf("RPATH "); 109 if (show_rpath) printf("RPATH ");
110 if (show_needed) printf("NEEDED ");
107 printf(" FILE\n"); 111 printf(" FILE\n");
108 show_banner = 0; 112 show_banner = 0;
109 } 113 }
110 114
111 /* dump all the good stuff */ 115 /* dump all the good stuff */
210 printf("%-5s ", (runpath ? runpath : rpath)); 214 printf("%-5s ", (runpath ? runpath : rpath));
211 else if (!be_quiet && !found_rpath) 215 else if (!be_quiet && !found_rpath)
212 printf(" - "); 216 printf(" - ");
213 } 217 }
214 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 */
215 if (find_sym) { 259 if (find_sym) {
216 void *symtab_void, *strtab_void; 260 void *symtab_void, *strtab_void;
217 char *versioned_symname = malloc(strlen(find_sym)+2); 261 char *versioned_symname;
262 size_t len;
218 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 }
219 sprintf(versioned_symname, "%s@", find_sym); 270 sprintf(versioned_symname, "%s@", find_sym);
271
220 symtab_void = elf_findsecbyname(elf, ".symtab"); 272 symtab_void = elf_findsecbyname(elf, ".symtab");
221 strtab_void = elf_findsecbyname(elf, ".strtab"); 273 strtab_void = elf_findsecbyname(elf, ".strtab");
222 274
223 if (symtab_void && strtab_void) { 275 if (symtab_void && strtab_void) {
224#define FIND_SYM(B) \ 276#define FIND_SYM(B) \
230 char *symname; \ 282 char *symname; \
231 for (i = 0; i < cnt; ++i) { \ 283 for (i = 0; i < cnt; ++i) { \
232 if (sym->st_name) { \ 284 if (sym->st_name) { \
233 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 285 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
234 if (*find_sym == '*') { \ 286 if (*find_sym == '*') { \
235 printf("%s(%s) %5lX %15s %s\n", ((found_sym == 0) ? "\n\t" : "\t"), \ 287 printf("%s(%s) %5lX %15s %s\n", \
288 ((found_sym == 0) ? "\n\t" : "\t"), \
236 (char *) basename(filename), \ 289 (char *)basename(filename), \
237 (long)sym->st_size, (char *) get_elfstttype(sym->st_info & 0xF), \ 290 (long)sym->st_size, \
238 symname); \ 291 (char *)get_elfstttype(sym->st_info), \
292 symname); \
239 found_sym = 1; \ 293 found_sym = 1; \
240 } \
241 if ((strcmp(find_sym, symname) == 0) || \ 294 } else if ((strcmp(find_sym, symname) == 0) || \
242 (strncmp(symname, versioned_symname, strlen(versioned_symname)) == 0)) \ 295 (strncmp(symname, versioned_symname, len) == 0)) \
243 found_sym++; \ 296 found_sym++; \
244 } \ 297 } \
245 ++sym; \ 298 ++sym; \
246 } } 299 } }
247 FIND_SYM(32) 300 FIND_SYM(32)
254 else if (!be_quiet) 307 else if (!be_quiet)
255 printf(" - "); 308 printf(" - ");
256 } 309 }
257 } 310 }
258 311
259 if (!be_quiet || found_pax || found_stack || found_textrel || found_rpath || found_sym) 312 if (!be_quiet || found_pax || found_stack || found_textrel || \
313 found_rpath || found_needed || found_sym)
260 printf("%s\n", filename); 314 printf("%s\n", filename);
261 315
262 unreadelf(elf); 316 unreadelf(elf);
263} 317}
264 318
267{ 321{
268 register DIR *dir; 322 register DIR *dir;
269 register struct dirent *dentry; 323 register struct dirent *dentry;
270 struct stat st_top, st; 324 struct stat st_top, st;
271 char buf[_POSIX_PATH_MAX]; 325 char buf[_POSIX_PATH_MAX];
272 size_t len = 0; 326 size_t pathlen = 0, len = 0;
273 327
274 /* make sure path exists */ 328 /* make sure path exists */
275 if (lstat(path, &st_top) == -1) 329 if (lstat(path, &st_top) == -1)
276 return; 330 return;
277 331
286 warnf("could not opendir %s: %s", path, strerror(errno)); 340 warnf("could not opendir %s: %s", path, strerror(errno));
287 return; 341 return;
288 } 342 }
289 if (be_verbose) printf("%s: scanning dir\n", path); 343 if (be_verbose) printf("%s: scanning dir\n", path);
290 344
345 pathlen = strlen(path);
291 while ((dentry = readdir(dir))) { 346 while ((dentry = readdir(dir))) {
292 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) 347 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
293 continue; 348 continue;
294 len = (strlen(path) + 2 + strlen(dentry->d_name)); 349 len = (pathlen + 1 + strlen(dentry->d_name) + 1);
295 if (len >= sizeof(buf)) warn("len > sizeof(buf); %d %d = %s\n", len, sizeof(buf), path); 350 if (len >= sizeof(buf)) {
296 assert(len < sizeof(buf)); 351 warnf("Skipping '%s': len > sizeof(buf); %d > %d\n", path, (int)len, (int)sizeof(buf));
352 continue;
353 }
297 sprintf(buf, "%s/%s", path, dentry->d_name); 354 sprintf(buf, "%s/%s", path, dentry->d_name);
298 if (lstat(buf, &st) != -1) { 355 if (lstat(buf, &st) != -1) {
299 if (S_ISREG(st.st_mode)) 356 if (S_ISREG(st.st_mode))
300 scanelf_file(buf); 357 scanelf_file(buf);
301 else if (dir_recurse && S_ISDIR(st.st_mode)) { 358 else if (dir_recurse && S_ISDIR(st.st_mode)) {
333 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1; 390 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1;
334 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1; 391 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1;
335 scanelf_dir(path); 392 scanelf_dir(path);
336 } 393 }
337 free(path); 394 free(path);
395 fclose(fp);
338 396
339 if (!scan_l) scanelf_dir("/lib"); 397 if (!scan_l) scanelf_dir("/lib");
340 if (!scan_ul) scanelf_dir("/usr/lib"); 398 if (!scan_ul) scanelf_dir("/usr/lib");
341 if (!scan_ull) scanelf_dir("/usr/local/lib"); 399 if (!scan_ull) scanelf_dir("/usr/local/lib");
342
343 fclose(fp);
344} 400}
345 401
346/* scan env PATH for paths */ 402/* scan env PATH for paths */
347static void scanelf_envpath() 403static void scanelf_envpath()
348{ 404{
351 path = getenv("PATH"); 407 path = getenv("PATH");
352 if (!path) 408 if (!path)
353 err("PATH is not set in your env !"); 409 err("PATH is not set in your env !");
354 410
355 if ((path = strdup(path)) == NULL) 411 if ((path = strdup(path)) == NULL)
356 err("stdup failed: %s", strerror(errno)); 412 err("strdup failed: %s", strerror(errno));
357 413
358 while ((p = strrchr(path, ':')) != NULL) { 414 while ((p = strrchr(path, ':')) != NULL) {
359 scanelf_dir(p + 1); 415 scanelf_dir(p + 1);
360 *p = 0; 416 *p = 0;
361 } 417 }
364} 420}
365 421
366 422
367 423
368/* usage / invocation handling functions */ 424/* usage / invocation handling functions */
369#define PARSE_FLAGS "plRmxetrs:aqvo:BhV" 425#define PARSE_FLAGS "plRmxetrns:aqvo:BhV"
370#define a_argument required_argument 426#define a_argument required_argument
371static struct option const long_opts[] = { 427static struct option const long_opts[] = {
372 {"path", no_argument, NULL, 'p'}, 428 {"path", no_argument, NULL, 'p'},
373 {"ldpath", no_argument, NULL, 'l'}, 429 {"ldpath", no_argument, NULL, 'l'},
374 {"recursive", no_argument, NULL, 'R'}, 430 {"recursive", no_argument, NULL, 'R'},
375 {"mount", no_argument, NULL, 'm'}, 431 {"mount", no_argument, NULL, 'm'},
376 {"pax", no_argument, NULL, 'x'}, 432 {"pax", no_argument, NULL, 'x'},
377 {"header", no_argument, NULL, 'e'}, 433 {"header", no_argument, NULL, 'e'},
378 {"textrel", no_argument, NULL, 't'}, 434 {"textrel", no_argument, NULL, 't'},
379 {"rpath", no_argument, NULL, 'r'}, 435 {"rpath", no_argument, NULL, 'r'},
436 {"needed", no_argument, NULL, 'n'},
380 {"symbol", a_argument, NULL, 's'}, 437 {"symbol", a_argument, NULL, 's'},
381 {"all", no_argument, NULL, 'a'}, 438 {"all", no_argument, NULL, 'a'},
382 {"quiet", no_argument, NULL, 'q'}, 439 {"quiet", no_argument, NULL, 'q'},
383 {"verbose", no_argument, NULL, 'v'}, 440 {"verbose", no_argument, NULL, 'v'},
384 {"file", a_argument, NULL, 'o'}, 441 {"file", a_argument, NULL, 'o'},
394 "Don't recursively cross mount points\n", 451 "Don't recursively cross mount points\n",
395 "Print PaX markings", 452 "Print PaX markings",
396 "Print GNU_STACK markings", 453 "Print GNU_STACK markings",
397 "Print TEXTREL information", 454 "Print TEXTREL information",
398 "Print RPATH information", 455 "Print RPATH information",
456 "Print NEEDED information",
399 "Find a specified symbol", 457 "Find a specified symbol",
400 "Print all scanned info (-x -e -t -r)\n", 458 "Print all scanned info (-x -e -t -r)\n",
401 "Only output 'bad' things", 459 "Only output 'bad' things",
402 "Be verbose (can be specified more than once)", 460 "Be verbose (can be specified more than once)",
403 "Write output stream to a filename", 461 "Write output stream to a filename",
459 case 'm': dir_crossmount = 0; break; 517 case 'm': dir_crossmount = 0; break;
460 case 'x': show_pax = 1; break; 518 case 'x': show_pax = 1; break;
461 case 'e': show_stack = 1; break; 519 case 'e': show_stack = 1; break;
462 case 't': show_textrel = 1; break; 520 case 't': show_textrel = 1; break;
463 case 'r': show_rpath = 1; break; 521 case 'r': show_rpath = 1; break;
522 case 'n': show_needed = 1; break;
464 case 'q': be_quiet = 1; break; 523 case 'q': be_quiet = 1; break;
465 case 'v': be_verbose = (be_verbose % 20) + 1; break; 524 case 'v': be_verbose = (be_verbose % 20) + 1; break;
466 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;
467 526
468 case ':': 527 case ':':
469 warn("Option missing parameter"); 528 warn("Option missing parameter");
470 usage(EXIT_FAILURE); 529 usage(EXIT_FAILURE);
471 break; 530 break;

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

  ViewVC Help
Powered by ViewVC 1.1.20