/[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.185 Revision 1.212
1/* 1/*
2 * Copyright 2003-2007 Gentoo Foundation 2 * Copyright 2003-2007 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.185 2007/08/18 04:59:32 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.212 2009/03/15 09:13:20 vapier Exp $
5 * 5 *
6 * Copyright 2003-2007 Ned Ludd - <solar@gentoo.org> 6 * Copyright 2003-2007 Ned Ludd - <solar@gentoo.org>
7 * Copyright 2004-2007 Mike Frysinger - <vapier@gentoo.org> 7 * Copyright 2004-2007 Mike Frysinger - <vapier@gentoo.org>
8 */ 8 */
9 9
10static const char *rcsid = "$Id: scanelf.c,v 1.212 2009/03/15 09:13:20 vapier Exp $";
11const char * const argv0 = "scanelf";
12
10#include "paxinc.h" 13#include "paxinc.h"
11
12static const char *rcsid = "$Id: scanelf.c,v 1.185 2007/08/18 04:59:32 vapier Exp $";
13#define argv0 "scanelf"
14 14
15#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+') 15#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+')
16 16
17/* prototypes */ 17/* prototypes */
18static int file_matches_list(const char *filename, char **matchlist); 18static int file_matches_list(const char *filename, char **matchlist);
25static void scanelf_envpath(void); 25static void scanelf_envpath(void);
26static void usage(int status); 26static void usage(int status);
27static char **get_split_env(const char *envvar); 27static char **get_split_env(const char *envvar);
28static void parseenv(void); 28static void parseenv(void);
29static int parseargs(int argc, char *argv[]); 29static int parseargs(int argc, char *argv[]);
30static char *xstrdup(const char *s);
31static void *xmalloc(size_t size);
32static void *xrealloc(void *ptr, size_t size);
33static void xstrncat(char **dst, const char *src, size_t *curr_len, size_t n);
34#define xstrcat(dst,src,curr_len) xstrncat(dst,src,curr_len,0)
35static inline void xchrcat(char **dst, const char append, size_t *curr_len);
36static int rematch(const char *regex, const char *match, int cflags); 30static int rematch(const char *regex, const char *match, int cflags);
37 31
38/* variables to control behavior */ 32/* variables to control behavior */
39static char match_etypes[126] = ""; 33static char match_etypes[126] = "";
40static char *ldpaths[256]; 34static char *ldpaths[256];
44static char scan_archives = 0; 38static char scan_archives = 0;
45static char dir_recurse = 0; 39static char dir_recurse = 0;
46static char dir_crossmount = 1; 40static char dir_crossmount = 1;
47static char show_pax = 0; 41static char show_pax = 0;
48static char show_perms = 0; 42static char show_perms = 0;
43static char show_size = 0;
49static char show_phdr = 0; 44static char show_phdr = 0;
50static char show_textrel = 0; 45static char show_textrel = 0;
51static char show_rpath = 0; 46static char show_rpath = 0;
52static char show_needed = 0; 47static char show_needed = 0;
53static char show_interp = 0; 48static char show_interp = 0;
54static char show_bind = 0; 49static char show_bind = 0;
55static char show_soname = 0; 50static char show_soname = 0;
56static char show_textrels = 0; 51static char show_textrels = 0;
57static char show_banner = 1; 52static char show_banner = 1;
58static char show_endian = 0; 53static char show_endian = 0;
54static char show_osabi = 0;
55static char show_eabi = 0;
59static char be_quiet = 0; 56static char be_quiet = 0;
60static char be_verbose = 0; 57static char be_verbose = 0;
61static char be_wewy_wewy_quiet = 0; 58static char be_wewy_wewy_quiet = 0;
62static char be_semi_verbose = 0; 59static char be_semi_verbose = 0;
63static char *find_sym = NULL, *versioned_symname = NULL; 60static char *find_sym = NULL;
64static char *find_lib = NULL; 61static char *find_lib = NULL;
65static char *find_section = NULL; 62static char *find_section = NULL;
66static char *out_format = NULL; 63static char *out_format = NULL;
67static char *search_path = NULL; 64static char *search_path = NULL;
68static char fix_elf = 0; 65static char fix_elf = 0;
71 68
72static char **qa_textrels = NULL; 69static char **qa_textrels = NULL;
73static char **qa_execstack = NULL; 70static char **qa_execstack = NULL;
74static char **qa_wx_load = NULL; 71static char **qa_wx_load = NULL;
75 72
76int match_bits = 0; 73static int match_bits = 0;
77unsigned int match_perms = 0; 74static unsigned int match_perms = 0;
78caddr_t ldcache = 0; 75static void *ldcache = NULL;
79size_t ldcache_size = 0; 76static size_t ldcache_size = 0;
80unsigned long setpax = 0UL; 77static unsigned long setpax = 0UL;
81 78
82int has_objdump = 0; 79static int has_objdump = 0;
83
84static char *getstr_perms(const char *fname);
85static char *getstr_perms(const char *fname) {
86 struct stat st;
87 static char buf[8];
88
89 if ((stat(fname, &st)) == (-1))
90 return (char *) "";
91
92 snprintf(buf, sizeof(buf), "%o", st.st_mode);
93
94 return (char *) buf + 2;
95}
96 80
97/* find the path to a file by name */ 81/* find the path to a file by name */
98static char *which(const char *fname) 82static char *which(const char *fname)
99{ 83{
100 static char fullpath[BUFSIZ]; 84 static char fullpath[__PAX_UTILS_PATH_MAX];
101 char *path, *p; 85 char *path, *p;
102 86
103 path = getenv("PATH"); 87 path = getenv("PATH");
104 if (!path) 88 if (!path)
105 return NULL; 89 return NULL;
106 90
107 path = xstrdup(path); 91 path = xstrdup(path);
108 while ((p = strrchr(path, ':')) != NULL) { 92 while ((p = strrchr(path, ':')) != NULL) {
109 snprintf(fullpath, sizeof(fullpath), "%s/%s", p + 1, fname); 93 snprintf(fullpath, sizeof(fullpath), "%s/%s", p + 1, fname);
110 *p = 0; 94 *p = 0;
111 if (access(fullpath, R_OK) != (-1)) { 95 if (access(fullpath, R_OK) != -1) {
112 free(path); 96 free(path);
113 return (char *) fullpath; 97 return fullpath;
114 } 98 }
115 } 99 }
116 free(path); 100 free(path);
117 return NULL; 101 return NULL;
118} 102}
123 regex_t preg; 107 regex_t preg;
124 int ret; 108 int ret;
125 109
126 if ((match == NULL) || (regex == NULL)) 110 if ((match == NULL) || (regex == NULL))
127 return EXIT_FAILURE; 111 return EXIT_FAILURE;
128
129 112
130 if ((ret = regcomp(&preg, regex, cflags))) { 113 if ((ret = regcomp(&preg, regex, cflags))) {
131 char err[256]; 114 char err[256];
132 115
133 if (regerror(ret, &preg, err, sizeof(err))) 116 if (regerror(ret, &preg, err, sizeof(err)))
202 } \ 185 } \
203 } 186 }
204 SHOW_PAX(32) 187 SHOW_PAX(32)
205 SHOW_PAX(64) 188 SHOW_PAX(64)
206 } 189 }
207
208 190
209 if (fix_elf && setpax) { 191 if (fix_elf && setpax) {
210 /* set the chpax settings */ 192 /* set the chpax settings */
211 if (elf->elf_class == ELFCLASS32) { 193 if (elf->elf_class == ELFCLASS32) {
212 if (EHDR32(elf->ehdr)->e_type == ET_DYN || EHDR32(elf->ehdr)->e_type == ET_EXEC) 194 if (EHDR32(elf->ehdr)->e_type == ET_DYN || EHDR32(elf->ehdr)->e_type == ET_EXEC)
271 warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \ 253 warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \
272 found = found_relro; \ 254 found = found_relro; \
273 offset = 4; \ 255 offset = 4; \
274 check_flags = PF_X; \ 256 check_flags = PF_X; \
275 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \ 257 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \
276 if (ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC) \ 258 if (EGET(ehdr->e_type) == ET_DYN || EGET(ehdr->e_type) == ET_EXEC) \
277 if (multi_load++ > max_pt_load) \ 259 if (multi_load++ > max_pt_load) \
278 warnf("%s: more than %i PT_LOAD's !?", elf->filename, max_pt_load); \ 260 warnf("%s: more than %i PT_LOAD's !?", elf->filename, max_pt_load); \
279 if (file_matches_list(elf->filename, qa_wx_load)) \ 261 if (file_matches_list(elf->filename, qa_wx_load)) \
280 continue; \ 262 continue; \
281 found = found_load; \ 263 found = found_load; \
339 return NULL; 321 return NULL;
340 else 322 else
341 return ret; 323 return ret;
342} 324}
343 325
326/*
327 * See if this ELF contains a DT_TEXTREL tag in any of its
328 * PT_DYNAMIC sections.
329 */
344static const char *scanelf_file_textrel(elfobj *elf, char *found_textrel) 330static const char *scanelf_file_textrel(elfobj *elf, char *found_textrel)
345{ 331{
346 static const char *ret = "TEXTREL"; 332 static const char *ret = "TEXTREL";
347 unsigned long i; 333 unsigned long i;
348 334
379 return NULL; 365 return NULL;
380 else 366 else
381 return " - "; 367 return " - ";
382} 368}
383 369
370/*
371 * Scan the .text section to see if there are any relocations in it.
372 * Should rewrite this to check PT_LOAD sections that are marked
373 * Executable rather than the section named '.text'.
374 */
384static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *found_textrel) 375static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *found_textrel)
385{ 376{
386 unsigned long s, r, rmax; 377 unsigned long s, r, rmax;
387 void *symtab_void, *strtab_void, *text_void; 378 void *symtab_void, *strtab_void, *text_void;
388 379
479 printf("%s", func_name); \ 470 printf("%s", func_name); \
480 } else \ 471 } else \
481 printf("(optimized out)"); \ 472 printf("(optimized out)"); \
482 printf(" [0x%lX]\n", (unsigned long)offset_tmp); \ 473 printf(" [0x%lX]\n", (unsigned long)offset_tmp); \
483 if (be_verbose && has_objdump) { \ 474 if (be_verbose && has_objdump) { \
475 Elf ## B ## _Addr end_addr = offset_tmp + EGET(func->st_size); \
484 char *sysbuf; \ 476 char *sysbuf; \
485 size_t syslen; \ 477 size_t syslen; \
478 int sysret; \
486 const char sysfmt[] = "objdump -r -R -d -w -l --start-address=0x%lX --stop-address=0x%lX %s | grep --color -i -C 3 '.*[[:space:]]%lX:[[:space:]]*R_.*'\n"; \ 479 const char sysfmt[] = "objdump -r -R -d -w -l --start-address=0x%lX --stop-address=0x%lX %s | grep --color -i -C 3 '.*[[:space:]]%lX:[[:space:]]*R_.*'\n"; \
487 syslen = sizeof(sysfmt) + strlen(elf->filename) + 3 * sizeof(unsigned long) + 1; \ 480 syslen = sizeof(sysfmt) + strlen(elf->filename) + 3 * sizeof(unsigned long) + 1; \
488 sysbuf = xmalloc(syslen); \ 481 sysbuf = xmalloc(syslen); \
489 if (sysbuf) { \
490 Elf ## B ## _Addr end_addr = offset_tmp + EGET(func->st_size); \
491 if (end_addr < r_offset) \ 482 if (end_addr < r_offset) \
492 /* not uncommon when things are optimized out */ \ 483 /* not uncommon when things are optimized out */ \
493 end_addr = r_offset + 0x100; \ 484 end_addr = r_offset + 0x100; \
494 snprintf(sysbuf, syslen, sysfmt, \ 485 snprintf(sysbuf, syslen, sysfmt, \
495 (unsigned long)offset_tmp, \ 486 (unsigned long)offset_tmp, \
496 (unsigned long)end_addr, \ 487 (unsigned long)end_addr, \
497 elf->filename, \ 488 elf->filename, \
498 (unsigned long)r_offset); \ 489 (unsigned long)r_offset); \
499 fflush(stdout); \ 490 fflush(stdout); \
500 system(sysbuf); \ 491 sysret = system(sysbuf); \
501 fflush(stdout); \ 492 fflush(stdout); \
502 free(sysbuf); \ 493 free(sysbuf); \
503 } \
504 } \ 494 } \
505 } \ 495 } \
506 } } 496 } }
507 SHOW_TEXTRELS(32) 497 SHOW_TEXTRELS(32)
508 SHOW_TEXTRELS(64) 498 SHOW_TEXTRELS(64)
702 692
703#if defined(__GLIBC__) || defined(__UCLIBC__) 693#if defined(__GLIBC__) || defined(__UCLIBC__)
704 694
705static char *lookup_cache_lib(elfobj *elf, char *fname) 695static char *lookup_cache_lib(elfobj *elf, char *fname)
706{ 696{
707 int fd = 0; 697 int fd;
708 char *strs; 698 char *strs;
709 static char buf[__PAX_UTILS_PATH_MAX] = ""; 699 static char buf[__PAX_UTILS_PATH_MAX] = "";
710 const char *cachefile = "/etc/ld.so.cache"; 700 const char cachefile[] = "/etc/ld.so.cache";
711 struct stat st; 701 struct stat st;
712 702
713 typedef struct { 703 typedef struct {
714 char magic[LDSO_CACHE_MAGIC_LEN]; 704 char magic[LDSO_CACHE_MAGIC_LEN];
715 char version[LDSO_CACHE_VER_LEN]; 705 char version[LDSO_CACHE_VER_LEN];
725 libentry_t *libent; 715 libentry_t *libent;
726 716
727 if (fname == NULL) 717 if (fname == NULL)
728 return NULL; 718 return NULL;
729 719
730 if (ldcache == 0) { 720 if (ldcache == NULL) {
731 if (stat(cachefile, &st) || (fd = open(cachefile, O_RDONLY)) == -1) 721 if (stat(cachefile, &st))
722 return NULL;
723
724 fd = open(cachefile, O_RDONLY);
725 if (fd == -1)
732 return NULL; 726 return NULL;
733 727
734 /* cache these values so we only map/unmap the cache file once */ 728 /* cache these values so we only map/unmap the cache file once */
735 ldcache_size = st.st_size; 729 ldcache_size = st.st_size;
736 ldcache = mmap(0, ldcache_size, PROT_READ, MAP_SHARED, fd, 0); 730 header = ldcache = mmap(0, ldcache_size, PROT_READ, MAP_SHARED, fd, 0);
737
738 close(fd); 731 close(fd);
739 732
740 if (ldcache == (caddr_t)-1) { 733 if (ldcache == MAP_FAILED) {
741 ldcache = 0; 734 ldcache = NULL;
742 return NULL; 735 return NULL;
743 } 736 }
744 737
745 if (memcmp(((header_t *) ldcache)->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN)) 738 if (memcmp(header->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN) ||
739 memcmp(header->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN))
740 {
741 munmap(ldcache, ldcache_size);
742 ldcache = NULL;
746 return NULL; 743 return NULL;
747 if (memcmp (((header_t *) ldcache)->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN))
748 return NULL;
749 } 744 }
745 } else
746 header = ldcache;
750 747
751 header = (header_t *) ldcache;
752 libent = (libentry_t *) (ldcache + sizeof(header_t)); 748 libent = ldcache + sizeof(header_t);
753 strs = (char *) &libent[header->nlibs]; 749 strs = (char *) &libent[header->nlibs];
754 750
755 for (fd = 0; fd < header->nlibs; fd++) { 751 for (fd = 0; fd < header->nlibs; ++fd) {
756 /* this should be more fine grained, but for now we assume that 752 /* This should be more fine grained, but for now we assume that
757 * diff arches will not be cached together. and we ignore the 753 * diff arches will not be cached together, and we ignore the
758 * the different multilib mips cases. */ 754 * the different multilib mips cases.
755 */
759 if (elf->elf_class == ELFCLASS64 && !(libent[fd].flags & FLAG_REQUIRED_MASK)) 756 if (elf->elf_class == ELFCLASS64 && !(libent[fd].flags & FLAG_REQUIRED_MASK))
760 continue; 757 continue;
761 if (elf->elf_class == ELFCLASS32 && (libent[fd].flags & FLAG_REQUIRED_MASK)) 758 if (elf->elf_class == ELFCLASS32 && (libent[fd].flags & FLAG_REQUIRED_MASK))
762 continue; 759 continue;
763 760
764 if (strcmp(fname, strs + libent[fd].sooffset) != 0) 761 if (strcmp(fname, strs + libent[fd].sooffset) != 0)
765 continue; 762 continue;
763
764 /* Return first hit because that is how the ldso rolls */
766 strncpy(buf, strs + libent[fd].liboffset, sizeof(buf)); 765 strncpy(buf, strs + libent[fd].liboffset, sizeof(buf));
766 break;
767 } 767 }
768
768 return buf; 769 return buf;
769} 770}
771
770#elif defined(__NetBSD__) 772#elif defined(__NetBSD__)
771static char *lookup_cache_lib(elfobj *elf, char *fname) 773static char *lookup_cache_lib(elfobj *elf, char *fname)
772{ 774{
773 static char buf[__PAX_UTILS_PATH_MAX] = ""; 775 static char buf[__PAX_UTILS_PATH_MAX] = "";
774 static struct stat st; 776 static struct stat st;
791 793
792 /* not found in any path */ 794 /* not found in any path */
793 return NULL; 795 return NULL;
794} 796}
795#else 797#else
798#ifdef __ELF__
796#warning Cache support not implemented for your target 799#warning Cache support not implemented for your target
800#endif
797static char *lookup_cache_lib(elfobj *elf, char *fname) 801static char *lookup_cache_lib(elfobj *elf, char *fname)
798{ 802{
799 return NULL; 803 return NULL;
800} 804}
801#endif 805#endif
942 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 946 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
943 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 947 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
944 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 948 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
945 Elf ## B ## _Off offset; \ 949 Elf ## B ## _Off offset; \
946 /* only look for soname in shared objects */ \ 950 /* only look for soname in shared objects */ \
947 if (ehdr->e_type != ET_DYN) \ 951 if (EGET(ehdr->e_type) != ET_DYN) \
948 return NULL; \ 952 return NULL; \
949 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 953 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
950 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \ 954 if (EGET(phdr[i].p_type) != PT_DYNAMIC || EGET(phdr[i].p_filesz) == 0) continue; \
951 offset = EGET(phdr[i].p_offset); \ 955 offset = EGET(phdr[i].p_offset); \
952 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 956 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
970 } 974 }
971 975
972 return NULL; 976 return NULL;
973} 977}
974 978
979static int scanelf_match_symname(const char *symname, const char *tomatch) {
980 /* We do things differently when checking with regexp */
981 if (g_match) {
982 return rematch(symname, tomatch, REG_EXTENDED) == 0;
983 } else {
984 const size_t symname_len = strlen(symname);
985 return (strncmp(symname, tomatch, symname_len) == 0 &&
986 /* Accept unversioned symbol names */
987 (tomatch[symname_len] == '\0' || tomatch[symname_len] == '@'));
988 }
989}
990
975static char *scanelf_file_sym(elfobj *elf, char *found_sym) 991static char *scanelf_file_sym(elfobj *elf, char *found_sym)
976{ 992{
977 unsigned long i; 993 unsigned long i;
978 char *ret; 994 char *ret;
979 void *symtab_void, *strtab_void; 995 void *symtab_void, *strtab_void;
992 unsigned long cnt = EGET(symtab->sh_entsize); \ 1008 unsigned long cnt = EGET(symtab->sh_entsize); \
993 char *symname; \ 1009 char *symname; \
994 if (cnt) \ 1010 if (cnt) \
995 cnt = EGET(symtab->sh_size) / cnt; \ 1011 cnt = EGET(symtab->sh_size) / cnt; \
996 for (i = 0; i < cnt; ++i) { \ 1012 for (i = 0; i < cnt; ++i) { \
1013 if ((void*)sym > (void*)elf->data_end) { \
1014 warnf("%s: corrupt ELF symbols - aborting", elf->filename); \
1015 goto break_out; \
1016 } \
997 if (sym->st_name) { \ 1017 if (sym->st_name) { \
998 /* make sure the symbol name is in acceptable memory range */ \ 1018 /* make sure the symbol name is in acceptable memory range */ \
999 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 1019 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
1000 if ((void*)symname > (void*)elf->data_end) { \ 1020 if ((void*)symname > (void*)elf->data_end) { \
1001 warnf("%s: corrupt ELF symbols", elf->filename); \ 1021 warnf("%s: corrupt ELF symbols", elf->filename); \
1002 ++sym; \ 1022 ++sym; \
1003 continue; \ 1023 continue; \
1004 } \ 1024 } \
1005 /* debug display ... show all symbols and some extra info */ \ 1025 /* debug display ... show all symbols and some extra info */ \
1006 if (g_match ? rematch(ret, symname, REG_EXTENDED) == 0 : *ret == '*') { \ 1026 if (0 && g_match ? rematch(ret, symname, REG_EXTENDED) == 0 : *ret == '*') { \
1007 printf("%s(%s) %5lX %15s %s %s\n", \ 1027 printf("%s(%s) %5lX %15s %s %s\n", \
1008 ((*found_sym == 0) ? "\n\t" : "\t"), \ 1028 ((*found_sym == 0) ? "\n\t" : "\t"), \
1009 elf->base_filename, \ 1029 elf->base_filename, \
1010 (unsigned long)sym->st_size, \ 1030 (unsigned long)sym->st_size, \
1011 get_elfstttype(sym->st_info), \ 1031 get_elfstttype(sym->st_info), \
1012 sym->st_shndx == SHN_UNDEF ? "U" : "D", symname); \ 1032 sym->st_shndx == SHN_UNDEF ? "U" : "D", symname); \
1013 *found_sym = 1; \ 1033 *found_sym = 1; \
1014 } else { \ 1034 } else { \
1015 /* allow the user to specify a comma delimited list of symbols to search for */ \ 1035 /* allow the user to specify a comma delimited list of symbols to search for */ \
1016 char *this_sym, *this_sym_ver, *next_sym; \ 1036 char *this_sym, *next_sym; \
1017 this_sym = ret; \ 1037 next_sym = ret; \
1018 this_sym_ver = versioned_symname; \ 1038 while (next_sym) { \
1019 do { \ 1039 this_sym = next_sym; \
1020 next_sym = strchr(this_sym, ','); \ 1040 if ((next_sym = strchr(this_sym, ','))) \
1021 if (next_sym == NULL) \ 1041 next_sym += 1; /* Skip the comma */ \
1022 next_sym = this_sym + strlen(this_sym); \
1023 /* do we want a defined symbol ? */ \ 1042 /* do we want a defined symbol ? */ \
1024 if (*this_sym == '+') { \ 1043 if (*this_sym == '+') { \
1025 if (sym->st_shndx == SHN_UNDEF) \ 1044 if (sym->st_shndx == SHN_UNDEF) \
1026 goto skip_this_sym##B; \ 1045 continue; \
1027 ++this_sym; \ 1046 ++this_sym; \
1028 ++this_sym_ver; \
1029 /* do we want an undefined symbol ? */ \ 1047 /* do we want an undefined symbol ? */ \
1030 } else if (*this_sym == '-') { \ 1048 } else if (*this_sym == '-') { \
1031 if (sym->st_shndx != SHN_UNDEF) \ 1049 if (sym->st_shndx != SHN_UNDEF) \
1032 goto skip_this_sym##B; \ 1050 continue; \
1033 ++this_sym; \ 1051 ++this_sym; \
1034 ++this_sym_ver; \
1035 } \ 1052 } \
1053 if (next_sym) /* Copy it so that we don't have to worry about the final , */ \
1054 this_sym = xstrndup(this_sym, next_sym-this_sym); \
1036 /* ok, lets compare the name now */ \ 1055 /* ok, lets compare the name now */ \
1037 if ((strncmp(this_sym, symname, (next_sym-this_sym)) == 0 && symname[next_sym-this_sym] == '\0') || \ 1056 if (scanelf_match_symname(this_sym, symname)) { \
1038 (strncmp(this_sym_ver, symname, strlen(this_sym_ver)) == 0)) { \
1039 if (be_semi_verbose) { \ 1057 if (be_semi_verbose) { \
1040 char buf[126]; \ 1058 char buf[126]; \
1041 snprintf(buf, sizeof(buf), "%lX %s %s", \ 1059 snprintf(buf, sizeof(buf), "%lX %s %s", \
1042 (unsigned long)sym->st_size, get_elfstttype(sym->st_info), this_sym); \ 1060 (unsigned long)sym->st_size, get_elfstttype(sym->st_info), this_sym); \
1043 ret = buf; \ 1061 ret = buf; \
1044 } else \ 1062 } else \
1045 ret = this_sym; \ 1063 ret = symname; \
1046 (*found_sym)++; \ 1064 (*found_sym)++; \
1047 goto break_out; \ 1065 goto break_out; \
1048 } \ 1066 } \
1049 skip_this_sym##B: this_sym = next_sym + 1; \ 1067 if (next_sym) free(this_sym); \
1050 } while (*next_sym != '\0'); \ 1068 } \
1051 } \ 1069 } \
1052 } \ 1070 } \
1053 ++sym; \ 1071 ++sym; \
1054 } } 1072 } }
1055 FIND_SYM(32) 1073 FIND_SYM(32)
1064 if (be_quiet) 1082 if (be_quiet)
1065 return NULL; 1083 return NULL;
1066 else 1084 else
1067 return (char *)" - "; 1085 return (char *)" - ";
1068} 1086}
1069
1070 1087
1071static char *scanelf_file_sections(elfobj *elf, char *found_section) 1088static char *scanelf_file_sections(elfobj *elf, char *found_section)
1072{ 1089{
1073 if (!find_section) 1090 if (!find_section)
1074 return NULL; 1091 return NULL;
1096 else 1113 else
1097 return (char *)" - "; 1114 return (char *)" - ";
1098} 1115}
1099 1116
1100/* scan an elf file and show all the fun stuff */ 1117/* scan an elf file and show all the fun stuff */
1101#define prints(str) write(fileno(stdout), str, strlen(str)) 1118#define prints(str) ({ ssize_t ret = write(fileno(stdout), str, strlen(str)); ret; })
1102static int scanelf_elfobj(elfobj *elf) 1119static int scanelf_elfobj(elfobj *elf)
1103{ 1120{
1104 unsigned long i; 1121 unsigned long i;
1105 char found_pax, found_phdr, found_relro, found_load, found_textrel, 1122 char found_pax, found_phdr, found_relro, found_load, found_textrel,
1106 found_rpath, found_needed, found_interp, found_bind, found_soname, 1123 found_rpath, found_needed, found_interp, found_bind, found_soname,
1120 printf("%s: scanning file\n", elf->filename); 1137 printf("%s: scanning file\n", elf->filename);
1121 1138
1122 /* init output buffer */ 1139 /* init output buffer */
1123 if (!out_buffer) { 1140 if (!out_buffer) {
1124 out_len = sizeof(char) * 80; 1141 out_len = sizeof(char) * 80;
1125 out_buffer = (char*)xmalloc(out_len); 1142 out_buffer = xmalloc(out_len);
1126 } 1143 }
1127 *out_buffer = '\0'; 1144 *out_buffer = '\0';
1128 1145
1129 /* show the header */ 1146 /* show the header */
1130 if (!be_quiet && show_banner) { 1147 if (!be_quiet && show_banner) {
1145 case 'r': prints("RPATH "); break; 1162 case 'r': prints("RPATH "); break;
1146 case 'M': prints("CLASS "); break; 1163 case 'M': prints("CLASS "); break;
1147 case 'n': prints("NEEDED "); break; 1164 case 'n': prints("NEEDED "); break;
1148 case 'i': prints("INTERP "); break; 1165 case 'i': prints("INTERP "); break;
1149 case 'b': prints("BIND "); break; 1166 case 'b': prints("BIND "); break;
1167 case 'Z': prints("SIZE "); break;
1150 case 'S': prints("SONAME "); break; 1168 case 'S': prints("SONAME "); break;
1151 case 's': prints("SYM "); break; 1169 case 's': prints("SYM "); break;
1152 case 'N': prints("LIB "); break; 1170 case 'N': prints("LIB "); break;
1153 case 'T': prints("TEXTRELS "); break; 1171 case 'T': prints("TEXTRELS "); break;
1154 case 'k': prints("SECTION "); break; 1172 case 'k': prints("SECTION "); break;
1155 case 'a': prints("ARCH "); break; 1173 case 'a': prints("ARCH "); break;
1174 case 'I': prints("OSABI "); break;
1175 case 'Y': prints("EABI "); break;
1156 case 'O': prints("PERM "); break; 1176 case 'O': prints("PERM "); break;
1157 case 'D': prints("ENDIAN "); break; 1177 case 'D': prints("ENDIAN "); break;
1158 default: warnf("'%c' has no title ?", out_format[i]); 1178 default: warnf("'%c' has no title ?", out_format[i]);
1159 } 1179 }
1160 } 1180 }
1166 1186
1167 /* dump all the good stuff */ 1187 /* dump all the good stuff */
1168 for (i = 0; out_format[i]; ++i) { 1188 for (i = 0; out_format[i]; ++i) {
1169 const char *out; 1189 const char *out;
1170 const char *tmp; 1190 const char *tmp;
1171 1191 static char ubuf[sizeof(unsigned long)*2];
1172 if (!IS_MODIFIER(out_format[i])) { 1192 if (!IS_MODIFIER(out_format[i])) {
1173 xchrcat(&out_buffer, out_format[i], &out_len); 1193 xchrcat(&out_buffer, out_format[i], &out_len);
1174 continue; 1194 continue;
1175 } 1195 }
1176 1196
1214 case 't': out = scanelf_file_textrel(elf, &found_textrel); break; 1234 case 't': out = scanelf_file_textrel(elf, &found_textrel); break;
1215 case 'T': out = scanelf_file_textrels(elf, &found_textrels, &found_textrel); break; 1235 case 'T': out = scanelf_file_textrels(elf, &found_textrels, &found_textrel); break;
1216 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break; 1236 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break;
1217 case 'M': out = get_elfeitype(EI_CLASS, elf->data[EI_CLASS]); break; 1237 case 'M': out = get_elfeitype(EI_CLASS, elf->data[EI_CLASS]); break;
1218 case 'D': out = get_endian(elf); break; 1238 case 'D': out = get_endian(elf); break;
1219 case 'O': out = getstr_perms(elf->filename); break; 1239 case 'O': out = strfileperms(elf->filename); break;
1220 case 'n': 1240 case 'n':
1221 case 'N': out = scanelf_file_needed_lib(elf, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break; 1241 case 'N': out = scanelf_file_needed_lib(elf, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break;
1222 case 'i': out = scanelf_file_interp(elf, &found_interp); break; 1242 case 'i': out = scanelf_file_interp(elf, &found_interp); break;
1223 case 'b': out = scanelf_file_bind(elf, &found_bind); break; 1243 case 'b': out = scanelf_file_bind(elf, &found_bind); break;
1224 case 'S': out = scanelf_file_soname(elf, &found_soname); break; 1244 case 'S': out = scanelf_file_soname(elf, &found_soname); break;
1225 case 's': out = scanelf_file_sym(elf, &found_sym); break; 1245 case 's': out = scanelf_file_sym(elf, &found_sym); break;
1226 case 'k': out = scanelf_file_sections(elf, &found_section); break; 1246 case 'k': out = scanelf_file_sections(elf, &found_section); break;
1227 case 'a': out = get_elfemtype(elf); break; 1247 case 'a': out = get_elfemtype(elf); break;
1248 case 'I': out = get_elfosabi(elf); break;
1249 case 'Y': out = get_elf_eabi(elf); break;
1250 case 'Z': snprintf(ubuf, sizeof(ubuf), "%lu", (unsigned long)elf->len); out = ubuf; break;;
1228 default: warnf("'%c' has no scan code?", out_format[i]); 1251 default: warnf("'%c' has no scan code?", out_format[i]);
1229 } 1252 }
1230 if (out) { 1253 if (out) {
1231 /* hack for comma delimited output like `scanelf -s sym1,sym2,sym3` */ 1254 /* hack for comma delimited output like `scanelf -s sym1,sym2,sym3` */
1232 if (out_format[i] == 's' && (tmp=strchr(out,',')) != NULL) 1255 if (out_format[i] == 's' && (tmp=strchr(out,',')) != NULL)
1278 if (strlen(match_etypes)) { 1301 if (strlen(match_etypes)) {
1279 char sbuf[126]; 1302 char sbuf[126];
1280 strncpy(sbuf, match_etypes, sizeof(sbuf)); 1303 strncpy(sbuf, match_etypes, sizeof(sbuf));
1281 if (strchr(match_etypes, ',') != NULL) { 1304 if (strchr(match_etypes, ',') != NULL) {
1282 char *p; 1305 char *p;
1283 while((p = strrchr(sbuf, ',')) != NULL) { 1306 while ((p = strrchr(sbuf, ',')) != NULL) {
1284 *p = 0; 1307 *p = 0;
1285 if (etype_lookup(p+1) == get_etype(elf)) 1308 if (etype_lookup(p+1) == get_etype(elf))
1286 goto label_ret; 1309 goto label_ret;
1287 } 1310 }
1288 } 1311 }
1308 1331
1309 ar = ar_open_fd(filename, fd); 1332 ar = ar_open_fd(filename, fd);
1310 if (ar == NULL) 1333 if (ar == NULL)
1311 return 1; 1334 return 1;
1312 1335
1313 ar_buffer = (char*)mmap(0, len, PROT_READ | (fix_elf ? PROT_WRITE : 0), (fix_elf ? MAP_SHARED : MAP_PRIVATE), fd, 0); 1336 ar_buffer = mmap(0, len, PROT_READ | (fix_elf ? PROT_WRITE : 0), (fix_elf ? MAP_SHARED : MAP_PRIVATE), fd, 0);
1314 while ((m=ar_next(ar)) != NULL) { 1337 while ((m=ar_next(ar)) != NULL) {
1315 elf = readelf_buffer(m->name, ar_buffer+lseek(fd,0,SEEK_CUR), m->size); 1338 elf = readelf_buffer(m->name, ar_buffer+lseek(fd,0,SEEK_CUR), m->size);
1316 if (elf) { 1339 if (elf) {
1317 scanelf_elfobj(elf); 1340 scanelf_elfobj(elf);
1318 unreadelf(elf); 1341 unreadelf(elf);
1449 if ((p = strrchr(path, '\r')) != NULL) 1472 if ((p = strrchr(path, '\r')) != NULL)
1450 *p = 0; 1473 *p = 0;
1451 if ((p = strchr(path, '\n')) != NULL) 1474 if ((p = strchr(path, '\n')) != NULL)
1452 *p = 0; 1475 *p = 0;
1453#ifdef __linux__ 1476#ifdef __linux__
1454 // recursive includes of the same file will make this segfault. 1477 /* recursive includes of the same file will make this segfault. */
1455 if ((memcmp(path, "include", 7) == 0) && isblank(path[7])) { 1478 if ((memcmp(path, "include", 7) == 0) && isblank(path[7])) {
1456 glob64_t gl; 1479 glob64_t gl;
1457 size_t x; 1480 size_t x;
1458 char gpath[__PAX_UTILS_PATH_MAX]; 1481 char gpath[__PAX_UTILS_PATH_MAX];
1459 1482
1492 1515
1493 fclose(fp); 1516 fclose(fp);
1494 return i; 1517 return i;
1495} 1518}
1496 1519
1497#elif defined(__FreeBSD__) || (__DragonFly__) 1520#elif defined(__FreeBSD__) || defined(__DragonFly__)
1498 1521
1499static int load_ld_cache_config(int i, const char *fname) 1522static int load_ld_cache_config(int i, const char *fname)
1500{ 1523{
1501 FILE *fp = NULL; 1524 FILE *fp = NULL;
1502 char *b = NULL, *p; 1525 char *b = NULL, *p;
1514 { 1537 {
1515 fclose(fp); 1538 fclose(fp);
1516 return i; 1539 return i;
1517 } 1540 }
1518 1541
1519 b = (char*)malloc(hdr.dirlistlen+1); 1542 b = xmalloc(hdr.dirlistlen + 1);
1520 if (fread(b, 1, hdr.dirlistlen+1, fp) != hdr.dirlistlen+1) { 1543 if (fread(b, 1, hdr.dirlistlen+1, fp) != hdr.dirlistlen+1) {
1521 fclose(fp); 1544 fclose(fp);
1522 free(b); 1545 free(b);
1523 return i; 1546 return i;
1524 } 1547 }
1536 fclose(fp); 1559 fclose(fp);
1537 return i; 1560 return i;
1538} 1561}
1539 1562
1540#else 1563#else
1541 1564#ifdef __ELF__
1542#warning Cache config support not implemented for your target 1565#warning Cache config support not implemented for your target
1566#endif
1543static int load_ld_cache_config(int i, const char *fname) 1567static int load_ld_cache_config(int i, const char *fname)
1544{ 1568{
1545 memset(ldpaths, 0x00, sizeof(ldpaths)); 1569 memset(ldpaths, 0x00, sizeof(ldpaths));
1570 return 0;
1546} 1571}
1547
1548#endif 1572#endif
1549 1573
1550/* scan /etc/ld.so.conf for paths */ 1574/* scan /etc/ld.so.conf for paths */
1551static void scanelf_ldpath(void) 1575static void scanelf_ldpath(void)
1552{ 1576{
1557 err("Unable to load any paths from ld.so.conf"); 1581 err("Unable to load any paths from ld.so.conf");
1558 1582
1559 scan_l = scan_ul = scan_ull = 0; 1583 scan_l = scan_ul = scan_ull = 0;
1560 1584
1561 while (ldpaths[i]) { 1585 while (ldpaths[i]) {
1562 if (!scan_l && !strcmp(ldpaths[i], "/lib")) scan_l = 1; 1586 if (!scan_l && !strcmp(ldpaths[i], "/lib")) scan_l = 1;
1563 if (!scan_ul && !strcmp(ldpaths[i], "/usr/lib")) scan_ul = 1; 1587 if (!scan_ul && !strcmp(ldpaths[i], "/usr/lib")) scan_ul = 1;
1564 if (!scan_ull && !strcmp(ldpaths[i], "/usr/local/lib")) scan_ull = 1; 1588 if (!scan_ull && !strcmp(ldpaths[i], "/usr/local/lib")) scan_ull = 1;
1565 scanelf_dir(ldpaths[i]); 1589 scanelf_dir(ldpaths[i]);
1566 ++i; 1590 ++i;
1567 } 1591 }
1568 1592
1587 } 1611 }
1588 1612
1589 free(path); 1613 free(path);
1590} 1614}
1591 1615
1592
1593/* usage / invocation handling functions */ /* Free Flags: c d j u w C G H I J K P Q U W Y Z */ 1616/* usage / invocation handling functions */ /* Free Flags: c d j u w C G H J K P Q U W */
1594#define PARSE_FLAGS "plRmyAXz:xetrnLibSs:k:gN:TaqvF:f:o:E:M:DO:BhV" 1617#define PARSE_FLAGS "plRmyAXz:xetrnLibSs:k:gN:TaqvF:f:o:E:M:DIYO:ZBhV"
1595#define a_argument required_argument 1618#define a_argument required_argument
1596static struct option const long_opts[] = { 1619static struct option const long_opts[] = {
1597 {"path", no_argument, NULL, 'p'}, 1620 {"path", no_argument, NULL, 'p'},
1598 {"ldpath", no_argument, NULL, 'l'}, 1621 {"ldpath", no_argument, NULL, 'l'},
1599 {"recursive", no_argument, NULL, 'R'}, 1622 {"recursive", no_argument, NULL, 'R'},
1617 {"gmatch", no_argument, NULL, 'g'}, 1640 {"gmatch", no_argument, NULL, 'g'},
1618 {"textrels", no_argument, NULL, 'T'}, 1641 {"textrels", no_argument, NULL, 'T'},
1619 {"etype", a_argument, NULL, 'E'}, 1642 {"etype", a_argument, NULL, 'E'},
1620 {"bits", a_argument, NULL, 'M'}, 1643 {"bits", a_argument, NULL, 'M'},
1621 {"endian", no_argument, NULL, 'D'}, 1644 {"endian", no_argument, NULL, 'D'},
1645 {"osabi", no_argument, NULL, 'I'},
1646 {"eabi", no_argument, NULL, 'Y'},
1622 {"perms", a_argument, NULL, 'O'}, 1647 {"perms", a_argument, NULL, 'O'},
1648 {"size", no_argument, NULL, 'Z'},
1623 {"all", no_argument, NULL, 'a'}, 1649 {"all", no_argument, NULL, 'a'},
1624 {"quiet", no_argument, NULL, 'q'}, 1650 {"quiet", no_argument, NULL, 'q'},
1625 {"verbose", no_argument, NULL, 'v'}, 1651 {"verbose", no_argument, NULL, 'v'},
1626 {"format", a_argument, NULL, 'F'}, 1652 {"format", a_argument, NULL, 'F'},
1627 {"from", a_argument, NULL, 'f'}, 1653 {"from", a_argument, NULL, 'f'},
1656 "Use strncmp to match libraries. (use with -N)", 1682 "Use strncmp to match libraries. (use with -N)",
1657 "Locate cause of TEXTREL", 1683 "Locate cause of TEXTREL",
1658 "Print only ELF files matching etype ET_DYN,ET_EXEC ...", 1684 "Print only ELF files matching etype ET_DYN,ET_EXEC ...",
1659 "Print only ELF files matching numeric bits", 1685 "Print only ELF files matching numeric bits",
1660 "Print Endianness", 1686 "Print Endianness",
1687 "Print OSABI",
1688 "Print EABI (EM_ARM Only)",
1661 "Print only ELF files matching octal permissions", 1689 "Print only ELF files matching octal permissions",
1690 "Print ELF file size",
1662 "Print all scanned info (-x -e -t -r -b)\n", 1691 "Print all scanned info (-x -e -t -r -b)\n",
1663 "Only output 'bad' things", 1692 "Only output 'bad' things",
1664 "Be verbose (can be specified more than once)", 1693 "Be verbose (can be specified more than once)",
1665 "Use specified format for output", 1694 "Use specified format for output",
1666 "Read input stream from a filename", 1695 "Read input stream from a filename",
1731 if (strcmp(optarg, "ELFCLASS64") == 0) 1760 if (strcmp(optarg, "ELFCLASS64") == 0)
1732 match_bits = 64; 1761 match_bits = 64;
1733 } 1762 }
1734 break; 1763 break;
1735 case 'O': 1764 case 'O':
1736 if (sscanf(optarg, "%o", &match_perms) == (-1)) 1765 if (sscanf(optarg, "%o", &match_perms) == -1)
1737 match_bits = 0; 1766 match_bits = 0;
1738 break; 1767 break;
1739 case 'o': { 1768 case 'o': {
1740 if (freopen(optarg, "w", stdout) == NULL) 1769 if (freopen(optarg, "w", stdout) == NULL)
1741 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 1770 err("Could not open output stream '%s': %s", optarg, strerror(errno));
1746 find_section = optarg; 1775 find_section = optarg;
1747 break; 1776 break;
1748 case 's': { 1777 case 's': {
1749 if (find_sym) warn("You prob don't want to specify -s twice"); 1778 if (find_sym) warn("You prob don't want to specify -s twice");
1750 find_sym = optarg; 1779 find_sym = optarg;
1751 versioned_symname = (char*)xmalloc(sizeof(char) * (strlen(find_sym)+1+1));
1752 sprintf(versioned_symname, "%s@", find_sym);
1753 break; 1780 break;
1754 } 1781 }
1755 case 'N': { 1782 case 'N': {
1756 if (find_lib) warn("You prob don't want to specify -N twice"); 1783 if (find_lib) warn("You prob don't want to specify -N twice");
1757 find_lib = optarg; 1784 find_lib = optarg;
1765 } 1792 }
1766 case 'z': { 1793 case 'z': {
1767 unsigned long flags = (PF_NOEMUTRAMP | PF_NORANDEXEC); 1794 unsigned long flags = (PF_NOEMUTRAMP | PF_NORANDEXEC);
1768 size_t x; 1795 size_t x;
1769 1796
1770 for (x = 0 ; x < strlen(optarg); x++) { 1797 for (x = 0; x < strlen(optarg); x++) {
1771 switch(optarg[x]) { 1798 switch (optarg[x]) {
1772 case 'p': 1799 case 'p':
1773 case 'P': 1800 case 'P':
1774 do_pax_state(optarg[x], PAGEEXEC); 1801 do_pax_state(optarg[x], PAGEEXEC);
1775 break; 1802 break;
1776 case 's': 1803 case 's':
1804 ((flags & PF_EMUTRAMP) && (flags & PF_NOEMUTRAMP)) || 1831 ((flags & PF_EMUTRAMP) && (flags & PF_NOEMUTRAMP)) ||
1805 ((flags & PF_RANDMMAP) && (flags & PF_NORANDMMAP)))) 1832 ((flags & PF_RANDMMAP) && (flags & PF_NORANDMMAP))))
1806 setpax = flags; 1833 setpax = flags;
1807 break; 1834 break;
1808 } 1835 }
1836 case 'Z': show_size = 1; break;
1809 case 'g': g_match = 1; break; 1837 case 'g': g_match = 1; break;
1810 case 'L': use_ldcache = 1; break; 1838 case 'L': use_ldcache = 1; break;
1811 case 'y': scan_symlink = 0; break; 1839 case 'y': scan_symlink = 0; break;
1812 case 'A': scan_archives = 1; break; 1840 case 'A': scan_archives = 1; break;
1813 case 'B': show_banner = 0; break; 1841 case 'B': show_banner = 0; break;
1827 case 'T': show_textrels = 1; break; 1855 case 'T': show_textrels = 1; break;
1828 case 'q': be_quiet = 1; break; 1856 case 'q': be_quiet = 1; break;
1829 case 'v': be_verbose = (be_verbose % 20) + 1; break; 1857 case 'v': be_verbose = (be_verbose % 20) + 1; break;
1830 case 'a': show_perms = show_pax = show_phdr = show_textrel = show_rpath = show_bind = show_endian = 1; break; 1858 case 'a': show_perms = show_pax = show_phdr = show_textrel = show_rpath = show_bind = show_endian = 1; break;
1831 case 'D': show_endian = 1; break; 1859 case 'D': show_endian = 1; break;
1860 case 'I': show_osabi = 1; break;
1861 case 'Y': show_eabi = 1; break;
1832 case ':': 1862 case ':':
1833 err("Option '%c' is missing parameter", optopt); 1863 err("Option '%c' is missing parameter", optopt);
1834 case '?': 1864 case '?':
1835 err("Unknown option '%c' or argument missing", optopt); 1865 err("Unknown option '%c' or argument missing", optopt);
1836 default: 1866 default:
1843 } 1873 }
1844 /* let the format option override all other options */ 1874 /* let the format option override all other options */
1845 if (out_format) { 1875 if (out_format) {
1846 show_pax = show_phdr = show_textrel = show_rpath = \ 1876 show_pax = show_phdr = show_textrel = show_rpath = \
1847 show_needed = show_interp = show_bind = show_soname = \ 1877 show_needed = show_interp = show_bind = show_soname = \
1848 show_textrels = show_perms = show_endian = 0; 1878 show_textrels = show_perms = show_endian = show_size = \
1879 show_osabi = show_eabi = 0;
1849 for (i = 0; out_format[i]; ++i) { 1880 for (i = 0; out_format[i]; ++i) {
1850 if (!IS_MODIFIER(out_format[i])) continue; 1881 if (!IS_MODIFIER(out_format[i])) continue;
1851 1882
1852 switch (out_format[++i]) { 1883 switch (out_format[++i]) {
1853 case '+': break; 1884 case '+': break;
1860 case 's': break; 1891 case 's': break;
1861 case 'N': break; 1892 case 'N': break;
1862 case 'o': break; 1893 case 'o': break;
1863 case 'a': break; 1894 case 'a': break;
1864 case 'M': break; 1895 case 'M': break;
1896 case 'Z': show_size = 1; break;
1865 case 'D': show_endian = 1; break; 1897 case 'D': show_endian = 1; break;
1898 case 'I': show_osabi = 1; break;
1899 case 'Y': show_eabi = 1; break;
1866 case 'O': show_perms = 1; break; 1900 case 'O': show_perms = 1; break;
1867 case 'x': show_pax = 1; break; 1901 case 'x': show_pax = 1; break;
1868 case 'e': show_phdr = 1; break; 1902 case 'e': show_phdr = 1; break;
1869 case 't': show_textrel = 1; break; 1903 case 't': show_textrel = 1; break;
1870 case 'r': show_rpath = 1; break; 1904 case 'r': show_rpath = 1; break;
1880 } 1914 }
1881 1915
1882 /* construct our default format */ 1916 /* construct our default format */
1883 } else { 1917 } else {
1884 size_t fmt_len = 30; 1918 size_t fmt_len = 30;
1885 out_format = (char*)xmalloc(sizeof(char) * fmt_len); 1919 out_format = xmalloc(sizeof(char) * fmt_len);
1920 *out_format = '\0';
1886 if (!be_quiet) xstrcat(&out_format, "%o ", &fmt_len); 1921 if (!be_quiet) xstrcat(&out_format, "%o ", &fmt_len);
1887 if (show_pax) xstrcat(&out_format, "%x ", &fmt_len); 1922 if (show_pax) xstrcat(&out_format, "%x ", &fmt_len);
1888 if (show_perms) xstrcat(&out_format, "%O ", &fmt_len); 1923 if (show_perms) xstrcat(&out_format, "%O ", &fmt_len);
1924 if (show_size) xstrcat(&out_format, "%Z ", &fmt_len);
1889 if (show_endian) xstrcat(&out_format, "%D ", &fmt_len); 1925 if (show_endian) xstrcat(&out_format, "%D ", &fmt_len);
1926 if (show_osabi) xstrcat(&out_format, "%I ", &fmt_len);
1927 if (show_eabi) xstrcat(&out_format, "%Y ", &fmt_len);
1890 if (show_phdr) xstrcat(&out_format, "%e ", &fmt_len); 1928 if (show_phdr) xstrcat(&out_format, "%e ", &fmt_len);
1891 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len); 1929 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len);
1892 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len); 1930 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len);
1893 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len); 1931 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
1894 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len); 1932 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
1919 search_path = argv[optind++]; 1957 search_path = argv[optind++];
1920 ret = scanelf_dir(search_path); 1958 ret = scanelf_dir(search_path);
1921 } 1959 }
1922 1960
1923 /* clean up */ 1961 /* clean up */
1924 free(versioned_symname);
1925 for (i = 0; ldpaths[i]; ++i) 1962 for (i = 0; ldpaths[i]; ++i)
1926 free(ldpaths[i]); 1963 free(ldpaths[i]);
1927 1964
1928 if (ldcache != 0) 1965 if (ldcache != 0)
1929 munmap(ldcache, ldcache_size); 1966 munmap(ldcache, ldcache_size);
1978 free(qa_textrels); 2015 free(qa_textrels);
1979 free(qa_execstack); 2016 free(qa_execstack);
1980 free(qa_wx_load); 2017 free(qa_wx_load);
1981} 2018}
1982#endif 2019#endif
1983
1984 2020
1985int main(int argc, char *argv[]) 2021int main(int argc, char *argv[])
1986{ 2022{
1987 int ret; 2023 int ret;
1988 if (argc < 2) 2024 if (argc < 2)
1997 "\t- 1 per QA_TEXTRELS/QA_EXECSTACK/QA_WX_LOAD"); 2033 "\t- 1 per QA_TEXTRELS/QA_EXECSTACK/QA_WX_LOAD");
1998#endif 2034#endif
1999 return ret; 2035 return ret;
2000} 2036}
2001 2037
2002
2003
2004/* utility funcs */
2005static char *xstrdup(const char *s)
2006{
2007 char *ret = strdup(s);
2008 if (!ret) err("Could not strdup(): %s", strerror(errno));
2009 return ret;
2010}
2011static void *xmalloc(size_t size)
2012{
2013 void *ret = malloc(size);
2014 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size);
2015 return ret;
2016}
2017static void *xrealloc(void *ptr, size_t size)
2018{
2019 void *ret = realloc(ptr, size);
2020 if (!ret) err("Could not realloc() %li bytes", (unsigned long)size);
2021 return ret;
2022}
2023static void xstrncat(char **dst, const char *src, size_t *curr_len, size_t n)
2024{
2025 size_t new_len;
2026
2027 new_len = strlen(*dst) + strlen(src);
2028 if (*curr_len <= new_len) {
2029 *curr_len = new_len + (*curr_len / 2);
2030 *dst = realloc(*dst, *curr_len);
2031 if (!*dst)
2032 err("could not realloc() %li bytes", (unsigned long)*curr_len);
2033 }
2034
2035 if (n)
2036 strncat(*dst, src, n);
2037 else
2038 strcat(*dst, src);
2039}
2040static inline void xchrcat(char **dst, const char append, size_t *curr_len)
2041{
2042 static char my_app[2];
2043 my_app[0] = append;
2044 my_app[1] = '\0';
2045 xstrcat(dst, my_app, curr_len);
2046}
2047
2048/* Match filename against entries in matchlist, return TRUE 2038/* Match filename against entries in matchlist, return TRUE
2049 * if the file is listed */ 2039 * if the file is listed */
2050static int file_matches_list(const char *filename, char **matchlist) 2040static int file_matches_list(const char *filename, char **matchlist)
2051{ 2041{
2052 char **file; 2042 char **file;

Legend:
Removed from v.1.185  
changed lines
  Added in v.1.212

  ViewVC Help
Powered by ViewVC 1.1.20