/[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.97 Revision 1.119
1/* 1/*
2 * Copyright 2003-2005 Gentoo Foundation 2 * Copyright 2003-2006 Gentoo Foundation
3 * Distributed under the terms of the GNU General Public License v2 3 * Distributed under the terms of the GNU General Public License v2
4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.97 2005/12/29 14:03:25 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.119 2006/02/05 02:25:58 solar Exp $
5 * 5 *
6 * Copyright 2003-2005 Ned Ludd - <solar@gentoo.org> 6 * Copyright 2003-2006 Ned Ludd - <solar@gentoo.org>
7 * Copyright 2004-2005 Mike Frysinger - <vapier@gentoo.org> 7 * Copyright 2004-2006 Mike Frysinger - <vapier@gentoo.org>
8 */ 8 */
9 9
10#include <stdio.h>
11#include <stdlib.h>
12#include <sys/types.h>
13#include <libgen.h>
14#include <limits.h>
15#include <string.h>
16#include <errno.h>
17#include <unistd.h>
18#include <sys/stat.h>
19#include <sys/mman.h>
20#include <fcntl.h>
21#include <dirent.h>
22#include <getopt.h>
23#include <assert.h>
24#include "paxinc.h" 10#include "paxinc.h"
25 11
26static const char *rcsid = "$Id: scanelf.c,v 1.97 2005/12/29 14:03:25 vapier Exp $"; 12static const char *rcsid = "$Id: scanelf.c,v 1.119 2006/02/05 02:25:58 solar Exp $";
27#define argv0 "scanelf" 13#define argv0 "scanelf"
28 14
29#define IS_MODIFIER(c) (c == '%' || c == '#') 15#define IS_MODIFIER(c) (c == '%' || c == '#')
30 16
31 17
32 18
33/* prototypes */ 19/* prototypes */
20static int scanelf_elfobj(elfobj *elf);
21static int scanelf_elf(const char *filename, int fd, size_t len);
22static int scanelf_archive(const char *filename, int fd, size_t len);
34static void scanelf_file(const char *filename); 23static void scanelf_file(const char *filename);
35static void scanelf_dir(const char *path); 24static void scanelf_dir(const char *path);
36static void scanelf_ldpath(); 25static void scanelf_ldpath(void);
37static void scanelf_envpath(); 26static void scanelf_envpath(void);
38static void usage(int status); 27static void usage(int status);
39static void parseargs(int argc, char *argv[]); 28static void parseargs(int argc, char *argv[]);
40static char *xstrdup(const char *s); 29static char *xstrdup(const char *s);
41static void *xmalloc(size_t size); 30static void *xmalloc(size_t size);
42static void xstrncat(char **dst, const char *src, size_t *curr_len, size_t n); 31static void xstrncat(char **dst, const char *src, size_t *curr_len, size_t n);
43#define xstrcat(dst,src,curr_len) xstrncat(dst,src,curr_len,0) 32#define xstrcat(dst,src,curr_len) xstrncat(dst,src,curr_len,0)
44static inline void xchrcat(char **dst, const char append, size_t *curr_len); 33static inline void xchrcat(char **dst, const char append, size_t *curr_len);
45 34
46/* variables to control behavior */ 35/* variables to control behavior */
36static char match_etypes[126] = "";
47static char *ldpaths[256]; 37static char *ldpaths[256];
48static char scan_ldpath = 0; 38static char scan_ldpath = 0;
49static char scan_envpath = 0; 39static char scan_envpath = 0;
50static char scan_symlink = 1; 40static char scan_symlink = 1;
41static char scan_archives = 0;
51static char dir_recurse = 0; 42static char dir_recurse = 0;
52static char dir_crossmount = 1; 43static char dir_crossmount = 1;
53static char show_pax = 0; 44static char show_pax = 0;
54static char show_phdr = 0; 45static char show_phdr = 0;
55static char show_textrel = 0; 46static char show_textrel = 0;
65static char be_wewy_wewy_quiet = 0; 56static char be_wewy_wewy_quiet = 0;
66static char *find_sym = NULL, *versioned_symname = NULL; 57static char *find_sym = NULL, *versioned_symname = NULL;
67static char *find_lib = NULL; 58static char *find_lib = NULL;
68static char *out_format = NULL; 59static char *out_format = NULL;
69static char *search_path = NULL; 60static char *search_path = NULL;
61static char fix_elf = 0;
70static char gmatch = 0; 62static char gmatch = 0;
71static char printcache = 0; 63static char use_ldcache = 0;
72 64
73 65
74caddr_t ldcache = 0; 66caddr_t ldcache = 0;
75size_t ldcache_size = 0; 67size_t ldcache_size = 0;
76 68
150 142
151static char *scanelf_file_phdr(elfobj *elf, char *found_phdr, char *found_relro, char *found_load) 143static char *scanelf_file_phdr(elfobj *elf, char *found_phdr, char *found_relro, char *found_load)
152{ 144{
153 static char ret[12]; 145 static char ret[12];
154 char *found; 146 char *found;
155 unsigned long i, shown;
156 unsigned char multi_stack, multi_relro, multi_load; 147 unsigned long i, shown, multi_stack, multi_relro, multi_load;
148 int max_pt_load;
157 149
158 if (!show_phdr) return NULL; 150 if (!show_phdr) return NULL;
159 151
160 memcpy(ret, "--- --- ---\0", 12); 152 memcpy(ret, "--- --- ---\0", 12);
161 153
162 shown = 0; 154 shown = 0;
163 multi_stack = multi_relro = multi_load = 0; 155 multi_stack = multi_relro = multi_load = 0;
156 max_pt_load = elf_max_pt_load(elf);
164 157
158#define NOTE_GNU_STACK ".note.GNU-stack"
165#define SHOW_PHDR(B) \ 159#define SHOW_PHDR(B) \
166 if (elf->elf_class == ELFCLASS ## B) { \ 160 if (elf->elf_class == ELFCLASS ## B) { \
167 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 161 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
168 Elf ## B ## _Off offset; \ 162 Elf ## B ## _Off offset; \
169 uint32_t flags, check_flags; \ 163 uint32_t flags, check_flags; \
179 if (multi_relro++) warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \ 173 if (multi_relro++) warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \
180 found = found_relro; \ 174 found = found_relro; \
181 offset = 4; \ 175 offset = 4; \
182 check_flags = PF_X; \ 176 check_flags = PF_X; \
183 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \ 177 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \
178 if (ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC) \
184 if (multi_load++ > 2) warnf("%s: more than 2 PT_LOAD's !?", elf->filename); \ 179 if (multi_load++ > max_pt_load) warnf("%s: more than %i PT_LOAD's !?", elf->filename, max_pt_load); \
185 found = found_load; \ 180 found = found_load; \
186 offset = 8; \ 181 offset = 8; \
187 check_flags = PF_W|PF_X; \ 182 check_flags = PF_W|PF_X; \
188 } else \ 183 } else \
189 continue; \ 184 continue; \
190 flags = EGET(phdr[i].p_flags); \ 185 flags = EGET(phdr[i].p_flags); \
191 if (be_quiet && ((flags & check_flags) != check_flags)) \ 186 if (be_quiet && ((flags & check_flags) != check_flags)) \
192 continue; \ 187 continue; \
188 if (fix_elf && ((flags & PF_X) != flags)) { \
189 ESET(phdr[i].p_flags, flags & (PF_X ^ (size_t)-1)); \
190 ret[3] = ret[7] = '!'; \
191 flags = EGET(phdr[i].p_flags); \
192 } \
193 memcpy(ret+offset, gnu_short_stack_flags(flags), 3); \ 193 memcpy(ret+offset, gnu_short_stack_flags(flags), 3); \
194 *found = 1; \ 194 *found = 1; \
195 ++shown; \ 195 ++shown; \
196 } \ 196 } \
197 } else if (elf->shdr != NULL) { \ 197 } else if (elf->shdr != NULL) { \
198 /* no program headers which means this is prob an object file */ \ 198 /* no program headers which means this is prob an object file */ \
199 Elf ## B ## _Shdr *shdr = SHDR ## B (elf->shdr); \ 199 Elf ## B ## _Shdr *shdr = SHDR ## B (elf->shdr); \
200 Elf ## B ## _Shdr *strtbl = shdr + EGET(ehdr->e_shstrndx); \ 200 Elf ## B ## _Shdr *strtbl = shdr + EGET(ehdr->e_shstrndx); \
201 char *str; \
202 if ((void*)strtbl > (void*)elf->data_end) \
203 goto skip_this_shdr##B; \
201 check_flags = SHF_WRITE|SHF_EXECINSTR; \ 204 check_flags = SHF_WRITE|SHF_EXECINSTR; \
202 for (i = 0; i < EGET(ehdr->e_shnum); ++i) { \ 205 for (i = 0; i < EGET(ehdr->e_shnum); ++i) { \
203 if (EGET(shdr[i].sh_type) != SHT_PROGBITS) continue; \ 206 if (EGET(shdr[i].sh_type) != SHT_PROGBITS) continue; \
204 offset = EGET(strtbl->sh_offset) + EGET(shdr[i].sh_name); \ 207 offset = EGET(strtbl->sh_offset) + EGET(shdr[i].sh_name); \
205 if (!strcmp((char*)(elf->data + offset), ".note.GNU-stack")) { \ 208 str = elf->data + offset; \
209 if (str > elf->data + offset + sizeof(NOTE_GNU_STACK)) continue; \
210 if (!strcmp(str, NOTE_GNU_STACK)) { \
206 if (multi_stack++) warnf("%s: multiple .note.GNU-stack's !?", elf->filename); \ 211 if (multi_stack++) warnf("%s: multiple .note.GNU-stack's !?", elf->filename); \
207 flags = EGET(shdr[i].sh_flags); \ 212 flags = EGET(shdr[i].sh_flags); \
208 if (be_quiet && ((flags & check_flags) != check_flags)) \ 213 if (be_quiet && ((flags & check_flags) != check_flags)) \
209 continue; \ 214 continue; \
210 ++*found_phdr; \ 215 ++*found_phdr; \
214 if (flags & SHF_EXECINSTR) ret[2] = 'X'; \ 219 if (flags & SHF_EXECINSTR) ret[2] = 'X'; \
215 if (flags & 0xFFFFFFF8) warn("Invalid section flags for GNU-stack"); \ 220 if (flags & 0xFFFFFFF8) warn("Invalid section flags for GNU-stack"); \
216 break; \ 221 break; \
217 } \ 222 } \
218 } \ 223 } \
224 skip_this_shdr##B: \
219 if (!multi_stack) { \ 225 if (!multi_stack) { \
220 *found_phdr = 1; \ 226 *found_phdr = 1; \
221 shown = 1; \ 227 shown = 1; \
222 memcpy(ret, "!WX", 3); \ 228 memcpy(ret, "!WX", 3); \
223 } \ 229 } \
327 if (be_verbose <= 2) continue; \ 333 if (be_verbose <= 2) continue; \
328 } else \ 334 } else \
329 *found_textrels = 1; \ 335 *found_textrels = 1; \
330 /* locate this relocation symbol name */ \ 336 /* locate this relocation symbol name */ \
331 sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 337 sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
338 if ((void*)sym > (void*)elf->data_end) { \
339 warn("%s: corrupt ELF symbol", elf->filename); \
340 continue; \
341 } \
332 sym_max = ELF ## B ## _R_SYM(r_info); \ 342 sym_max = ELF ## B ## _R_SYM(r_info); \
333 if (sym_max * EGET(symtab->sh_entsize) < symtab->sh_size) \ 343 if (sym_max * EGET(symtab->sh_entsize) < symtab->sh_size) \
334 sym += sym_max; \ 344 sym += sym_max; \
335 else \ 345 else \
336 sym = NULL; \ 346 sym = NULL; \
368 warnf("ELF %s has TEXTREL markings but doesnt appear to have any real TEXTREL's !?", elf->filename); 378 warnf("ELF %s has TEXTREL markings but doesnt appear to have any real TEXTREL's !?", elf->filename);
369 379
370 return NULL; 380 return NULL;
371} 381}
372 382
373static void rpath_security_checks(elfobj *, char *); 383static void rpath_security_checks(elfobj *, char *, const char *);
374static void rpath_security_checks(elfobj *elf, char *item) { 384static void rpath_security_checks(elfobj *elf, char *item, const char *dt_type)
385{
375 struct stat st; 386 struct stat st;
376 switch (*item) { 387 switch (*item) {
377 case '/': break; 388 case '/': break;
378 case '.': 389 case '.':
379 warnf("Security problem with relative RPATH '%s' in %s", item, elf->filename); 390 warnf("Security problem with relative %s '%s' in %s", dt_type, item, elf->filename);
380 break; 391 break;
392 case ':':
381 case '\0': 393 case '\0':
382 warnf("Security problem NULL RPATH in %s", elf->filename); 394 warnf("Security problem NULL %s in %s", dt_type, elf->filename);
383 break; 395 break;
384 case '$': 396 case '$':
385 if (fstat(elf->fd, &st) != -1) 397 if (fstat(elf->fd, &st) != -1)
386 if ((st.st_mode & S_ISUID) || (st.st_mode & S_ISGID)) 398 if ((st.st_mode & S_ISUID) || (st.st_mode & S_ISGID))
387 warnf("Security problem with RPATH='%s' in %s with mode set of %o", 399 warnf("Security problem with %s='%s' in %s with mode set of %o",
388 item, elf->filename, st.st_mode & 07777); 400 dt_type, item, elf->filename, st.st_mode & 07777);
389 break; 401 break;
390 default: 402 default:
391 warnf("Maybe? sec problem with RPATH='%s' in %s", item, elf->filename); 403 warnf("Maybe? sec problem with %s='%s' in %s", dt_type, item, elf->filename);
392 break; 404 break;
393 } 405 }
394} 406}
395static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len) 407static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len)
396{ 408{
432 /* Verify the memory is somewhat sane */ \ 444 /* Verify the memory is somewhat sane */ \
433 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 445 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
434 if (offset < (Elf ## B ## _Off)elf->len) { \ 446 if (offset < (Elf ## B ## _Off)elf->len) { \
435 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \ 447 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \
436 *r = (char*)(elf->data + offset); \ 448 *r = (char*)(elf->data + offset); \
449 /* cache the length in case we need to nuke this section later on */ \
450 if (fix_elf) \
451 offset = strlen(*r); \
437 /* If quiet, don't output paths in ld.so.conf */ \ 452 /* If quiet, don't output paths in ld.so.conf */ \
438 if (be_quiet) { \ 453 if (be_quiet) { \
439 size_t len; \ 454 size_t len; \
440 char *start, *end; \ 455 char *start, *end; \
441 /* note that we only 'chop' off leading known paths. */ \ 456 /* note that we only 'chop' off leading known paths. */ \
442 /* since *r is read-only memory, we can only move the ptr forward. */ \ 457 /* since *r is read-only memory, we can only move the ptr forward. */ \
443 start = *r; \ 458 start = *r; \
444 /* scan each path in : delimited list */ \ 459 /* scan each path in : delimited list */ \
445 while (start) { \ 460 while (start) { \
446 rpath_security_checks(elf, start); \ 461 rpath_security_checks(elf, start, get_elfdtype(word)); \
447 end = strchr(start, ':'); \ 462 end = strchr(start, ':'); \
448 len = (end ? abs(end - start) : strlen(start)); \ 463 len = (end ? abs(end - start) : strlen(start)); \
464 if (use_ldcache) \
449 for (s = 0; ldpaths[s]; ++s) { \ 465 for (s = 0; ldpaths[s]; ++s) \
450 if (!strncmp(ldpaths[s], start, len) && !ldpaths[s][len]) { \ 466 if (!strncmp(ldpaths[s], start, len) && !ldpaths[s][len]) { \
451 *r = (end ? end + 1 : NULL); \ 467 *r = end; \
468 /* corner case ... if RPATH reads "/usr/lib:", we want \
469 * to show ':' rather than '' */ \
470 if (end && end[1] != '\0') \
471 (*r)++; \
452 break; \ 472 break; \
453 } \ 473 } \
454 } \
455 if (!*r || !ldpaths[s] || !end) \ 474 if (!*r || !end) \
456 start = NULL; \ 475 break; \
457 else \ 476 else \
458 start = start + len + 1; \ 477 start = start + len + 1; \
459 } \ 478 } \
460 } \ 479 } \
480 if (*r) { \
481 if (fix_elf > 2 || (fix_elf && **r == '\0')) { \
482 /* just nuke it */ \
483 nuke_it##B: \
484 memset(*r, 0x00, offset); \
485 *r = NULL; \
486 ESET(dyn->d_tag, DT_DEBUG); \
487 ESET(dyn->d_un.d_ptr, 0); \
488 } else if (fix_elf) { \
489 /* try to clean "bad" paths */ \
490 size_t len, tmpdir_len; \
491 char *start, *end; \
492 const char *tmpdir; \
493 start = *r; \
494 tmpdir = (getenv("TMPDIR") ? : "."); \
495 tmpdir_len = strlen(tmpdir); \
496 while (1) { \
497 end = strchr(start, ':'); \
498 if (start == end) { \
499 eat_this_path##B: \
500 len = strlen(end); \
501 memmove(start, end+1, len); \
502 start[len-1] = '\0'; \
503 end = start - 1; \
504 } else if (tmpdir && !strncmp(start, tmpdir, tmpdir_len)) { \
505 if (!end) { \
506 if (start == *r) \
507 goto nuke_it##B; \
508 *--start = '\0'; \
509 } else \
510 goto eat_this_path##B; \
511 } \
512 if (!end) \
513 break; \
514 start = end + 1; \
515 } \
516 if (**r == '\0') \
517 goto nuke_it##B; \
518 } \
519 if (*r) \
461 if (*r) *found_rpath = 1; \ 520 *found_rpath = 1; \
521 } \
462 } \ 522 } \
463 ++dyn; \ 523 ++dyn; \
464 } \ 524 } \
465 } } 525 } }
466 SHOW_RPATH(32) 526 SHOW_RPATH(32)
508static char *lookup_cache_lib(elfobj *, char *); 568static char *lookup_cache_lib(elfobj *, char *);
509static char *lookup_cache_lib(elfobj *elf, char *fname) 569static char *lookup_cache_lib(elfobj *elf, char *fname)
510{ 570{
511 int fd = 0; 571 int fd = 0;
512 char *strs; 572 char *strs;
513 static char buf[_POSIX_PATH_MAX] = ""; 573 static char buf[__PAX_UTILS_PATH_MAX] = "";
514 const char *cachefile = "/etc/ld.so.cache"; 574 const char *cachefile = "/etc/ld.so.cache";
515 struct stat st; 575 struct stat st;
516 576
517 typedef struct { 577 typedef struct {
518 char magic[LDSO_CACHE_MAGIC_LEN]; 578 char magic[LDSO_CACHE_MAGIC_LEN];
539 ldcache_size = st.st_size; 599 ldcache_size = st.st_size;
540 ldcache = mmap(0, ldcache_size, PROT_READ, MAP_SHARED, fd, 0); 600 ldcache = mmap(0, ldcache_size, PROT_READ, MAP_SHARED, fd, 0);
541 601
542 close(fd); 602 close(fd);
543 603
544 if (ldcache == (caddr_t)-1) 604 if (ldcache == (caddr_t)-1) {
605 ldcache = 0;
545 return NULL; 606 return NULL;
607 }
546 608
547 if (memcmp(((header_t *) ldcache)->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN)) 609 if (memcmp(((header_t *) ldcache)->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN))
548 return NULL; 610 return NULL;
549 if (memcmp (((header_t *) ldcache)->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN)) 611 if (memcmp (((header_t *) ldcache)->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN))
550 return NULL; 612 return NULL;
604 } \ 666 } \
605 needed = (char*)(elf->data + offset); \ 667 needed = (char*)(elf->data + offset); \
606 if (op == 0) { \ 668 if (op == 0) { \
607 if (!be_wewy_wewy_quiet) { \ 669 if (!be_wewy_wewy_quiet) { \
608 if (*found_needed) xchrcat(ret, ',', ret_len); \ 670 if (*found_needed) xchrcat(ret, ',', ret_len); \
609 if (printcache) \ 671 if (use_ldcache) \
610 if ((p = lookup_cache_lib(elf, needed)) != NULL) \ 672 if ((p = lookup_cache_lib(elf, needed)) != NULL) \
611 needed = p; \ 673 needed = p; \
612 xstrcat(ret, needed, ret_len); \ 674 xstrcat(ret, needed, ret_len); \
613 } \ 675 } \
614 *found_needed = 1; \ 676 *found_needed = 1; \
754#define FIND_SYM(B) \ 816#define FIND_SYM(B) \
755 if (elf->elf_class == ELFCLASS ## B) { \ 817 if (elf->elf_class == ELFCLASS ## B) { \
756 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 818 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
757 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 819 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
758 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 820 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
759 unsigned long cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \ 821 unsigned long cnt = EGET(symtab->sh_entsize); \
760 char *symname; \ 822 char *symname; \
823 if (cnt) \
824 cnt = EGET(symtab->sh_size) / cnt; \
761 for (i = 0; i < cnt; ++i) { \ 825 for (i = 0; i < cnt; ++i) { \
762 if (sym->st_name) { \ 826 if (sym->st_name) { \
763 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 827 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
828 if ((void*)symname > (void*)elf->data_end) { \
829 warnf("%s: corrupt ELF symbols", elf->filename); \
830 continue; \
831 } \
764 if (*find_sym == '*') { \ 832 if (*find_sym == '*') { \
765 printf("%s(%s) %5lX %15s %s\n", \ 833 printf("%s(%s) %5lX %15s %s\n", \
766 ((*found_sym == 0) ? "\n\t" : "\t"), \ 834 ((*found_sym == 0) ? "\n\t" : "\t"), \
767 elf->base_filename, \ 835 elf->base_filename, \
768 (unsigned long)sym->st_size, \ 836 (unsigned long)sym->st_size, \
800 if (be_quiet) 868 if (be_quiet)
801 return NULL; 869 return NULL;
802 else 870 else
803 return (char *)" - "; 871 return (char *)" - ";
804} 872}
873
874
805/* scan an elf file and show all the fun stuff */ 875/* scan an elf file and show all the fun stuff */
806#define prints(str) write(fileno(stdout), str, strlen(str)) 876#define prints(str) write(fileno(stdout), str, strlen(str))
807static void scanelf_file(const char *filename) 877static int scanelf_elfobj(elfobj *elf)
808{ 878{
809 unsigned long i; 879 unsigned long i;
810 char found_pax, found_phdr, found_relro, found_load, found_textrel, 880 char found_pax, found_phdr, found_relro, found_load, found_textrel,
811 found_rpath, found_needed, found_interp, found_bind, found_soname, 881 found_rpath, found_needed, found_interp, found_bind, found_soname,
812 found_sym, found_lib, found_file, found_textrels; 882 found_sym, found_lib, found_file, found_textrels;
813 elfobj *elf;
814 struct stat st;
815 static char *out_buffer = NULL; 883 static char *out_buffer = NULL;
816 static size_t out_len; 884 static size_t out_len;
817
818 /* make sure 'filename' exists */
819 if (lstat(filename, &st) == -1) {
820 if (be_verbose > 2) printf("%s: does not exist\n", filename);
821 return;
822 }
823 /* always handle regular files and handle symlinked files if no -y */
824 if (S_ISLNK(st.st_mode)) {
825 if (!scan_symlink) return;
826 stat(filename, &st);
827 }
828 if (!S_ISREG(st.st_mode)) {
829 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
830 return;
831 }
832 885
833 found_pax = found_phdr = found_relro = found_load = found_textrel = \ 886 found_pax = found_phdr = found_relro = found_load = found_textrel = \
834 found_rpath = found_needed = found_interp = found_bind = found_soname = \ 887 found_rpath = found_needed = found_interp = found_bind = found_soname = \
835 found_sym = found_lib = found_file = found_textrels = 0; 888 found_sym = found_lib = found_file = found_textrels = 0;
836 889
837 /* verify this is real ELF */
838 if ((elf = readelf(filename)) == NULL) {
839 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
840 return;
841 }
842
843 if (be_verbose > 1) 890 if (be_verbose > 2)
844 printf("%s: scanning file {%s,%s}\n", filename, 891 printf("%s: scanning file {%s,%s}\n", elf->filename,
845 get_elfeitype(EI_CLASS, elf->elf_class), 892 get_elfeitype(EI_CLASS, elf->elf_class),
846 get_elfeitype(EI_DATA, elf->data[EI_DATA])); 893 get_elfeitype(EI_DATA, elf->data[EI_DATA]));
847 else if (be_verbose) 894 else if (be_verbose > 1)
848 printf("%s: scanning file\n", filename); 895 printf("%s: scanning file\n", elf->filename);
849 896
850 /* init output buffer */ 897 /* init output buffer */
851 if (!out_buffer) { 898 if (!out_buffer) {
852 out_len = sizeof(char) * 80; 899 out_len = sizeof(char) * 80;
853 out_buffer = (char*)xmalloc(out_len); 900 out_buffer = (char*)xmalloc(out_len);
907 case '#': 954 case '#':
908 xchrcat(&out_buffer, out_format[i], &out_len); break; 955 xchrcat(&out_buffer, out_format[i], &out_len); break;
909 case 'F': 956 case 'F':
910 found_file = 1; 957 found_file = 1;
911 if (be_wewy_wewy_quiet) break; 958 if (be_wewy_wewy_quiet) break;
912 xstrcat(&out_buffer, filename, &out_len); 959 xstrcat(&out_buffer, elf->filename, &out_len);
913 break; 960 break;
914 case 'p': 961 case 'p':
915 found_file = 1; 962 found_file = 1;
916 if (be_wewy_wewy_quiet) break; 963 if (be_wewy_wewy_quiet) break;
917 tmp = filename; 964 tmp = elf->filename;
918 if (search_path) { 965 if (search_path) {
919 ssize_t len_search = strlen(search_path); 966 ssize_t len_search = strlen(search_path);
920 ssize_t len_file = strlen(filename); 967 ssize_t len_file = strlen(elf->filename);
921 if (!strncmp(filename, search_path, len_search) && \ 968 if (!strncmp(elf->filename, search_path, len_search) && \
922 len_file > len_search) 969 len_file > len_search)
923 tmp += len_search; 970 tmp += len_search;
924 if (*tmp == '/' && search_path[len_search-1] == '/') tmp++; 971 if (*tmp == '/' && search_path[len_search-1] == '/') tmp++;
925 } 972 }
926 xstrcat(&out_buffer, tmp, &out_len); 973 xstrcat(&out_buffer, tmp, &out_len);
927 break; 974 break;
928 case 'f': 975 case 'f':
929 found_file = 1; 976 found_file = 1;
930 if (be_wewy_wewy_quiet) break; 977 if (be_wewy_wewy_quiet) break;
931 tmp = strrchr(filename, '/'); 978 tmp = strrchr(elf->filename, '/');
932 tmp = (tmp == NULL ? filename : tmp+1); 979 tmp = (tmp == NULL ? elf->filename : tmp+1);
933 xstrcat(&out_buffer, tmp, &out_len); 980 xstrcat(&out_buffer, tmp, &out_len);
934 break; 981 break;
935 case 'o': out = get_elfetype(elf); break; 982 case 'o': out = get_elfetype(elf); break;
936 case 'x': out = scanelf_file_pax(elf, &found_pax); break; 983 case 'x': out = scanelf_file_pax(elf, &found_pax); break;
937 case 'e': out = scanelf_file_phdr(elf, &found_phdr, &found_relro, &found_load); break; 984 case 'e': out = scanelf_file_phdr(elf, &found_phdr, &found_relro, &found_load); break;
960 found_rpath || found_needed || found_interp || found_bind || \ 1007 found_rpath || found_needed || found_interp || found_bind || \
961 found_soname || found_sym || found_lib || found_textrels) 1008 found_soname || found_sym || found_lib || found_textrels)
962 1009
963 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) { 1010 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) {
964 xchrcat(&out_buffer, ' ', &out_len); 1011 xchrcat(&out_buffer, ' ', &out_len);
965 xstrcat(&out_buffer, filename, &out_len); 1012 xstrcat(&out_buffer, elf->filename, &out_len);
966 } 1013 }
967 if (!be_quiet || (be_quiet && FOUND_SOMETHING())) { 1014 if (!be_quiet || (be_quiet && FOUND_SOMETHING())) {
968 puts(out_buffer); 1015 puts(out_buffer);
969 fflush(stdout); 1016 fflush(stdout);
970 } 1017 }
971 1018
1019 return 0;
1020}
1021
1022/* scan a single elf */
1023static int scanelf_elf(const char *filename, int fd, size_t len)
1024{
1025 int ret;
1026 elfobj *elf;
1027
1028 /* verify this is real ELF */
1029 if ((elf = _readelf_fd(filename, fd, len, !fix_elf)) == NULL) {
1030 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
1031 return 1;
1032 }
1033
1034 if (strlen(match_etypes)) {
1035 char sbuf[126];
1036 strncpy(sbuf, match_etypes, sizeof(sbuf));
1037 if (strchr(match_etypes, ',') != NULL) {
1038 char *p;
1039 while((p = strrchr(sbuf, ',')) != NULL) {
1040 *p = 0;
1041 if (atoi(p+1) == get_etype(elf))
1042 goto label_ret;
1043 }
1044 }
1045 if (atoi(sbuf) != get_etype(elf)) {
1046 ret = 1;
1047 goto label_done;
1048 }
1049 }
1050
1051label_ret:
1052 ret = scanelf_elfobj(elf);
1053
1054label_done:
972 unreadelf(elf); 1055 unreadelf(elf);
1056 return ret;
1057}
1058
1059/* scan an archive of elfs */
1060static int scanelf_archive(const char *filename, int fd, size_t len)
1061{
1062 archive_handle *ar;
1063 archive_member *m;
1064 char *ar_buffer;
1065 elfobj *elf;
1066
1067 ar = ar_open_fd(filename, fd);
1068 if (ar == NULL)
1069 return 1;
1070
1071 ar_buffer = (char*)mmap(0, len, PROT_READ | (fix_elf ? PROT_WRITE : 0), (fix_elf ? MAP_SHARED : MAP_PRIVATE), fd, 0);
1072 while ((m=ar_next(ar)) != NULL) {
1073 elf = readelf_buffer(m->name, ar_buffer+lseek(fd,0,SEEK_CUR), m->size);
1074 if (elf) {
1075 scanelf_elfobj(elf);
1076 unreadelf(elf);
1077 }
1078 }
1079 munmap(ar_buffer, len);
1080
1081 return 0;
1082}
1083/* scan a file which may be an elf or an archive or some other magical beast */
1084static void scanelf_file(const char *filename)
1085{
1086 struct stat st;
1087 int fd;
1088
1089 /* make sure 'filename' exists */
1090 if (lstat(filename, &st) == -1) {
1091 if (be_verbose > 2) printf("%s: does not exist\n", filename);
1092 return;
1093 }
1094
1095 /* always handle regular files and handle symlinked files if no -y */
1096 if (S_ISLNK(st.st_mode)) {
1097 if (!scan_symlink) return;
1098 stat(filename, &st);
1099 }
1100 if (!S_ISREG(st.st_mode)) {
1101 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
1102 return;
1103 }
1104
1105 if ((fd=open(filename, (fix_elf ? O_RDWR : O_RDONLY))) == -1)
1106 return;
1107
1108 if (scanelf_elf(filename, fd, st.st_size) == 1 && scan_archives)
1109 /* if it isn't an ELF, maybe it's an .a archive */
1110 scanelf_archive(filename, fd, st.st_size);
1111
1112 close(fd);
973} 1113}
974 1114
975/* scan a directory for ET_EXEC files and print when we find one */ 1115/* scan a directory for ET_EXEC files and print when we find one */
976static void scanelf_dir(const char *path) 1116static void scanelf_dir(const char *path)
977{ 1117{
978 register DIR *dir; 1118 register DIR *dir;
979 register struct dirent *dentry; 1119 register struct dirent *dentry;
980 struct stat st_top, st; 1120 struct stat st_top, st;
981 char buf[_POSIX_PATH_MAX]; 1121 char buf[__PAX_UTILS_PATH_MAX];
982 size_t pathlen = 0, len = 0; 1122 size_t pathlen = 0, len = 0;
983 1123
984 /* make sure path exists */ 1124 /* make sure path exists */
985 if (lstat(path, &st_top) == -1) { 1125 if (lstat(path, &st_top) == -1) {
986 if (be_verbose > 2) printf("%s: does not exist\n", path); 1126 if (be_verbose > 2) printf("%s: does not exist\n", path);
996 /* now scan the dir looking for fun stuff */ 1136 /* now scan the dir looking for fun stuff */
997 if ((dir = opendir(path)) == NULL) { 1137 if ((dir = opendir(path)) == NULL) {
998 warnf("could not opendir %s: %s", path, strerror(errno)); 1138 warnf("could not opendir %s: %s", path, strerror(errno));
999 return; 1139 return;
1000 } 1140 }
1001 if (be_verbose) printf("%s: scanning dir\n", path); 1141 if (be_verbose > 1) printf("%s: scanning dir\n", path);
1002 1142
1003 pathlen = strlen(path); 1143 pathlen = strlen(path);
1004 while ((dentry = readdir(dir))) { 1144 while ((dentry = readdir(dir))) {
1005 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) 1145 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
1006 continue; 1146 continue;
1025 1165
1026static int scanelf_from_file(char *filename) 1166static int scanelf_from_file(char *filename)
1027{ 1167{
1028 FILE *fp = NULL; 1168 FILE *fp = NULL;
1029 char *p; 1169 char *p;
1030 char path[_POSIX_PATH_MAX]; 1170 char path[__PAX_UTILS_PATH_MAX];
1031 1171
1032 if (((strcmp(filename, "-")) == 0) && (ttyname(0) == NULL)) 1172 if (((strcmp(filename, "-")) == 0) && (ttyname(0) == NULL))
1033 fp = stdin; 1173 fp = stdin;
1034 else if ((fp = fopen(filename, "r")) == NULL) 1174 else if ((fp = fopen(filename, "r")) == NULL)
1035 return 1; 1175 return 1;
1036 1176
1037 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) { 1177 while ((fgets(path, __PAX_UTILS_PATH_MAX, fp)) != NULL) {
1038 if ((p = strchr(path, '\n')) != NULL) 1178 if ((p = strchr(path, '\n')) != NULL)
1039 *p = 0; 1179 *p = 0;
1040 search_path = path; 1180 search_path = path;
1041 scanelf_dir(path); 1181 scanelf_dir(path);
1042 } 1182 }
1047 1187
1048static void load_ld_so_conf() 1188static void load_ld_so_conf()
1049{ 1189{
1050 FILE *fp = NULL; 1190 FILE *fp = NULL;
1051 char *p; 1191 char *p;
1052 char path[_POSIX_PATH_MAX]; 1192 char path[__PAX_UTILS_PATH_MAX];
1053 int i = 0; 1193 int i = 0;
1054 1194
1055 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 1195 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
1056 return; 1196 return;
1057 1197
1058 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) { 1198 while ((fgets(path, __PAX_UTILS_PATH_MAX, fp)) != NULL) {
1059 if (*path != '/') 1199 if (*path != '/')
1060 continue; 1200 continue;
1061 1201
1062 if ((p = strrchr(path, '\r')) != NULL) 1202 if ((p = strrchr(path, '\r')) != NULL)
1063 *p = 0; 1203 *p = 0;
1116 free(path); 1256 free(path);
1117} 1257}
1118 1258
1119 1259
1120/* usage / invocation handling functions */ 1260/* usage / invocation handling functions */
1121#define PARSE_FLAGS "plRmyxetrnLibSs:gN:TaqvF:f:o:BhV" 1261#define PARSE_FLAGS "plRmyAXxetrnLibSs:gN:TaqvF:f:o:E:BhV"
1122#define a_argument required_argument 1262#define a_argument required_argument
1123static struct option const long_opts[] = { 1263static struct option const long_opts[] = {
1124 {"path", no_argument, NULL, 'p'}, 1264 {"path", no_argument, NULL, 'p'},
1125 {"ldpath", no_argument, NULL, 'l'}, 1265 {"ldpath", no_argument, NULL, 'l'},
1126 {"recursive", no_argument, NULL, 'R'}, 1266 {"recursive", no_argument, NULL, 'R'},
1127 {"mount", no_argument, NULL, 'm'}, 1267 {"mount", no_argument, NULL, 'm'},
1128 {"symlink", no_argument, NULL, 'y'}, 1268 {"symlink", no_argument, NULL, 'y'},
1269 {"archives", no_argument, NULL, 'A'},
1270 {"ldcache", no_argument, NULL, 'L'},
1271 {"fix", no_argument, NULL, 'X'},
1129 {"pax", no_argument, NULL, 'x'}, 1272 {"pax", no_argument, NULL, 'x'},
1130 {"header", no_argument, NULL, 'e'}, 1273 {"header", no_argument, NULL, 'e'},
1131 {"textrel", no_argument, NULL, 't'}, 1274 {"textrel", no_argument, NULL, 't'},
1132 {"rpath", no_argument, NULL, 'r'}, 1275 {"rpath", no_argument, NULL, 'r'},
1133 {"needed", no_argument, NULL, 'n'}, 1276 {"needed", no_argument, NULL, 'n'},
1134 {"ldcache", no_argument, NULL, 'L'},
1135 {"interp", no_argument, NULL, 'i'}, 1277 {"interp", no_argument, NULL, 'i'},
1136 {"bind", no_argument, NULL, 'b'}, 1278 {"bind", no_argument, NULL, 'b'},
1137 {"soname", no_argument, NULL, 'S'}, 1279 {"soname", no_argument, NULL, 'S'},
1138 {"symbol", a_argument, NULL, 's'}, 1280 {"symbol", a_argument, NULL, 's'},
1139 {"lib", a_argument, NULL, 'N'}, 1281 {"lib", a_argument, NULL, 'N'},
1140 {"gmatch", no_argument, NULL, 'g'}, 1282 {"gmatch", no_argument, NULL, 'g'},
1141 {"textrels", no_argument, NULL, 'T'}, 1283 {"textrels", no_argument, NULL, 'T'},
1284 {"etype", a_argument, NULL, 'E'},
1142 {"all", no_argument, NULL, 'a'}, 1285 {"all", no_argument, NULL, 'a'},
1143 {"quiet", no_argument, NULL, 'q'}, 1286 {"quiet", no_argument, NULL, 'q'},
1144 {"verbose", no_argument, NULL, 'v'}, 1287 {"verbose", no_argument, NULL, 'v'},
1145 {"format", a_argument, NULL, 'F'}, 1288 {"format", a_argument, NULL, 'F'},
1146 {"from", a_argument, NULL, 'f'}, 1289 {"from", a_argument, NULL, 'f'},
1154static const char *opts_help[] = { 1297static const char *opts_help[] = {
1155 "Scan all directories in PATH environment", 1298 "Scan all directories in PATH environment",
1156 "Scan all directories in /etc/ld.so.conf", 1299 "Scan all directories in /etc/ld.so.conf",
1157 "Scan directories recursively", 1300 "Scan directories recursively",
1158 "Don't recursively cross mount points", 1301 "Don't recursively cross mount points",
1159 "Don't scan symlinks\n", 1302 "Don't scan symlinks",
1303 "Scan archives (.a files)",
1304 "Utilize ld.so.cache information (use with -r/-n)",
1305 "Try and 'fix' bad things (use with -r/-e)\n",
1160 "Print PaX markings", 1306 "Print PaX markings",
1161 "Print GNU_STACK/PT_LOAD markings", 1307 "Print GNU_STACK/PT_LOAD markings",
1162 "Print TEXTREL information", 1308 "Print TEXTREL information",
1163 "Print RPATH information", 1309 "Print RPATH information",
1164 "Print NEEDED information", 1310 "Print NEEDED information",
1165 "Resolve NEEDED information (use with -n)",
1166 "Print INTERP information", 1311 "Print INTERP information",
1167 "Print BIND information", 1312 "Print BIND information",
1168 "Print SONAME information", 1313 "Print SONAME information",
1169 "Find a specified symbol", 1314 "Find a specified symbol",
1170 "Find a specified library", 1315 "Find a specified library",
1171 "Use strncmp to match libraries. (use with -N)", 1316 "Use strncmp to match libraries. (use with -N)",
1172 "Locate cause of TEXTREL", 1317 "Locate cause of TEXTREL",
1318 "Print only ELF files matching numeric constant",
1173 "Print all scanned info (-x -e -t -r -b)\n", 1319 "Print all scanned info (-x -e -t -r -b)\n",
1174 "Only output 'bad' things", 1320 "Only output 'bad' things",
1175 "Be verbose (can be specified more than once)", 1321 "Be verbose (can be specified more than once)",
1176 "Use specified format for output", 1322 "Use specified format for output",
1177 "Read input stream from a filename", 1323 "Read input stream from a filename",
1185/* display usage and exit */ 1331/* display usage and exit */
1186static void usage(int status) 1332static void usage(int status)
1187{ 1333{
1188 unsigned long i; 1334 unsigned long i;
1189 printf("* Scan ELF binaries for stuff\n\n" 1335 printf("* Scan ELF binaries for stuff\n\n"
1190 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0); 1336 "Usage: %s [options] <dir1/file1> [dir2 dirN file2 fileN ...]\n\n", argv0);
1191 printf("Options: -[%s]\n", PARSE_FLAGS); 1337 printf("Options: -[%s]\n", PARSE_FLAGS);
1192 for (i = 0; long_opts[i].name; ++i) 1338 for (i = 0; long_opts[i].name; ++i)
1193 if (long_opts[i].has_arg == no_argument) 1339 if (long_opts[i].has_arg == no_argument)
1194 printf(" -%c, --%-13s* %s\n", long_opts[i].val, 1340 printf(" -%c, --%-13s* %s\n", long_opts[i].val,
1195 long_opts[i].name, opts_help[i]); 1341 long_opts[i].name, opts_help[i]);
1229 VERSION, __FILE__, __DATE__, rcsid, argv0); 1375 VERSION, __FILE__, __DATE__, rcsid, argv0);
1230 exit(EXIT_SUCCESS); 1376 exit(EXIT_SUCCESS);
1231 break; 1377 break;
1232 case 'h': usage(EXIT_SUCCESS); break; 1378 case 'h': usage(EXIT_SUCCESS); break;
1233 case 'f': 1379 case 'f':
1234 if (from_file) err("Don't specify -f twice"); 1380 if (from_file) warn("You prob don't want to specify -f twice");
1235 from_file = xstrdup(optarg); 1381 from_file = optarg;
1382 break;
1383 case 'E':
1384 strncpy(match_etypes, optarg, sizeof(match_etypes));
1236 break; 1385 break;
1237 case 'o': { 1386 case 'o': {
1238 FILE *fp = NULL; 1387 FILE *fp = NULL;
1239 if ((fp = freopen(optarg, "w", stdout)) == NULL) 1388 if ((fp = freopen(optarg, "w", stdout)) == NULL)
1240 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 1389 err("Could not open output stream '%s': %s", optarg, strerror(errno));
1260 out_format = optarg; 1409 out_format = optarg;
1261 break; 1410 break;
1262 } 1411 }
1263 1412
1264 case 'g': gmatch = 1; /* break; any reason we dont breal; here ? */ 1413 case 'g': gmatch = 1; /* break; any reason we dont breal; here ? */
1265 case 'L': printcache = 1; break; 1414 case 'L': use_ldcache = 1; break;
1266 case 'y': scan_symlink = 0; break; 1415 case 'y': scan_symlink = 0; break;
1416 case 'A': scan_archives = 1; break;
1267 case 'B': show_banner = 0; break; 1417 case 'B': show_banner = 0; break;
1268 case 'l': scan_ldpath = 1; break; 1418 case 'l': scan_ldpath = 1; break;
1269 case 'p': scan_envpath = 1; break; 1419 case 'p': scan_envpath = 1; break;
1270 case 'R': dir_recurse = 1; break; 1420 case 'R': dir_recurse = 1; break;
1271 case 'm': dir_crossmount = 0; break; 1421 case 'm': dir_crossmount = 0; break;
1422 case 'X': ++fix_elf; break;
1272 case 'x': show_pax = 1; break; 1423 case 'x': show_pax = 1; break;
1273 case 'e': show_phdr = 1; break; 1424 case 'e': show_phdr = 1; break;
1274 case 't': show_textrel = 1; break; 1425 case 't': show_textrel = 1; break;
1275 case 'r': show_rpath = 1; break; 1426 case 'r': show_rpath = 1; break;
1276 case 'n': show_needed = 1; break; 1427 case 'n': show_needed = 1; break;
1281 case 'q': be_quiet = 1; break; 1432 case 'q': be_quiet = 1; break;
1282 case 'v': be_verbose = (be_verbose % 20) + 1; break; 1433 case 'v': be_verbose = (be_verbose % 20) + 1; break;
1283 case 'a': show_pax = show_phdr = show_textrel = show_rpath = show_bind = 1; break; 1434 case 'a': show_pax = show_phdr = show_textrel = show_rpath = show_bind = 1; break;
1284 1435
1285 case ':': 1436 case ':':
1286 err("Option missing parameter\n"); 1437 err("Option '%c' is missing parameter", optopt);
1287 case '?': 1438 case '?':
1288 err("Unknown option\n"); 1439 err("Unknown option '%c' or argument missing", optopt);
1289 default: 1440 default:
1290 err("Unhandled option '%c'", i); 1441 err("Unhandled option '%c'; please report this", i);
1291 } 1442 }
1292 } 1443 }
1293 1444
1294 /* let the format option override all other options */ 1445 /* let the format option override all other options */
1295 if (out_format) { 1446 if (out_format) {
1342 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len); 1493 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
1343 } 1494 }
1344 if (be_verbose > 2) printf("Format: %s\n", out_format); 1495 if (be_verbose > 2) printf("Format: %s\n", out_format);
1345 1496
1346 /* now lets actually do the scanning */ 1497 /* now lets actually do the scanning */
1347 if (scan_ldpath || (show_rpath && be_quiet)) 1498 if (scan_ldpath || use_ldcache)
1348 load_ld_so_conf(); 1499 load_ld_so_conf();
1349 if (scan_ldpath) scanelf_ldpath(); 1500 if (scan_ldpath) scanelf_ldpath();
1350 if (scan_envpath) scanelf_envpath(); 1501 if (scan_envpath) scanelf_envpath();
1351 if (from_file) { 1502 if (from_file) {
1352 scanelf_from_file(from_file); 1503 scanelf_from_file(from_file);
1353 free(from_file);
1354 from_file = *argv; 1504 from_file = *argv;
1355 } 1505 }
1356 if (optind == argc && !scan_ldpath && !scan_envpath && !from_file) 1506 if (optind == argc && !scan_ldpath && !scan_envpath && !from_file)
1357 err("Nothing to scan !?"); 1507 err("Nothing to scan !?");
1358 while (optind < argc) { 1508 while (optind < argc) {

Legend:
Removed from v.1.97  
changed lines
  Added in v.1.119

  ViewVC Help
Powered by ViewVC 1.1.20