/[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.61 Revision 1.71
1/* 1/*
2 * Copyright 2003 Ned Ludd <solar@gentoo.org>
3 * Copyright 1999-2005 Gentoo Foundation 2 * Copyright 2003-2005 Gentoo Foundation
4 * Distributed under the terms of the GNU General Public License v2 3 * Distributed under the terms of the GNU General Public License v2
5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.61 2005/05/28 22:09:36 solar Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.71 2005/06/04 02:50:50 vapier Exp $
6 * 5 *
7 ******************************************************************** 6 ********************************************************************
8 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 8 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the 9 * published by the Free Software Foundation; either version 2 of the
34#include <dirent.h> 33#include <dirent.h>
35#include <getopt.h> 34#include <getopt.h>
36#include <assert.h> 35#include <assert.h>
37#include "paxelf.h" 36#include "paxelf.h"
38 37
39static const char *rcsid = "$Id: scanelf.c,v 1.61 2005/05/28 22:09:36 solar Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.71 2005/06/04 02:50:50 vapier Exp $";
40#define argv0 "scanelf" 39#define argv0 "scanelf"
40
41#define IS_MODIFIER(c) (c == '%' || c == '#')
41 42
42 43
43 44
44/* prototypes */ 45/* prototypes */
45static void scanelf_file(const char *filename); 46static void scanelf_file(const char *filename);
68static char show_interp = 0; 69static char show_interp = 0;
69static char show_bind = 0; 70static char show_bind = 0;
70static char show_banner = 1; 71static char show_banner = 1;
71static char be_quiet = 0; 72static char be_quiet = 0;
72static char be_verbose = 0; 73static char be_verbose = 0;
74static char be_wewy_wewy_quiet = 0;
73static char *find_sym = NULL, *versioned_symname = NULL; 75static char *find_sym = NULL, *versioned_symname = NULL;
74static char *out_format = NULL; 76static char *out_format = NULL;
77static char *search_path = NULL;
78
75 79
76 80
77/* sub-funcs for scanelf_file() */ 81/* sub-funcs for scanelf_file() */
78static char *scanelf_file_pax(elfobj *elf, char *found_pax) 82static char *scanelf_file_pax(elfobj *elf, char *found_pax)
79{ 83{
121 if (be_quiet && !shown) 125 if (be_quiet && !shown)
122 return NULL; 126 return NULL;
123 return ret; 127 return ret;
124 128
125} 129}
126static char *scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro) 130static char *scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro, char *found_load)
127{ 131{
128 static char ret[8] = "--- ---"; 132 static char ret[12];
129 char *found; 133 char *found;
130 unsigned long i, off, shown; 134 unsigned long i, off, shown, check_flags;
135 unsigned char multi_stack, multi_relro, multi_load;
131 136
132 if (!show_stack) return NULL; 137 if (!show_stack) return NULL;
133 138
139 memcpy(ret, "--- --- ---\0", 12);
140
134 shown = 0; 141 shown = 0;
142 multi_stack = multi_relro = multi_load = 0;
135 143
136 if (elf->phdr) { 144 if (elf->phdr) {
137#define SHOW_STACK(B) \ 145#define SHOW_STACK(B) \
138 if (elf->elf_class == ELFCLASS ## B) { \ 146 if (elf->elf_class == ELFCLASS ## B) { \
139 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 147 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
140 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 148 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
149 uint32_t flags; \
141 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 150 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
142 if (EGET(phdr[i].p_type) == PT_GNU_STACK) { \ 151 if (EGET(phdr[i].p_type) == PT_GNU_STACK) { \
152 if (multi_stack++) warnf("%s: multiple PT_GNU_STACK's !?", elf->filename); \
143 found = found_stack; \ 153 found = found_stack; \
144 off = 0; \ 154 off = 0; \
155 check_flags = PF_X; \
145 } else if (EGET(phdr[i].p_type) == PT_GNU_RELRO) { \ 156 } else if (EGET(phdr[i].p_type) == PT_GNU_RELRO) { \
157 if (multi_relro++) warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \
146 found = found_relro; \ 158 found = found_relro; \
147 off = 4; \ 159 off = 4; \
160 check_flags = PF_X; \
161 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \
162 if (multi_load++ > 2) warnf("%s: more than 2 PT_LOAD's !?", elf->filename); \
163 found = found_load; \
164 off = 8; \
165 check_flags = PF_W|PF_X; \
148 } else \ 166 } else \
149 continue; \ 167 continue; \
150 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \ 168 flags = EGET(phdr[i].p_flags); \
169 if (be_quiet && ((flags & check_flags) != check_flags)) \
151 continue; \ 170 continue; \
152 memcpy(ret+off, gnu_short_stack_flags(EGET(phdr[i].p_flags)), 3); \ 171 memcpy(ret+off, gnu_short_stack_flags(flags), 3); \
153 *found = 1; \ 172 *found = 1; \
154 ++shown; \ 173 ++shown; \
155 } \ 174 } \
156 } 175 }
157 SHOW_STACK(32) 176 SHOW_STACK(32)
163 else 182 else
164 return ret; 183 return ret;
165} 184}
166static char *scanelf_file_textrel(elfobj *elf, char *found_textrel) 185static char *scanelf_file_textrel(elfobj *elf, char *found_textrel)
167{ 186{
168 static char *ret = "TEXTREL"; 187 static char ret[] = "TEXTREL";
169 unsigned long i; 188 unsigned long i;
170 189
171 if (!show_textrel) return NULL; 190 if (!show_textrel) return NULL;
172 191
173 if (elf->phdr) { 192 if (elf->phdr) {
184 dyn = DYN ## B (elf->data + offset); \ 203 dyn = DYN ## B (elf->data + offset); \
185 while (EGET(dyn->d_tag) != DT_NULL) { \ 204 while (EGET(dyn->d_tag) != DT_NULL) { \
186 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \ 205 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
187 *found_textrel = 1; \ 206 *found_textrel = 1; \
188 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \ 207 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
189 return ret; \ 208 return (be_wewy_wewy_quiet ? NULL : ret); \
190 } \ 209 } \
191 ++dyn; \ 210 ++dyn; \
192 } \ 211 } \
193 } } 212 } }
194 SHOW_TEXTREL(32) 213 SHOW_TEXTREL(32)
195 SHOW_TEXTREL(64) 214 SHOW_TEXTREL(64)
196 } 215 }
197 216
198 if (be_quiet) 217 if (be_quiet || be_wewy_wewy_quiet)
199 return NULL; 218 return NULL;
200 else 219 else
201 return " - "; 220 return (char *)" - ";
202} 221}
203static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len) 222static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len)
204{ 223{
205 /* TODO: when checking RPATH entries, check each subpath (between :) in ld.so.conf */
206 unsigned long i, s; 224 unsigned long i, s;
207 char *rpath, *runpath, **r; 225 char *rpath, *runpath, **r;
208 void *strtbl_void; 226 void *strtbl_void;
209 227
210 if (!show_rpath) return; 228 if (!show_rpath) return;
238 ++dyn; \ 256 ++dyn; \
239 continue; \ 257 continue; \
240 } \ 258 } \
241 /* Verify the memory is somewhat sane */ \ 259 /* Verify the memory is somewhat sane */ \
242 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 260 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
243 if (offset < elf->len) { \ 261 if (offset < (Elf ## B ## _Off)elf->len) { \
244 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \ 262 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \
245 *r = (char*)(elf->data + offset); \ 263 *r = (char*)(elf->data + offset); \
246 /* If quiet, don't output paths in ld.so.conf */ \ 264 /* If quiet, don't output paths in ld.so.conf */ \
247 if (be_quiet) \ 265 if (be_quiet) { \
266 size_t len; \
267 char *start, *end; \
248 for (s = 0; ldpaths[s]; ++s) \ 268 for (s = 0; *r && ldpaths[s]; ++s) { \
249 if (!strcmp(ldpaths[s], *r)) { \ 269 /* scan each path in : delimited list */ \
250 *r = NULL; \ 270 start = *r; \
271 end = strchr(start, ':'); \
272 while ((start && ((end = strchr(start, ':')) != NULL)) || start) { \
273 len = (end ? abs(end - start) : strlen(start)); \
274 if (!strncmp(ldpaths[s], start, len) && !ldpaths[s][len]) { \
275 *r = (end ? end + 1 : NULL); \
251 break; \ 276 break; \
277 } \
278 start = (end ? start + len + 1 : NULL); \
252 } \ 279 } \
280 } \
281 } \
253 if (*r) *found_rpath = 1; \ 282 if (*r) *found_rpath = 1; \
254 } \ 283 } \
255 ++dyn; \ 284 ++dyn; \
256 } \ 285 } \
257 } } 286 } }
258 SHOW_RPATH(32) 287 SHOW_RPATH(32)
259 SHOW_RPATH(64) 288 SHOW_RPATH(64)
260 } 289 }
290
291 if (be_wewy_wewy_quiet) return;
261 292
262 if (rpath && runpath) { 293 if (rpath && runpath) {
263 if (!strcmp(rpath, runpath)) { 294 if (!strcmp(rpath, runpath)) {
264 xstrcat(ret, runpath, ret_len); 295 xstrcat(ret, runpath, ret_len);
265 } else { 296 } else {
299 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 330 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
300 dyn = DYN ## B (elf->data + offset); \ 331 dyn = DYN ## B (elf->data + offset); \
301 while (EGET(dyn->d_tag) != DT_NULL) { \ 332 while (EGET(dyn->d_tag) != DT_NULL) { \
302 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 333 if (EGET(dyn->d_tag) == DT_NEEDED) { \
303 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 334 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
304 if (offset >= elf->len) { \ 335 if (offset >= (Elf ## B ## _Off)elf->len) { \
305 ++dyn; \ 336 ++dyn; \
306 continue; \ 337 continue; \
307 } \ 338 } \
308 needed = (char*)(elf->data + offset); \ 339 needed = (char*)(elf->data + offset); \
309 if (*found_needed) xchrcat(ret, ',', ret_len); \ 340 if (*found_needed) xchrcat(ret, ',', ret_len); \
310 xstrcat(ret, needed, ret_len); \ 341 if (!be_wewy_wewy_quiet) xstrcat(ret, needed, ret_len); \
311 *found_needed = 1; \ 342 *found_needed = 1; \
312 } \ 343 } \
313 ++dyn; \ 344 ++dyn; \
314 } \ 345 } \
315 } } 346 } }
328 if (strtbl_void) { 359 if (strtbl_void) {
329#define SHOW_INTERP(B) \ 360#define SHOW_INTERP(B) \
330 if (elf->elf_class == ELFCLASS ## B) { \ 361 if (elf->elf_class == ELFCLASS ## B) { \
331 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 362 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
332 *found_interp = 1; \ 363 *found_interp = 1; \
333 return elf->data + EGET(strtbl->sh_offset); \ 364 return (be_wewy_wewy_quiet ? NULL : elf->data + EGET(strtbl->sh_offset)); \
334 } 365 }
335 SHOW_INTERP(32) 366 SHOW_INTERP(32)
336 SHOW_INTERP(64) 367 SHOW_INTERP(64)
337 } 368 }
338 return NULL; 369 return NULL;
360 if (EGET(dyn->d_tag) == DT_BIND_NOW || \ 391 if (EGET(dyn->d_tag) == DT_BIND_NOW || \
361 (EGET(dyn->d_tag) == DT_FLAGS && EGET(dyn->d_un.d_val) & DF_BIND_NOW)) \ 392 (EGET(dyn->d_tag) == DT_FLAGS && EGET(dyn->d_un.d_val) & DF_BIND_NOW)) \
362 { \ 393 { \
363 if (be_quiet) return NULL; \ 394 if (be_quiet) return NULL; \
364 *found_bind = 1; \ 395 *found_bind = 1; \
365 return "NOW"; \ 396 return (char *)(be_wewy_wewy_quiet ? NULL : "NOW"); \
366 } \ 397 } \
367 ++dyn; \ 398 ++dyn; \
368 } \ 399 } \
369 } \ 400 } \
370 } 401 }
371 SHOW_BIND(32) 402 SHOW_BIND(32)
372 SHOW_BIND(64) 403 SHOW_BIND(64)
373 404
405 if (be_wewy_wewy_quiet) return NULL;
406
374 if (be_quiet && !fstat(elf->fd, &s) && !(s.st_mode & S_ISUID || s.st_mode & S_ISGID)) { 407 if (be_quiet && !fstat(elf->fd, &s) && !(s.st_mode & S_ISUID || s.st_mode & S_ISGID)) {
375 return NULL; 408 return NULL;
376 } else { 409 } else {
377 *found_bind = 1; 410 *found_bind = 1;
378 return "LAZY"; 411 return (char *) "LAZY";
379 } 412 }
380} 413}
381static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename) 414static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename)
382{ 415{
383 unsigned long i; 416 unsigned long i;
384 void *symtab_void, *strtab_void; 417 void *symtab_void, *strtab_void;
385 418
386 if (!find_sym) return NULL; 419 if (!find_sym) return NULL;
387 420
421 /* debug sections */
388 symtab_void = elf_findsecbyname(elf, ".symtab"); 422 symtab_void = elf_findsecbyname(elf, ".symtab");
389 strtab_void = elf_findsecbyname(elf, ".strtab"); 423 strtab_void = elf_findsecbyname(elf, ".strtab");
424 /* fall back to runtime sections */
425 if (!symtab_void || !strtab_void) {
426 symtab_void = elf_findsecbyname(elf, ".dynsym");
427 strtab_void = elf_findsecbyname(elf, ".dynstr");
428 }
390 429
391 if (symtab_void && strtab_void) { 430 if (symtab_void && strtab_void) {
392 char *base, *basemem; 431 char *base, *basemem;
393 basemem = xstrdup(filename); 432 basemem = xstrdup(filename);
394 base = basename(basemem); 433 base = basename(basemem);
418 } } 457 } }
419 FIND_SYM(32) 458 FIND_SYM(32)
420 FIND_SYM(64) 459 FIND_SYM(64)
421 free(basemem); 460 free(basemem);
422 } 461 }
462
463 if (be_wewy_wewy_quiet) return NULL;
464
423 if (*find_sym != '*' && *found_sym) 465 if (*find_sym != '*' && *found_sym)
424 return find_sym; 466 return find_sym;
425 if (be_quiet) 467 if (be_quiet)
426 return NULL; 468 return NULL;
427 else 469 else
428 return " - "; 470 return (char *)" - ";
429} 471}
430/* scan an elf file and show all the fun stuff */ 472/* scan an elf file and show all the fun stuff */
431// #define prints(str) fputs(str, stdout)
432#define prints(str) write(fileno(stdout), str, strlen(str)) 473#define prints(str) write(fileno(stdout), str, strlen(str))
433static void scanelf_file(const char *filename) 474static void scanelf_file(const char *filename)
434{ 475{
435 unsigned long i; 476 unsigned long i;
436 char found_pax, found_stack, found_relro, found_textrel, 477 char found_pax, found_stack, found_relro, found_load, found_textrel,
437 found_rpath, found_needed, found_interp, found_bind, 478 found_rpath, found_needed, found_interp, found_bind,
438 found_sym, found_file; 479 found_sym, found_file;
439 elfobj *elf; 480 elfobj *elf;
440 struct stat st; 481 struct stat st;
441 static char *out_buffer = NULL; 482 static char *out_buffer = NULL;
454 if (!S_ISREG(st.st_mode)) { 495 if (!S_ISREG(st.st_mode)) {
455 if (be_verbose > 2) printf("%s: skipping non-file\n", filename); 496 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
456 return; 497 return;
457 } 498 }
458 499
459 found_pax = found_stack = found_relro = found_textrel = \ 500 found_pax = found_stack = found_relro = found_load = \
460 found_rpath = found_needed = found_interp = found_bind = \ 501 found_textrel = found_rpath = found_needed = found_interp = \
461 found_sym = found_file = 0; 502 found_bind = found_sym = found_file = 0;
462 503
463 /* verify this is real ELF */ 504 /* verify this is real ELF */
464 if ((elf = readelf(filename)) == NULL) { 505 if ((elf = readelf(filename)) == NULL) {
465 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 506 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
466 return; 507 return;
467 } 508 }
468 509
469 if (be_verbose > 1) 510 if (be_verbose > 1)
470 printf("%s: scanning file {%s,%s}\n", filename, 511 printf("%s: scanning file {%s,%s}\n", filename,
471 get_elfeitype(elf, EI_CLASS, elf->elf_class), 512 get_elfeitype(EI_CLASS, elf->elf_class),
472 get_elfeitype(elf, EI_DATA, elf->data[EI_DATA])); 513 get_elfeitype(EI_DATA, elf->data[EI_DATA]));
473 else if (be_verbose) 514 else if (be_verbose)
474 printf("%s: scanning file\n", filename); 515 printf("%s: scanning file\n", filename);
475 516
476 /* init output buffer */ 517 /* init output buffer */
477 if (!out_buffer) { 518 if (!out_buffer) {
481 *out_buffer = '\0'; 522 *out_buffer = '\0';
482 523
483 /* show the header */ 524 /* show the header */
484 if (!be_quiet && show_banner) { 525 if (!be_quiet && show_banner) {
485 for (i = 0; out_format[i]; ++i) { 526 for (i = 0; out_format[i]; ++i) {
486 if (out_format[i] != '%') continue; 527 if (!IS_MODIFIER(out_format[i])) continue;
487 528
488 switch (out_format[++i]) { 529 switch (out_format[++i]) {
489 case '%': break; 530 case '%': break;
531 case '#': break;
532 case 'F':
533 case 'p':
490 case 'F': prints("FILE "); found_file = 1; break; 534 case 'f': prints("FILE "); found_file = 1; break;
491 case 'o': prints(" TYPE "); break; 535 case 'o': prints(" TYPE "); break;
492 case 'x': prints(" PAX "); break; 536 case 'x': prints(" PAX "); break;
493 case 'e': prints("STK/REL "); break; 537 case 'e': prints("STK/REL/PTL "); break;
494 case 't': prints("TEXTREL "); break; 538 case 't': prints("TEXTREL "); break;
495 case 'r': prints("RPATH "); break; 539 case 'r': prints("RPATH "); break;
496 case 'n': prints("NEEDED "); break; 540 case 'n': prints("NEEDED "); break;
497 case 'i': prints("INTERP "); break; 541 case 'i': prints("INTERP "); break;
498 case 'b': prints("BIND "); break; 542 case 'b': prints("BIND "); break;
506 } 550 }
507 551
508 /* dump all the good stuff */ 552 /* dump all the good stuff */
509 for (i = 0; out_format[i]; ++i) { 553 for (i = 0; out_format[i]; ++i) {
510 const char *out; 554 const char *out;
555 const char *tmp;
511 556
512 /* make sure we trim leading spaces in quiet mode */ 557 /* make sure we trim leading spaces in quiet mode */
513 if (be_quiet && *out_buffer == ' ' && !out_buffer[1]) 558 if (be_quiet && *out_buffer == ' ' && !out_buffer[1])
514 *out_buffer = '\0'; 559 *out_buffer = '\0';
515 560
516 if (out_format[i] != '%') { 561 if (!IS_MODIFIER(out_format[i])) {
517 xchrcat(&out_buffer, out_format[i], &out_len); 562 xchrcat(&out_buffer, out_format[i], &out_len);
518 continue; 563 continue;
519 } 564 }
520 565
521 out = NULL; 566 out = NULL;
567 be_wewy_wewy_quiet = (out_format[i] == '#');
522 switch (out_format[++i]) { 568 switch (out_format[++i]) {
569 case '%':
570 case '#':
523 case '%': xchrcat(&out_buffer, '%', &out_len); break; 571 xchrcat(&out_buffer, out_format[i], &out_len); break;
524 case 'F': found_file = 1; xstrcat(&out_buffer, filename, &out_len); break; 572 case 'F':
573 if (be_wewy_wewy_quiet) break;
574 found_file = 1;
575 xstrcat(&out_buffer, filename, &out_len);
576 break;
577 case 'p':
578 if (be_wewy_wewy_quiet) break;
579 found_file = 1;
580 tmp = filename;
581 if (search_path) {
582 ssize_t len_search = strlen(search_path);
583 ssize_t len_file = strlen(filename);
584 if (!strncmp(filename, search_path, len_search) && \
585 len_file > len_search)
586 tmp += len_search;
587 if (*tmp == '/' && search_path[len_search-1] == '/') tmp++;
588 }
589 xstrcat(&out_buffer, tmp, &out_len);
590 break;
591 case 'f':
592 if (be_wewy_wewy_quiet) break;
593 found_file = 1;
594 tmp = strrchr(filename, '/');
595 tmp = (tmp == NULL ? filename : tmp+1);
596 xstrcat(&out_buffer, tmp, &out_len);
597 break;
525 case 'o': out = get_elfetype(elf); break; 598 case 'o': out = get_elfetype(elf); break;
526 case 'x': out = scanelf_file_pax(elf, &found_pax); break; 599 case 'x': out = scanelf_file_pax(elf, &found_pax); break;
527 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro); break; 600 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro, &found_load); break;
528 case 't': out = scanelf_file_textrel(elf, &found_textrel); break; 601 case 't': out = scanelf_file_textrel(elf, &found_textrel); break;
529 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break; 602 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break;
530 case 'n': scanelf_file_needed(elf, &found_needed, &out_buffer, &out_len); break; 603 case 'n': scanelf_file_needed(elf, &found_needed, &out_buffer, &out_len); break;
531 case 'i': out = scanelf_file_interp(elf, &found_interp); break; 604 case 'i': out = scanelf_file_interp(elf, &found_interp); break;
532 case 'b': out = scanelf_file_bind(elf, &found_bind); break; 605 case 'b': out = scanelf_file_bind(elf, &found_bind); break;
534 } 607 }
535 if (out) xstrcat(&out_buffer, out, &out_len); 608 if (out) xstrcat(&out_buffer, out, &out_len);
536 } 609 }
537 610
538#define FOUND_SOMETHING() \ 611#define FOUND_SOMETHING() \
539 (found_pax || found_stack || found_textrel || found_rpath || \ 612 (found_pax || found_stack || found_relro || found_load || found_textrel || \
540 found_needed || found_interp || found_bind || found_sym) 613 found_rpath || found_needed || found_interp || found_bind || found_sym)
541 614
542 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) { 615 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) {
543 xchrcat(&out_buffer, ' ', &out_len); 616 xchrcat(&out_buffer, ' ', &out_len);
544 xstrcat(&out_buffer, filename, &out_len); 617 xstrcat(&out_buffer, filename, &out_len);
545 } 618 }
611 return 1; 684 return 1;
612 685
613 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) { 686 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) {
614 if ((p = strchr(path, '\n')) != NULL) 687 if ((p = strchr(path, '\n')) != NULL)
615 *p = 0; 688 *p = 0;
689 search_path = path;
616 scanelf_dir(path); 690 scanelf_dir(path);
617 } 691 }
618 if (fp != stdin) 692 if (fp != stdin)
619 fclose(fp); 693 fclose(fp);
620 return 0; 694 return 0;
720 {"help", no_argument, NULL, 'h'}, 794 {"help", no_argument, NULL, 'h'},
721 {"version", no_argument, NULL, 'V'}, 795 {"version", no_argument, NULL, 'V'},
722 {NULL, no_argument, NULL, 0x0} 796 {NULL, no_argument, NULL, 0x0}
723}; 797};
724 798
725static char *opts_help[] = { 799static const char *opts_help[] = {
726 "Scan all directories in PATH environment", 800 "Scan all directories in PATH environment",
727 "Scan all directories in /etc/ld.so.conf", 801 "Scan all directories in /etc/ld.so.conf",
728 "Scan directories recursively", 802 "Scan directories recursively",
729 "Don't recursively cross mount points", 803 "Don't recursively cross mount points",
730 "Don't scan symlinks\n", 804 "Don't scan symlinks\n",
731 "Print PaX markings", 805 "Print PaX markings",
732 "Print GNU_STACK markings", 806 "Print GNU_STACK/PT_LOAD markings",
733 "Print TEXTREL information", 807 "Print TEXTREL information",
734 "Print RPATH information", 808 "Print RPATH information",
735 "Print NEEDED information", 809 "Print NEEDED information",
736 "Print INTERP information", 810 "Print INTERP information",
737 "Print BIND information", 811 "Print BIND information",
765 839
766 if (status != EXIT_SUCCESS) 840 if (status != EXIT_SUCCESS)
767 exit(status); 841 exit(status);
768 842
769 puts("\nThe format modifiers for the -F option are:"); 843 puts("\nThe format modifiers for the -F option are:");
770 puts(" %F Filename \t%x PaX Flags \t%e STACK/RELRO"); 844 puts(" F Filename \tx PaX Flags \te STACK/RELRO");
771 puts(" %t TEXTREL \t%r RPATH \t%n NEEDED"); 845 puts(" t TEXTREL \tr RPATH \tn NEEDED");
772 puts(" %i INTERP \t%b BIND \t%s symbol"); 846 puts(" i INTERP \tb BIND \ts symbol");
847 puts(" p filename (with search path removed)");
848 puts(" f base filename");
849 puts("Prefix each modifier with '%' (verbose) or '#' (silent)");
773 850
774 exit(status); 851 exit(status);
775} 852}
776 853
777/* parse command line arguments and preform needed actions */ 854/* parse command line arguments and preform needed actions */
790 __FILE__, __DATE__, rcsid, argv0); 867 __FILE__, __DATE__, rcsid, argv0);
791 exit(EXIT_SUCCESS); 868 exit(EXIT_SUCCESS);
792 break; 869 break;
793 case 'h': usage(EXIT_SUCCESS); break; 870 case 'h': usage(EXIT_SUCCESS); break;
794 case 'f': 871 case 'f':
795 if (from_file == NULL) 872 if (from_file) err("Don't specify -f twice");
796 from_file = xstrdup(optarg); 873 from_file = xstrdup(optarg);
797 break; 874 break;
798 case 'o': { 875 case 'o': {
799 FILE *fp = NULL; 876 FILE *fp = NULL;
800 fp = freopen(optarg, "w", stdout); 877 if ((fp = freopen(optarg, "w", stdout)) == NULL)
801 if (fp == NULL)
802 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 878 err("Could not open output stream '%s': %s", optarg, strerror(errno));
803 stdout = fp; 879 SET_STDOUT(fp);
804 break; 880 break;
805 } 881 }
806 882
807 case 's': { 883 case 's': {
808 size_t len; 884 size_t len;
885 if (find_sym) err("Don't specify -s twice");
809 find_sym = xstrdup(optarg); 886 find_sym = xstrdup(optarg);
810 len = strlen(find_sym) + 1; 887 len = strlen(find_sym) + 1;
811 versioned_symname = (char*)xmalloc(sizeof(char) * (len+1)); 888 versioned_symname = (char*)xmalloc(sizeof(char) * (len+1));
812 sprintf(versioned_symname, "%s@", find_sym); 889 sprintf(versioned_symname, "%s@", find_sym);
813 break; 890 break;
814 } 891 }
815 892
816 case 'F': { 893 case 'F': {
817 if (!out_format) 894 if (out_format) err("Don't specify -F twice");
818 out_format = xstrdup(optarg); 895 out_format = xstrdup(optarg);
819 break; 896 break;
820 } 897 }
821 898
822 case 'y': scan_symlink = 0; break; 899 case 'y': scan_symlink = 0; break;
823 case 'B': show_banner = 0; break; 900 case 'B': show_banner = 0; break;
849 /* let the format option override all other options */ 926 /* let the format option override all other options */
850 if (out_format) { 927 if (out_format) {
851 show_pax = show_stack = show_textrel = show_rpath = \ 928 show_pax = show_stack = show_textrel = show_rpath = \
852 show_needed = show_interp = show_bind = 0; 929 show_needed = show_interp = show_bind = 0;
853 for (i = 0; out_format[i]; ++i) { 930 for (i = 0; out_format[i]; ++i) {
854 if (out_format[i] != '%') continue; 931 if (!IS_MODIFIER(out_format[i])) continue;
855 932
856 switch (out_format[++i]) { 933 switch (out_format[++i]) {
857 case '%': break; 934 case '%': break;
935 case '#': break;
858 case 'F': break; 936 case 'F': break;
937 case 'p': break;
938 case 'f': break;
859 case 's': break; 939 case 's': break;
860 case 'o': break; 940 case 'o': break;
861 case 'x': show_pax = 1; break; 941 case 'x': show_pax = 1; break;
862 case 'e': show_stack = 1; break; 942 case 'e': show_stack = 1; break;
863 case 't': show_textrel = 1; break; 943 case 't': show_textrel = 1; break;
898 free(from_file); 978 free(from_file);
899 from_file = *argv; 979 from_file = *argv;
900 } 980 }
901 if (optind == argc && !scan_ldpath && !scan_envpath && !from_file) 981 if (optind == argc && !scan_ldpath && !scan_envpath && !from_file)
902 err("Nothing to scan !?"); 982 err("Nothing to scan !?");
903 while (optind < argc) 983 while (optind < argc) {
904 scanelf_dir(argv[optind++]); 984 search_path = argv[optind++];
985 scanelf_dir(search_path);
986 }
905 987
906 /* clean up */ 988 /* clean up */
907 if (find_sym) { 989 if (find_sym) {
908 free(find_sym); 990 free(find_sym);
909 free(versioned_symname); 991 free(versioned_symname);
930 return ret; 1012 return ret;
931} 1013}
932 1014
933static void xstrcat(char **dst, const char *src, size_t *curr_len) 1015static void xstrcat(char **dst, const char *src, size_t *curr_len)
934{ 1016{
935 long new_len; 1017 size_t new_len;
936 1018
937 new_len = strlen(*dst) + strlen(src); 1019 new_len = strlen(*dst) + strlen(src);
938 if (*curr_len <= new_len) { 1020 if (*curr_len <= new_len) {
939 *curr_len = new_len + (*curr_len / 2); 1021 *curr_len = new_len + (*curr_len / 2);
940 *dst = realloc(*dst, *curr_len); 1022 *dst = realloc(*dst, *curr_len);
959 if (argc < 2) 1041 if (argc < 2)
960 usage(EXIT_FAILURE); 1042 usage(EXIT_FAILURE);
961 parseargs(argc, argv); 1043 parseargs(argc, argv);
962 fclose(stdout); 1044 fclose(stdout);
963#ifdef __BOUNDS_CHECKING_ON 1045#ifdef __BOUNDS_CHECKING_ON
964 warn("The calls to add/delete heap should be off by 1 due to the out_buffer not being freed in scanelf_file()"); 1046 warn("The calls to add/delete heap should be off by 1 due to the out_buffer not being freed in scanelf_file()");
965#endif 1047#endif
966 return EXIT_SUCCESS; 1048 return EXIT_SUCCESS;
967} 1049}

Legend:
Removed from v.1.61  
changed lines
  Added in v.1.71

  ViewVC Help
Powered by ViewVC 1.1.20