/[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.213 Revision 1.214
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/scanelf.c,v 1.213 2009/12/01 10:18:58 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.214 2009/12/01 10:19:42 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.213 2009/12/01 10:18:58 vapier Exp $"; 10static const char *rcsid = "$Id: scanelf.c,v 1.214 2009/12/01 10:19:42 vapier Exp $";
11const char * const argv0 = "scanelf"; 11const char * const argv0 = "scanelf";
12 12
13#include "paxinc.h" 13#include "paxinc.h"
14 14
15#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+') 15#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+')
977 } 977 }
978 978
979 return NULL; 979 return NULL;
980} 980}
981 981
982static int scanelf_match_symname(const char *symname, const char *tomatch) { 982static int scanelf_match_symname(const char *symname, const char *tomatch)
983{
983 /* We do things differently when checking with regexp */ 984 /* We do things differently when checking with regexp */
984 if (g_match) { 985 if (g_match) {
985 return rematch(symname, tomatch, REG_EXTENDED) == 0; 986 return rematch(symname, tomatch, REG_EXTENDED) == 0;
986 } else { 987 } else {
987 const size_t symname_len = strlen(symname); 988 const size_t symname_len = strlen(symname);
996 unsigned long i; 997 unsigned long i;
997 char *ret; 998 char *ret;
998 void *symtab_void, *strtab_void; 999 void *symtab_void, *strtab_void;
999 1000
1000 if (!find_sym) return NULL; 1001 if (!find_sym) return NULL;
1001 ret = find_sym; 1002 ret = NULL;
1002 1003
1003 scanelf_file_get_symtabs(elf, &symtab_void, &strtab_void); 1004 scanelf_file_get_symtabs(elf, &symtab_void, &strtab_void);
1004 1005
1005 if (symtab_void && strtab_void) { 1006 if (symtab_void && strtab_void) {
1006#define FIND_SYM(B) \ 1007#define FIND_SYM(B) \
1008 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 1009 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
1009 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 1010 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
1010 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 1011 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
1011 unsigned long cnt = EGET(symtab->sh_entsize); \ 1012 unsigned long cnt = EGET(symtab->sh_entsize); \
1012 char *symname; \ 1013 char *symname; \
1014 size_t ret_len = 0; \
1013 if (cnt) \ 1015 if (cnt) \
1014 cnt = EGET(symtab->sh_size) / cnt; \ 1016 cnt = EGET(symtab->sh_size) / cnt; \
1015 for (i = 0; i < cnt; ++i) { \ 1017 for (i = 0; i < cnt; ++i) { \
1016 if ((void*)sym > (void*)elf->data_end) { \ 1018 if ((void*)sym > (void*)elf->data_end) { \
1017 warnf("%s: corrupt ELF symbols - aborting", elf->filename); \ 1019 warnf("%s: corrupt ELF symbols - aborting", elf->filename); \
1018 goto break_out; \ 1020 goto break_out; \
1019 } \ 1021 } \
1020 if (sym->st_name) { \ 1022 if (sym->st_name) { \
1023 char *this_sym, *next_sym; \
1024 bool all_syms; \
1021 /* make sure the symbol name is in acceptable memory range */ \ 1025 /* make sure the symbol name is in acceptable memory range */ \
1022 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 1026 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
1023 if ((void*)symname > (void*)elf->data_end) { \ 1027 if ((void*)symname > (void*)elf->data_end) { \
1024 warnf("%s: corrupt ELF symbols", elf->filename); \ 1028 warnf("%s: corrupt ELF symbols", elf->filename); \
1025 ++sym; \ 1029 ++sym; \
1026 continue; \ 1030 continue; \
1027 } \ 1031 } \
1028 /* debug display ... show all symbols and some extra info */ \
1029 if (0 && g_match ? rematch(ret, symname, REG_EXTENDED) == 0 : *ret == '*') { \
1030 printf("%s(%s) %5lX %15s %s %s\n", \
1031 ((*found_sym == 0) ? "\n\t" : "\t"), \
1032 elf->base_filename, \
1033 (unsigned long)sym->st_size, \
1034 get_elfstttype(sym->st_info), \
1035 sym->st_shndx == SHN_UNDEF ? "U" : "D", symname); \
1036 *found_sym = 1; \
1037 } else { \
1038 /* allow the user to specify a comma delimited list of symbols to search for */ \ 1032 /* allow the user to specify a comma delimited list of symbols to search for */ \
1039 char *this_sym, *next_sym; \ 1033 all_syms = false; \
1040 next_sym = ret; \ 1034 next_sym = NULL; \
1035 do { \
1036 bool inc_notype, inc_object, inc_func, inc_file, \
1037 inc_local, inc_global, inc_weak, \
1038 inc_def, inc_undef, inc_abs, inc_common; \
1039 unsigned int stt, stb, shn; \
1040 char saved = saved; /* shut gcc up */ \
1041 while (next_sym) { \ 1041 if (next_sym) { \
1042 next_sym[-1] = saved; \
1042 this_sym = next_sym; \ 1043 this_sym = next_sym; \
1044 } else \
1045 this_sym = find_sym; \
1043 if ((next_sym = strchr(this_sym, ','))) \ 1046 if ((next_sym = strchr(this_sym, ','))) { \
1047 saved = *next_sym; \
1048 *next_sym = '\0'; /* make parsing easier */ \
1044 next_sym += 1; /* Skip the comma */ \ 1049 next_sym += 1; /* Skip the comma */ \
1045 /* do we want a defined symbol ? */ \ 1050 } \
1051 /* symbol selection! */ \
1052 inc_notype = inc_object = inc_func = inc_file = \
1053 inc_local = inc_global = inc_weak = \
1054 inc_def = inc_undef = inc_abs = inc_common = \
1055 (*this_sym != '%'); \
1056 if (!inc_notype) { \
1057 if (this_sym[1] == '%') \
1058 all_syms = true; /* %% hack */ \
1059 while (*(this_sym++)) { \
1046 if (*this_sym == '+') { \ 1060 if (*this_sym == '%') { \
1047 if (sym->st_shndx == SHN_UNDEF) \
1048 continue; \
1049 ++this_sym; \ 1061 ++this_sym; \
1050 /* do we want an undefined symbol ? */ \ 1062 break; \
1051 } else if (*this_sym == '-') { \ 1063 } \
1052 if (sym->st_shndx != SHN_UNDEF) \ 1064 switch (*this_sym) { \
1053 continue; \ 1065 case 'n': inc_notype = true; break; \
1054 ++this_sym; \ 1066 case 'o': inc_object = true; break; \
1067 case 'f': inc_func = true; break; \
1068 case 'F': inc_file = true; break; \
1069 case 'l': inc_local = true; break; \
1070 case 'g': inc_global = true; break; \
1071 case 'w': inc_weak = true; break; \
1072 case 'd': inc_def = true; break; \
1073 case 'u': inc_undef = true; break; \
1074 case 'a': inc_abs = true; break; \
1075 case 'c': inc_common = true; break; \
1076 default: err("invalid symbol selector '%c'", *this_sym); \
1077 } \
1055 } \ 1078 } \
1056 if (next_sym) /* Copy it so that we don't have to worry about the final , */ \ 1079 if (!inc_notype && !inc_object && !inc_func && !inc_file) \
1057 this_sym = xstrndup(this_sym, next_sym-this_sym); \ 1080 inc_notype = inc_object = inc_func = inc_file = true; \
1058 /* ok, lets compare the name now */ \ 1081 if (!inc_local && !inc_global && !inc_weak) \
1082 inc_local = inc_global = inc_weak = true; \
1083 if (!inc_def && !inc_undef && !inc_abs && !inc_common) \
1084 inc_def = inc_undef = inc_abs = inc_common = true; \
1085 } else if (*this_sym == '+') { \
1086 inc_undef = false; \
1087 ++this_sym; \
1088 } else if (*this_sym == '-') { \
1089 inc_def = inc_abs = inc_common = false; \
1090 ++this_sym; \
1091 } \
1092 /* filter symbols */ \
1093 stt = ELF##B##_ST_TYPE(EGET(sym->st_info)); \
1094 stb = ELF##B##_ST_BIND(EGET(sym->st_info)); \
1095 shn = EGET(sym->st_shndx); \
1096 if ((!inc_notype && stt == STT_NOTYPE) || \
1097 (!inc_object && stt == STT_OBJECT) || \
1098 (!inc_func && stt == STT_FUNC ) || \
1099 (!inc_file && stt == STT_FILE ) || \
1100 (!inc_local && stb == STB_LOCAL ) || \
1101 (!inc_global && stb == STB_GLOBAL) || \
1102 (!inc_weak && stb == STB_WEAK ) || \
1103 (!inc_def && shn && shn < SHN_LORESERVE) || \
1104 (!inc_undef && shn == SHN_UNDEF ) || \
1105 (!inc_abs && shn == SHN_ABS ) || \
1106 (!inc_common && shn == SHN_COMMON)) \
1107 continue; \
1108 /* still here !? */ \
1109 if (*this_sym == '*' || !*this_sym) { \
1110 if (*this_sym == '*') \
1111 printf("%s(%s) %5lX %15s %15s %15s %s\n", \
1112 ((*found_sym == 0) ? "\n\t" : "\t"), \
1113 elf->base_filename, \
1114 (unsigned long)EGET(sym->st_size), \
1115 get_elfstttype(stt), \
1116 get_elfstbtype(stb), \
1117 get_elfshntype(shn), \
1118 symname); \
1119 else \
1120 printf("%s%s", ((*found_sym == 0) ? "" : ","), symname); \
1121 *found_sym = 1; \
1122 if (next_sym) next_sym[-1] = saved; \
1123 break; \
1059 if (scanelf_match_symname(this_sym, symname)) { \ 1124 } else if (scanelf_match_symname(this_sym, symname)) { \
1125 *found_sym = 1; \
1060 if (be_semi_verbose) { \ 1126 if (be_semi_verbose) { \
1061 char buf[126]; \ 1127 char buf[1024]; \
1062 snprintf(buf, sizeof(buf), "%lX %s %s", \ 1128 snprintf(buf, sizeof(buf), "%lX %s %s", \
1063 (unsigned long)sym->st_size, get_elfstttype(sym->st_info), this_sym); \ 1129 (unsigned long)EGET(sym->st_size), \
1130 get_elfstttype(stt), \
1131 this_sym); \
1064 ret = buf; \ 1132 ret = xstrdup(buf); \
1065 } else \ 1133 } else { \
1066 ret = symname; \ 1134 if (ret) xchrcat(&ret, ',', &ret_len); \
1067 (*found_sym)++; \ 1135 xstrcat(&ret, symname, &ret_len); \
1136 } \
1137 if (next_sym) next_sym[-1] = saved; \
1138 if (all_syms) \
1139 break; \
1140 else \
1068 goto break_out; \ 1141 goto break_out; \
1069 } \
1070 if (next_sym) free(this_sym); \
1071 } \ 1142 } \
1072 } \ 1143 } while (next_sym); \
1073 } \ 1144 } \
1074 ++sym; \ 1145 ++sym; \
1075 } } 1146 } }
1076 FIND_SYM(32) 1147 FIND_SYM(32)
1077 FIND_SYM(64) 1148 FIND_SYM(64)
1251 case 'I': out = get_elfosabi(elf); break; 1322 case 'I': out = get_elfosabi(elf); break;
1252 case 'Y': out = get_elf_eabi(elf); break; 1323 case 'Y': out = get_elf_eabi(elf); break;
1253 case 'Z': snprintf(ubuf, sizeof(ubuf), "%lu", (unsigned long)elf->len); out = ubuf; break;; 1324 case 'Z': snprintf(ubuf, sizeof(ubuf), "%lu", (unsigned long)elf->len); out = ubuf; break;;
1254 default: warnf("'%c' has no scan code?", out_format[i]); 1325 default: warnf("'%c' has no scan code?", out_format[i]);
1255 } 1326 }
1256 if (out) { 1327 if (out)
1257 /* hack for comma delimited output like `scanelf -s sym1,sym2,sym3` */
1258 if (out_format[i] == 's' && (tmp=strchr(out,',')) != NULL)
1259 xstrncat(&out_buffer, out, &out_len, (tmp-out));
1260 else
1261 xstrcat(&out_buffer, out, &out_len); 1328 xstrcat(&out_buffer, out, &out_len);
1262 }
1263 } 1329 }
1264 1330
1265#define FOUND_SOMETHING() \ 1331#define FOUND_SOMETHING() \
1266 (found_pax || found_phdr || found_relro || found_load || found_textrel || \ 1332 (found_pax || found_phdr || found_relro || found_load || found_textrel || \
1267 found_rpath || found_needed || found_interp || found_bind || \ 1333 found_rpath || found_needed || found_interp || found_bind || \

Legend:
Removed from v.1.213  
changed lines
  Added in v.1.214

  ViewVC Help
Powered by ViewVC 1.1.20