/[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.91 Revision 1.98
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.91 2005/12/07 01:04:52 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.98 2006/01/05 03:12:07 vapier 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#define __USE_GNU
16#include <string.h>
17#include <errno.h>
18#include <unistd.h>
19#include <sys/stat.h>
20#include <dirent.h>
21#include <getopt.h>
22#include <assert.h>
23#include "paxinc.h" 10#include "paxinc.h"
24 11
25static const char *rcsid = "$Id: scanelf.c,v 1.91 2005/12/07 01:04:52 vapier Exp $"; 12static const char *rcsid = "$Id: scanelf.c,v 1.98 2006/01/05 03:12:07 vapier Exp $";
26#define argv0 "scanelf" 13#define argv0 "scanelf"
27 14
28#define IS_MODIFIER(c) (c == '%' || c == '#') 15#define IS_MODIFIER(c) (c == '%' || c == '#')
29 16
30 17
36static void scanelf_envpath(); 23static void scanelf_envpath();
37static void usage(int status); 24static void usage(int status);
38static void parseargs(int argc, char *argv[]); 25static void parseargs(int argc, char *argv[]);
39static char *xstrdup(const char *s); 26static char *xstrdup(const char *s);
40static void *xmalloc(size_t size); 27static void *xmalloc(size_t size);
41static void xstrcat(char **dst, const char *src, size_t *curr_len); 28static void xstrncat(char **dst, const char *src, size_t *curr_len, size_t n);
29#define xstrcat(dst,src,curr_len) xstrncat(dst,src,curr_len,0)
42static inline void xchrcat(char **dst, const char append, size_t *curr_len); 30static inline void xchrcat(char **dst, const char append, size_t *curr_len);
43 31
44/* variables to control behavior */ 32/* variables to control behavior */
45static char *ldpaths[256]; 33static char *ldpaths[256];
46static char scan_ldpath = 0; 34static char scan_ldpath = 0;
64static char *find_sym = NULL, *versioned_symname = NULL; 52static char *find_sym = NULL, *versioned_symname = NULL;
65static char *find_lib = NULL; 53static char *find_lib = NULL;
66static char *out_format = NULL; 54static char *out_format = NULL;
67static char *search_path = NULL; 55static char *search_path = NULL;
68static char gmatch = 0; 56static char gmatch = 0;
57static char printcache = 0;
69 58
59
60caddr_t ldcache = 0;
61size_t ldcache_size = 0;
70 62
71/* sub-funcs for scanelf_file() */ 63/* sub-funcs for scanelf_file() */
72static void scanelf_file_get_symtabs(elfobj *elf, void **sym, void **tab) 64static void scanelf_file_get_symtabs(elfobj *elf, void **sym, void **tab)
73{ 65{
74 /* find the best SHT_DYNSYM and SHT_STRTAB sections */ 66 /* find the best SHT_DYNSYM and SHT_STRTAB sections */
477 } else if (rpath || runpath) 469 } else if (rpath || runpath)
478 xstrcat(ret, (runpath ? runpath : rpath), ret_len); 470 xstrcat(ret, (runpath ? runpath : rpath), ret_len);
479 else if (!be_quiet) 471 else if (!be_quiet)
480 xstrcat(ret, " - ", ret_len); 472 xstrcat(ret, " - ", ret_len);
481} 473}
474
475#define LDSO_CACHE_MAGIC "ld.so-"
476#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1)
477#define LDSO_CACHE_VER "1.7.0"
478#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1)
479#define FLAG_ANY -1
480#define FLAG_TYPE_MASK 0x00ff
481#define FLAG_LIBC4 0x0000
482#define FLAG_ELF 0x0001
483#define FLAG_ELF_LIBC5 0x0002
484#define FLAG_ELF_LIBC6 0x0003
485#define FLAG_REQUIRED_MASK 0xff00
486#define FLAG_SPARC_LIB64 0x0100
487#define FLAG_IA64_LIB64 0x0200
488#define FLAG_X8664_LIB64 0x0300
489#define FLAG_S390_LIB64 0x0400
490#define FLAG_POWERPC_LIB64 0x0500
491#define FLAG_MIPS64_LIBN32 0x0600
492#define FLAG_MIPS64_LIBN64 0x0700
493
494static char *lookup_cache_lib(elfobj *, char *);
495static char *lookup_cache_lib(elfobj *elf, char *fname)
496{
497 int fd = 0;
498 char *strs;
499 static char buf[_POSIX_PATH_MAX] = "";
500 const char *cachefile = "/etc/ld.so.cache";
501 struct stat st;
502
503 typedef struct {
504 char magic[LDSO_CACHE_MAGIC_LEN];
505 char version[LDSO_CACHE_VER_LEN];
506 int nlibs;
507 } header_t;
508 header_t *header;
509
510 typedef struct {
511 int flags;
512 int sooffset;
513 int liboffset;
514 } libentry_t;
515 libentry_t *libent;
516
517 if (fname == NULL)
518 return NULL;
519
520 if (ldcache == 0) {
521 if (stat(cachefile, &st) || (fd = open(cachefile, O_RDONLY)) == -1)
522 return NULL;
523
524 /* cache these values so we only map/unmap the cache file once */
525 ldcache_size = st.st_size;
526 ldcache = mmap(0, ldcache_size, PROT_READ, MAP_SHARED, fd, 0);
527
528 close(fd);
529
530 if (ldcache == (caddr_t)-1)
531 return NULL;
532
533 if (memcmp(((header_t *) ldcache)->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN))
534 return NULL;
535 if (memcmp (((header_t *) ldcache)->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN))
536 return NULL;
537 }
538
539 header = (header_t *) ldcache;
540 libent = (libentry_t *) (ldcache + sizeof(header_t));
541 strs = (char *) &libent[header->nlibs];
542
543 for (fd = 0; fd < header->nlibs; fd++) {
544 /* this should be more fine grained, but for now we assume that
545 * diff arches will not be cached together. and we ignore the
546 * the different multilib mips cases. */
547 if (elf->elf_class == ELFCLASS64 && !(libent[fd].flags & FLAG_REQUIRED_MASK))
548 continue;
549 if (elf->elf_class == ELFCLASS32 && (libent[fd].flags & FLAG_REQUIRED_MASK))
550 continue;
551
552 if (strcmp(fname, strs + libent[fd].sooffset) != 0)
553 continue;
554 strncpy(buf, strs + libent[fd].liboffset, sizeof(buf));
555 }
556 return buf;
557}
558
559
482static const char *scanelf_file_needed_lib(elfobj *elf, char *found_needed, char *found_lib, int op, char **ret, size_t *ret_len) 560static const char *scanelf_file_needed_lib(elfobj *elf, char *found_needed, char *found_lib, int op, char **ret, size_t *ret_len)
483{ 561{
484 unsigned long i; 562 unsigned long i;
485 char *needed; 563 char *needed;
486 void *strtbl_void; 564 void *strtbl_void;
565 char *p;
487 566
488 if ((op==0 && !show_needed) || (op==1 && !find_lib)) return NULL; 567 if ((op==0 && !show_needed) || (op==1 && !find_lib)) return NULL;
489 568
490 strtbl_void = elf_findsecbyname(elf, ".dynstr"); 569 strtbl_void = elf_findsecbyname(elf, ".dynstr");
491 570
511 } \ 590 } \
512 needed = (char*)(elf->data + offset); \ 591 needed = (char*)(elf->data + offset); \
513 if (op == 0) { \ 592 if (op == 0) { \
514 if (!be_wewy_wewy_quiet) { \ 593 if (!be_wewy_wewy_quiet) { \
515 if (*found_needed) xchrcat(ret, ',', ret_len); \ 594 if (*found_needed) xchrcat(ret, ',', ret_len); \
595 if (printcache) \
596 if ((p = lookup_cache_lib(elf, needed)) != NULL) \
597 needed = p; \
516 xstrcat(ret, needed, ret_len); \ 598 xstrcat(ret, needed, ret_len); \
517 } \ 599 } \
518 *found_needed = 1; \ 600 *found_needed = 1; \
519 } else { \ 601 } else { \
520 if (!strncmp(find_lib, needed, strlen( !gmatch ? needed : find_lib))) { \ 602 if (!strncmp(find_lib, needed, strlen( !gmatch ? needed : find_lib))) { \
644 return NULL; 726 return NULL;
645} 727}
646static char *scanelf_file_sym(elfobj *elf, char *found_sym) 728static char *scanelf_file_sym(elfobj *elf, char *found_sym)
647{ 729{
648 unsigned long i; 730 unsigned long i;
731 char *ret;
649 void *symtab_void, *strtab_void; 732 void *symtab_void, *strtab_void;
650 733
651 if (!find_sym) return NULL; 734 if (!find_sym) return NULL;
735 ret = find_sym;
652 736
653 scanelf_file_get_symtabs(elf, &symtab_void, &strtab_void); 737 scanelf_file_get_symtabs(elf, &symtab_void, &strtab_void);
654 738
655 if (symtab_void && strtab_void) { 739 if (symtab_void && strtab_void) {
656#define FIND_SYM(B) \ 740#define FIND_SYM(B) \
665 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 749 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
666 if (*find_sym == '*') { \ 750 if (*find_sym == '*') { \
667 printf("%s(%s) %5lX %15s %s\n", \ 751 printf("%s(%s) %5lX %15s %s\n", \
668 ((*found_sym == 0) ? "\n\t" : "\t"), \ 752 ((*found_sym == 0) ? "\n\t" : "\t"), \
669 elf->base_filename, \ 753 elf->base_filename, \
670 (long)sym->st_size, \ 754 (unsigned long)sym->st_size, \
671 (char *)get_elfstttype(sym->st_info), \ 755 get_elfstttype(sym->st_info), \
672 symname); \ 756 symname); \
673 *found_sym = 1; \ 757 *found_sym = 1; \
674 } else if ((strcmp(find_sym, symname) == 0) || \ 758 } else { \
759 char *this_sym, *next_sym; \
760 this_sym = find_sym; \
761 do { \
762 next_sym = strchr(this_sym, ','); \
763 if (next_sym == NULL) \
764 next_sym = this_sym + strlen(this_sym); \
765 if ((strncmp(this_sym, symname, (next_sym-this_sym)) == 0 && symname[next_sym-this_sym] == '\0') || \
675 (strcmp(symname, versioned_symname) == 0)) \ 766 (strcmp(symname, versioned_symname) == 0)) { \
767 ret = this_sym; \
676 (*found_sym)++; \ 768 (*found_sym)++; \
769 goto break_out; \
770 } \
771 this_sym = next_sym + 1; \
772 } while (*next_sym != '\0'); \
773 } \
677 } \ 774 } \
678 ++sym; \ 775 ++sym; \
679 } } 776 } }
680 FIND_SYM(32) 777 FIND_SYM(32)
681 FIND_SYM(64) 778 FIND_SYM(64)
682 } 779 }
683 780
781break_out:
684 if (be_wewy_wewy_quiet) return NULL; 782 if (be_wewy_wewy_quiet) return NULL;
685 783
686 if (*find_sym != '*' && *found_sym) 784 if (*find_sym != '*' && *found_sym)
687 return find_sym; 785 return ret;
688 if (be_quiet) 786 if (be_quiet)
689 return NULL; 787 return NULL;
690 else 788 else
691 return (char *)" - "; 789 return (char *)" - ";
692} 790}
832 case 'b': out = scanelf_file_bind(elf, &found_bind); break; 930 case 'b': out = scanelf_file_bind(elf, &found_bind); break;
833 case 'S': out = scanelf_file_soname(elf, &found_soname); break; 931 case 'S': out = scanelf_file_soname(elf, &found_soname); break;
834 case 's': out = scanelf_file_sym(elf, &found_sym); break; 932 case 's': out = scanelf_file_sym(elf, &found_sym); break;
835 default: warnf("'%c' has no scan code?", out_format[i]); 933 default: warnf("'%c' has no scan code?", out_format[i]);
836 } 934 }
935 if (out) {
936 /* hack for comma delimited output like `scanelf -s sym1,sym2,sym3` */
937 if (out_format[i] == 's' && (tmp=strchr(out,',')) != NULL)
938 xstrncat(&out_buffer, out, &out_len, (tmp-out));
939 else
837 if (out) xstrcat(&out_buffer, out, &out_len); 940 xstrcat(&out_buffer, out, &out_len);
941 }
838 } 942 }
839 943
840#define FOUND_SOMETHING() \ 944#define FOUND_SOMETHING() \
841 (found_pax || found_phdr || found_relro || found_load || found_textrel || \ 945 (found_pax || found_phdr || found_relro || found_load || found_textrel || \
842 found_rpath || found_needed || found_interp || found_bind || \ 946 found_rpath || found_needed || found_interp || found_bind || \
997 1101
998 free(path); 1102 free(path);
999} 1103}
1000 1104
1001 1105
1002
1003/* usage / invocation handling functions */ 1106/* usage / invocation handling functions */
1004#define PARSE_FLAGS "plRmyxetrnibSs:gN:TaqvF:f:o:BhV" 1107#define PARSE_FLAGS "plRmyxetrnLibSs:gN:TaqvF:f:o:BhV"
1005#define a_argument required_argument 1108#define a_argument required_argument
1006static struct option const long_opts[] = { 1109static struct option const long_opts[] = {
1007 {"path", no_argument, NULL, 'p'}, 1110 {"path", no_argument, NULL, 'p'},
1008 {"ldpath", no_argument, NULL, 'l'}, 1111 {"ldpath", no_argument, NULL, 'l'},
1009 {"recursive", no_argument, NULL, 'R'}, 1112 {"recursive", no_argument, NULL, 'R'},
1012 {"pax", no_argument, NULL, 'x'}, 1115 {"pax", no_argument, NULL, 'x'},
1013 {"header", no_argument, NULL, 'e'}, 1116 {"header", no_argument, NULL, 'e'},
1014 {"textrel", no_argument, NULL, 't'}, 1117 {"textrel", no_argument, NULL, 't'},
1015 {"rpath", no_argument, NULL, 'r'}, 1118 {"rpath", no_argument, NULL, 'r'},
1016 {"needed", no_argument, NULL, 'n'}, 1119 {"needed", no_argument, NULL, 'n'},
1120 {"ldcache", no_argument, NULL, 'L'},
1017 {"interp", no_argument, NULL, 'i'}, 1121 {"interp", no_argument, NULL, 'i'},
1018 {"bind", no_argument, NULL, 'b'}, 1122 {"bind", no_argument, NULL, 'b'},
1019 {"soname", no_argument, NULL, 'S'}, 1123 {"soname", no_argument, NULL, 'S'},
1020 {"symbol", a_argument, NULL, 's'}, 1124 {"symbol", a_argument, NULL, 's'},
1021 {"lib", a_argument, NULL, 'N'}, 1125 {"lib", a_argument, NULL, 'N'},
1042 "Print PaX markings", 1146 "Print PaX markings",
1043 "Print GNU_STACK/PT_LOAD markings", 1147 "Print GNU_STACK/PT_LOAD markings",
1044 "Print TEXTREL information", 1148 "Print TEXTREL information",
1045 "Print RPATH information", 1149 "Print RPATH information",
1046 "Print NEEDED information", 1150 "Print NEEDED information",
1151 "Resolve NEEDED information (use with -n)",
1047 "Print INTERP information", 1152 "Print INTERP information",
1048 "Print BIND information", 1153 "Print BIND information",
1049 "Print SONAME information", 1154 "Print SONAME information",
1050 "Find a specified symbol", 1155 "Find a specified symbol",
1051 "Find a specified library", 1156 "Find a specified library",
1122 SET_STDOUT(fp); 1227 SET_STDOUT(fp);
1123 break; 1228 break;
1124 } 1229 }
1125 1230
1126 case 's': { 1231 case 's': {
1127 size_t len;
1128 if (find_sym) err("Don't specify -s twice"); 1232 if (find_sym) warn("You prob don't want to specify -s twice");
1129 find_sym = xstrdup(optarg); 1233 find_sym = optarg;
1130 len = strlen(find_sym) + 1;
1131 versioned_symname = (char*)xmalloc(sizeof(char) * (len+1)); 1234 versioned_symname = (char*)xmalloc(sizeof(char) * (strlen(find_sym)+1+1));
1132 sprintf(versioned_symname, "%s@", find_sym); 1235 sprintf(versioned_symname, "%s@", find_sym);
1133 break; 1236 break;
1134 } 1237 }
1135 case 'N': { 1238 case 'N': {
1136 if (find_lib) err("Don't specify -N twice"); 1239 if (find_lib) warn("You prob don't want to specify -N twice");
1137 find_lib = xstrdup(optarg); 1240 find_lib = optarg;
1138 break; 1241 break;
1139 } 1242 }
1140 1243
1141 case 'F': { 1244 case 'F': {
1142 if (out_format) err("Don't specify -F twice"); 1245 if (out_format) warn("You prob don't want to specify -F twice");
1143 out_format = xstrdup(optarg); 1246 out_format = optarg;
1144 break; 1247 break;
1145 } 1248 }
1146 1249
1147 case 'g': gmatch = 1; 1250 case 'g': gmatch = 1; /* break; any reason we dont breal; here ? */
1251 case 'L': printcache = 1; break;
1148 case 'y': scan_symlink = 0; break; 1252 case 'y': scan_symlink = 0; break;
1149 case 'B': show_banner = 0; break; 1253 case 'B': show_banner = 0; break;
1150 case 'l': scan_ldpath = 1; break; 1254 case 'l': scan_ldpath = 1; break;
1151 case 'p': scan_envpath = 1; break; 1255 case 'p': scan_envpath = 1; break;
1152 case 'R': dir_recurse = 1; break; 1256 case 'R': dir_recurse = 1; break;
1241 search_path = argv[optind++]; 1345 search_path = argv[optind++];
1242 scanelf_dir(search_path); 1346 scanelf_dir(search_path);
1243 } 1347 }
1244 1348
1245 /* clean up */ 1349 /* clean up */
1246 if (find_sym) { 1350 if (versioned_symname) free(versioned_symname);
1247 free(find_sym);
1248 free(versioned_symname);
1249 }
1250 if (find_lib) free(find_lib);
1251 if (out_format) free(out_format);
1252 for (i = 0; ldpaths[i]; ++i) 1351 for (i = 0; ldpaths[i]; ++i)
1253 free(ldpaths[i]); 1352 free(ldpaths[i]);
1353
1354 if (ldcache != 0)
1355 munmap(ldcache, ldcache_size);
1254} 1356}
1255 1357
1256 1358
1257 1359
1258/* utility funcs */ 1360/* utility funcs */
1260{ 1362{
1261 char *ret = strdup(s); 1363 char *ret = strdup(s);
1262 if (!ret) err("Could not strdup(): %s", strerror(errno)); 1364 if (!ret) err("Could not strdup(): %s", strerror(errno));
1263 return ret; 1365 return ret;
1264} 1366}
1265
1266static void *xmalloc(size_t size) 1367static void *xmalloc(size_t size)
1267{ 1368{
1268 void *ret = malloc(size); 1369 void *ret = malloc(size);
1269 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size); 1370 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size);
1270 return ret; 1371 return ret;
1271} 1372}
1272
1273static void xstrcat(char **dst, const char *src, size_t *curr_len) 1373static void xstrncat(char **dst, const char *src, size_t *curr_len, size_t n)
1274{ 1374{
1275 size_t new_len; 1375 size_t new_len;
1276 1376
1277 new_len = strlen(*dst) + strlen(src); 1377 new_len = strlen(*dst) + strlen(src);
1278 if (*curr_len <= new_len) { 1378 if (*curr_len <= new_len) {
1279 *curr_len = new_len + (*curr_len / 2); 1379 *curr_len = new_len + (*curr_len / 2);
1280 *dst = realloc(*dst, *curr_len); 1380 *dst = realloc(*dst, *curr_len);
1281 if (!*dst) 1381 if (!*dst)
1282 err("could not realloc %li bytes", (unsigned long)*curr_len); 1382 err("could not realloc() %li bytes", (unsigned long)*curr_len);
1283 } 1383 }
1284 1384
1385 if (n)
1386 strncat(*dst, src, n);
1387 else
1285 strcat(*dst, src); 1388 strcat(*dst, src);
1286} 1389}
1287
1288static inline void xchrcat(char **dst, const char append, size_t *curr_len) 1390static inline void xchrcat(char **dst, const char append, size_t *curr_len)
1289{ 1391{
1290 static char my_app[2]; 1392 static char my_app[2];
1291 my_app[0] = append; 1393 my_app[0] = append;
1292 my_app[1] = '\0'; 1394 my_app[1] = '\0';

Legend:
Removed from v.1.91  
changed lines
  Added in v.1.98

  ViewVC Help
Powered by ViewVC 1.1.20