/[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.61
1/* 1/*
2 * Copyright 2003 Ned Ludd <solar@gentoo.org> 2 * Copyright 2003 Ned Ludd <solar@gentoo.org>
3 * Copyright 1999-2005 Gentoo Foundation 3 * Copyright 1999-2005 Gentoo Foundation
4 * Distributed under the terms of the GNU General Public License v2 4 * Distributed under the terms of the GNU General Public License v2
5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.43 2005/05/06 02:55:27 vapier Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.61 2005/05/28 22:09:36 solar Exp $
6 * 6 *
7 ******************************************************************** 7 ********************************************************************
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the 10 * published by the Free Software Foundation; either version 2 of the
22 */ 22 */
23 23
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <sys/types.h> 26#include <sys/types.h>
27#include <libgen.h>
28#include <limits.h>
27#define __USE_GNU 29#define __USE_GNU
28#include <string.h> 30#include <string.h>
29#include <errno.h> 31#include <errno.h>
30#include <unistd.h> 32#include <unistd.h>
31#include <sys/stat.h> 33#include <sys/stat.h>
32#include <dirent.h> 34#include <dirent.h>
33#include <getopt.h> 35#include <getopt.h>
34#include <assert.h> 36#include <assert.h>
35
36#include "paxelf.h" 37#include "paxelf.h"
37 38
38static const char *rcsid = "$Id: scanelf.c,v 1.43 2005/05/06 02:55:27 vapier Exp $"; 39static const char *rcsid = "$Id: scanelf.c,v 1.61 2005/05/28 22:09:36 solar Exp $";
39#define argv0 "scanelf" 40#define argv0 "scanelf"
40 41
41 42
42 43
43/* prototypes */ 44/* prototypes */
45static void scanelf_dir(const char *path); 46static void scanelf_dir(const char *path);
46static void scanelf_ldpath(); 47static void scanelf_ldpath();
47static void scanelf_envpath(); 48static void scanelf_envpath();
48static void usage(int status); 49static void usage(int status);
49static void parseargs(int argc, char *argv[]); 50static void parseargs(int argc, char *argv[]);
50static char *xstrdup(char *s); 51static char *xstrdup(const char *s);
51static void *xmalloc(size_t size); 52static void *xmalloc(size_t size);
52static void xstrcat(char **dst, const char *src, size_t *curr_len); 53static void xstrcat(char **dst, const char *src, size_t *curr_len);
53static inline void xchrcat(char **dst, const char append, size_t *curr_len); 54static inline void xchrcat(char **dst, const char append, size_t *curr_len);
54static int xemptybuffer(const char *buff);
55 55
56/* variables to control behavior */ 56/* variables to control behavior */
57static char *ldpaths[256];
57static char scan_ldpath = 0; 58static char scan_ldpath = 0;
58static char scan_envpath = 0; 59static char scan_envpath = 0;
59static char scan_symlink = 1; 60static char scan_symlink = 1;
60static char dir_recurse = 0; 61static char dir_recurse = 0;
61static char dir_crossmount = 1; 62static char dir_crossmount = 1;
63static char show_stack = 0; 64static char show_stack = 0;
64static char show_textrel = 0; 65static char show_textrel = 0;
65static char show_rpath = 0; 66static char show_rpath = 0;
66static char show_needed = 0; 67static char show_needed = 0;
67static char show_interp = 0; 68static char show_interp = 0;
69static char show_bind = 0;
68static char show_banner = 1; 70static char show_banner = 1;
69static char be_quiet = 0; 71static char be_quiet = 0;
70static char be_verbose = 0; 72static char be_verbose = 0;
71static char *find_sym = NULL, *versioned_symname = NULL; 73static char *find_sym = NULL, *versioned_symname = NULL;
72static char *out_format = NULL; 74static char *out_format = NULL;
73 75
74 76
75
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
275 symtab_void = elf_findsecbyname(elf, ".symtab"); 388 symtab_void = elf_findsecbyname(elf, ".symtab");
276 strtab_void = elf_findsecbyname(elf, ".strtab"); 389 strtab_void = elf_findsecbyname(elf, ".strtab");
277 390
278 if (symtab_void && strtab_void) { 391 if (symtab_void && strtab_void) {
392 char *base, *basemem;
393 basemem = xstrdup(filename);
394 base = basename(basemem);
279#define FIND_SYM(B) \ 395#define FIND_SYM(B) \
280 if (elf->elf_class == ELFCLASS ## B) { \ 396 if (elf->elf_class == ELFCLASS ## B) { \
281 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 397 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
282 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 398 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
283 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 399 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
284 int cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \ 400 unsigned long cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \
285 char *symname; \ 401 char *symname; \
286 for (i = 0; i < cnt; ++i) { \ 402 for (i = 0; i < cnt; ++i) { \
287 if (sym->st_name) { \ 403 if (sym->st_name) { \
288 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 404 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
289 if (*find_sym == '*') { \ 405 if (*find_sym == '*') { \
290 printf("%s(%s) %5lX %15s %s\n", \ 406 printf("%s(%s) %5lX %15s %s\n", \
291 ((*found_sym == 0) ? "\n\t" : "\t"), \ 407 ((*found_sym == 0) ? "\n\t" : "\t"), \
292 (char *)basename(filename), \ 408 base, \
293 (long)sym->st_size, \ 409 (long)sym->st_size, \
294 (char *)get_elfstttype(sym->st_info), \ 410 (char *)get_elfstttype(sym->st_info), \
295 symname); \ 411 symname); \
296 *found_sym = 1; \ 412 *found_sym = 1; \
297 } else if ((strcmp(find_sym, symname) == 0) || \ 413 } else if ((strcmp(find_sym, symname) == 0) || \
300 } \ 416 } \
301 ++sym; \ 417 ++sym; \
302 } } 418 } }
303 FIND_SYM(32) 419 FIND_SYM(32)
304 FIND_SYM(64) 420 FIND_SYM(64)
421 free(basemem);
305 } 422 }
306 if (*find_sym != '*' && *found_sym) 423 if (*find_sym != '*' && *found_sym)
307 return find_sym; 424 return find_sym;
308 if (be_quiet) 425 if (be_quiet)
309 return NULL; 426 return NULL;
310 else 427 else
311 return " - "; 428 return " - ";
312} 429}
313/* scan an elf file and show all the fun stuff */ 430/* scan an elf file and show all the fun stuff */
314#define prints(str) fputs(str, stdout) 431// #define prints(str) fputs(str, stdout)
432#define prints(str) write(fileno(stdout), str, strlen(str))
315static void scanelf_file(const char *filename) 433static void scanelf_file(const char *filename)
316{ 434{
317 int i; 435 unsigned long i;
318 char found_pax, found_stack, found_relro, found_textrel, 436 char found_pax, found_stack, found_relro, found_textrel,
319 found_rpath, found_needed, found_interp, found_sym, 437 found_rpath, found_needed, found_interp, found_bind,
320 found_file; 438 found_sym, found_file;
321 elfobj *elf; 439 elfobj *elf;
322 struct stat st; 440 struct stat st;
323 static char *out_buffer = NULL; 441 static char *out_buffer = NULL;
324 static size_t out_len; 442 static size_t out_len;
325 443
327 if (lstat(filename, &st) == -1) { 445 if (lstat(filename, &st) == -1) {
328 if (be_verbose > 2) printf("%s: does not exist\n", filename); 446 if (be_verbose > 2) printf("%s: does not exist\n", filename);
329 return; 447 return;
330 } 448 }
331 /* always handle regular files and handle symlinked files if no -y */ 449 /* 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))) { 450 if (S_ISLNK(st.st_mode)) {
451 if (!scan_symlink) return;
452 stat(filename, &st);
453 }
454 if (!S_ISREG(st.st_mode)) {
333 if (be_verbose > 2) printf("%s: skipping non-file\n", filename); 455 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
334 return; 456 return;
335 } 457 }
336 458
337 found_pax = found_stack = found_relro = found_textrel = \ 459 found_pax = found_stack = found_relro = found_textrel = \
338 found_rpath = found_needed = found_interp = found_sym = \ 460 found_rpath = found_needed = found_interp = found_bind = \
339 found_file = 0; 461 found_sym = found_file = 0;
340 462
341 /* verify this is real ELF */ 463 /* verify this is real ELF */
342 if ((elf = readelf(filename)) == NULL) { 464 if ((elf = readelf(filename)) == NULL) {
343 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 465 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
344 return; 466 return;
358 } 480 }
359 *out_buffer = '\0'; 481 *out_buffer = '\0';
360 482
361 /* show the header */ 483 /* show the header */
362 if (!be_quiet && show_banner) { 484 if (!be_quiet && show_banner) {
363 for (i=0; out_format[i]; ++i) { 485 for (i = 0; out_format[i]; ++i) {
364 if (out_format[i] != '%') continue; 486 if (out_format[i] != '%') continue;
365 487
366 switch (out_format[++i]) { 488 switch (out_format[++i]) {
367 case '%': break; 489 case '%': break;
368 case 'F': prints("FILE "); break; 490 case 'F': prints("FILE "); found_file = 1; break;
369 case 'o': prints(" TYPE "); break; 491 case 'o': prints(" TYPE "); break;
370 case 'x': prints(" PAX "); break; 492 case 'x': prints(" PAX "); break;
371 case 'e': prints("STK/REL "); break; 493 case 'e': prints("STK/REL "); break;
372 case 't': prints("TEXTREL "); break; 494 case 't': prints("TEXTREL "); break;
373 case 'r': prints("RPATH "); break; 495 case 'r': prints("RPATH "); break;
374 case 'n': prints("NEEDED "); break; 496 case 'n': prints("NEEDED "); break;
375 case 'i': prints("INTERP "); break; 497 case 'i': prints("INTERP "); break;
498 case 'b': prints("BIND "); break;
376 case 's': prints("SYM "); break; 499 case 's': prints("SYM "); break;
377 } 500 }
378 } 501 }
502 if (!found_file) prints("FILE ");
379 prints("\n"); 503 prints("\n");
504 found_file = 0;
380 show_banner = 0; 505 show_banner = 0;
381 } 506 }
382 507
383 /* dump all the good stuff */ 508 /* dump all the good stuff */
384 for (i=0; out_format[i]; ++i) { 509 for (i = 0; out_format[i]; ++i) {
385 const char *out; 510 const char *out;
386 511
387 /* make sure we trim leading spaces in quiet mode */ 512 /* make sure we trim leading spaces in quiet mode */
388 if (be_quiet && *out_buffer == ' ' && !out_buffer[1]) 513 if (be_quiet && *out_buffer == ' ' && !out_buffer[1])
389 *out_buffer = '\0'; 514 *out_buffer = '\0';
402 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro); break; 527 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro); break;
403 case 't': out = scanelf_file_textrel(elf, &found_textrel); break; 528 case 't': out = scanelf_file_textrel(elf, &found_textrel); break;
404 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break; 529 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; 530 case 'n': scanelf_file_needed(elf, &found_needed, &out_buffer, &out_len); break;
406 case 'i': out = scanelf_file_interp(elf, &found_interp); break; 531 case 'i': out = scanelf_file_interp(elf, &found_interp); break;
532 case 'b': out = scanelf_file_bind(elf, &found_bind); break;
407 case 's': out = scanelf_file_sym(elf, &found_sym, filename); break; 533 case 's': out = scanelf_file_sym(elf, &found_sym, filename); break;
408 } 534 }
409 if (out) xstrcat(&out_buffer, out, &out_len); 535 if (out) xstrcat(&out_buffer, out, &out_len);
410 } 536 }
411 537
412 if (!found_file) { 538#define FOUND_SOMETHING() \
413 if (!be_quiet || found_pax || found_stack || found_textrel || \ 539 (found_pax || found_stack || found_textrel || found_rpath || \
414 found_rpath || found_needed || found_interp || found_sym) 540 found_needed || found_interp || found_bind || found_sym)
541
542 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) {
543 xchrcat(&out_buffer, ' ', &out_len);
415 xstrcat(&out_buffer, filename, &out_len); 544 xstrcat(&out_buffer, filename, &out_len);
416 } 545 }
417 if (!(be_quiet && xemptybuffer(out_buffer))) 546 if (!be_quiet || (be_quiet && FOUND_SOMETHING()))
418 puts(out_buffer); 547 puts(out_buffer);
419 548
420 unreadelf(elf); 549 unreadelf(elf);
421} 550}
422 551
468 } 597 }
469 } 598 }
470 closedir(dir); 599 closedir(dir);
471} 600}
472 601
602static int scanelf_from_file(char *filename)
603{
604 FILE *fp = NULL;
605 char *p;
606 char path[_POSIX_PATH_MAX];
607
608 if (((strcmp(filename, "-")) == 0) && (ttyname(0) == NULL))
609 fp = stdin;
610 else if ((fp = fopen(filename, "r")) == NULL)
611 return 1;
612
613 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) {
614 if ((p = strchr(path, '\n')) != NULL)
615 *p = 0;
616 scanelf_dir(path);
617 }
618 if (fp != stdin)
619 fclose(fp);
620 return 0;
621}
622
623static void load_ld_so_conf()
624{
625 FILE *fp = NULL;
626 char *p;
627 char path[_POSIX_PATH_MAX];
628 int i = 0;
629
630 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
631 return;
632
633 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) {
634 if (*path != '/')
635 continue;
636
637 if ((p = strrchr(path, '\r')) != NULL)
638 *p = 0;
639 if ((p = strchr(path, '\n')) != NULL)
640 *p = 0;
641
642 ldpaths[i++] = xstrdup(path);
643
644 if (i + 1 == sizeof(ldpaths) / sizeof(*ldpaths))
645 break;
646 }
647 ldpaths[i] = NULL;
648
649 fclose(fp);
650}
651
473/* scan /etc/ld.so.conf for paths */ 652/* scan /etc/ld.so.conf for paths */
474static void scanelf_ldpath() 653static void scanelf_ldpath()
475{ 654{
476 char scan_l, scan_ul, scan_ull; 655 char scan_l, scan_ul, scan_ull;
477 char *path, *p; 656 int i = 0;
478 FILE *fp;
479 657
480 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 658 if (!ldpaths[0])
481 err("Unable to open ld.so.conf: %s", strerror(errno)); 659 err("Unable to load any paths from ld.so.conf");
482 660
483 scan_l = scan_ul = scan_ull = 0; 661 scan_l = scan_ul = scan_ull = 0;
484 662
485 path = (char*)xmalloc(_POSIX_PATH_MAX); 663 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; 664 if (!scan_l && !strcmp(ldpaths[i], "/lib")) scan_l = 1;
493 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1; 665 if (!scan_ul && !strcmp(ldpaths[i], "/usr/lib")) scan_ul = 1;
494 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1; 666 if (!scan_ull && !strcmp(ldpaths[i], "/usr/local/lib")) scan_ull = 1;
495 scanelf_dir(path); 667 scanelf_dir(ldpaths[i]);
668 ++i;
496 } 669 }
497 free(path);
498 fclose(fp);
499 670
500 if (!scan_l) scanelf_dir("/lib"); 671 if (!scan_l) scanelf_dir("/lib");
501 if (!scan_ul) scanelf_dir("/usr/lib"); 672 if (!scan_ul) scanelf_dir("/usr/lib");
502 if (!scan_ull) scanelf_dir("/usr/local/lib"); 673 if (!scan_ull) scanelf_dir("/usr/local/lib");
503} 674}
521} 692}
522 693
523 694
524 695
525/* usage / invocation handling functions */ 696/* usage / invocation handling functions */
526#define PARSE_FLAGS "plRmyxetrnis:aqvF:o:BhV" 697#define PARSE_FLAGS "plRmyxetrnibs:aqvF:f:o:BhV"
527#define a_argument required_argument 698#define a_argument required_argument
528static struct option const long_opts[] = { 699static struct option const long_opts[] = {
529 {"path", no_argument, NULL, 'p'}, 700 {"path", no_argument, NULL, 'p'},
530 {"ldpath", no_argument, NULL, 'l'}, 701 {"ldpath", no_argument, NULL, 'l'},
531 {"recursive", no_argument, NULL, 'R'}, 702 {"recursive", no_argument, NULL, 'R'},
535 {"header", no_argument, NULL, 'e'}, 706 {"header", no_argument, NULL, 'e'},
536 {"textrel", no_argument, NULL, 't'}, 707 {"textrel", no_argument, NULL, 't'},
537 {"rpath", no_argument, NULL, 'r'}, 708 {"rpath", no_argument, NULL, 'r'},
538 {"needed", no_argument, NULL, 'n'}, 709 {"needed", no_argument, NULL, 'n'},
539 {"interp", no_argument, NULL, 'i'}, 710 {"interp", no_argument, NULL, 'i'},
711 {"bind", no_argument, NULL, 'b'},
540 {"symbol", a_argument, NULL, 's'}, 712 {"symbol", a_argument, NULL, 's'},
541 {"all", no_argument, NULL, 'a'}, 713 {"all", no_argument, NULL, 'a'},
542 {"quiet", no_argument, NULL, 'q'}, 714 {"quiet", no_argument, NULL, 'q'},
543 {"verbose", no_argument, NULL, 'v'}, 715 {"verbose", no_argument, NULL, 'v'},
544 {"format", a_argument, NULL, 'F'}, 716 {"format", a_argument, NULL, 'F'},
717 {"from", a_argument, NULL, 'f'},
545 {"file", a_argument, NULL, 'o'}, 718 {"file", a_argument, NULL, 'o'},
546 {"nobanner", no_argument, NULL, 'B'}, 719 {"nobanner", no_argument, NULL, 'B'},
547 {"help", no_argument, NULL, 'h'}, 720 {"help", no_argument, NULL, 'h'},
548 {"version", no_argument, NULL, 'V'}, 721 {"version", no_argument, NULL, 'V'},
549 {NULL, no_argument, NULL, 0x0} 722 {NULL, no_argument, NULL, 0x0}
550}; 723};
724
551static char *opts_help[] = { 725static char *opts_help[] = {
552 "Scan all directories in PATH environment", 726 "Scan all directories in PATH environment",
553 "Scan all directories in /etc/ld.so.conf", 727 "Scan all directories in /etc/ld.so.conf",
554 "Scan directories recursively", 728 "Scan directories recursively",
555 "Don't recursively cross mount points", 729 "Don't recursively cross mount points",
558 "Print GNU_STACK markings", 732 "Print GNU_STACK markings",
559 "Print TEXTREL information", 733 "Print TEXTREL information",
560 "Print RPATH information", 734 "Print RPATH information",
561 "Print NEEDED information", 735 "Print NEEDED information",
562 "Print INTERP information", 736 "Print INTERP information",
737 "Print BIND information",
563 "Find a specified symbol", 738 "Find a specified symbol",
564 "Print all scanned info (-x -e -t -r)\n", 739 "Print all scanned info (-x -e -t -r -n -i -b)\n",
565 "Only output 'bad' things", 740 "Only output 'bad' things",
566 "Be verbose (can be specified more than once)", 741 "Be verbose (can be specified more than once)",
567 "Use specified format for output", 742 "Use specified format for output",
743 "Read input stream from a filename",
568 "Write output stream to a filename", 744 "Write output stream to a filename",
569 "Don't display the header", 745 "Don't display the header",
570 "Print this help and exit", 746 "Print this help and exit",
571 "Print version and exit", 747 "Print version and exit",
572 NULL 748 NULL
573}; 749};
574 750
575/* display usage and exit */ 751/* display usage and exit */
576static void usage(int status) 752static void usage(int status)
577{ 753{
578 int i; 754 unsigned long i;
579 printf(" Scan ELF binaries for stuff\n\n" 755 printf("* Scan ELF binaries for stuff\n\n"
580 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0); 756 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0);
581 printf("Options: -[%s]\n", PARSE_FLAGS); 757 printf("Options: -[%s]\n", PARSE_FLAGS);
582 for (i = 0; long_opts[i].name; ++i) 758 for (i = 0; long_opts[i].name; ++i)
583 if (long_opts[i].has_arg == no_argument) 759 if (long_opts[i].has_arg == no_argument)
584 printf(" -%c, --%-13s %s\n", long_opts[i].val, 760 printf(" -%c, --%-13s* %s\n", long_opts[i].val,
585 long_opts[i].name, opts_help[i]); 761 long_opts[i].name, opts_help[i]);
586 else 762 else
587 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val, 763 printf(" -%c, --%-6s <arg> * %s\n", long_opts[i].val,
588 long_opts[i].name, opts_help[i]); 764 long_opts[i].name, opts_help[i]);
765
766 if (status != EXIT_SUCCESS)
767 exit(status);
768
769 puts("\nThe format modifiers for the -F option are:");
770 puts(" %F Filename \t%x PaX Flags \t%e STACK/RELRO");
771 puts(" %t TEXTREL \t%r RPATH \t%n NEEDED");
772 puts(" %i INTERP \t%b BIND \t%s symbol");
773
589 exit(status); 774 exit(status);
590} 775}
591 776
592/* parse command line arguments and preform needed actions */ 777/* parse command line arguments and preform needed actions */
593static void parseargs(int argc, char *argv[]) 778static void parseargs(int argc, char *argv[])
594{ 779{
595 int flag; 780 int i;
781 char *from_file = NULL;
596 782
597 opterr = 0; 783 opterr = 0;
598 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) { 784 while ((i=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
599 switch (flag) { 785 switch (i) {
600 786
601 case 'V': 787 case 'V':
602 printf("%s compiled %s\n%s\n" 788 printf("%s compiled %s\n%s\n"
603 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n", 789 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n",
604 __FILE__, __DATE__, rcsid, argv0); 790 __FILE__, __DATE__, rcsid, argv0);
605 exit(EXIT_SUCCESS); 791 exit(EXIT_SUCCESS);
606 break; 792 break;
607 case 'h': usage(EXIT_SUCCESS); break; 793 case 'h': usage(EXIT_SUCCESS); break;
608 794 case 'f':
795 if (from_file == NULL)
796 from_file = xstrdup(optarg);
797 break;
609 case 'o': { 798 case 'o': {
610 FILE *fp = NULL; 799 FILE *fp = NULL;
611 fp = freopen(optarg, "w", stdout); 800 fp = freopen(optarg, "w", stdout);
612 if (fp == NULL) 801 if (fp == NULL)
613 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 802 err("Could not open output stream '%s': %s", optarg, strerror(errno));
623 sprintf(versioned_symname, "%s@", find_sym); 812 sprintf(versioned_symname, "%s@", find_sym);
624 break; 813 break;
625 } 814 }
626 815
627 case 'F': { 816 case 'F': {
817 if (!out_format)
628 out_format = strdup(optarg); 818 out_format = xstrdup(optarg);
629 break; 819 break;
630 } 820 }
631 821
632 case 'y': scan_symlink = 0; break; 822 case 'y': scan_symlink = 0; break;
633 case 'B': show_banner = 0; break; 823 case 'B': show_banner = 0; break;
639 case 'e': show_stack = 1; break; 829 case 'e': show_stack = 1; break;
640 case 't': show_textrel = 1; break; 830 case 't': show_textrel = 1; break;
641 case 'r': show_rpath = 1; break; 831 case 'r': show_rpath = 1; break;
642 case 'n': show_needed = 1; break; 832 case 'n': show_needed = 1; break;
643 case 'i': show_interp = 1; break; 833 case 'i': show_interp = 1; break;
834 case 'b': show_bind = 1; break;
644 case 'q': be_quiet = 1; break; 835 case 'q': be_quiet = 1; break;
645 case 'v': be_verbose = (be_verbose % 20) + 1; break; 836 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; 837 case 'a': show_pax = show_stack = show_textrel = show_rpath = \
838 show_needed = show_interp = show_bind = 1; break;
647 839
648 case ':': 840 case ':':
649 warn("Option missing parameter\n"); 841 err("Option missing parameter\n");
650 usage(EXIT_FAILURE);
651 break;
652 case '?': 842 case '?':
653 warn("Unknown option\n"); 843 err("Unknown option\n");
654 usage(EXIT_FAILURE);
655 break;
656 default: 844 default:
657 err("Unhandled option '%c'", flag); 845 err("Unhandled option '%c'", i);
658 break;
659 }
660 } 846 }
661 847 }
662 if (be_quiet && be_verbose)
663 err("You can be quiet or you can be verbose, not both, stupid");
664 848
665 /* let the format option override all other options */ 849 /* let the format option override all other options */
666 if (out_format) { 850 if (out_format) {
667 show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 0; 851 show_pax = show_stack = show_textrel = show_rpath = \
852 show_needed = show_interp = show_bind = 0;
668 for (flag=0; out_format[flag]; ++flag) { 853 for (i = 0; out_format[i]; ++i) {
669 if (out_format[flag] != '%') continue; 854 if (out_format[i] != '%') continue;
670 855
671 switch (out_format[++flag]) { 856 switch (out_format[++i]) {
672 case '%': break; 857 case '%': break;
673 case 'F': break; 858 case 'F': break;
674 case 's': break; 859 case 's': break;
675 case 'o': break; 860 case 'o': break;
676 case 'x': show_pax = 1; break; 861 case 'x': show_pax = 1; break;
677 case 'e': show_stack = 1; break; 862 case 'e': show_stack = 1; break;
678 case 't': show_textrel = 1; break; 863 case 't': show_textrel = 1; break;
679 case 'r': show_rpath = 1; break; 864 case 'r': show_rpath = 1; break;
680 case 'n': show_needed = 1; break; 865 case 'n': show_needed = 1; break;
681 case 'i': show_interp = 1; break; 866 case 'i': show_interp = 1; break;
867 case 'b': show_bind = 1; break;
682 default: 868 default:
683 err("Invalid format specifier '%c' (byte %i)", 869 err("Invalid format specifier '%c' (byte %i)",
684 out_format[flag], flag+1); 870 out_format[i], i+1);
685 } 871 }
686 } 872 }
687 873
688 /* construct our default format */ 874 /* construct our default format */
689 } else { 875 } else {
694 if (show_stack) xstrcat(&out_format, "%e ", &fmt_len); 880 if (show_stack) xstrcat(&out_format, "%e ", &fmt_len);
695 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len); 881 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len);
696 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len); 882 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len);
697 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len); 883 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
698 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len); 884 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
885 if (show_bind) xstrcat(&out_format, "%b ", &fmt_len);
699 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len); 886 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len);
700 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len); 887 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
701 } 888 }
702 if (be_verbose > 2) printf("Format: %s\n", out_format); 889 if (be_verbose > 2) printf("Format: %s\n", out_format);
703 890
704 /* now lets actually do the scanning */ 891 /* now lets actually do the scanning */
892 if (scan_ldpath || (show_rpath && be_quiet))
893 load_ld_so_conf();
705 if (scan_ldpath) scanelf_ldpath(); 894 if (scan_ldpath) scanelf_ldpath();
706 if (scan_envpath) scanelf_envpath(); 895 if (scan_envpath) scanelf_envpath();
896 if (from_file) {
897 scanelf_from_file(from_file);
898 free(from_file);
899 from_file = *argv;
900 }
707 if (optind == argc && !scan_ldpath && !scan_envpath) 901 if (optind == argc && !scan_ldpath && !scan_envpath && !from_file)
708 err("Nothing to scan !?"); 902 err("Nothing to scan !?");
709 while (optind < argc) 903 while (optind < argc)
710 scanelf_dir(argv[optind++]); 904 scanelf_dir(argv[optind++]);
711 905
712 /* clean up */ 906 /* clean up */
713 if (find_sym) { 907 if (find_sym) {
714 free(find_sym); 908 free(find_sym);
715 free(versioned_symname); 909 free(versioned_symname);
716 } 910 }
717 if (out_format) free(out_format); 911 if (out_format) free(out_format);
912 for (i = 0; ldpaths[i]; ++i)
913 free(ldpaths[i]);
718} 914}
719 915
720 916
721 917
722/* utility funcs */ 918/* utility funcs */
723static char *xstrdup(char *s) 919static char *xstrdup(const char *s)
724{ 920{
725 char *ret = strdup(s); 921 char *ret = strdup(s);
726 if (!ret) err("Could not strdup(): %s", strerror(errno)); 922 if (!ret) err("Could not strdup(): %s", strerror(errno));
727 return ret; 923 return ret;
728} 924}
925
729static void *xmalloc(size_t size) 926static void *xmalloc(size_t size)
730{ 927{
731 void *ret = malloc(size); 928 void *ret = malloc(size);
732 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size); 929 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size);
733 return ret; 930 return ret;
734} 931}
932
735static void xstrcat(char **dst, const char *src, size_t *curr_len) 933static void xstrcat(char **dst, const char *src, size_t *curr_len)
736{ 934{
737 long new_len; 935 long new_len;
738 936
739 new_len = strlen(*dst) + strlen(src); 937 new_len = strlen(*dst) + strlen(src);
744 err("could not realloc %li bytes", (unsigned long)*curr_len); 942 err("could not realloc %li bytes", (unsigned long)*curr_len);
745 } 943 }
746 944
747 strcat(*dst, src); 945 strcat(*dst, src);
748} 946}
947
749static inline void xchrcat(char **dst, const char append, size_t *curr_len) 948static inline void xchrcat(char **dst, const char append, size_t *curr_len)
750{ 949{
751 static char my_app[2]; 950 static char my_app[2];
752 my_app[0] = append; 951 my_app[0] = append;
753 my_app[1] = '\0'; 952 my_app[1] = '\0';
754 xstrcat(dst, my_app, curr_len); 953 xstrcat(dst, my_app, curr_len);
755} 954}
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 955
766 956
767int main(int argc, char *argv[]) 957int main(int argc, char *argv[])
768{ 958{
769 if (argc < 2) 959 if (argc < 2)
770 usage(EXIT_FAILURE); 960 usage(EXIT_FAILURE);
771 parseargs(argc, argv); 961 parseargs(argc, argv);
772 fclose(stdout); 962 fclose(stdout);
963#ifdef __BOUNDS_CHECKING_ON
964 warn("The calls to add/delete heap should be off by 1 due to the out_buffer not being freed in scanelf_file()");
965#endif
773 return EXIT_SUCCESS; 966 return EXIT_SUCCESS;
774} 967}

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

  ViewVC Help
Powered by ViewVC 1.1.20