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

Legend:
Removed from v.1.32  
changed lines
  Added in v.1.59

  ViewVC Help
Powered by ViewVC 1.1.20