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

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

  ViewVC Help
Powered by ViewVC 1.1.20