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

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

  ViewVC Help
Powered by ViewVC 1.1.20