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

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

  ViewVC Help
Powered by ViewVC 1.1.20