/[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.43 Revision 1.67
1/* 1/*
2 * Copyright 2003 Ned Ludd <solar@gentoo.org>
3 * Copyright 1999-2005 Gentoo Foundation 2 * Copyright 2003-2005 Gentoo Foundation
4 * Distributed under the terms of the GNU General Public License v2 3 * Distributed under the terms of the GNU General Public License v2
5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.43 2005/05/06 02:55:27 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.67 2005/06/03 02:56:18 vapier Exp $
6 * 5 *
7 ******************************************************************** 6 ********************************************************************
8 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 8 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the 9 * published by the Free Software Foundation; either version 2 of the
22 */ 21 */
23 22
24#include <stdio.h> 23#include <stdio.h>
25#include <stdlib.h> 24#include <stdlib.h>
26#include <sys/types.h> 25#include <sys/types.h>
26#include <libgen.h>
27#include <limits.h>
27#define __USE_GNU 28#define __USE_GNU
28#include <string.h> 29#include <string.h>
29#include <errno.h> 30#include <errno.h>
30#include <unistd.h> 31#include <unistd.h>
31#include <sys/stat.h> 32#include <sys/stat.h>
32#include <dirent.h> 33#include <dirent.h>
33#include <getopt.h> 34#include <getopt.h>
34#include <assert.h> 35#include <assert.h>
35
36#include "paxelf.h" 36#include "paxelf.h"
37 37
38static const char *rcsid = "$Id: scanelf.c,v 1.43 2005/05/06 02:55:27 vapier Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.67 2005/06/03 02:56:18 vapier Exp $";
39#define argv0 "scanelf" 39#define argv0 "scanelf"
40 40
41 41
42 42
43/* prototypes */ 43/* prototypes */
45static void scanelf_dir(const char *path); 45static void scanelf_dir(const char *path);
46static void scanelf_ldpath(); 46static void scanelf_ldpath();
47static void scanelf_envpath(); 47static void scanelf_envpath();
48static void usage(int status); 48static void usage(int status);
49static void parseargs(int argc, char *argv[]); 49static void parseargs(int argc, char *argv[]);
50static char *xstrdup(char *s); 50static char *xstrdup(const char *s);
51static void *xmalloc(size_t size); 51static void *xmalloc(size_t size);
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);
55 54
56/* variables to control behavior */ 55/* variables to control behavior */
56static char *ldpaths[256];
57static char scan_ldpath = 0; 57static char scan_ldpath = 0;
58static char scan_envpath = 0; 58static char scan_envpath = 0;
59static char scan_symlink = 1; 59static char scan_symlink = 1;
60static char dir_recurse = 0; 60static char dir_recurse = 0;
61static char dir_crossmount = 1; 61static char dir_crossmount = 1;
63static char show_stack = 0; 63static char show_stack = 0;
64static char show_textrel = 0; 64static char show_textrel = 0;
65static char show_rpath = 0; 65static char show_rpath = 0;
66static char show_needed = 0; 66static char show_needed = 0;
67static char show_interp = 0; 67static char show_interp = 0;
68static char show_bind = 0;
68static char show_banner = 1; 69static char show_banner = 1;
69static char be_quiet = 0; 70static char be_quiet = 0;
70static char be_verbose = 0; 71static char be_verbose = 0;
71static char *find_sym = NULL, *versioned_symname = NULL; 72static char *find_sym = NULL, *versioned_symname = NULL;
72static char *out_format = NULL; 73static char *out_format = NULL;
73 74static char *search_path = NULL;
74 75
75 76
76/* sub-funcs for scanelf_file() */ 77/* sub-funcs for scanelf_file() */
77static char *scanelf_file_pax(elfobj *elf, char *found_pax) 78static char *scanelf_file_pax(elfobj *elf, char *found_pax)
78{ 79{
79 static char *paxflags; 80 static char *paxflags;
81 static char ret[7];
82 unsigned long i, shown;
83
80 84
81 if (!show_pax) return NULL; 85 if (!show_pax) return NULL;
82 86
87 shown = 0;
88 memset(&ret, 0, sizeof(ret));
89
90 if (elf->phdr) {
91#define SHOW_PAX(B) \
92 if (elf->elf_class == ELFCLASS ## B) { \
93 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
94 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
95 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
96 if (EGET(phdr[i].p_type) != PT_PAX_FLAGS) \
97 continue; \
98 if (be_quiet && (EGET(phdr[i].p_flags) == 10240)) \
99 continue; \
100 memcpy(ret, pax_short_pf_flags(EGET(phdr[i].p_flags)), 6); \
101 *found_pax = 1; \
102 ++shown; \
103 break; \
104 } \
105 }
106 SHOW_PAX(32)
107 SHOW_PAX(64)
108 }
109
110 /* fall back to EI_PAX if no PT_PAX was found */
111 if (!*ret) {
83 paxflags = pax_short_hf_flags(PAX_FLAGS(elf)); 112 paxflags = pax_short_hf_flags(EI_PAX_FLAGS(elf));
84 if (!be_quiet || (be_quiet && strncmp(paxflags, "PeMRxS", 6))) { 113 if (!be_quiet || (be_quiet && EI_PAX_FLAGS(elf))) {
85 *found_pax = 1; 114 *found_pax = 1;
86 return paxflags; 115 return paxflags;
87 } 116 }
117 strncpy(ret, paxflags, sizeof(ret));
118 // ++shown;
119 }
88 120
121 if (be_quiet && !shown)
89 return NULL; 122 return NULL;
123 return ret;
124
90} 125}
91static char *scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro) 126static char *scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro)
92{ 127{
93 static char ret[8]; 128 static char ret[8] = "--- ---";
94 char *found; 129 char *found;
95 int i, off, shown; 130 unsigned long i, off, shown;
96 131
97 if (!show_stack) return NULL; 132 if (!show_stack) return NULL;
98 133
99 shown = 0; 134 shown = 0;
100 strcpy(ret, "--- ---"); 135
136 if (elf->phdr) {
101#define SHOW_STACK(B) \ 137#define SHOW_STACK(B) \
102 if (elf->elf_class == ELFCLASS ## B) { \ 138 if (elf->elf_class == ELFCLASS ## B) { \
103 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 139 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
104 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 140 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
105 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 141 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
106 if (EGET(phdr[i].p_type) == PT_GNU_STACK) { \ 142 if (EGET(phdr[i].p_type) == PT_GNU_STACK) { \
107 found = found_stack; \ 143 found = found_stack; \
108 off = 0; \ 144 off = 0; \
109 } else if (EGET(phdr[i].p_type) == PT_GNU_RELRO) { \ 145 } else if (EGET(phdr[i].p_type) == PT_GNU_RELRO) { \
110 found = found_relro; \ 146 found = found_relro; \
111 off = 3; \ 147 off = 4; \
112 } else \ 148 } else \
113 continue; \ 149 continue; \
114 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \ 150 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \
115 continue; \ 151 continue; \
116 memcpy(ret+off, gnu_short_stack_flags(EGET(phdr[i].p_flags)), 3); \ 152 memcpy(ret+off, gnu_short_stack_flags(EGET(phdr[i].p_flags)), 3); \
118 ++shown; \ 154 ++shown; \
119 } \ 155 } \
120 } 156 }
121 SHOW_STACK(32) 157 SHOW_STACK(32)
122 SHOW_STACK(64) 158 SHOW_STACK(64)
159 }
160
123 if (be_quiet && !shown) 161 if (be_quiet && !shown)
124 return NULL; 162 return NULL;
125 else 163 else
126 return ret; 164 return ret;
127} 165}
128static char *scanelf_file_textrel(elfobj *elf, char *found_textrel) 166static char *scanelf_file_textrel(elfobj *elf, char *found_textrel)
129{ 167{
130 static char *ret = "TEXTREL"; 168 static char *ret = "TEXTREL";
131 int i; 169 unsigned long i;
132 170
133 if (!show_textrel) return NULL; 171 if (!show_textrel) return NULL;
134 172
173 if (elf->phdr) {
135#define SHOW_TEXTREL(B) \ 174#define SHOW_TEXTREL(B) \
136 if (elf->elf_class == ELFCLASS ## B) { \ 175 if (elf->elf_class == ELFCLASS ## B) { \
137 Elf ## B ## _Dyn *dyn; \ 176 Elf ## B ## _Dyn *dyn; \
138 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 177 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
139 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 178 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
179 Elf ## B ## _Off offset; \
140 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 180 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
141 if (phdr[i].p_type != PT_DYNAMIC) continue; \ 181 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
182 offset = EGET(phdr[i].p_offset); \
183 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
142 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 184 dyn = DYN ## B (elf->data + offset); \
143 while (EGET(dyn->d_tag) != DT_NULL) { \ 185 while (EGET(dyn->d_tag) != DT_NULL) { \
144 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \ 186 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
145 *found_textrel = 1; \ 187 *found_textrel = 1; \
146 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \ 188 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
147 return ret; \ 189 return ret; \
149 ++dyn; \ 191 ++dyn; \
150 } \ 192 } \
151 } } 193 } }
152 SHOW_TEXTREL(32) 194 SHOW_TEXTREL(32)
153 SHOW_TEXTREL(64) 195 SHOW_TEXTREL(64)
196 }
197
154 if (be_quiet) 198 if (be_quiet)
155 return NULL; 199 return NULL;
156 else 200 else
157 return " - "; 201 return " - ";
158} 202}
159static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len) 203static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len)
160{ 204{
161 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */ 205 /* TODO: when checking RPATH entries, check each subpath (between :) in ld.so.conf */
162 int i; 206 unsigned long i, s;
163 char *rpath, *runpath; 207 char *rpath, *runpath, **r;
164 void *strtbl_void; 208 void *strtbl_void;
165 209
166 if (!show_rpath) return; 210 if (!show_rpath) return;
167 211
168 strtbl_void = elf_findsecbyname(elf, ".dynstr"); 212 strtbl_void = elf_findsecbyname(elf, ".dynstr");
169 rpath = runpath = NULL; 213 rpath = runpath = NULL;
170 214
171 if (strtbl_void) { 215 if (elf->phdr && strtbl_void) {
172#define SHOW_RPATH(B) \ 216#define SHOW_RPATH(B) \
173 if (elf->elf_class == ELFCLASS ## B) { \ 217 if (elf->elf_class == ELFCLASS ## B) { \
174 Elf ## B ## _Dyn *dyn; \ 218 Elf ## B ## _Dyn *dyn; \
175 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 219 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
176 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 220 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
177 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 221 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
222 Elf ## B ## _Off offset; \
223 Elf ## B ## _Xword word; \
224 /* Scan all the program headers */ \
178 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 225 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
226 /* Just scan dynamic headers */ \
179 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 227 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
228 offset = EGET(phdr[i].p_offset); \
229 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
230 /* Just scan dynamic RPATH/RUNPATH headers */ \
180 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 231 dyn = DYN ## B (elf->data + offset); \
181 while (EGET(dyn->d_tag) != DT_NULL) { \ 232 while ((word=EGET(dyn->d_tag)) != DT_NULL) { \
182 if (EGET(dyn->d_tag) == DT_RPATH) { \ 233 if (word == DT_RPATH) { \
183 if (rpath) warn("ELF has multiple DT_RPATH's !?"); \ 234 r = &rpath; \
235 } else if (word == DT_RUNPATH) { \
236 r = &runpath; \
237 } else { \
238 ++dyn; \
239 continue; \
240 } \
241 /* Verify the memory is somewhat sane */ \
184 rpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 242 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
243 if (offset < elf->len) { \
244 if (*r) warn("ELF has multiple %s's !?", get_elfdtype(word)); \
245 *r = (char*)(elf->data + offset); \
246 /* If quiet, don't output paths in ld.so.conf */ \
247 if (be_quiet) \
248 for (s = 0; ldpaths[s]; ++s) \
249 if (!strcmp(ldpaths[s], *r)) { \
250 *r = NULL; \
251 break; \
252 } \
185 *found_rpath = 1; \ 253 if (*r) *found_rpath = 1; \
186 } else if (EGET(dyn->d_tag) == DT_RUNPATH) { \
187 if (runpath) warn("ELF has multiple DT_RUNPATH's !?"); \
188 runpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
189 *found_rpath = 1; \
190 } \ 254 } \
191 ++dyn; \ 255 ++dyn; \
192 } \ 256 } \
193 } } 257 } }
194 SHOW_RPATH(32) 258 SHOW_RPATH(32)
211 else if (!be_quiet) 275 else if (!be_quiet)
212 xstrcat(ret, " - ", ret_len); 276 xstrcat(ret, " - ", ret_len);
213} 277}
214static void scanelf_file_needed(elfobj *elf, char *found_needed, char **ret, size_t *ret_len) 278static void scanelf_file_needed(elfobj *elf, char *found_needed, char **ret, size_t *ret_len)
215{ 279{
216 int i; 280 unsigned long i;
217 char *needed; 281 char *needed;
218 void *strtbl_void; 282 void *strtbl_void;
219 283
220 if (!show_needed) return; 284 if (!show_needed) return;
221 285
222 strtbl_void = elf_findsecbyname(elf, ".dynstr"); 286 strtbl_void = elf_findsecbyname(elf, ".dynstr");
223 287
224 if (strtbl_void) { 288 if (elf->phdr && strtbl_void) {
225#define SHOW_NEEDED(B) \ 289#define SHOW_NEEDED(B) \
226 if (elf->elf_class == ELFCLASS ## B) { \ 290 if (elf->elf_class == ELFCLASS ## B) { \
227 Elf ## B ## _Dyn *dyn; \ 291 Elf ## B ## _Dyn *dyn; \
228 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 292 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
229 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 293 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
230 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 294 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
295 Elf ## B ## _Off offset; \
231 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 296 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
232 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 297 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
298 offset = EGET(phdr[i].p_offset); \
299 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
233 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 300 dyn = DYN ## B (elf->data + offset); \
234 while (EGET(dyn->d_tag) != DT_NULL) { \ 301 while (EGET(dyn->d_tag) != DT_NULL) { \
235 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 302 if (EGET(dyn->d_tag) == DT_NEEDED) { \
236 needed = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 303 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
304 if (offset >= elf->len) { \
305 ++dyn; \
306 continue; \
307 } \
308 needed = (char*)(elf->data + offset); \
237 if (*found_needed) xchrcat(ret, ',', ret_len); \ 309 if (*found_needed) xchrcat(ret, ',', ret_len); \
238 xstrcat(ret, needed, ret_len); \ 310 xstrcat(ret, needed, ret_len); \
239 *found_needed = 1; \ 311 *found_needed = 1; \
240 } \ 312 } \
241 ++dyn; \ 313 ++dyn; \
263 SHOW_INTERP(32) 335 SHOW_INTERP(32)
264 SHOW_INTERP(64) 336 SHOW_INTERP(64)
265 } 337 }
266 return NULL; 338 return NULL;
267} 339}
340static char *scanelf_file_bind(elfobj *elf, char *found_bind)
341{
342 unsigned long i;
343 struct stat s;
344
345 if (!show_bind) return NULL;
346 if (!elf->phdr) return NULL;
347
348#define SHOW_BIND(B) \
349 if (elf->elf_class == ELFCLASS ## B) { \
350 Elf ## B ## _Dyn *dyn; \
351 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
352 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
353 Elf ## B ## _Off offset; \
354 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
355 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
356 offset = EGET(phdr[i].p_offset); \
357 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
358 dyn = DYN ## B (elf->data + offset); \
359 while (EGET(dyn->d_tag) != DT_NULL) { \
360 if (EGET(dyn->d_tag) == DT_BIND_NOW || \
361 (EGET(dyn->d_tag) == DT_FLAGS && EGET(dyn->d_un.d_val) & DF_BIND_NOW)) \
362 { \
363 if (be_quiet) return NULL; \
364 *found_bind = 1; \
365 return "NOW"; \
366 } \
367 ++dyn; \
368 } \
369 } \
370 }
371 SHOW_BIND(32)
372 SHOW_BIND(64)
373
374 if (be_quiet && !fstat(elf->fd, &s) && !(s.st_mode & S_ISUID || s.st_mode & S_ISGID)) {
375 return NULL;
376 } else {
377 *found_bind = 1;
378 return "LAZY";
379 }
380}
268static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename) 381static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename)
269{ 382{
270 int i; 383 unsigned long i;
271 void *symtab_void, *strtab_void; 384 void *symtab_void, *strtab_void;
272 385
273 if (!find_sym) return NULL; 386 if (!find_sym) return NULL;
274 387
388 /* debug sections */
275 symtab_void = elf_findsecbyname(elf, ".symtab"); 389 symtab_void = elf_findsecbyname(elf, ".symtab");
276 strtab_void = elf_findsecbyname(elf, ".strtab"); 390 strtab_void = elf_findsecbyname(elf, ".strtab");
391 /* fall back to runtime sections */
392 if (!symtab_void || !strtab_void) {
393 symtab_void = elf_findsecbyname(elf, ".dynsym");
394 strtab_void = elf_findsecbyname(elf, ".dynstr");
395 }
277 396
278 if (symtab_void && strtab_void) { 397 if (symtab_void && strtab_void) {
398 char *base, *basemem;
399 basemem = xstrdup(filename);
400 base = basename(basemem);
279#define FIND_SYM(B) \ 401#define FIND_SYM(B) \
280 if (elf->elf_class == ELFCLASS ## B) { \ 402 if (elf->elf_class == ELFCLASS ## B) { \
281 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 403 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
282 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 404 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
283 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 405 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
284 int cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \ 406 unsigned long cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \
285 char *symname; \ 407 char *symname; \
286 for (i = 0; i < cnt; ++i) { \ 408 for (i = 0; i < cnt; ++i) { \
287 if (sym->st_name) { \ 409 if (sym->st_name) { \
288 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 410 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
289 if (*find_sym == '*') { \ 411 if (*find_sym == '*') { \
290 printf("%s(%s) %5lX %15s %s\n", \ 412 printf("%s(%s) %5lX %15s %s\n", \
291 ((*found_sym == 0) ? "\n\t" : "\t"), \ 413 ((*found_sym == 0) ? "\n\t" : "\t"), \
292 (char *)basename(filename), \ 414 base, \
293 (long)sym->st_size, \ 415 (long)sym->st_size, \
294 (char *)get_elfstttype(sym->st_info), \ 416 (char *)get_elfstttype(sym->st_info), \
295 symname); \ 417 symname); \
296 *found_sym = 1; \ 418 *found_sym = 1; \
297 } else if ((strcmp(find_sym, symname) == 0) || \ 419 } else if ((strcmp(find_sym, symname) == 0) || \
300 } \ 422 } \
301 ++sym; \ 423 ++sym; \
302 } } 424 } }
303 FIND_SYM(32) 425 FIND_SYM(32)
304 FIND_SYM(64) 426 FIND_SYM(64)
427 free(basemem);
305 } 428 }
306 if (*find_sym != '*' && *found_sym) 429 if (*find_sym != '*' && *found_sym)
307 return find_sym; 430 return find_sym;
308 if (be_quiet) 431 if (be_quiet)
309 return NULL; 432 return NULL;
310 else 433 else
311 return " - "; 434 return " - ";
312} 435}
313/* scan an elf file and show all the fun stuff */ 436/* scan an elf file and show all the fun stuff */
314#define prints(str) fputs(str, stdout) 437// #define prints(str) fputs(str, stdout)
438#define prints(str) write(fileno(stdout), str, strlen(str))
315static void scanelf_file(const char *filename) 439static void scanelf_file(const char *filename)
316{ 440{
317 int i; 441 unsigned long i;
318 char found_pax, found_stack, found_relro, found_textrel, 442 char found_pax, found_stack, found_relro, found_textrel,
319 found_rpath, found_needed, found_interp, found_sym, 443 found_rpath, found_needed, found_interp, found_bind,
320 found_file; 444 found_sym, found_file;
321 elfobj *elf; 445 elfobj *elf;
322 struct stat st; 446 struct stat st;
323 static char *out_buffer = NULL; 447 static char *out_buffer = NULL;
324 static size_t out_len; 448 static size_t out_len;
325 449
327 if (lstat(filename, &st) == -1) { 451 if (lstat(filename, &st) == -1) {
328 if (be_verbose > 2) printf("%s: does not exist\n", filename); 452 if (be_verbose > 2) printf("%s: does not exist\n", filename);
329 return; 453 return;
330 } 454 }
331 /* always handle regular files and handle symlinked files if no -y */ 455 /* always handle regular files and handle symlinked files if no -y */
332 if (!(S_ISREG(st.st_mode) || (S_ISLNK(st.st_mode) && scan_symlink))) { 456 if (S_ISLNK(st.st_mode)) {
457 if (!scan_symlink) return;
458 stat(filename, &st);
459 }
460 if (!S_ISREG(st.st_mode)) {
333 if (be_verbose > 2) printf("%s: skipping non-file\n", filename); 461 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
334 return; 462 return;
335 } 463 }
336 464
337 found_pax = found_stack = found_relro = found_textrel = \ 465 found_pax = found_stack = found_relro = found_textrel = \
338 found_rpath = found_needed = found_interp = found_sym = \ 466 found_rpath = found_needed = found_interp = found_bind = \
339 found_file = 0; 467 found_sym = found_file = 0;
340 468
341 /* verify this is real ELF */ 469 /* verify this is real ELF */
342 if ((elf = readelf(filename)) == NULL) { 470 if ((elf = readelf(filename)) == NULL) {
343 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 471 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
344 return; 472 return;
358 } 486 }
359 *out_buffer = '\0'; 487 *out_buffer = '\0';
360 488
361 /* show the header */ 489 /* show the header */
362 if (!be_quiet && show_banner) { 490 if (!be_quiet && show_banner) {
363 for (i=0; out_format[i]; ++i) { 491 for (i = 0; out_format[i]; ++i) {
364 if (out_format[i] != '%') continue; 492 if (out_format[i] != '%') continue;
365 493
366 switch (out_format[++i]) { 494 switch (out_format[++i]) {
367 case '%': break; 495 case '%': break;
496 case 'F':
497 case 'p':
368 case 'F': prints("FILE "); break; 498 case 'f': prints("FILE "); found_file = 1; break;
369 case 'o': prints(" TYPE "); break; 499 case 'o': prints(" TYPE "); break;
370 case 'x': prints(" PAX "); break; 500 case 'x': prints(" PAX "); break;
371 case 'e': prints("STK/REL "); break; 501 case 'e': prints("STK/REL "); break;
372 case 't': prints("TEXTREL "); break; 502 case 't': prints("TEXTREL "); break;
373 case 'r': prints("RPATH "); break; 503 case 'r': prints("RPATH "); break;
374 case 'n': prints("NEEDED "); break; 504 case 'n': prints("NEEDED "); break;
375 case 'i': prints("INTERP "); break; 505 case 'i': prints("INTERP "); break;
506 case 'b': prints("BIND "); break;
376 case 's': prints("SYM "); break; 507 case 's': prints("SYM "); break;
377 } 508 }
378 } 509 }
510 if (!found_file) prints("FILE ");
379 prints("\n"); 511 prints("\n");
512 found_file = 0;
380 show_banner = 0; 513 show_banner = 0;
381 } 514 }
382 515
383 /* dump all the good stuff */ 516 /* dump all the good stuff */
384 for (i=0; out_format[i]; ++i) { 517 for (i = 0; out_format[i]; ++i) {
385 const char *out; 518 const char *out;
519 const char *tmp;
386 520
387 /* make sure we trim leading spaces in quiet mode */ 521 /* make sure we trim leading spaces in quiet mode */
388 if (be_quiet && *out_buffer == ' ' && !out_buffer[1]) 522 if (be_quiet && *out_buffer == ' ' && !out_buffer[1])
389 *out_buffer = '\0'; 523 *out_buffer = '\0';
390 524
395 529
396 out = NULL; 530 out = NULL;
397 switch (out_format[++i]) { 531 switch (out_format[++i]) {
398 case '%': xchrcat(&out_buffer, '%', &out_len); break; 532 case '%': xchrcat(&out_buffer, '%', &out_len); break;
399 case 'F': found_file = 1; xstrcat(&out_buffer, filename, &out_len); break; 533 case 'F': found_file = 1; xstrcat(&out_buffer, filename, &out_len); break;
534 case 'p':
535 found_file = 1;
536 tmp = filename;
537 if (search_path) {
538 ssize_t len_search = strlen(search_path);
539 ssize_t len_file = strlen(filename);
540 if (!strncmp(filename, search_path, len_search) && \
541 len_file > len_search)
542 tmp += len_search;
543 if (*tmp == '/' && search_path[len_search-1] == '/') tmp++;
544 }
545 xstrcat(&out_buffer, tmp, &out_len);
546 break;
547 case 'f':
548 found_file = 1;
549 tmp = strrchr(filename, '/');
550 tmp = (tmp == NULL ? filename : tmp+1);
551 xstrcat(&out_buffer, tmp, &out_len);
552 break;
400 case 'o': out = get_elfetype(elf); break; 553 case 'o': out = get_elfetype(elf); break;
401 case 'x': out = scanelf_file_pax(elf, &found_pax); break; 554 case 'x': out = scanelf_file_pax(elf, &found_pax); break;
402 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro); break; 555 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro); break;
403 case 't': out = scanelf_file_textrel(elf, &found_textrel); break; 556 case 't': out = scanelf_file_textrel(elf, &found_textrel); break;
404 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break; 557 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break;
405 case 'n': scanelf_file_needed(elf, &found_needed, &out_buffer, &out_len); break; 558 case 'n': scanelf_file_needed(elf, &found_needed, &out_buffer, &out_len); break;
406 case 'i': out = scanelf_file_interp(elf, &found_interp); break; 559 case 'i': out = scanelf_file_interp(elf, &found_interp); break;
560 case 'b': out = scanelf_file_bind(elf, &found_bind); break;
407 case 's': out = scanelf_file_sym(elf, &found_sym, filename); break; 561 case 's': out = scanelf_file_sym(elf, &found_sym, filename); break;
408 } 562 }
409 if (out) xstrcat(&out_buffer, out, &out_len); 563 if (out) xstrcat(&out_buffer, out, &out_len);
410 } 564 }
411 565
412 if (!found_file) { 566#define FOUND_SOMETHING() \
413 if (!be_quiet || found_pax || found_stack || found_textrel || \ 567 (found_pax || found_stack || found_textrel || found_rpath || \
414 found_rpath || found_needed || found_interp || found_sym) 568 found_needed || found_interp || found_bind || found_sym)
569
570 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) {
571 xchrcat(&out_buffer, ' ', &out_len);
415 xstrcat(&out_buffer, filename, &out_len); 572 xstrcat(&out_buffer, filename, &out_len);
416 } 573 }
417 if (!(be_quiet && xemptybuffer(out_buffer))) 574 if (!be_quiet || (be_quiet && FOUND_SOMETHING()))
418 puts(out_buffer); 575 puts(out_buffer);
419 576
420 unreadelf(elf); 577 unreadelf(elf);
421} 578}
422 579
468 } 625 }
469 } 626 }
470 closedir(dir); 627 closedir(dir);
471} 628}
472 629
630static int scanelf_from_file(char *filename)
631{
632 FILE *fp = NULL;
633 char *p;
634 char path[_POSIX_PATH_MAX];
635
636 if (((strcmp(filename, "-")) == 0) && (ttyname(0) == NULL))
637 fp = stdin;
638 else if ((fp = fopen(filename, "r")) == NULL)
639 return 1;
640
641 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) {
642 if ((p = strchr(path, '\n')) != NULL)
643 *p = 0;
644 search_path = path;
645 scanelf_dir(path);
646 }
647 if (fp != stdin)
648 fclose(fp);
649 return 0;
650}
651
652static void load_ld_so_conf()
653{
654 FILE *fp = NULL;
655 char *p;
656 char path[_POSIX_PATH_MAX];
657 int i = 0;
658
659 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
660 return;
661
662 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) {
663 if (*path != '/')
664 continue;
665
666 if ((p = strrchr(path, '\r')) != NULL)
667 *p = 0;
668 if ((p = strchr(path, '\n')) != NULL)
669 *p = 0;
670
671 ldpaths[i++] = xstrdup(path);
672
673 if (i + 1 == sizeof(ldpaths) / sizeof(*ldpaths))
674 break;
675 }
676 ldpaths[i] = NULL;
677
678 fclose(fp);
679}
680
473/* scan /etc/ld.so.conf for paths */ 681/* scan /etc/ld.so.conf for paths */
474static void scanelf_ldpath() 682static void scanelf_ldpath()
475{ 683{
476 char scan_l, scan_ul, scan_ull; 684 char scan_l, scan_ul, scan_ull;
477 char *path, *p; 685 int i = 0;
478 FILE *fp;
479 686
480 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 687 if (!ldpaths[0])
481 err("Unable to open ld.so.conf: %s", strerror(errno)); 688 err("Unable to load any paths from ld.so.conf");
482 689
483 scan_l = scan_ul = scan_ull = 0; 690 scan_l = scan_ul = scan_ull = 0;
484 691
485 path = (char*)xmalloc(_POSIX_PATH_MAX); 692 while (ldpaths[i]) {
486 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
487 if (*path == '/') {
488 if ((p = strrchr(path, '\r')) != NULL)
489 *p = 0;
490 if ((p = strrchr(path, '\n')) != NULL)
491 *p = 0;
492 if (!scan_l && !strcmp(path, "/lib")) scan_l = 1; 693 if (!scan_l && !strcmp(ldpaths[i], "/lib")) scan_l = 1;
493 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1; 694 if (!scan_ul && !strcmp(ldpaths[i], "/usr/lib")) scan_ul = 1;
494 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1; 695 if (!scan_ull && !strcmp(ldpaths[i], "/usr/local/lib")) scan_ull = 1;
495 scanelf_dir(path); 696 scanelf_dir(ldpaths[i]);
697 ++i;
496 } 698 }
497 free(path);
498 fclose(fp);
499 699
500 if (!scan_l) scanelf_dir("/lib"); 700 if (!scan_l) scanelf_dir("/lib");
501 if (!scan_ul) scanelf_dir("/usr/lib"); 701 if (!scan_ul) scanelf_dir("/usr/lib");
502 if (!scan_ull) scanelf_dir("/usr/local/lib"); 702 if (!scan_ull) scanelf_dir("/usr/local/lib");
503} 703}
521} 721}
522 722
523 723
524 724
525/* usage / invocation handling functions */ 725/* usage / invocation handling functions */
526#define PARSE_FLAGS "plRmyxetrnis:aqvF:o:BhV" 726#define PARSE_FLAGS "plRmyxetrnibs:aqvF:f:o:BhV"
527#define a_argument required_argument 727#define a_argument required_argument
528static struct option const long_opts[] = { 728static struct option const long_opts[] = {
529 {"path", no_argument, NULL, 'p'}, 729 {"path", no_argument, NULL, 'p'},
530 {"ldpath", no_argument, NULL, 'l'}, 730 {"ldpath", no_argument, NULL, 'l'},
531 {"recursive", no_argument, NULL, 'R'}, 731 {"recursive", no_argument, NULL, 'R'},
535 {"header", no_argument, NULL, 'e'}, 735 {"header", no_argument, NULL, 'e'},
536 {"textrel", no_argument, NULL, 't'}, 736 {"textrel", no_argument, NULL, 't'},
537 {"rpath", no_argument, NULL, 'r'}, 737 {"rpath", no_argument, NULL, 'r'},
538 {"needed", no_argument, NULL, 'n'}, 738 {"needed", no_argument, NULL, 'n'},
539 {"interp", no_argument, NULL, 'i'}, 739 {"interp", no_argument, NULL, 'i'},
740 {"bind", no_argument, NULL, 'b'},
540 {"symbol", a_argument, NULL, 's'}, 741 {"symbol", a_argument, NULL, 's'},
541 {"all", no_argument, NULL, 'a'}, 742 {"all", no_argument, NULL, 'a'},
542 {"quiet", no_argument, NULL, 'q'}, 743 {"quiet", no_argument, NULL, 'q'},
543 {"verbose", no_argument, NULL, 'v'}, 744 {"verbose", no_argument, NULL, 'v'},
544 {"format", a_argument, NULL, 'F'}, 745 {"format", a_argument, NULL, 'F'},
746 {"from", a_argument, NULL, 'f'},
545 {"file", a_argument, NULL, 'o'}, 747 {"file", a_argument, NULL, 'o'},
546 {"nobanner", no_argument, NULL, 'B'}, 748 {"nobanner", no_argument, NULL, 'B'},
547 {"help", no_argument, NULL, 'h'}, 749 {"help", no_argument, NULL, 'h'},
548 {"version", no_argument, NULL, 'V'}, 750 {"version", no_argument, NULL, 'V'},
549 {NULL, no_argument, NULL, 0x0} 751 {NULL, no_argument, NULL, 0x0}
550}; 752};
753
551static char *opts_help[] = { 754static char *opts_help[] = {
552 "Scan all directories in PATH environment", 755 "Scan all directories in PATH environment",
553 "Scan all directories in /etc/ld.so.conf", 756 "Scan all directories in /etc/ld.so.conf",
554 "Scan directories recursively", 757 "Scan directories recursively",
555 "Don't recursively cross mount points", 758 "Don't recursively cross mount points",
558 "Print GNU_STACK markings", 761 "Print GNU_STACK markings",
559 "Print TEXTREL information", 762 "Print TEXTREL information",
560 "Print RPATH information", 763 "Print RPATH information",
561 "Print NEEDED information", 764 "Print NEEDED information",
562 "Print INTERP information", 765 "Print INTERP information",
766 "Print BIND information",
563 "Find a specified symbol", 767 "Find a specified symbol",
564 "Print all scanned info (-x -e -t -r)\n", 768 "Print all scanned info (-x -e -t -r -n -i -b)\n",
565 "Only output 'bad' things", 769 "Only output 'bad' things",
566 "Be verbose (can be specified more than once)", 770 "Be verbose (can be specified more than once)",
567 "Use specified format for output", 771 "Use specified format for output",
772 "Read input stream from a filename",
568 "Write output stream to a filename", 773 "Write output stream to a filename",
569 "Don't display the header", 774 "Don't display the header",
570 "Print this help and exit", 775 "Print this help and exit",
571 "Print version and exit", 776 "Print version and exit",
572 NULL 777 NULL
573}; 778};
574 779
575/* display usage and exit */ 780/* display usage and exit */
576static void usage(int status) 781static void usage(int status)
577{ 782{
578 int i; 783 unsigned long i;
579 printf(" Scan ELF binaries for stuff\n\n" 784 printf("* Scan ELF binaries for stuff\n\n"
580 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0); 785 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0);
581 printf("Options: -[%s]\n", PARSE_FLAGS); 786 printf("Options: -[%s]\n", PARSE_FLAGS);
582 for (i = 0; long_opts[i].name; ++i) 787 for (i = 0; long_opts[i].name; ++i)
583 if (long_opts[i].has_arg == no_argument) 788 if (long_opts[i].has_arg == no_argument)
584 printf(" -%c, --%-13s %s\n", long_opts[i].val, 789 printf(" -%c, --%-13s* %s\n", long_opts[i].val,
585 long_opts[i].name, opts_help[i]); 790 long_opts[i].name, opts_help[i]);
586 else 791 else
587 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val, 792 printf(" -%c, --%-6s <arg> * %s\n", long_opts[i].val,
588 long_opts[i].name, opts_help[i]); 793 long_opts[i].name, opts_help[i]);
794
795 if (status != EXIT_SUCCESS)
796 exit(status);
797
798 puts("\nThe format modifiers for the -F option are:");
799 puts(" %F Filename \t%x PaX Flags \t%e STACK/RELRO");
800 puts(" %t TEXTREL \t%r RPATH \t%n NEEDED");
801 puts(" %i INTERP \t%b BIND \t%s symbol");
802 puts(" %p filename (with search path removed)");
803 puts(" %f base filename");
804
589 exit(status); 805 exit(status);
590} 806}
591 807
592/* parse command line arguments and preform needed actions */ 808/* parse command line arguments and preform needed actions */
593static void parseargs(int argc, char *argv[]) 809static void parseargs(int argc, char *argv[])
594{ 810{
595 int flag; 811 int i;
812 char *from_file = NULL;
596 813
597 opterr = 0; 814 opterr = 0;
598 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) { 815 while ((i=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
599 switch (flag) { 816 switch (i) {
600 817
601 case 'V': 818 case 'V':
602 printf("%s compiled %s\n%s\n" 819 printf("%s compiled %s\n%s\n"
603 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n", 820 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n",
604 __FILE__, __DATE__, rcsid, argv0); 821 __FILE__, __DATE__, rcsid, argv0);
605 exit(EXIT_SUCCESS); 822 exit(EXIT_SUCCESS);
606 break; 823 break;
607 case 'h': usage(EXIT_SUCCESS); break; 824 case 'h': usage(EXIT_SUCCESS); break;
608 825 case 'f':
826 if (from_file) err("Don't specify -f twice");
827 from_file = xstrdup(optarg);
828 break;
609 case 'o': { 829 case 'o': {
610 FILE *fp = NULL; 830 FILE *fp = NULL;
611 fp = freopen(optarg, "w", stdout); 831 if ((fp = freopen(optarg, "w", stdout)) == NULL)
612 if (fp == NULL)
613 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 832 err("Could not open output stream '%s': %s", optarg, strerror(errno));
614 stdout = fp; 833 SET_STDOUT(fp);
615 break; 834 break;
616 } 835 }
617 836
618 case 's': { 837 case 's': {
619 size_t len; 838 size_t len;
839 if (find_sym) err("Don't specify -s twice");
620 find_sym = xstrdup(optarg); 840 find_sym = xstrdup(optarg);
621 len = strlen(find_sym) + 1; 841 len = strlen(find_sym) + 1;
622 versioned_symname = (char*)xmalloc(sizeof(char) * (len+1)); 842 versioned_symname = (char*)xmalloc(sizeof(char) * (len+1));
623 sprintf(versioned_symname, "%s@", find_sym); 843 sprintf(versioned_symname, "%s@", find_sym);
624 break; 844 break;
625 } 845 }
626 846
627 case 'F': { 847 case 'F': {
848 if (out_format) err("Don't specify -F twice");
628 out_format = strdup(optarg); 849 out_format = xstrdup(optarg);
629 break; 850 break;
630 } 851 }
631 852
632 case 'y': scan_symlink = 0; break; 853 case 'y': scan_symlink = 0; break;
633 case 'B': show_banner = 0; break; 854 case 'B': show_banner = 0; break;
639 case 'e': show_stack = 1; break; 860 case 'e': show_stack = 1; break;
640 case 't': show_textrel = 1; break; 861 case 't': show_textrel = 1; break;
641 case 'r': show_rpath = 1; break; 862 case 'r': show_rpath = 1; break;
642 case 'n': show_needed = 1; break; 863 case 'n': show_needed = 1; break;
643 case 'i': show_interp = 1; break; 864 case 'i': show_interp = 1; break;
865 case 'b': show_bind = 1; break;
644 case 'q': be_quiet = 1; break; 866 case 'q': be_quiet = 1; break;
645 case 'v': be_verbose = (be_verbose % 20) + 1; break; 867 case 'v': be_verbose = (be_verbose % 20) + 1; break;
646 case 'a': show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 1; break; 868 case 'a': show_pax = show_stack = show_textrel = show_rpath = \
869 show_needed = show_interp = show_bind = 1; break;
647 870
648 case ':': 871 case ':':
649 warn("Option missing parameter\n"); 872 err("Option missing parameter\n");
650 usage(EXIT_FAILURE);
651 break;
652 case '?': 873 case '?':
653 warn("Unknown option\n"); 874 err("Unknown option\n");
654 usage(EXIT_FAILURE);
655 break;
656 default: 875 default:
657 err("Unhandled option '%c'", flag); 876 err("Unhandled option '%c'", i);
658 break;
659 }
660 } 877 }
661 878 }
662 if (be_quiet && be_verbose)
663 err("You can be quiet or you can be verbose, not both, stupid");
664 879
665 /* let the format option override all other options */ 880 /* let the format option override all other options */
666 if (out_format) { 881 if (out_format) {
667 show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 0; 882 show_pax = show_stack = show_textrel = show_rpath = \
883 show_needed = show_interp = show_bind = 0;
668 for (flag=0; out_format[flag]; ++flag) { 884 for (i = 0; out_format[i]; ++i) {
669 if (out_format[flag] != '%') continue; 885 if (out_format[i] != '%') continue;
670 886
671 switch (out_format[++flag]) { 887 switch (out_format[++i]) {
672 case '%': break; 888 case '%': break;
673 case 'F': break; 889 case 'F': break;
890 case 'p': break;
891 case 'f': break;
674 case 's': break; 892 case 's': break;
675 case 'o': break; 893 case 'o': break;
676 case 'x': show_pax = 1; break; 894 case 'x': show_pax = 1; break;
677 case 'e': show_stack = 1; break; 895 case 'e': show_stack = 1; break;
678 case 't': show_textrel = 1; break; 896 case 't': show_textrel = 1; break;
679 case 'r': show_rpath = 1; break; 897 case 'r': show_rpath = 1; break;
680 case 'n': show_needed = 1; break; 898 case 'n': show_needed = 1; break;
681 case 'i': show_interp = 1; break; 899 case 'i': show_interp = 1; break;
900 case 'b': show_bind = 1; break;
682 default: 901 default:
683 err("Invalid format specifier '%c' (byte %i)", 902 err("Invalid format specifier '%c' (byte %i)",
684 out_format[flag], flag+1); 903 out_format[i], i+1);
685 } 904 }
686 } 905 }
687 906
688 /* construct our default format */ 907 /* construct our default format */
689 } else { 908 } else {
694 if (show_stack) xstrcat(&out_format, "%e ", &fmt_len); 913 if (show_stack) xstrcat(&out_format, "%e ", &fmt_len);
695 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len); 914 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len);
696 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len); 915 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len);
697 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len); 916 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
698 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len); 917 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
918 if (show_bind) xstrcat(&out_format, "%b ", &fmt_len);
699 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len); 919 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len);
700 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len); 920 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
701 } 921 }
702 if (be_verbose > 2) printf("Format: %s\n", out_format); 922 if (be_verbose > 2) printf("Format: %s\n", out_format);
703 923
704 /* now lets actually do the scanning */ 924 /* now lets actually do the scanning */
925 if (scan_ldpath || (show_rpath && be_quiet))
926 load_ld_so_conf();
705 if (scan_ldpath) scanelf_ldpath(); 927 if (scan_ldpath) scanelf_ldpath();
706 if (scan_envpath) scanelf_envpath(); 928 if (scan_envpath) scanelf_envpath();
929 if (from_file) {
930 scanelf_from_file(from_file);
931 free(from_file);
932 from_file = *argv;
933 }
707 if (optind == argc && !scan_ldpath && !scan_envpath) 934 if (optind == argc && !scan_ldpath && !scan_envpath && !from_file)
708 err("Nothing to scan !?"); 935 err("Nothing to scan !?");
709 while (optind < argc) 936 while (optind < argc) {
710 scanelf_dir(argv[optind++]); 937 search_path = argv[optind++];
938 scanelf_dir(search_path);
939 }
711 940
712 /* clean up */ 941 /* clean up */
713 if (find_sym) { 942 if (find_sym) {
714 free(find_sym); 943 free(find_sym);
715 free(versioned_symname); 944 free(versioned_symname);
716 } 945 }
717 if (out_format) free(out_format); 946 if (out_format) free(out_format);
947 for (i = 0; ldpaths[i]; ++i)
948 free(ldpaths[i]);
718} 949}
719 950
720 951
721 952
722/* utility funcs */ 953/* utility funcs */
723static char *xstrdup(char *s) 954static char *xstrdup(const char *s)
724{ 955{
725 char *ret = strdup(s); 956 char *ret = strdup(s);
726 if (!ret) err("Could not strdup(): %s", strerror(errno)); 957 if (!ret) err("Could not strdup(): %s", strerror(errno));
727 return ret; 958 return ret;
728} 959}
960
729static void *xmalloc(size_t size) 961static void *xmalloc(size_t size)
730{ 962{
731 void *ret = malloc(size); 963 void *ret = malloc(size);
732 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size); 964 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size);
733 return ret; 965 return ret;
734} 966}
967
735static void xstrcat(char **dst, const char *src, size_t *curr_len) 968static void xstrcat(char **dst, const char *src, size_t *curr_len)
736{ 969{
737 long new_len; 970 long new_len;
738 971
739 new_len = strlen(*dst) + strlen(src); 972 new_len = strlen(*dst) + strlen(src);
744 err("could not realloc %li bytes", (unsigned long)*curr_len); 977 err("could not realloc %li bytes", (unsigned long)*curr_len);
745 } 978 }
746 979
747 strcat(*dst, src); 980 strcat(*dst, src);
748} 981}
982
749static inline void xchrcat(char **dst, const char append, size_t *curr_len) 983static inline void xchrcat(char **dst, const char append, size_t *curr_len)
750{ 984{
751 static char my_app[2]; 985 static char my_app[2];
752 my_app[0] = append; 986 my_app[0] = append;
753 my_app[1] = '\0'; 987 my_app[1] = '\0';
754 xstrcat(dst, my_app, curr_len); 988 xstrcat(dst, my_app, curr_len);
755} 989}
756static int xemptybuffer(const char *buff)
757{
758 long i;
759 for (i=0; buff[i]; ++i)
760 if (buff[i] != ' ')
761 return 0;
762 return 1;
763}
764
765 990
766 991
767int main(int argc, char *argv[]) 992int main(int argc, char *argv[])
768{ 993{
769 if (argc < 2) 994 if (argc < 2)
770 usage(EXIT_FAILURE); 995 usage(EXIT_FAILURE);
771 parseargs(argc, argv); 996 parseargs(argc, argv);
772 fclose(stdout); 997 fclose(stdout);
998#ifdef __BOUNDS_CHECKING_ON
999 warn("The calls to add/delete heap should be off by 1 due to the out_buffer not being freed in scanelf_file()");
1000#endif
773 return EXIT_SUCCESS; 1001 return EXIT_SUCCESS;
774} 1002}

Legend:
Removed from v.1.43  
changed lines
  Added in v.1.67

  ViewVC Help
Powered by ViewVC 1.1.20