/[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.37 Revision 1.40
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.37 2005/04/16 06:34:39 vapier Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.40 2005/04/21 00:13:03 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
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.37 2005/04/16 06:34:39 vapier Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.40 2005/04/21 00:13:03 solar Exp $";
39#define argv0 "scanelf" 39#define argv0 "scanelf"
40 40
41 41
42 42
43/* prototypes */ 43/* prototypes */
57static char show_pax = 0; 57static char show_pax = 0;
58static char show_stack = 0; 58static char show_stack = 0;
59static char show_textrel = 0; 59static char show_textrel = 0;
60static char show_rpath = 0; 60static char show_rpath = 0;
61static char show_needed = 0; 61static char show_needed = 0;
62static char show_interp = 0;
62static char show_banner = 1; 63static char show_banner = 1;
63static char be_quiet = 0; 64static char be_quiet = 0;
64static char be_verbose = 0; 65static char be_verbose = 0;
66static char *find_sym = NULL, *versioned_symname = NULL;
65static char *find_sym = NULL; 67static char *out_format = NULL;
66 68
67 69
68 70
69/* scan an elf file and show all the fun stuff */ 71/* sub-funcs for scanelf_file() */
70static void scanelf_file(const char *filename) 72static void scanelf_file_pax(elfobj *elf, char *found_pax)
73{
74 char *paxflags;
75 if (!show_pax) return;
76
77 paxflags = pax_short_hf_flags(PAX_FLAGS(elf));
78 if (!be_quiet || (be_quiet && strncmp(paxflags, "PeMRxS", 6))) {
79 *found_pax = 1;
80 printf("%s ", pax_short_hf_flags(PAX_FLAGS(elf)));
81 }
82}
83static void scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro)
71{ 84{
72 int i; 85 int i;
73 char found_pax, found_stack, found_relro, found_textrel,
74 found_rpath, found_needed, found_sym;
75 elfobj *elf;
76 struct stat st;
77
78 /* make sure 'filename' exists */
79 if (lstat(filename, &st) == -1)
80 return;
81 /* always handle regular files and handle symlinked files if no -y */
82 if (!(S_ISREG(st.st_mode) || (S_ISLNK(st.st_mode) && scan_symlink)))
83 return;
84
85 found_pax = found_stack = found_relro = found_textrel = \
86 found_rpath = found_needed = found_sym = 0;
87
88 /* verify this is real ELF */
89 if ((elf = readelf(filename)) == NULL) {
90 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
91 return;
92 }
93
94 if (be_verbose > 1)
95 printf("%s: {%s,%s} scanning file\n", filename,
96 get_elfeitype(elf, EI_CLASS, elf->elf_class),
97 get_elfeitype(elf, EI_DATA, elf->data[EI_DATA]));
98 else if (be_verbose)
99 printf("%s: scanning file\n", filename);
100
101 /* show the header */
102 if (!be_quiet && show_banner) {
103 printf(" TYPE ");
104 if (show_pax) printf(" PAX ");
105 if (show_stack) printf("STK/REL ");
106 if (show_textrel) printf("TEXTREL ");
107 if (show_rpath) printf("RPATH ");
108 if (show_needed) printf("NEEDED ");
109 printf(" FILE\n");
110 show_banner = 0;
111 }
112
113 /* dump all the good stuff */
114 if (!be_quiet)
115 printf("%-7s ", get_elfetype(elf));
116
117 if (show_pax) {
118 char *paxflags = pax_short_hf_flags(PAX_FLAGS(elf));
119 if (!be_quiet || (be_quiet && strncmp(paxflags, "PeMRxS", 6))) {
120 found_pax = 1;
121 printf("%s ", pax_short_hf_flags(PAX_FLAGS(elf)));
122 }
123 }
124
125 /* stack fun */
126 if (show_stack) { 86 if (!show_stack) return;
127#define SHOW_STACK(B) \ 87#define SHOW_STACK(B) \
128 if (elf->elf_class == ELFCLASS ## B) { \ 88 if (elf->elf_class == ELFCLASS ## B) { \
129 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 89 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
130 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 90 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
131 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 91 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
132 if (EGET(phdr[i].p_type) != PT_GNU_STACK && \ 92 if (EGET(phdr[i].p_type) != PT_GNU_STACK && \
133 EGET(phdr[i].p_type) != PT_GNU_RELRO) continue; \ 93 EGET(phdr[i].p_type) != PT_GNU_RELRO) continue; \
134 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \ 94 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \
135 continue; \ 95 continue; \
136 if (EGET(phdr[i].p_type) == PT_GNU_STACK) \ 96 if (EGET(phdr[i].p_type) == PT_GNU_STACK) \
137 found_stack = 1; \ 97 *found_stack = 1; \
138 if (EGET(phdr[i].p_type) == PT_GNU_RELRO) \ 98 if (EGET(phdr[i].p_type) == PT_GNU_RELRO) \
139 found_relro = 1; \ 99 *found_relro = 1; \
140 printf("%s ", gnu_short_stack_flags(EGET(phdr[i].p_flags))); \ 100 printf("%s ", gnu_short_stack_flags(EGET(phdr[i].p_flags))); \
101 } \
102 }
103 SHOW_STACK(32)
104 SHOW_STACK(64)
105 if (!be_quiet && !*found_stack) printf("--- ");
106 if (!be_quiet && !*found_relro) printf("--- ");
107}
108static void scanelf_file_textrel(elfobj *elf, char *found_textrel)
109{
110 int i;
111 if (!show_textrel) return;
112#define SHOW_TEXTREL(B) \
113 if (elf->elf_class == ELFCLASS ## B) { \
114 Elf ## B ## _Dyn *dyn; \
115 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
116 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
117 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
118 if (phdr[i].p_type != PT_DYNAMIC) continue; \
119 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
120 while (EGET(dyn->d_tag) != DT_NULL) { \
121 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
122 *found_textrel = 1; \
123 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
124 printf("TEXTREL "); \
125 } \
126 ++dyn; \
141 } \ 127 } \
142 }
143 SHOW_STACK(32)
144 SHOW_STACK(64)
145 if (!be_quiet && !found_stack) printf("--- ");
146 if (!be_quiet && !found_relro) printf("--- ");
147 }
148
149 /* textrel fun */
150 if (show_textrel) {
151#define SHOW_TEXTREL(B) \
152 if (elf->elf_class == ELFCLASS ## B) { \
153 Elf ## B ## _Dyn *dyn; \
154 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
155 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
156 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
157 if (phdr[i].p_type != PT_DYNAMIC) continue; \
158 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
159 while (EGET(dyn->d_tag) != DT_NULL) { \
160 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
161 found_textrel = 1; \
162 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
163 fputs("TEXTREL ", stdout); \
164 } \
165 ++dyn; \
166 } \
167 } } 128 } }
168 SHOW_TEXTREL(32) 129 SHOW_TEXTREL(32)
169 SHOW_TEXTREL(64) 130 SHOW_TEXTREL(64)
170 if (!be_quiet && !found_textrel) fputs("------- ", stdout); 131 if (!be_quiet && !*found_textrel) printf("------- ");
171 } 132}
172 133static void scanelf_file_rpath(elfobj *elf, char *found_rpath)
173 /* rpath fun */ 134{
174 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */ 135 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */
175 if (show_rpath) { 136 int i;
176 char *rpath, *runpath; 137 char *rpath, *runpath;
138 void *strtbl_void;
139
140 if (!show_rpath) return;
141
177 void *strtbl_void = elf_findsecbyname(elf, ".dynstr"); 142 strtbl_void = elf_findsecbyname(elf, ".dynstr");
178 rpath = runpath = NULL; 143 rpath = runpath = NULL;
179 144
180 if (strtbl_void) { 145 if (strtbl_void) {
181#define SHOW_RPATH(B) \ 146#define SHOW_RPATH(B) \
182 if (elf->elf_class == ELFCLASS ## B) { \ 147 if (elf->elf_class == ELFCLASS ## B) { \
183 Elf ## B ## _Dyn *dyn; \ 148 Elf ## B ## _Dyn *dyn; \
184 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 149 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
185 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 150 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
188 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 153 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
189 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 154 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
190 while (EGET(dyn->d_tag) != DT_NULL) { \ 155 while (EGET(dyn->d_tag) != DT_NULL) { \
191 if (EGET(dyn->d_tag) == DT_RPATH) { \ 156 if (EGET(dyn->d_tag) == DT_RPATH) { \
192 rpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 157 rpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
193 found_rpath = 1; \ 158 *found_rpath = 1; \
194 } else if (EGET(dyn->d_tag) == DT_RUNPATH) { \ 159 } else if (EGET(dyn->d_tag) == DT_RUNPATH) { \
195 runpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 160 runpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
196 found_rpath = 1; \ 161 *found_rpath = 1; \
197 } \ 162 } \
198 ++dyn; \ 163 ++dyn; \
199 } \ 164 } \
200 } } 165 } }
201 SHOW_RPATH(32) 166 SHOW_RPATH(32)
202 SHOW_RPATH(64) 167 SHOW_RPATH(64)
203 } 168 }
204 if (rpath && runpath) { 169 if (rpath && runpath) {
205 if (!strcmp(rpath, runpath)) 170 if (!strcmp(rpath, runpath))
206 printf("%-5s ", runpath); 171 printf("%-5s ", runpath);
207 else { 172 else {
208 fprintf(stderr, "%s's RPATH [%s] != RUNPATH [%s]\n", filename, rpath, runpath); 173 fprintf(stderr, "RPATH [%s] != RUNPATH [%s]\n", rpath, runpath);
209 printf("{%s,%s} ", rpath, runpath); 174 printf("{%s,%s} ", rpath, runpath);
210 } 175 }
211 } else if (rpath || runpath) 176 } else if (rpath || runpath)
212 printf("%-5s ", (runpath ? runpath : rpath)); 177 printf("%-5s ", (runpath ? runpath : rpath));
213 else if (!be_quiet && !found_rpath) 178 else if (!be_quiet && !*found_rpath)
214 printf(" - "); 179 printf(" - ");
215 } 180}
216 181static void scanelf_file_needed(elfobj *elf, char *found_needed)
217 /* print out all the NEEDED entries */ 182{
218 if (show_needed) { 183 int i;
219 char *needed; 184 char *needed;
185 void *strtbl_void;
186
187 if (!show_needed) return;
188
220 void *strtbl_void = elf_findsecbyname(elf, ".dynstr"); 189 strtbl_void = elf_findsecbyname(elf, ".dynstr");
221 190
222 if (strtbl_void) { 191 if (strtbl_void) {
223#define SHOW_NEEDED(B) \ 192#define SHOW_NEEDED(B) \
224 if (elf->elf_class == ELFCLASS ## B) { \ 193 if (elf->elf_class == ELFCLASS ## B) { \
225 Elf ## B ## _Dyn *dyn; \ 194 Elf ## B ## _Dyn *dyn; \
226 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 195 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
227 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 196 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
228 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 197 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
229 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 198 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
230 if (be_verbose && EGET(phdr[i].p_type) == PT_INTERP) { \
231 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
232 printf("%s\n", elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr)); \
233 exit(0); \
234 } \
235 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 199 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
236 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 200 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
237 while (EGET(dyn->d_tag) != DT_NULL) { \ 201 while (EGET(dyn->d_tag) != DT_NULL) { \
238 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 202 if (EGET(dyn->d_tag) == DT_NEEDED) { \
239 needed = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 203 needed = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
240 if (found_needed) printf(","); \ 204 if (*found_needed) printf(","); \
241 printf("%s", needed); \ 205 printf("%s", needed); \
242 found_needed = 1; \ 206 *found_needed = 1; \
243 } \ 207 } \
244 ++dyn; \ 208 ++dyn; \
245 } \ 209 } \
246 } } 210 } }
247 SHOW_NEEDED(32) 211 SHOW_NEEDED(32)
248 SHOW_NEEDED(64) 212 SHOW_NEEDED(64)
249 } 213 }
250 if (!be_quiet && !found_needed) 214 if (!be_quiet && !*found_needed)
251 printf(" - "); 215 printf(" - ");
252 else if (found_needed) 216 else if (*found_needed)
253 printf(" "); 217 printf(" ");
218}
219static void scanelf_file_interp(elfobj *elf, char *found_interp)
220{
221 void *strtbl_void;
222
223 if (!show_interp) return;
224
225 strtbl_void = elf_findsecbyname(elf, ".interp");
226
227 if (strtbl_void) {
228#define SHOW_INTERP(B) \
229 if (elf->elf_class == ELFCLASS ## B) { \
230 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
231 printf("%s ", elf->data + EGET(strtbl->sh_offset)); \
232 *found_interp = 1; \
254 } 233 }
255 234 SHOW_INTERP(32)
256 /* search the symbol table for a specified symbol */ 235 SHOW_INTERP(64)
257 if (find_sym) { 236 }
237 if (!be_quiet && !*found_interp)
238 printf(" - ");
239 else if (*found_interp)
240 printf(" ");
241}
242static void scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename)
243{
244 int i;
258 void *symtab_void, *strtab_void; 245 void *symtab_void, *strtab_void;
259 char *versioned_symname;
260 size_t len;
261 246
262 len = strlen(find_sym) + 1; 247 if (!find_sym) return;
263 versioned_symname = (char *)malloc(sizeof(char) * (len+1));
264 if (!versioned_symname) {
265 warnf("Could not malloc() mem for sym scan");
266 return;
267 }
268 sprintf(versioned_symname, "%s@", find_sym);
269 248
270 symtab_void = elf_findsecbyname(elf, ".symtab"); 249 symtab_void = elf_findsecbyname(elf, ".symtab");
271 strtab_void = elf_findsecbyname(elf, ".strtab"); 250 strtab_void = elf_findsecbyname(elf, ".strtab");
272 251
273 if (symtab_void && strtab_void) { 252 if (symtab_void && strtab_void) {
274#define FIND_SYM(B) \ 253#define FIND_SYM(B) \
275 if (elf->elf_class == ELFCLASS ## B) { \ 254 if (elf->elf_class == ELFCLASS ## B) { \
276 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 255 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
277 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 256 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
278 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 257 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
281 for (i = 0; i < cnt; ++i) { \ 260 for (i = 0; i < cnt; ++i) { \
282 if (sym->st_name) { \ 261 if (sym->st_name) { \
283 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 262 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
284 if (*find_sym == '*') { \ 263 if (*find_sym == '*') { \
285 printf("%s(%s) %5lX %15s %s\n", \ 264 printf("%s(%s) %5lX %15s %s\n", \
286 ((found_sym == 0) ? "\n\t" : "\t"), \ 265 ((*found_sym == 0) ? "\n\t" : "\t"), \
287 (char *)basename(filename), \ 266 (char *)basename(filename), \
288 (long)sym->st_size, \ 267 (long)sym->st_size, \
289 (char *)get_elfstttype(sym->st_info), \ 268 (char *)get_elfstttype(sym->st_info), \
290 symname); \ 269 symname); \
291 found_sym = 1; \ 270 *found_sym = 1; \
292 } else if ((strcmp(find_sym, symname) == 0) || \ 271 } else if ((strcmp(find_sym, symname) == 0) || \
293 (strncmp(symname, versioned_symname, len) == 0)) \ 272 (strcmp(symname, versioned_symname) == 0)) \
294 found_sym++; \ 273 (*found_sym)++; \
295 } \ 274 } \
296 ++sym; \ 275 ++sym; \
297 } } 276 } }
298 FIND_SYM(32) 277 FIND_SYM(32)
299 FIND_SYM(64) 278 FIND_SYM(64)
300 } 279 }
301 free(versioned_symname);
302 if (*find_sym != '*') { 280 if (*find_sym != '*') {
303 if (found_sym) 281 if (*found_sym)
304 printf(" %s ", find_sym); 282 printf(" %s ", find_sym);
305 else if (!be_quiet) 283 else if (!be_quiet)
306 fputs(" - ", stdout); 284 printf(" - ");
285 }
286}
287/* scan an elf file and show all the fun stuff */
288static void scanelf_file(const char *filename)
289{
290 int i;
291 char found_pax, found_stack, found_relro, found_textrel,
292 found_rpath, found_needed, found_interp, found_sym,
293 found_file;
294 elfobj *elf;
295 struct stat st;
296
297 /* make sure 'filename' exists */
298 if (lstat(filename, &st) == -1) {
299 if (be_verbose > 2) printf("%s: does not exist\n", filename);
300 return;
301 }
302 /* 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))) {
304 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
305 return;
306 }
307
308 found_pax = found_stack = found_relro = found_textrel = \
309 found_rpath = found_needed = found_interp = found_sym = \
310 found_file = 0;
311
312 /* verify this is real ELF */
313 if ((elf = readelf(filename)) == NULL) {
314 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
315 return;
316 }
317
318 if (be_verbose > 1)
319 printf("%s: {%s,%s} scanning file\n", filename,
320 get_elfeitype(elf, EI_CLASS, elf->elf_class),
321 get_elfeitype(elf, EI_DATA, elf->data[EI_DATA]));
322 else if (be_verbose)
323 printf("%s: scanning file\n", filename);
324
325 /* show the header */
326 if (!be_quiet && show_banner) {
327 if (out_format) {
328 for (i=0; out_format[i]; ++i) {
329 if (out_format[i] != '%') continue;
330
331 switch (out_format[++i]) {
332 case '%': break;
333 case 'F': printf("FILE "); break;
334 case 'x': printf(" PAX "); break;
335 case 'e': printf("STK/REL "); break;
336 case 't': printf("TEXTREL "); break;
337 case 'r': printf("RPATH "); break;
338 case 'n': printf("NEEDED "); break;
339 case 'i': printf("INTERP "); break;
340 case 's': printf("SYM "); break;
341 }
307 } 342 }
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 ");
308 } 352 }
353 if (!found_file) printf(" FILE");
354 printf("\n");
355 show_banner = 0;
356 }
309 357
358 /* 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) {
364 if (out_format[i] != '%') {
365 printf("%c", out_format[i]);
366 continue;
367 }
368
369 switch (out_format[++i]) {
370 case '%': printf("%%"); break;
371 case 'F': found_file = 1; printf("%s ", filename); break;
372 case 'x': scanelf_file_pax(elf, &found_pax); break;
373 case 'e': scanelf_file_stack(elf, &found_stack, &found_relro); break;
374 case 't': scanelf_file_textrel(elf, &found_textrel); break;
375 case 'r': scanelf_file_rpath(elf, &found_rpath); break;
376 case 'n': scanelf_file_needed(elf, &found_needed); break;
377 case 'i': scanelf_file_interp(elf, &found_interp); break;
378 case 's': scanelf_file_sym(elf, &found_sym, filename); break;
379 }
380 }
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
391 if (!found_file) {
310 if (!be_quiet || found_pax || found_stack || found_textrel || \ 392 if (!be_quiet || found_pax || found_stack || found_textrel || \
311 found_rpath || found_needed || found_sym) 393 found_rpath || found_needed || found_sym)
312 puts(filename); 394 puts(filename);
395 } else {
396 printf("\n");
397 }
313 398
314 unreadelf(elf); 399 unreadelf(elf);
315} 400}
316 401
317/* scan a directory for ET_EXEC files and print when we find one */ 402/* scan a directory for ET_EXEC files and print when we find one */
322 struct stat st_top, st; 407 struct stat st_top, st;
323 char buf[_POSIX_PATH_MAX]; 408 char buf[_POSIX_PATH_MAX];
324 size_t pathlen = 0, len = 0; 409 size_t pathlen = 0, len = 0;
325 410
326 /* make sure path exists */ 411 /* make sure path exists */
327 if (lstat(path, &st_top) == -1) 412 if (lstat(path, &st_top) == -1) {
413 if (be_verbose > 2) printf("%s: does not exist\n", path);
328 return; 414 return;
415 }
329 416
330 /* ok, if it isn't a directory, assume we can open it */ 417 /* ok, if it isn't a directory, assume we can open it */
331 if (!S_ISDIR(st_top.st_mode)) { 418 if (!S_ISDIR(st_top.st_mode)) {
332 scanelf_file(path); 419 scanelf_file(path);
333 return; 420 return;
418} 505}
419 506
420 507
421 508
422/* usage / invocation handling functions */ 509/* usage / invocation handling functions */
423#define PARSE_FLAGS "plRmyxetrns:aqvo:BhV" 510#define PARSE_FLAGS "plRmyxetrnis:aqvF:o:BhV"
424#define a_argument required_argument 511#define a_argument required_argument
425static struct option const long_opts[] = { 512static struct option const long_opts[] = {
426 {"path", no_argument, NULL, 'p'}, 513 {"path", no_argument, NULL, 'p'},
427 {"ldpath", no_argument, NULL, 'l'}, 514 {"ldpath", no_argument, NULL, 'l'},
428 {"recursive", no_argument, NULL, 'R'}, 515 {"recursive", no_argument, NULL, 'R'},
431 {"pax", no_argument, NULL, 'x'}, 518 {"pax", no_argument, NULL, 'x'},
432 {"header", no_argument, NULL, 'e'}, 519 {"header", no_argument, NULL, 'e'},
433 {"textrel", no_argument, NULL, 't'}, 520 {"textrel", no_argument, NULL, 't'},
434 {"rpath", no_argument, NULL, 'r'}, 521 {"rpath", no_argument, NULL, 'r'},
435 {"needed", no_argument, NULL, 'n'}, 522 {"needed", no_argument, NULL, 'n'},
523 {"interp", no_argument, NULL, 'i'},
436 {"symbol", a_argument, NULL, 's'}, 524 {"symbol", a_argument, NULL, 's'},
437 {"all", no_argument, NULL, 'a'}, 525 {"all", no_argument, NULL, 'a'},
438 {"quiet", no_argument, NULL, 'q'}, 526 {"quiet", no_argument, NULL, 'q'},
439 {"verbose", no_argument, NULL, 'v'}, 527 {"verbose", no_argument, NULL, 'v'},
528 {"format", a_argument, NULL, 'F'},
440 {"file", a_argument, NULL, 'o'}, 529 {"file", a_argument, NULL, 'o'},
441 {"nobanner", no_argument, NULL, 'B'}, 530 {"nobanner", no_argument, NULL, 'B'},
442 {"help", no_argument, NULL, 'h'}, 531 {"help", no_argument, NULL, 'h'},
443 {"version", no_argument, NULL, 'V'}, 532 {"version", no_argument, NULL, 'V'},
444 {NULL, no_argument, NULL, 0x0} 533 {NULL, no_argument, NULL, 0x0}
452 "Print PaX markings", 541 "Print PaX markings",
453 "Print GNU_STACK markings", 542 "Print GNU_STACK markings",
454 "Print TEXTREL information", 543 "Print TEXTREL information",
455 "Print RPATH information", 544 "Print RPATH information",
456 "Print NEEDED information", 545 "Print NEEDED information",
546 "Print INTERP information",
457 "Find a specified symbol", 547 "Find a specified symbol",
458 "Print all scanned info (-x -e -t -r)\n", 548 "Print all scanned info (-x -e -t -r)\n",
459 "Only output 'bad' things", 549 "Only output 'bad' things",
460 "Be verbose (can be specified more than once)", 550 "Be verbose (can be specified more than once)",
551 "Use specified format for output",
461 "Write output stream to a filename", 552 "Write output stream to a filename",
462 "Don't display the header", 553 "Don't display the header",
463 "Print this help and exit", 554 "Print this help and exit",
464 "Print version and exit", 555 "Print version and exit",
465 NULL 556 NULL
489 580
490 opterr = 0; 581 opterr = 0;
491 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) { 582 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
492 switch (flag) { 583 switch (flag) {
493 584
494 case 'V': /* version info */ 585 case 'V':
495 printf("%s compiled %s\n%s\n" 586 printf("%s compiled %s\n%s\n"
496 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n", 587 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n",
497 __FILE__, __DATE__, rcsid, argv0); 588 __FILE__, __DATE__, rcsid, argv0);
498 exit(EXIT_SUCCESS); 589 exit(EXIT_SUCCESS);
499 break; 590 break;
506 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 597 err("Could not open output stream '%s': %s", optarg, strerror(errno));
507 stdout = fp; 598 stdout = fp;
508 break; 599 break;
509 } 600 }
510 601
602 case 's': {
603 size_t len;
511 case 's': find_sym = strdup(optarg); break; 604 find_sym = strdup(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;
611 versioned_symname = (char *)malloc(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);
619 break;
620 }
621
622 case 'F': {
623 out_format = strdup(optarg);
624 if (!out_format)
625 err("Could not malloc() mem for output format");
626 break;
627 }
512 628
513 case 'y': scan_symlink = 0; break; 629 case 'y': scan_symlink = 0; break;
514 case 'B': show_banner = 0; break; 630 case 'B': show_banner = 0; break;
515 case 'l': scan_ldpath = 1; break; 631 case 'l': scan_ldpath = 1; break;
516 case 'p': scan_envpath = 1; break; 632 case 'p': scan_envpath = 1; break;
519 case 'x': show_pax = 1; break; 635 case 'x': show_pax = 1; break;
520 case 'e': show_stack = 1; break; 636 case 'e': show_stack = 1; break;
521 case 't': show_textrel = 1; break; 637 case 't': show_textrel = 1; break;
522 case 'r': show_rpath = 1; break; 638 case 'r': show_rpath = 1; break;
523 case 'n': show_needed = 1; break; 639 case 'n': show_needed = 1; break;
640 case 'i': show_interp = 1; break;
524 case 'q': be_quiet = 1; break; 641 case 'q': be_quiet = 1; break;
525 case 'v': be_verbose = (be_verbose % 20) + 1; break; 642 case 'v': be_verbose = (be_verbose % 20) + 1; break;
526 case 'a': show_pax = show_stack = show_textrel = show_needed = show_rpath = 1; break; 643 case 'a': show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 1; break;
527 644
528 case ':': 645 case ':':
529 warn("Option missing parameter"); 646 warn("Option missing parameter\n");
530 usage(EXIT_FAILURE); 647 usage(EXIT_FAILURE);
531 break; 648 break;
532 case '?': 649 case '?':
533 warn("Unknown option"); 650 warn("Unknown option\n");
534 usage(EXIT_FAILURE); 651 usage(EXIT_FAILURE);
535 break; 652 break;
536 default: 653 default:
537 err("Unhandled option '%c'", flag); 654 err("Unhandled option '%c'", flag);
538 break; 655 break;
540 } 657 }
541 658
542 if (be_quiet && be_verbose) 659 if (be_quiet && be_verbose)
543 err("You can be quiet or you can be verbose, not both, stupid"); 660 err("You can be quiet or you can be verbose, not both, stupid");
544 661
662 /* let the format option override all other options */
663 if (out_format) {
664 show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 0;
665 for (flag=0; out_format[flag]; ++flag) {
666 if (out_format[flag] != '%') continue;
667
668 switch (out_format[++flag]) {
669 case '%': break;
670 case 'F': break;
671 case 's': break;
672 case 'x': show_pax = 1; break;
673 case 'e': show_stack = 1; break;
674 case 't': show_textrel = 1; break;
675 case 'r': show_rpath = 1; break;
676 case 'n': show_needed = 1; break;
677 case 'i': show_interp = 1; break;
678 default:
679 err("Invalid format specifier '%c' (byte %i)",
680 out_format[flag], flag+1);
681 }
682 }
683 }
684
685 /* now lets actually do the scanning */
545 if (scan_ldpath) scanelf_ldpath(); 686 if (scan_ldpath) scanelf_ldpath();
546 if (scan_envpath) scanelf_envpath(); 687 if (scan_envpath) scanelf_envpath();
547 if (optind == argc && !scan_ldpath && !scan_envpath) 688 if (optind == argc && !scan_ldpath && !scan_envpath)
548 err("Nothing to scan !?"); 689 err("Nothing to scan !?");
549 while (optind < argc) 690 while (optind < argc)
550 scanelf_dir(argv[optind++]); 691 scanelf_dir(argv[optind++]);
551 692
552 if (find_sym) free(find_sym); 693 /* clean up */
694 if (find_sym) {
695 free(find_sym);
696 free(versioned_symname);
697 }
698 if (out_format) free(out_format);
553} 699}
554 700
555 701
556 702
557int main(int argc, char *argv[]) 703int main(int argc, char *argv[])

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

  ViewVC Help
Powered by ViewVC 1.1.20