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

Legend:
Removed from v.1.40  
changed lines
  Added in v.1.60

  ViewVC Help
Powered by ViewVC 1.1.20