/[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.233 Revision 1.234
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.233 2011/10/03 16:19:18 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.234 2011/10/13 04:49:30 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.233 2011/10/03 16:19:18 vapier Exp $"; 10static const char rcsid[] = "$Id: scanelf.c,v 1.234 2011/10/13 04:49:30 vapier Exp $";
11const char argv0[] = "scanelf"; 11const char 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 == '+')
141 141
142 return ret; 142 return ret;
143} 143}
144 144
145/* sub-funcs for scanelf_fileat() */ 145/* sub-funcs for scanelf_fileat() */
146static void scanelf_file_get_symtabs(elfobj *elf, void **sym, void **tab) 146static void scanelf_file_get_symtabs(elfobj *elf, void **sym, void **str)
147{ 147{
148 /* find the best SHT_DYNSYM and SHT_STRTAB sections */ 148 /* find the best SHT_DYNSYM and SHT_STRTAB sections */
149 149
150 /* debug sections */ 150 /* debug sections */
151 void *symtab = elf_findsecbyname(elf, ".symtab"); 151 void *symtab = elf_findsecbyname(elf, ".symtab");
163 } else \ 163 } else \
164 *sym = symtab ? symtab : dynsym; \ 164 *sym = symtab ? symtab : dynsym; \
165 if (strtab && dynstr) { \ 165 if (strtab && dynstr) { \
166 Elf ## B ## _Shdr *estrtab = strtab; \ 166 Elf ## B ## _Shdr *estrtab = strtab; \
167 Elf ## B ## _Shdr *edynstr = dynstr; \ 167 Elf ## B ## _Shdr *edynstr = dynstr; \
168 *tab = (EGET(estrtab->sh_size) > EGET(edynstr->sh_size)) ? strtab : dynstr; \ 168 *str = (EGET(estrtab->sh_size) > EGET(edynstr->sh_size)) ? strtab : dynstr; \
169 } else \ 169 } else \
170 *tab = strtab ? strtab : dynstr; \ 170 *str = strtab ? strtab : dynstr; \
171 } 171 }
172 GET_SYMTABS(32) 172 GET_SYMTABS(32)
173 GET_SYMTABS(64) 173 GET_SYMTABS(64)
174
175 if (*sym && *str)
176 return;
177
178 /*
179 * damn, they're really going to make us work for it huh?
180 * reconstruct the section header info out of the dynamic
181 * tags so we can see what symbols this guy uses at runtime.
182 */
183#define GET_SYMTABS_DT(B) \
184 if (elf->elf_class == ELFCLASS ## B) { \
185 size_t i; \
186 static Elf ## B ## _Shdr sym_shdr, str_shdr; \
187 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
188 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
189 Elf ## B ## _Addr vsym, vstr, vhash, vgnu_hash; \
190 Elf ## B ## _Dyn *dyn; \
191 Elf ## B ## _Off offset; \
192 \
193 /* lookup symbols used at runtime with DT_SYMTAB / DT_STRTAB */ \
194 vsym = vstr = vhash = vgnu_hash = 0; \
195 memset(&sym_shdr, 0, sizeof(sym_shdr)); \
196 memset(&str_shdr, 0, sizeof(str_shdr)); \
197 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
198 if (EGET(phdr[i].p_type) != PT_DYNAMIC) \
199 continue; \
200 \
201 offset = EGET(phdr[i].p_offset); \
202 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) \
203 continue; \
204 \
205 dyn = DYN ## B (elf->vdata + offset); \
206 while (EGET(dyn->d_tag) != DT_NULL) { \
207 switch (EGET(dyn->d_tag)) { \
208 case DT_SYMTAB: vsym = EGET(dyn->d_un.d_val); break; \
209 case DT_SYMENT: sym_shdr.sh_entsize = dyn->d_un.d_val; break; \
210 case DT_STRTAB: vstr = EGET(dyn->d_un.d_val); break; \
211 case DT_STRSZ: str_shdr.sh_size = dyn->d_un.d_val; break; \
212 case DT_HASH: vhash = EGET(dyn->d_un.d_val); break; \
213 /*case DT_GNU_HASH: vgnu_hash = EGET(dyn->d_un.d_val); break;*/ \
214 } \
215 ++dyn; \
216 } \
217 if (vsym && vstr) \
218 break; \
219 } \
220 if (!vsym || !vstr || !(vhash || vgnu_hash)) \
221 return; \
222 \
223 /* calc offset into the ELF by finding the load addr of the syms */ \
224 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
225 Elf ## B ## _Addr vaddr = EGET(phdr[i].p_vaddr); \
226 Elf ## B ## _Addr filesz = EGET(phdr[i].p_filesz); \
227 offset = EGET(phdr[i].p_offset); \
228 \
229 if (EGET(phdr[i].p_type) != PT_LOAD) \
230 continue; \
231 \
232 if (vhash >= vaddr && vhash < vaddr + filesz) { \
233 /* Scan the hash table to see how many entries we have */ \
234 Elf32_Word max_sym_idx = 0; \
235 Elf32_Word *hashtbl = elf->vdata + offset + (vhash - vaddr); \
236 Elf32_Word b, nbuckets = EGET(hashtbl[0]); \
237 Elf32_Word nchains = EGET(hashtbl[1]); \
238 Elf32_Word *buckets = &hashtbl[2]; \
239 Elf32_Word *chains = &buckets[nbuckets]; \
240 Elf32_Word sym_idx; \
241 \
242 for (b = 0; b < nbuckets; ++b) { \
243 if (!buckets[b]) \
244 continue; \
245 for (sym_idx = buckets[b]; sym_idx < nchains && sym_idx; sym_idx = chains[sym_idx]) \
246 if (max_sym_idx < sym_idx) \
247 max_sym_idx = sym_idx; \
248 } \
249 ESET(sym_shdr.sh_size, sym_shdr.sh_entsize * max_sym_idx); \
250 } \
251 \
252 if (vsym >= vaddr && vsym < vaddr + filesz) { \
253 ESET(sym_shdr.sh_offset, offset + (vsym - vaddr)); \
254 *sym = &sym_shdr; \
255 } \
256 \
257 if (vstr >= vaddr && vstr < vaddr + filesz) { \
258 ESET(str_shdr.sh_offset, offset + (vstr - vaddr)); \
259 *str = &str_shdr; \
260 } \
261 } \
262 }
263 GET_SYMTABS_DT(32)
264 GET_SYMTABS_DT(64)
174} 265}
175 266
176static char *scanelf_file_pax(elfobj *elf, char *found_pax) 267static char *scanelf_file_pax(elfobj *elf, char *found_pax)
177{ 268{
178 static char ret[7]; 269 static char ret[7];
1181 next_sym[-1] = saved; 1272 next_sym[-1] = saved;
1182} 1273}
1183 1274
1184static const char *scanelf_file_sym(elfobj *elf, char *found_sym) 1275static const char *scanelf_file_sym(elfobj *elf, char *found_sym)
1185{ 1276{
1186 unsigned long i;
1187 char *ret; 1277 char *ret;
1188 void *symtab_void, *strtab_void; 1278 void *symtab_void, *strtab_void;
1189 1279
1190 if (!find_sym) return NULL; 1280 if (!find_sym) return NULL;
1191 ret = NULL; 1281 ret = NULL;
1196#define FIND_SYM(B) \ 1286#define FIND_SYM(B) \
1197 if (elf->elf_class == ELFCLASS ## B) { \ 1287 if (elf->elf_class == ELFCLASS ## B) { \
1198 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 1288 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
1199 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 1289 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
1200 Elf ## B ## _Sym *sym = SYM ## B (elf->vdata + EGET(symtab->sh_offset)); \ 1290 Elf ## B ## _Sym *sym = SYM ## B (elf->vdata + EGET(symtab->sh_offset)); \
1201 unsigned long cnt = EGET(symtab->sh_entsize); \ 1291 Elf ## B ## _Word i, cnt = EGET(symtab->sh_entsize); \
1202 char *symname; \ 1292 char *symname; \
1203 size_t ret_len = 0; \ 1293 size_t ret_len = 0; \
1204 if (cnt) \ 1294 if (cnt) \
1205 cnt = EGET(symtab->sh_size) / cnt; \ 1295 cnt = EGET(symtab->sh_size) / cnt; \
1206 for (i = 0; i < cnt; ++i) { \ 1296 for (i = 0; i < cnt; ++i) { \
1223 EGET(sym->st_shndx), \ 1313 EGET(sym->st_shndx), \
1224 /* st_size can be 64bit, but no one is really that big, so screw em */ \ 1314 /* st_size can be 64bit, but no one is really that big, so screw em */ \
1225 EGET(sym->st_size)); \ 1315 EGET(sym->st_size)); \
1226 } \ 1316 } \
1227 ++sym; \ 1317 ++sym; \
1228 } } 1318 } \
1319 }
1229 FIND_SYM(32) 1320 FIND_SYM(32)
1230 FIND_SYM(64) 1321 FIND_SYM(64)
1231 } 1322 }
1232 1323
1233break_out: 1324break_out:

Legend:
Removed from v.1.233  
changed lines
  Added in v.1.234

  ViewVC Help
Powered by ViewVC 1.1.20