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

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

  ViewVC Help
Powered by ViewVC 1.1.20