/[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.47 Revision 1.48
1/* 1/*
2 * Copyright 2003 Ned Ludd <solar@gentoo.org> 2 * Copyright 2003 Ned Ludd <solar@gentoo.org>
3 * Copyright 1999-2005 Gentoo Foundation 3 * Copyright 1999-2005 Gentoo Foundation
4 * Distributed under the terms of the GNU General Public License v2 4 * Distributed under the terms of the GNU General Public License v2
5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.47 2005/05/18 01:08:46 vapier Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.48 2005/05/18 02:51:02 vapier Exp $
6 * 6 *
7 ******************************************************************** 7 ********************************************************************
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the 10 * published by the Free Software Foundation; either version 2 of the
33#include <getopt.h> 33#include <getopt.h>
34#include <assert.h> 34#include <assert.h>
35 35
36#include "paxelf.h" 36#include "paxelf.h"
37 37
38static const char *rcsid = "$Id: scanelf.c,v 1.47 2005/05/18 01:08:46 vapier Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.48 2005/05/18 02:51:02 vapier Exp $";
39#define argv0 "scanelf" 39#define argv0 "scanelf"
40 40
41 41
42 42
43/* prototypes */ 43/* prototypes */
52static void xstrcat(char **dst, const char *src, size_t *curr_len); 52static void xstrcat(char **dst, const char *src, size_t *curr_len);
53static inline void xchrcat(char **dst, const char append, size_t *curr_len); 53static inline void xchrcat(char **dst, const char append, size_t *curr_len);
54static int xemptybuffer(const char *buff); 54static int xemptybuffer(const char *buff);
55 55
56/* variables to control behavior */ 56/* variables to control behavior */
57static char *ldpaths[256];
57static char scan_ldpath = 0; 58static char scan_ldpath = 0;
58static char scan_envpath = 0; 59static char scan_envpath = 0;
59static char scan_symlink = 1; 60static char scan_symlink = 1;
60static char dir_recurse = 0; 61static char dir_recurse = 0;
61static char dir_crossmount = 1; 62static char dir_crossmount = 1;
166 else 167 else
167 return " - "; 168 return " - ";
168} 169}
169static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len) 170static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len)
170{ 171{
171 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */ 172 /* TODO: when checking RPATH entries, check each subpath (between :) in ld.so.conf */
172 unsigned long i; 173 unsigned long i, s;
173 char *rpath, *runpath; 174 char *rpath, *runpath, **r;
174 void *strtbl_void; 175 void *strtbl_void;
175 176
176 if (!show_rpath) return; 177 if (!show_rpath) return;
177 178
178 strtbl_void = elf_findsecbyname(elf, ".dynstr"); 179 strtbl_void = elf_findsecbyname(elf, ".dynstr");
184 Elf ## B ## _Dyn *dyn; \ 185 Elf ## B ## _Dyn *dyn; \
185 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 186 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
186 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 187 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
187 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 188 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
188 Elf ## B ## _Off offset; \ 189 Elf ## B ## _Off offset; \
190 Elf ## B ## _Sxword word; \
191 /* Scan all the program headers */ \
189 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 192 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
193 /* Just scan dynamic headers */ \
190 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 194 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
191 offset = EGET(phdr[i].p_offset); \ 195 offset = EGET(phdr[i].p_offset); \
192 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 196 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
197 /* Just scan dynamic RPATH/RUNPATH headers */ \
193 dyn = DYN ## B (elf->data + offset); \ 198 dyn = DYN ## B (elf->data + offset); \
194 while (EGET(dyn->d_tag) != DT_NULL) { \ 199 while ((word=EGET(dyn->d_tag)) != DT_NULL) { \
195 if (EGET(dyn->d_tag) == DT_RPATH) { \ 200 if (word == DT_RPATH) { \
196 if (rpath) warn("ELF has multiple DT_RPATH's !?"); \ 201 r = &rpath; \
202 } else if (word == DT_RUNPATH) { \
203 r = &runpath; \
204 } else { \
205 ++dyn; \
206 continue; \
207 } \
208 /* Verify the memory is somewhat sane */ \
197 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 209 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
198 if (offset >= elf->len) continue; \ 210 if (offset < elf->len) { \
211 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \
199 rpath = (char*)(elf->data + offset); \ 212 *r = (char*)(elf->data + offset); \
213 /* If quiet, don't output paths in ld.so.conf */ \
214 if (be_quiet) \
215 for (s = 0; ldpaths[s]; ++s) \
216 if (!strcmp(ldpaths[s], *r)) { \
217 *r = NULL; \
218 break; \
219 } \
200 *found_rpath = 1; \ 220 if (*r) *found_rpath = 1; \
201 } else if (EGET(dyn->d_tag) == DT_RUNPATH) { \
202 if (runpath) warn("ELF has multiple DT_RUNPATH's !?"); \
203 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
204 if (offset >= elf->len) continue; \
205 runpath = (char*)(elf->data + offset); \
206 *found_rpath = 1; \
207 } \ 221 } \
208 ++dyn; \ 222 ++dyn; \
209 } \ 223 } \
210 } } 224 } }
211 SHOW_RPATH(32) 225 SHOW_RPATH(32)
511 if (fp != stdin) 525 if (fp != stdin)
512 fclose(fp); 526 fclose(fp);
513 return 0; 527 return 0;
514} 528}
515 529
530static void load_ld_so_conf()
531{
532 FILE *fp = NULL;
533 char *p;
534 char path[_POSIX_PATH_MAX];
535 int i = 0;
536
537 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
538 return;
539
540 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) {
541 if (*path != '/')
542 continue;
543
544 if ((p = strrchr(path, '\r')) != NULL)
545 *p = 0;
546 if ((p = strchr(path, '\n')) != NULL)
547 *p = 0;
548
549 ldpaths[i++] = xstrdup(path);
550
551 if (i + 1 == sizeof(ldpaths) / sizeof(*ldpaths))
552 break;
553 }
554 ldpaths[i] = NULL;
555
556 fclose(fp);
557}
558
516/* scan /etc/ld.so.conf for paths */ 559/* scan /etc/ld.so.conf for paths */
517static void scanelf_ldpath() 560static void scanelf_ldpath()
518{ 561{
519 char scan_l, scan_ul, scan_ull; 562 char scan_l, scan_ul, scan_ull;
520 char *path, *p; 563 int i = 0;
521 FILE *fp;
522 564
523 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 565 if (!ldpaths[0])
524 err("Unable to open ld.so.conf: %s", strerror(errno)); 566 err("Unable to load any paths from ld.so.conf");
525 567
526 scan_l = scan_ul = scan_ull = 0; 568 scan_l = scan_ul = scan_ull = 0;
527 569
528 path = (char*)xmalloc(_POSIX_PATH_MAX); 570 while (ldpaths[i]) {
529 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
530 if (*path == '/') {
531 if ((p = strrchr(path, '\r')) != NULL)
532 *p = 0;
533 if ((p = strrchr(path, '\n')) != NULL)
534 *p = 0;
535 if (!scan_l && !strcmp(path, "/lib")) scan_l = 1; 571 if (!scan_l && !strcmp(ldpaths[i], "/lib")) scan_l = 1;
536 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1; 572 if (!scan_ul && !strcmp(ldpaths[i], "/usr/lib")) scan_ul = 1;
537 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1; 573 if (!scan_ull && !strcmp(ldpaths[i], "/usr/local/lib")) scan_ull = 1;
538 scanelf_dir(path); 574 scanelf_dir(ldpaths[i]);
575 ++i;
539 } 576 }
540 free(path);
541 fclose(fp);
542 577
543 if (!scan_l) scanelf_dir("/lib"); 578 if (!scan_l) scanelf_dir("/lib");
544 if (!scan_ul) scanelf_dir("/usr/lib"); 579 if (!scan_ul) scanelf_dir("/usr/lib");
545 if (!scan_ull) scanelf_dir("/usr/local/lib"); 580 if (!scan_ull) scanelf_dir("/usr/local/lib");
546} 581}
644} 679}
645 680
646/* parse command line arguments and preform needed actions */ 681/* parse command line arguments and preform needed actions */
647static void parseargs(int argc, char *argv[]) 682static void parseargs(int argc, char *argv[])
648{ 683{
649 int flag; 684 int i;
650 char *from_file = NULL; 685 char *from_file = NULL;
651 686
652 opterr = 0; 687 opterr = 0;
653 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) { 688 while ((i=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
654 switch (flag) { 689 switch (i) {
655 690
656 case 'V': 691 case 'V':
657 printf("%s compiled %s\n%s\n" 692 printf("%s compiled %s\n%s\n"
658 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n", 693 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n",
659 __FILE__, __DATE__, rcsid, argv0); 694 __FILE__, __DATE__, rcsid, argv0);
710 case '?': 745 case '?':
711 warn("Unknown option\n"); 746 warn("Unknown option\n");
712 usage(EXIT_FAILURE); 747 usage(EXIT_FAILURE);
713 break; 748 break;
714 default: 749 default:
715 err("Unhandled option '%c'", flag); 750 err("Unhandled option '%c'", i);
716 break; 751 break;
717 } 752 }
718 } 753 }
719 754
720 if (be_quiet && be_verbose) 755 if (be_quiet && be_verbose)
721 err("You can be quiet or you can be verbose, not both, stupid"); 756 err("You can be quiet or you can be verbose, not both, stupid");
722 757
723 /* let the format option override all other options */ 758 /* let the format option override all other options */
724 if (out_format) { 759 if (out_format) {
725 show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 0; 760 show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 0;
726 for (flag=0; out_format[flag]; ++flag) { 761 for (i = 0; out_format[i]; ++i) {
727 if (out_format[flag] != '%') continue; 762 if (out_format[i] != '%') continue;
728 763
729 switch (out_format[++flag]) { 764 switch (out_format[++i]) {
730 case '%': break; 765 case '%': break;
731 case 'F': break; 766 case 'F': break;
732 case 's': break; 767 case 's': break;
733 case 'o': break; 768 case 'o': break;
734 case 'x': show_pax = 1; break; 769 case 'x': show_pax = 1; break;
737 case 'r': show_rpath = 1; break; 772 case 'r': show_rpath = 1; break;
738 case 'n': show_needed = 1; break; 773 case 'n': show_needed = 1; break;
739 case 'i': show_interp = 1; break; 774 case 'i': show_interp = 1; break;
740 default: 775 default:
741 err("Invalid format specifier '%c' (byte %i)", 776 err("Invalid format specifier '%c' (byte %i)",
742 out_format[flag], flag+1); 777 out_format[i], i+1);
743 } 778 }
744 } 779 }
745 780
746 /* construct our default format */ 781 /* construct our default format */
747 } else { 782 } else {
758 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len); 793 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
759 } 794 }
760 if (be_verbose > 2) printf("Format: %s\n", out_format); 795 if (be_verbose > 2) printf("Format: %s\n", out_format);
761 796
762 /* now lets actually do the scanning */ 797 /* now lets actually do the scanning */
798 if (scan_ldpath || (show_rpath && be_quiet))
799 load_ld_so_conf();
763 if (scan_ldpath) scanelf_ldpath(); 800 if (scan_ldpath) scanelf_ldpath();
764 if (scan_envpath) scanelf_envpath(); 801 if (scan_envpath) scanelf_envpath();
765 if (from_file) { 802 if (from_file) {
766 scanelf_from_file(from_file); 803 scanelf_from_file(from_file);
767 free(from_file); 804 free(from_file);
776 if (find_sym) { 813 if (find_sym) {
777 free(find_sym); 814 free(find_sym);
778 free(versioned_symname); 815 free(versioned_symname);
779 } 816 }
780 if (out_format) free(out_format); 817 if (out_format) free(out_format);
818 for (i = 0; ldpaths[i]; ++i)
819 free(ldpaths[i]);
781} 820}
782 821
783 822
784 823
785/* utility funcs */ 824/* utility funcs */

Legend:
Removed from v.1.47  
changed lines
  Added in v.1.48

  ViewVC Help
Powered by ViewVC 1.1.20