/[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.75 Revision 1.91
1/* 1/*
2 * Copyright 2003-2005 Gentoo Foundation 2 * Copyright 2003-2005 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.75 2005/06/06 23:32:38 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.91 2005/12/07 01:04:52 vapier Exp $
5 * 5 *
6 ******************************************************************** 6 * Copyright 2003-2005 Ned Ludd - <solar@gentoo.org>
7 * This program is free software; you can redistribute it and/or 7 * Copyright 2004-2005 Mike Frysinger - <vapier@gentoo.org>
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 * MA 02111-1307, USA.
21 */ 8 */
22 9
23#include <stdio.h> 10#include <stdio.h>
24#include <stdlib.h> 11#include <stdlib.h>
25#include <sys/types.h> 12#include <sys/types.h>
31#include <unistd.h> 18#include <unistd.h>
32#include <sys/stat.h> 19#include <sys/stat.h>
33#include <dirent.h> 20#include <dirent.h>
34#include <getopt.h> 21#include <getopt.h>
35#include <assert.h> 22#include <assert.h>
36#include "paxelf.h" 23#include "paxinc.h"
37 24
38static const char *rcsid = "$Id: scanelf.c,v 1.75 2005/06/06 23:32:38 vapier Exp $"; 25static const char *rcsid = "$Id: scanelf.c,v 1.91 2005/12/07 01:04:52 vapier Exp $";
39#define argv0 "scanelf" 26#define argv0 "scanelf"
40 27
41#define IS_MODIFIER(c) (c == '%' || c == '#') 28#define IS_MODIFIER(c) (c == '%' || c == '#')
42 29
43 30
66static char show_textrel = 0; 53static char show_textrel = 0;
67static char show_rpath = 0; 54static char show_rpath = 0;
68static char show_needed = 0; 55static char show_needed = 0;
69static char show_interp = 0; 56static char show_interp = 0;
70static char show_bind = 0; 57static char show_bind = 0;
58static char show_soname = 0;
59static char show_textrels = 0;
71static char show_banner = 1; 60static char show_banner = 1;
72static char be_quiet = 0; 61static char be_quiet = 0;
73static char be_verbose = 0; 62static char be_verbose = 0;
74static char be_wewy_wewy_quiet = 0; 63static char be_wewy_wewy_quiet = 0;
75static char *find_sym = NULL, *versioned_symname = NULL; 64static char *find_sym = NULL, *versioned_symname = NULL;
76static char *find_lib = NULL; 65static char *find_lib = NULL;
77static char *out_format = NULL; 66static char *out_format = NULL;
78static char *search_path = NULL; 67static char *search_path = NULL;
79 68static char gmatch = 0;
80 69
81 70
82/* sub-funcs for scanelf_file() */ 71/* sub-funcs for scanelf_file() */
72static void scanelf_file_get_symtabs(elfobj *elf, void **sym, void **tab)
73{
74 /* find the best SHT_DYNSYM and SHT_STRTAB sections */
75#define GET_SYMTABS(B) \
76 if (elf->elf_class == ELFCLASS ## B) { \
77 Elf ## B ## _Shdr *symtab, *strtab, *dynsym, *dynstr; \
78 /* debug sections */ \
79 symtab = SHDR ## B (elf_findsecbyname(elf, ".symtab")); \
80 strtab = SHDR ## B (elf_findsecbyname(elf, ".strtab")); \
81 /* runtime sections */ \
82 dynsym = SHDR ## B (elf_findsecbyname(elf, ".dynsym")); \
83 dynstr = SHDR ## B (elf_findsecbyname(elf, ".dynstr")); \
84 if (symtab && dynsym) { \
85 *sym = (void*)((EGET(symtab->sh_size) > EGET(dynsym->sh_size)) ? symtab : dynsym); \
86 } else { \
87 *sym = (void*)(symtab ? symtab : dynsym); \
88 } \
89 if (strtab && dynstr) { \
90 *tab = (void*)((EGET(strtab->sh_size) > EGET(dynstr->sh_size)) ? strtab : dynstr); \
91 } else { \
92 *tab = (void*)(strtab ? strtab : dynstr); \
93 } \
94 }
95 GET_SYMTABS(32)
96 GET_SYMTABS(64)
97}
83static char *scanelf_file_pax(elfobj *elf, char *found_pax) 98static char *scanelf_file_pax(elfobj *elf, char *found_pax)
84{ 99{
85 static char *paxflags;
86 static char ret[7]; 100 static char ret[7];
87 unsigned long i, shown; 101 unsigned long i, shown;
88
89 102
90 if (!show_pax) return NULL; 103 if (!show_pax) return NULL;
91 104
92 shown = 0; 105 shown = 0;
93 memset(&ret, 0, sizeof(ret)); 106 memset(&ret, 0, sizeof(ret));
112 SHOW_PAX(64) 125 SHOW_PAX(64)
113 } 126 }
114 127
115 /* fall back to EI_PAX if no PT_PAX was found */ 128 /* fall back to EI_PAX if no PT_PAX was found */
116 if (!*ret) { 129 if (!*ret) {
130 static char *paxflags;
117 paxflags = pax_short_hf_flags(EI_PAX_FLAGS(elf)); 131 paxflags = pax_short_hf_flags(EI_PAX_FLAGS(elf));
118 if (!be_quiet || (be_quiet && EI_PAX_FLAGS(elf))) { 132 if (!be_quiet || (be_quiet && EI_PAX_FLAGS(elf))) {
119 *found_pax = 1; 133 *found_pax = 1;
120 return paxflags; 134 return (be_wewy_wewy_quiet ? NULL : paxflags);
121 } 135 }
122 strncpy(ret, paxflags, sizeof(ret)); 136 strncpy(ret, paxflags, sizeof(ret));
123 // ++shown;
124 } 137 }
125 138
126 if (be_quiet && !shown) 139 if (be_wewy_wewy_quiet || (be_quiet && !shown))
127 return NULL; 140 return NULL;
141 else
128 return ret; 142 return ret;
129
130} 143}
144
131static char *scanelf_file_phdr(elfobj *elf, char *found_phdr, char *found_relro, char *found_load) 145static char *scanelf_file_phdr(elfobj *elf, char *found_phdr, char *found_relro, char *found_load)
132{ 146{
133 static char ret[12]; 147 static char ret[12];
134 char *found; 148 char *found;
135 unsigned long i, off, shown, check_flags; 149 unsigned long i, shown;
136 unsigned char multi_stack, multi_relro, multi_load; 150 unsigned char multi_stack, multi_relro, multi_load;
137 151
138 if (!show_phdr) return NULL; 152 if (!show_phdr) return NULL;
139 153
140 memcpy(ret, "--- --- ---\0", 12); 154 memcpy(ret, "--- --- ---\0", 12);
141 155
142 shown = 0; 156 shown = 0;
143 multi_stack = multi_relro = multi_load = 0; 157 multi_stack = multi_relro = multi_load = 0;
144 158
145 if (elf->phdr) {
146#define SHOW_PHDR(B) \ 159#define SHOW_PHDR(B) \
147 if (elf->elf_class == ELFCLASS ## B) { \ 160 if (elf->elf_class == ELFCLASS ## B) { \
148 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 161 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
162 Elf ## B ## _Off offset; \
163 uint32_t flags, check_flags; \
164 if (elf->phdr != NULL) { \
149 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 165 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
150 uint32_t flags; \
151 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 166 for (i = 0; i < EGET(ehdr->e_phnum); ++i) { \
152 if (EGET(phdr[i].p_type) == PT_GNU_STACK) { \ 167 if (EGET(phdr[i].p_type) == PT_GNU_STACK) { \
153 if (multi_stack++) warnf("%s: multiple PT_GNU_STACK's !?", elf->filename); \ 168 if (multi_stack++) warnf("%s: multiple PT_GNU_STACK's !?", elf->filename); \
154 found = found_phdr; \ 169 found = found_phdr; \
155 off = 0; \ 170 offset = 0; \
156 check_flags = PF_X; \ 171 check_flags = PF_X; \
157 } else if (EGET(phdr[i].p_type) == PT_GNU_RELRO) { \ 172 } else if (EGET(phdr[i].p_type) == PT_GNU_RELRO) { \
158 if (multi_relro++) warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \ 173 if (multi_relro++) warnf("%s: multiple PT_GNU_RELRO's !?", elf->filename); \
159 found = found_relro; \ 174 found = found_relro; \
160 off = 4; \ 175 offset = 4; \
161 check_flags = PF_X; \ 176 check_flags = PF_X; \
162 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \ 177 } else if (EGET(phdr[i].p_type) == PT_LOAD) { \
163 if (multi_load++ > 2) warnf("%s: more than 2 PT_LOAD's !?", elf->filename); \ 178 if (multi_load++ > 2) warnf("%s: more than 2 PT_LOAD's !?", elf->filename); \
164 found = found_load; \ 179 found = found_load; \
165 off = 8; \ 180 offset = 8; \
166 check_flags = PF_W|PF_X; \ 181 check_flags = PF_W|PF_X; \
167 } else \ 182 } else \
168 continue; \ 183 continue; \
169 flags = EGET(phdr[i].p_flags); \ 184 flags = EGET(phdr[i].p_flags); \
170 if (be_quiet && ((flags & check_flags) != check_flags)) \ 185 if (be_quiet && ((flags & check_flags) != check_flags)) \
171 continue; \ 186 continue; \
172 memcpy(ret+off, gnu_short_stack_flags(flags), 3); \ 187 memcpy(ret+offset, gnu_short_stack_flags(flags), 3); \
173 *found = 1; \ 188 *found = 1; \
174 ++shown; \ 189 ++shown; \
190 } \
191 } else if (elf->shdr != NULL) { \
192 /* no program headers which means this is prob an object file */ \
193 Elf ## B ## _Shdr *shdr = SHDR ## B (elf->shdr); \
194 Elf ## B ## _Shdr *strtbl = shdr + EGET(ehdr->e_shstrndx); \
195 check_flags = SHF_WRITE|SHF_EXECINSTR; \
196 for (i = 0; i < EGET(ehdr->e_shnum); ++i) { \
197 if (EGET(shdr[i].sh_type) != SHT_PROGBITS) continue; \
198 offset = EGET(strtbl->sh_offset) + EGET(shdr[i].sh_name); \
199 if (!strcmp((char*)(elf->data + offset), ".note.GNU-stack")) { \
200 if (multi_stack++) warnf("%s: multiple .note.GNU-stack's !?", elf->filename); \
201 flags = EGET(shdr[i].sh_flags); \
202 if (be_quiet && ((flags & check_flags) != check_flags)) \
203 continue; \
204 ++*found_phdr; \
205 shown = 1; \
206 if (flags & SHF_WRITE) ret[0] = 'W'; \
207 if (flags & SHF_ALLOC) ret[1] = 'A'; \
208 if (flags & SHF_EXECINSTR) ret[2] = 'X'; \
209 if (flags & 0xFFFFFFF8) warn("Invalid section flags for GNU-stack"); \
210 break; \
211 } \
212 } \
213 if (!multi_stack) { \
214 *found_phdr = 1; \
215 shown = 1; \
216 memcpy(ret, "!WX", 3); \
217 } \
175 } \ 218 } \
176 } 219 }
177 SHOW_PHDR(32) 220 SHOW_PHDR(32)
178 SHOW_PHDR(64) 221 SHOW_PHDR(64)
179 }
180 222
181 if (be_quiet && !shown) 223 if (be_wewy_wewy_quiet || (be_quiet && !shown))
182 return NULL; 224 return NULL;
183 else 225 else
184 return ret; 226 return ret;
185} 227}
186static char *scanelf_file_textrel(elfobj *elf, char *found_textrel) 228static const char *scanelf_file_textrel(elfobj *elf, char *found_textrel)
187{ 229{
188 static char ret[] = "TEXTREL"; 230 static const char *ret = "TEXTREL";
189 unsigned long i; 231 unsigned long i;
190 232
191 if (!show_textrel) return NULL; 233 if (!show_textrel && !show_textrels) return NULL;
192 234
193 if (elf->phdr) { 235 if (elf->phdr) {
194#define SHOW_TEXTREL(B) \ 236#define SHOW_TEXTREL(B) \
195 if (elf->elf_class == ELFCLASS ## B) { \ 237 if (elf->elf_class == ELFCLASS ## B) { \
196 Elf ## B ## _Dyn *dyn; \ 238 Elf ## B ## _Dyn *dyn; \
216 } 258 }
217 259
218 if (be_quiet || be_wewy_wewy_quiet) 260 if (be_quiet || be_wewy_wewy_quiet)
219 return NULL; 261 return NULL;
220 else 262 else
221 return (char *)" - "; 263 return " - ";
264}
265static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *found_textrel)
266{
267 unsigned long s, r, rmax;
268 void *symtab_void, *strtab_void, *text_void;
269
270 if (!show_textrels) return NULL;
271
272 /* don't search for TEXTREL's if the ELF doesn't have any */
273 if (!*found_textrel) scanelf_file_textrel(elf, found_textrel);
274 if (!*found_textrel) return NULL;
275
276 scanelf_file_get_symtabs(elf, &symtab_void, &strtab_void);
277 text_void = elf_findsecbyname(elf, ".text");
278
279 if (symtab_void && strtab_void && text_void && elf->shdr) {
280#define SHOW_TEXTRELS(B) \
281 if (elf->elf_class == ELFCLASS ## B) { \
282 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
283 Elf ## B ## _Shdr *shdr = SHDR ## B (elf->shdr); \
284 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
285 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
286 Elf ## B ## _Shdr *text = SHDR ## B (text_void); \
287 Elf ## B ## _Addr vaddr = EGET(text->sh_addr); \
288 uint ## B ## _t memsz = EGET(text->sh_size); \
289 Elf ## B ## _Rel *rel; \
290 Elf ## B ## _Rela *rela; \
291 /* search the section headers for relocations */ \
292 for (s = 0; s < EGET(ehdr->e_shnum); ++s) { \
293 uint32_t sh_type = EGET(shdr[s].sh_type); \
294 if (sh_type == SHT_REL) { \
295 rel = REL ## B (elf->data + EGET(shdr[s].sh_offset)); \
296 rela = NULL; \
297 rmax = EGET(shdr[s].sh_size) / sizeof(*rel); \
298 } else if (sh_type == SHT_RELA) { \
299 rel = NULL; \
300 rela = RELA ## B (elf->data + EGET(shdr[s].sh_offset)); \
301 rmax = EGET(shdr[s].sh_size) / sizeof(*rela); \
302 } else \
303 continue; \
304 /* now see if any of the relocs are in the .text */ \
305 for (r = 0; r < rmax; ++r) { \
306 unsigned long sym_max; \
307 Elf ## B ## _Addr offset_tmp; \
308 Elf ## B ## _Sym *func; \
309 Elf ## B ## _Sym *sym; \
310 Elf ## B ## _Addr r_offset; \
311 uint ## B ## _t r_info; \
312 if (sh_type == SHT_REL) { \
313 r_offset = EGET(rel[r].r_offset); \
314 r_info = EGET(rel[r].r_info); \
315 } else { \
316 r_offset = EGET(rela[r].r_offset); \
317 r_info = EGET(rela[r].r_info); \
318 } \
319 /* make sure this relocation is inside of the .text */ \
320 if (r_offset < vaddr || r_offset >= vaddr + memsz) { \
321 if (be_verbose <= 2) continue; \
322 } else \
323 *found_textrels = 1; \
324 /* locate this relocation symbol name */ \
325 sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
326 sym_max = ELF ## B ## _R_SYM(r_info); \
327 if (sym_max * EGET(symtab->sh_entsize) < symtab->sh_size) \
328 sym += sym_max; \
329 else \
330 sym = NULL; \
331 sym_max = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \
332 /* show the raw details about this reloc */ \
333 printf(" %s: ", elf->base_filename); \
334 if (sym && sym->st_name) \
335 printf("%s", (char*)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name))); \
336 else \
337 printf("(memory/fake?)"); \
338 printf(" [0x%lX]", (unsigned long)r_offset); \
339 /* now try to find the closest symbol that this rel is probably in */ \
340 sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
341 func = NULL; \
342 offset_tmp = 0; \
343 while (sym_max--) { \
344 if (EGET(sym->st_value) < r_offset && EGET(sym->st_value) > offset_tmp) { \
345 func = sym; \
346 offset_tmp = EGET(sym->st_value); \
347 } \
348 ++sym; \
349 } \
350 printf(" in "); \
351 if (func && func->st_name) \
352 printf("%s", (char*)(elf->data + EGET(strtab->sh_offset) + EGET(func->st_name))); \
353 else \
354 printf("(NULL: fake?)"); \
355 printf(" [0x%lX]\n", (unsigned long)offset_tmp); \
356 } \
357 } }
358 SHOW_TEXTRELS(32)
359 SHOW_TEXTRELS(64)
360 }
361 if (!*found_textrels)
362 warnf("ELF %s has TEXTREL markings but doesnt appear to have any real TEXTREL's !?", elf->filename);
363
364 return NULL;
365}
366
367static void rpath_security_checks(elfobj *, char *);
368static void rpath_security_checks(elfobj *elf, char *item) {
369 struct stat st;
370 switch (*item) {
371 case '/': break;
372 case '.':
373 warnf("Security problem with relative RPATH '%s' in %s", item, elf->filename);
374 break;
375 case '\0':
376 warnf("Security problem NULL RPATH in %s", elf->filename);
377 break;
378 case '$':
379 if (fstat(elf->fd, &st) != -1)
380 if ((st.st_mode & S_ISUID) || (st.st_mode & S_ISGID))
381 warnf("Security problem with RPATH='%s' in %s with mode set of %o",
382 item, elf->filename, st.st_mode & 07777);
383 break;
384 default:
385 warnf("Maybe? sec problem with RPATH='%s' in %s", item, elf->filename);
386 break;
387 }
222} 388}
223static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len) 389static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len)
224{ 390{
225 unsigned long i, s; 391 unsigned long i, s;
226 char *rpath, *runpath, **r; 392 char *rpath, *runpath, **r;
269 /* note that we only 'chop' off leading known paths. */ \ 435 /* note that we only 'chop' off leading known paths. */ \
270 /* since *r is read-only memory, we can only move the ptr forward. */ \ 436 /* since *r is read-only memory, we can only move the ptr forward. */ \
271 start = *r; \ 437 start = *r; \
272 /* scan each path in : delimited list */ \ 438 /* scan each path in : delimited list */ \
273 while (start) { \ 439 while (start) { \
440 rpath_security_checks(elf, start); \
274 end = strchr(start, ':'); \ 441 end = strchr(start, ':'); \
275 len = (end ? abs(end - start) : strlen(start)); \ 442 len = (end ? abs(end - start) : strlen(start)); \
276 for (s = 0; ldpaths[s]; ++s) { \ 443 for (s = 0; ldpaths[s]; ++s) { \
277 if (!strncmp(ldpaths[s], start, len) && !ldpaths[s][len]) { \ 444 if (!strncmp(ldpaths[s], start, len) && !ldpaths[s][len]) { \
278 *r = (end ? end + 1 : NULL); \ 445 *r = (end ? end + 1 : NULL); \
310 } else if (rpath || runpath) 477 } else if (rpath || runpath)
311 xstrcat(ret, (runpath ? runpath : rpath), ret_len); 478 xstrcat(ret, (runpath ? runpath : rpath), ret_len);
312 else if (!be_quiet) 479 else if (!be_quiet)
313 xstrcat(ret, " - ", ret_len); 480 xstrcat(ret, " - ", ret_len);
314} 481}
315static char *scanelf_file_needed_lib(elfobj *elf, char *found_needed, char *found_lib, int op, char **ret, size_t *ret_len) 482static const char *scanelf_file_needed_lib(elfobj *elf, char *found_needed, char *found_lib, int op, char **ret, size_t *ret_len)
316{ 483{
317 unsigned long i; 484 unsigned long i;
318 char *needed; 485 char *needed;
319 void *strtbl_void; 486 void *strtbl_void;
320 487
348 if (*found_needed) xchrcat(ret, ',', ret_len); \ 515 if (*found_needed) xchrcat(ret, ',', ret_len); \
349 xstrcat(ret, needed, ret_len); \ 516 xstrcat(ret, needed, ret_len); \
350 } \ 517 } \
351 *found_needed = 1; \ 518 *found_needed = 1; \
352 } else { \ 519 } else { \
353 if (strcmp(find_lib, needed)) return NULL; \ 520 if (!strncmp(find_lib, needed, strlen( !gmatch ? needed : find_lib))) { \
354 *found_lib = 1; \ 521 *found_lib = 1; \
355 return (be_wewy_wewy_quiet ? NULL : find_lib); \ 522 return (be_wewy_wewy_quiet ? NULL : needed); \
523 } \
356 } \ 524 } \
357 } \ 525 } \
358 ++dyn; \ 526 ++dyn; \
359 } \ 527 } \
360 } } 528 } }
361 SHOW_NEEDED(32) 529 SHOW_NEEDED(32)
362 SHOW_NEEDED(64) 530 SHOW_NEEDED(64)
531 if (op == 0 && !*found_needed && be_verbose)
532 warn("ELF lacks DT_NEEDED sections: %s", elf->filename);
363 } 533 }
364 534
365 return NULL; 535 return NULL;
366} 536}
367static char *scanelf_file_interp(elfobj *elf, char *found_interp) 537static char *scanelf_file_interp(elfobj *elf, char *found_interp)
425 } else { 595 } else {
426 *found_bind = 1; 596 *found_bind = 1;
427 return (char *) "LAZY"; 597 return (char *) "LAZY";
428 } 598 }
429} 599}
600static char *scanelf_file_soname(elfobj *elf, char *found_soname)
601{
602 unsigned long i;
603 char *soname;
604 void *strtbl_void;
605
606 if (!show_soname) return NULL;
607
608 strtbl_void = elf_findsecbyname(elf, ".dynstr");
609
610 if (elf->phdr && strtbl_void) {
611#define SHOW_SONAME(B) \
612 if (elf->elf_class == ELFCLASS ## B) { \
613 Elf ## B ## _Dyn *dyn; \
614 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
615 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
616 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
617 Elf ## B ## _Off offset; \
618 /* only look for soname in shared objects */ \
619 if (ehdr->e_type != ET_DYN) \
620 return NULL; \
621 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
622 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
623 offset = EGET(phdr[i].p_offset); \
624 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
625 dyn = DYN ## B (elf->data + offset); \
626 while (EGET(dyn->d_tag) != DT_NULL) { \
627 if (EGET(dyn->d_tag) == DT_SONAME) { \
628 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
629 if (offset >= (Elf ## B ## _Off)elf->len) { \
630 ++dyn; \
631 continue; \
632 } \
633 soname = (char*)(elf->data + offset); \
634 *found_soname = 1; \
635 return (be_wewy_wewy_quiet ? NULL : soname); \
636 } \
637 ++dyn; \
638 } \
639 } }
640 SHOW_SONAME(32)
641 SHOW_SONAME(64)
642 }
643
644 return NULL;
645}
430static char *scanelf_file_sym(elfobj *elf, char *found_sym) 646static char *scanelf_file_sym(elfobj *elf, char *found_sym)
431{ 647{
432 unsigned long i; 648 unsigned long i;
433 void *symtab_void, *strtab_void; 649 void *symtab_void, *strtab_void;
434 650
435 if (!find_sym) return NULL; 651 if (!find_sym) return NULL;
436 652
437 /* debug sections */ 653 scanelf_file_get_symtabs(elf, &symtab_void, &strtab_void);
438 symtab_void = elf_findsecbyname(elf, ".symtab");
439 strtab_void = elf_findsecbyname(elf, ".strtab");
440 /* fall back to runtime sections */
441 if (!symtab_void || !strtab_void) {
442 symtab_void = elf_findsecbyname(elf, ".dynsym");
443 strtab_void = elf_findsecbyname(elf, ".dynstr");
444 }
445 654
446 if (symtab_void && strtab_void) { 655 if (symtab_void && strtab_void) {
447 char *base, *basemem;
448 basemem = xstrdup(elf->filename);
449 base = basename(basemem);
450#define FIND_SYM(B) \ 656#define FIND_SYM(B) \
451 if (elf->elf_class == ELFCLASS ## B) { \ 657 if (elf->elf_class == ELFCLASS ## B) { \
452 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 658 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
453 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 659 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
454 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 660 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
458 if (sym->st_name) { \ 664 if (sym->st_name) { \
459 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 665 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
460 if (*find_sym == '*') { \ 666 if (*find_sym == '*') { \
461 printf("%s(%s) %5lX %15s %s\n", \ 667 printf("%s(%s) %5lX %15s %s\n", \
462 ((*found_sym == 0) ? "\n\t" : "\t"), \ 668 ((*found_sym == 0) ? "\n\t" : "\t"), \
463 base, \ 669 elf->base_filename, \
464 (long)sym->st_size, \ 670 (long)sym->st_size, \
465 (char *)get_elfstttype(sym->st_info), \ 671 (char *)get_elfstttype(sym->st_info), \
466 symname); \ 672 symname); \
467 *found_sym = 1; \ 673 *found_sym = 1; \
468 } else if ((strcmp(find_sym, symname) == 0) || \ 674 } else if ((strcmp(find_sym, symname) == 0) || \
471 } \ 677 } \
472 ++sym; \ 678 ++sym; \
473 } } 679 } }
474 FIND_SYM(32) 680 FIND_SYM(32)
475 FIND_SYM(64) 681 FIND_SYM(64)
476 free(basemem);
477 } 682 }
478 683
479 if (be_wewy_wewy_quiet) return NULL; 684 if (be_wewy_wewy_quiet) return NULL;
480 685
481 if (*find_sym != '*' && *found_sym) 686 if (*find_sym != '*' && *found_sym)
489#define prints(str) write(fileno(stdout), str, strlen(str)) 694#define prints(str) write(fileno(stdout), str, strlen(str))
490static void scanelf_file(const char *filename) 695static void scanelf_file(const char *filename)
491{ 696{
492 unsigned long i; 697 unsigned long i;
493 char found_pax, found_phdr, found_relro, found_load, found_textrel, 698 char found_pax, found_phdr, found_relro, found_load, found_textrel,
494 found_rpath, found_needed, found_interp, found_bind, 699 found_rpath, found_needed, found_interp, found_bind, found_soname,
495 found_sym, found_lib, found_file; 700 found_sym, found_lib, found_file, found_textrels;
496 elfobj *elf; 701 elfobj *elf;
497 struct stat st; 702 struct stat st;
498 static char *out_buffer = NULL; 703 static char *out_buffer = NULL;
499 static size_t out_len; 704 static size_t out_len;
500 705
511 if (!S_ISREG(st.st_mode)) { 716 if (!S_ISREG(st.st_mode)) {
512 if (be_verbose > 2) printf("%s: skipping non-file\n", filename); 717 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
513 return; 718 return;
514 } 719 }
515 720
516 found_pax = found_phdr = found_relro = found_load = \ 721 found_pax = found_phdr = found_relro = found_load = found_textrel = \
517 found_textrel = found_rpath = found_needed = found_interp = \ 722 found_rpath = found_needed = found_interp = found_bind = found_soname = \
518 found_bind = found_sym = found_lib = found_file = 0; 723 found_sym = found_lib = found_file = found_textrels = 0;
519 724
520 /* verify this is real ELF */ 725 /* verify this is real ELF */
521 if ((elf = readelf(filename)) == NULL) { 726 if ((elf = readelf(filename)) == NULL) {
522 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 727 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
523 return; 728 return;
554 case 't': prints("TEXTREL "); break; 759 case 't': prints("TEXTREL "); break;
555 case 'r': prints("RPATH "); break; 760 case 'r': prints("RPATH "); break;
556 case 'n': prints("NEEDED "); break; 761 case 'n': prints("NEEDED "); break;
557 case 'i': prints("INTERP "); break; 762 case 'i': prints("INTERP "); break;
558 case 'b': prints("BIND "); break; 763 case 'b': prints("BIND "); break;
764 case 'S': prints("SONAME "); break;
559 case 's': prints("SYM "); break; 765 case 's': prints("SYM "); break;
560 case 'N': prints("LIB "); break; 766 case 'N': prints("LIB "); break;
767 case 'T': prints("TEXTRELS "); break;
768 default: warnf("'%c' has no title ?", out_format[i]);
561 } 769 }
562 } 770 }
563 if (!found_file) prints("FILE "); 771 if (!found_file) prints("FILE ");
564 prints("\n"); 772 prints("\n");
565 found_file = 0; 773 found_file = 0;
585 switch (out_format[++i]) { 793 switch (out_format[++i]) {
586 case '%': 794 case '%':
587 case '#': 795 case '#':
588 xchrcat(&out_buffer, out_format[i], &out_len); break; 796 xchrcat(&out_buffer, out_format[i], &out_len); break;
589 case 'F': 797 case 'F':
798 found_file = 1;
590 if (be_wewy_wewy_quiet) break; 799 if (be_wewy_wewy_quiet) break;
591 found_file = 1;
592 xstrcat(&out_buffer, filename, &out_len); 800 xstrcat(&out_buffer, filename, &out_len);
593 break; 801 break;
594 case 'p': 802 case 'p':
803 found_file = 1;
595 if (be_wewy_wewy_quiet) break; 804 if (be_wewy_wewy_quiet) break;
596 found_file = 1;
597 tmp = filename; 805 tmp = filename;
598 if (search_path) { 806 if (search_path) {
599 ssize_t len_search = strlen(search_path); 807 ssize_t len_search = strlen(search_path);
600 ssize_t len_file = strlen(filename); 808 ssize_t len_file = strlen(filename);
601 if (!strncmp(filename, search_path, len_search) && \ 809 if (!strncmp(filename, search_path, len_search) && \
604 if (*tmp == '/' && search_path[len_search-1] == '/') tmp++; 812 if (*tmp == '/' && search_path[len_search-1] == '/') tmp++;
605 } 813 }
606 xstrcat(&out_buffer, tmp, &out_len); 814 xstrcat(&out_buffer, tmp, &out_len);
607 break; 815 break;
608 case 'f': 816 case 'f':
817 found_file = 1;
609 if (be_wewy_wewy_quiet) break; 818 if (be_wewy_wewy_quiet) break;
610 found_file = 1;
611 tmp = strrchr(filename, '/'); 819 tmp = strrchr(filename, '/');
612 tmp = (tmp == NULL ? filename : tmp+1); 820 tmp = (tmp == NULL ? filename : tmp+1);
613 xstrcat(&out_buffer, tmp, &out_len); 821 xstrcat(&out_buffer, tmp, &out_len);
614 break; 822 break;
615 case 'o': out = get_elfetype(elf); break; 823 case 'o': out = get_elfetype(elf); break;
616 case 'x': out = scanelf_file_pax(elf, &found_pax); break; 824 case 'x': out = scanelf_file_pax(elf, &found_pax); break;
617 case 'e': out = scanelf_file_phdr(elf, &found_phdr, &found_relro, &found_load); break; 825 case 'e': out = scanelf_file_phdr(elf, &found_phdr, &found_relro, &found_load); break;
618 case 't': out = scanelf_file_textrel(elf, &found_textrel); break; 826 case 't': out = scanelf_file_textrel(elf, &found_textrel); break;
827 case 'T': out = scanelf_file_textrels(elf, &found_textrels, &found_textrel); break;
619 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break; 828 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break;
620 case 'n': 829 case 'n':
621 case 'N': out = scanelf_file_needed_lib(elf, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break; 830 case 'N': out = scanelf_file_needed_lib(elf, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break;
622 case 'i': out = scanelf_file_interp(elf, &found_interp); break; 831 case 'i': out = scanelf_file_interp(elf, &found_interp); break;
623 case 'b': out = scanelf_file_bind(elf, &found_bind); break; 832 case 'b': out = scanelf_file_bind(elf, &found_bind); break;
833 case 'S': out = scanelf_file_soname(elf, &found_soname); break;
624 case 's': out = scanelf_file_sym(elf, &found_sym); break; 834 case 's': out = scanelf_file_sym(elf, &found_sym); break;
835 default: warnf("'%c' has no scan code?", out_format[i]);
625 } 836 }
626 if (out) xstrcat(&out_buffer, out, &out_len); 837 if (out) xstrcat(&out_buffer, out, &out_len);
627 } 838 }
628 839
629#define FOUND_SOMETHING() \ 840#define FOUND_SOMETHING() \
630 (found_pax || found_phdr || found_relro || found_load || found_textrel || \ 841 (found_pax || found_phdr || found_relro || found_load || found_textrel || \
631 found_rpath || found_needed || found_interp || found_bind || found_sym || found_lib) 842 found_rpath || found_needed || found_interp || found_bind || \
843 found_soname || found_sym || found_lib || found_textrels)
632 844
633 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) { 845 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) {
634 xchrcat(&out_buffer, ' ', &out_len); 846 xchrcat(&out_buffer, ' ', &out_len);
635 xstrcat(&out_buffer, filename, &out_len); 847 xstrcat(&out_buffer, filename, &out_len);
636 } 848 }
637 if (!be_quiet || (be_quiet && FOUND_SOMETHING())) 849 if (!be_quiet || (be_quiet && FOUND_SOMETHING())) {
638 puts(out_buffer); 850 puts(out_buffer);
851 fflush(stdout);
852 }
639 853
640 unreadelf(elf); 854 unreadelf(elf);
641} 855}
642 856
643/* scan a directory for ET_EXEC files and print when we find one */ 857/* scan a directory for ET_EXEC files and print when we find one */
672 while ((dentry = readdir(dir))) { 886 while ((dentry = readdir(dir))) {
673 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) 887 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
674 continue; 888 continue;
675 len = (pathlen + 1 + strlen(dentry->d_name) + 1); 889 len = (pathlen + 1 + strlen(dentry->d_name) + 1);
676 if (len >= sizeof(buf)) { 890 if (len >= sizeof(buf)) {
677 warnf("Skipping '%s': len > sizeof(buf); %lu > %lu\n", path, len, sizeof(buf)); 891 warnf("Skipping '%s': len > sizeof(buf); %lu > %lu\n", path,
892 (unsigned long)len, (unsigned long)sizeof(buf));
678 continue; 893 continue;
679 } 894 }
680 sprintf(buf, "%s/%s", path, dentry->d_name); 895 sprintf(buf, "%s/%s", path, dentry->d_name);
681 if (lstat(buf, &st) != -1) { 896 if (lstat(buf, &st) != -1) {
682 if (S_ISREG(st.st_mode)) 897 if (S_ISREG(st.st_mode))
784} 999}
785 1000
786 1001
787 1002
788/* usage / invocation handling functions */ 1003/* usage / invocation handling functions */
789#define PARSE_FLAGS "plRmyxetrnibs:N:aqvF:f:o:BhV" 1004#define PARSE_FLAGS "plRmyxetrnibSs:gN:TaqvF:f:o:BhV"
790#define a_argument required_argument 1005#define a_argument required_argument
791static struct option const long_opts[] = { 1006static struct option const long_opts[] = {
792 {"path", no_argument, NULL, 'p'}, 1007 {"path", no_argument, NULL, 'p'},
793 {"ldpath", no_argument, NULL, 'l'}, 1008 {"ldpath", no_argument, NULL, 'l'},
794 {"recursive", no_argument, NULL, 'R'}, 1009 {"recursive", no_argument, NULL, 'R'},
799 {"textrel", no_argument, NULL, 't'}, 1014 {"textrel", no_argument, NULL, 't'},
800 {"rpath", no_argument, NULL, 'r'}, 1015 {"rpath", no_argument, NULL, 'r'},
801 {"needed", no_argument, NULL, 'n'}, 1016 {"needed", no_argument, NULL, 'n'},
802 {"interp", no_argument, NULL, 'i'}, 1017 {"interp", no_argument, NULL, 'i'},
803 {"bind", no_argument, NULL, 'b'}, 1018 {"bind", no_argument, NULL, 'b'},
1019 {"soname", no_argument, NULL, 'S'},
804 {"symbol", a_argument, NULL, 's'}, 1020 {"symbol", a_argument, NULL, 's'},
805 {"lib", a_argument, NULL, 'N'}, 1021 {"lib", a_argument, NULL, 'N'},
1022 {"gmatch", no_argument, NULL, 'g'},
1023 {"textrels", no_argument, NULL, 'T'},
806 {"all", no_argument, NULL, 'a'}, 1024 {"all", no_argument, NULL, 'a'},
807 {"quiet", no_argument, NULL, 'q'}, 1025 {"quiet", no_argument, NULL, 'q'},
808 {"verbose", no_argument, NULL, 'v'}, 1026 {"verbose", no_argument, NULL, 'v'},
809 {"format", a_argument, NULL, 'F'}, 1027 {"format", a_argument, NULL, 'F'},
810 {"from", a_argument, NULL, 'f'}, 1028 {"from", a_argument, NULL, 'f'},
811 {"file", a_argument, NULL, 'o'}, 1029 {"file", a_argument, NULL, 'o'},
812 {"nobanner", no_argument, NULL, 'B'}, 1030 {"nobanner", no_argument, NULL, 'B'},
813 {"help", no_argument, NULL, 'h'}, 1031 {"help", no_argument, NULL, 'h'},
814 {"version", no_argument, NULL, 'V'}, 1032 {"version", no_argument, NULL, 'V'},
815 {NULL, no_argument, NULL, 0x0} 1033 {NULL, no_argument, NULL, 0x0}
816}; 1034};
826 "Print TEXTREL information", 1044 "Print TEXTREL information",
827 "Print RPATH information", 1045 "Print RPATH information",
828 "Print NEEDED information", 1046 "Print NEEDED information",
829 "Print INTERP information", 1047 "Print INTERP information",
830 "Print BIND information", 1048 "Print BIND information",
1049 "Print SONAME information",
831 "Find a specified symbol", 1050 "Find a specified symbol",
832 "Find a specified library", 1051 "Find a specified library",
1052 "Use strncmp to match libraries. (use with -N)",
1053 "Locate cause of TEXTREL",
833 "Print all scanned info (-x -e -t -r -n -i -b)\n", 1054 "Print all scanned info (-x -e -t -r -b)\n",
834 "Only output 'bad' things", 1055 "Only output 'bad' things",
835 "Be verbose (can be specified more than once)", 1056 "Be verbose (can be specified more than once)",
836 "Use specified format for output", 1057 "Use specified format for output",
837 "Read input stream from a filename", 1058 "Read input stream from a filename",
838 "Write output stream to a filename", 1059 "Write output stream to a filename",
862 1083
863 puts("\nThe format modifiers for the -F option are:"); 1084 puts("\nThe format modifiers for the -F option are:");
864 puts(" F Filename \tx PaX Flags \te STACK/RELRO"); 1085 puts(" F Filename \tx PaX Flags \te STACK/RELRO");
865 puts(" t TEXTREL \tr RPATH \tn NEEDED"); 1086 puts(" t TEXTREL \tr RPATH \tn NEEDED");
866 puts(" i INTERP \tb BIND \ts symbol"); 1087 puts(" i INTERP \tb BIND \ts symbol");
867 puts(" N library \to Type"); 1088 puts(" N library \to Type \tT TEXTRELs");
1089 puts(" S SONAME");
868 puts(" p filename (with search path removed)"); 1090 puts(" p filename (with search path removed)");
869 puts(" f base filename"); 1091 puts(" f filename (short name/basename)");
870 puts("Prefix each modifier with '%' (verbose) or '#' (silent)"); 1092 puts("Prefix each modifier with '%' (verbose) or '#' (silent)");
871 1093
872 exit(status); 1094 exit(status);
873} 1095}
874 1096
881 opterr = 0; 1103 opterr = 0;
882 while ((i=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) { 1104 while ((i=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
883 switch (i) { 1105 switch (i) {
884 1106
885 case 'V': 1107 case 'V':
886 printf("%s compiled %s\n%s\n" 1108 printf("pax-utils-%s: %s compiled %s\n%s\n"
887 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n", 1109 "%s written for Gentoo by <solar and vapier @ gentoo.org>\n",
888 __FILE__, __DATE__, rcsid, argv0); 1110 VERSION, __FILE__, __DATE__, rcsid, argv0);
889 exit(EXIT_SUCCESS); 1111 exit(EXIT_SUCCESS);
890 break; 1112 break;
891 case 'h': usage(EXIT_SUCCESS); break; 1113 case 'h': usage(EXIT_SUCCESS); break;
892 case 'f': 1114 case 'f':
893 if (from_file) err("Don't specify -f twice"); 1115 if (from_file) err("Don't specify -f twice");
920 if (out_format) err("Don't specify -F twice"); 1142 if (out_format) err("Don't specify -F twice");
921 out_format = xstrdup(optarg); 1143 out_format = xstrdup(optarg);
922 break; 1144 break;
923 } 1145 }
924 1146
1147 case 'g': gmatch = 1;
925 case 'y': scan_symlink = 0; break; 1148 case 'y': scan_symlink = 0; break;
926 case 'B': show_banner = 0; break; 1149 case 'B': show_banner = 0; break;
927 case 'l': scan_ldpath = 1; break; 1150 case 'l': scan_ldpath = 1; break;
928 case 'p': scan_envpath = 1; break; 1151 case 'p': scan_envpath = 1; break;
929 case 'R': dir_recurse = 1; break; 1152 case 'R': dir_recurse = 1; break;
933 case 't': show_textrel = 1; break; 1156 case 't': show_textrel = 1; break;
934 case 'r': show_rpath = 1; break; 1157 case 'r': show_rpath = 1; break;
935 case 'n': show_needed = 1; break; 1158 case 'n': show_needed = 1; break;
936 case 'i': show_interp = 1; break; 1159 case 'i': show_interp = 1; break;
937 case 'b': show_bind = 1; break; 1160 case 'b': show_bind = 1; break;
1161 case 'S': show_soname = 1; break;
1162 case 'T': show_textrels = 1; break;
938 case 'q': be_quiet = 1; break; 1163 case 'q': be_quiet = 1; break;
939 case 'v': be_verbose = (be_verbose % 20) + 1; break; 1164 case 'v': be_verbose = (be_verbose % 20) + 1; break;
940 case 'a': show_pax = show_phdr = show_textrel = show_rpath = \ 1165 case 'a': show_pax = show_phdr = show_textrel = show_rpath = show_bind = 1; break;
941 show_needed = show_interp = show_bind = 1; break;
942 1166
943 case ':': 1167 case ':':
944 err("Option missing parameter\n"); 1168 err("Option missing parameter\n");
945 case '?': 1169 case '?':
946 err("Unknown option\n"); 1170 err("Unknown option\n");
950 } 1174 }
951 1175
952 /* let the format option override all other options */ 1176 /* let the format option override all other options */
953 if (out_format) { 1177 if (out_format) {
954 show_pax = show_phdr = show_textrel = show_rpath = \ 1178 show_pax = show_phdr = show_textrel = show_rpath = \
955 show_needed = show_interp = show_bind = 0; 1179 show_needed = show_interp = show_bind = show_soname = \
1180 show_textrels = 0;
956 for (i = 0; out_format[i]; ++i) { 1181 for (i = 0; out_format[i]; ++i) {
957 if (!IS_MODIFIER(out_format[i])) continue; 1182 if (!IS_MODIFIER(out_format[i])) continue;
958 1183
959 switch (out_format[++i]) { 1184 switch (out_format[++i]) {
960 case '%': break; 1185 case '%': break;
970 case 't': show_textrel = 1; break; 1195 case 't': show_textrel = 1; break;
971 case 'r': show_rpath = 1; break; 1196 case 'r': show_rpath = 1; break;
972 case 'n': show_needed = 1; break; 1197 case 'n': show_needed = 1; break;
973 case 'i': show_interp = 1; break; 1198 case 'i': show_interp = 1; break;
974 case 'b': show_bind = 1; break; 1199 case 'b': show_bind = 1; break;
1200 case 'S': show_soname = 1; break;
1201 case 'T': show_textrels = 1; break;
975 default: 1202 default:
976 err("Invalid format specifier '%c' (byte %i)", 1203 err("Invalid format specifier '%c' (byte %i)",
977 out_format[i], i+1); 1204 out_format[i], i+1);
978 } 1205 }
979 } 1206 }
980 1207
981 /* construct our default format */ 1208 /* construct our default format */
982 } else { 1209 } else {
983 size_t fmt_len = 30; 1210 size_t fmt_len = 30;
984 out_format = (char*)xmalloc(sizeof(char) * fmt_len); 1211 out_format = (char*)xmalloc(sizeof(char) * fmt_len);
985 if (!be_quiet) xstrcat(&out_format, "%o ", &fmt_len); 1212 if (!be_quiet) xstrcat(&out_format, "%o ", &fmt_len);
986 if (show_pax) xstrcat(&out_format, "%x ", &fmt_len); 1213 if (show_pax) xstrcat(&out_format, "%x ", &fmt_len);
987 if (show_phdr) xstrcat(&out_format, "%e ", &fmt_len); 1214 if (show_phdr) xstrcat(&out_format, "%e ", &fmt_len);
988 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len); 1215 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len);
989 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len); 1216 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len);
990 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len); 1217 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
991 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len); 1218 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
992 if (show_bind) xstrcat(&out_format, "%b ", &fmt_len); 1219 if (show_bind) xstrcat(&out_format, "%b ", &fmt_len);
1220 if (show_soname) xstrcat(&out_format, "%S ", &fmt_len);
1221 if (show_textrels) xstrcat(&out_format, "%T ", &fmt_len);
993 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len); 1222 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len);
994 if (find_lib) xstrcat(&out_format, "%N ", &fmt_len); 1223 if (find_lib) xstrcat(&out_format, "%N ", &fmt_len);
995 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len); 1224 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
996 } 1225 }
997 if (be_verbose > 2) printf("Format: %s\n", out_format); 1226 if (be_verbose > 2) printf("Format: %s\n", out_format);
998 1227
999 /* now lets actually do the scanning */ 1228 /* now lets actually do the scanning */
1000 if (scan_ldpath || (show_rpath && be_quiet)) 1229 if (scan_ldpath || (show_rpath && be_quiet))

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

  ViewVC Help
Powered by ViewVC 1.1.20