/[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.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.32 2005/04/07 00:01:40 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.32 2005/04/07 00:01:40 vapier Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.40 2005/04/21 00:13:03 solar 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);
60static void parseargs(int argc, char *argv[]); 49static void parseargs(int argc, char *argv[]);
61 50
62/* variables to control behavior */ 51/* variables to control behavior */
63static char scan_ldpath = 0; 52static char scan_ldpath = 0;
64static char scan_envpath = 0; 53static char scan_envpath = 0;
54static char scan_symlink = 1;
65static char dir_recurse = 0; 55static char dir_recurse = 0;
66static char dir_crossmount = 1; 56static char dir_crossmount = 1;
67static char show_pax = 0; 57static char show_pax = 0;
68static char show_stack = 0; 58static char show_stack = 0;
69static char show_textrel = 0; 59static char show_textrel = 0;
70static char show_rpath = 0; 60static char show_rpath = 0;
71static char show_needed = 0; 61static char show_needed = 0;
62static char show_interp = 0;
72static char show_banner = 1; 63static char show_banner = 1;
73static char be_quiet = 0; 64static char be_quiet = 0;
74static char be_verbose = 0; 65static char be_verbose = 0;
66static char *find_sym = NULL, *versioned_symname = NULL;
75static char *find_sym = NULL; 67static char *out_format = NULL;
76 68
77 69
78 70
79/* scan an elf file and show all the fun stuff */ 71/* sub-funcs for scanelf_file() */
80static 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)
81{ 84{
82 int i; 85 int i;
83 char found_pax, found_stack, found_relro, found_textrel,
84 found_rpath, found_needed, found_sym;
85 elfobj *elf;
86
87 found_pax = found_stack = found_relro = found_textrel = \
88 found_rpath = found_needed = found_sym = 0;
89
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));
121 if (!be_quiet || (be_quiet && strncmp(paxflags, "PeMRxS", 6))) {
122 found_pax = 1;
123 printf("%s ", pax_short_hf_flags(PAX_FLAGS(elf)));
124 }
125 }
126
127 /* stack fun */
128 if (show_stack) { 86 if (!show_stack) return;
129#define SHOW_STACK(B) \ 87#define SHOW_STACK(B) \
130 if (elf->elf_class == ELFCLASS ## B) { \ 88 if (elf->elf_class == ELFCLASS ## B) { \
131 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 89 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
132 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 90 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
133 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 91 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
134 if (EGET(phdr[i].p_type) != PT_GNU_STACK && \ 92 if (EGET(phdr[i].p_type) != PT_GNU_STACK && \
135 EGET(phdr[i].p_type) != PT_GNU_RELRO) continue; \ 93 EGET(phdr[i].p_type) != PT_GNU_RELRO) continue; \
136 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \ 94 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \
137 continue; \ 95 continue; \
138 if (EGET(phdr[i].p_type) == PT_GNU_STACK) \ 96 if (EGET(phdr[i].p_type) == PT_GNU_STACK) \
139 found_stack = 1; \ 97 *found_stack = 1; \
140 if (EGET(phdr[i].p_type) == PT_GNU_RELRO) \ 98 if (EGET(phdr[i].p_type) == PT_GNU_RELRO) \
141 found_relro = 1; \ 99 *found_relro = 1; \
142 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; \
143 } \ 127 } \
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 } } 128 } }
170 SHOW_TEXTREL(32) 129 SHOW_TEXTREL(32)
171 SHOW_TEXTREL(64) 130 SHOW_TEXTREL(64)
172 if (!be_quiet && !found_textrel) printf("------- "); 131 if (!be_quiet && !*found_textrel) printf("------- ");
173 } 132}
174 133static void scanelf_file_rpath(elfobj *elf, char *found_rpath)
175 /* rpath fun */ 134{
176 /* 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 */
177 if (show_rpath) { 136 int i;
178 char *rpath, *runpath; 137 char *rpath, *runpath;
138 void *strtbl_void;
139
140 if (!show_rpath) return;
141
179 void *strtbl_void = elf_findsecbyname(elf, ".dynstr"); 142 strtbl_void = elf_findsecbyname(elf, ".dynstr");
180 rpath = runpath = NULL; 143 rpath = runpath = NULL;
181 144
182 if (strtbl_void) { 145 if (strtbl_void) {
183#define SHOW_RPATH(B) \ 146#define SHOW_RPATH(B) \
184 if (elf->elf_class == ELFCLASS ## B) { \ 147 if (elf->elf_class == ELFCLASS ## B) { \
185 Elf ## B ## _Dyn *dyn; \ 148 Elf ## B ## _Dyn *dyn; \
186 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 149 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
187 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 150 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
190 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 153 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
191 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 154 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
192 while (EGET(dyn->d_tag) != DT_NULL) { \ 155 while (EGET(dyn->d_tag) != DT_NULL) { \
193 if (EGET(dyn->d_tag) == DT_RPATH) { \ 156 if (EGET(dyn->d_tag) == DT_RPATH) { \
194 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); \
195 found_rpath = 1; \ 158 *found_rpath = 1; \
196 } else if (EGET(dyn->d_tag) == DT_RUNPATH) { \ 159 } else if (EGET(dyn->d_tag) == DT_RUNPATH) { \
197 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); \
198 found_rpath = 1; \ 161 *found_rpath = 1; \
199 } \ 162 } \
200 ++dyn; \ 163 ++dyn; \
201 } \ 164 } \
202 } } 165 } }
203 SHOW_RPATH(32) 166 SHOW_RPATH(32)
204 SHOW_RPATH(64) 167 SHOW_RPATH(64)
205 } 168 }
206 if (rpath && runpath) { 169 if (rpath && runpath) {
207 if (!strcmp(rpath, runpath)) 170 if (!strcmp(rpath, runpath))
208 printf("%-5s ", runpath); 171 printf("%-5s ", runpath);
209 else { 172 else {
210 fprintf(stderr, "%s's RPATH [%s] != RUNPATH [%s]\n", filename, rpath, runpath); 173 fprintf(stderr, "RPATH [%s] != RUNPATH [%s]\n", rpath, runpath);
211 printf("{%s,%s} ", rpath, runpath); 174 printf("{%s,%s} ", rpath, runpath);
212 } 175 }
213 } else if (rpath || runpath) 176 } else if (rpath || runpath)
214 printf("%-5s ", (runpath ? runpath : rpath)); 177 printf("%-5s ", (runpath ? runpath : rpath));
215 else if (!be_quiet && !found_rpath) 178 else if (!be_quiet && !*found_rpath)
216 printf(" - "); 179 printf(" - ");
217 } 180}
218 181static void scanelf_file_needed(elfobj *elf, char *found_needed)
219 /* print out all the NEEDED entries */ 182{
220 if (show_needed) { 183 int i;
221 char *needed; 184 char *needed;
185 void *strtbl_void;
186
187 if (!show_needed) return;
188
222 void *strtbl_void = elf_findsecbyname(elf, ".dynstr"); 189 strtbl_void = elf_findsecbyname(elf, ".dynstr");
223 190
224 if (strtbl_void) { 191 if (strtbl_void) {
225#define SHOW_NEEDED(B) \ 192#define SHOW_NEEDED(B) \
226 if (elf->elf_class == ELFCLASS ## B) { \ 193 if (elf->elf_class == ELFCLASS ## B) { \
227 Elf ## B ## _Dyn *dyn; \ 194 Elf ## B ## _Dyn *dyn; \
228 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 195 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
229 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 196 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
230 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 197 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
231 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 198 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; \ 199 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
238 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 200 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
239 while (EGET(dyn->d_tag) != DT_NULL) { \ 201 while (EGET(dyn->d_tag) != DT_NULL) { \
240 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 202 if (EGET(dyn->d_tag) == DT_NEEDED) { \
241 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); \
242 if (found_needed) printf(","); \ 204 if (*found_needed) printf(","); \
243 printf("%s", needed); \ 205 printf("%s", needed); \
244 found_needed = 1; \ 206 *found_needed = 1; \
245 } \ 207 } \
246 ++dyn; \ 208 ++dyn; \
247 } \ 209 } \
248 } } 210 } }
249 SHOW_NEEDED(32) 211 SHOW_NEEDED(32)
250 SHOW_NEEDED(64) 212 SHOW_NEEDED(64)
251 } 213 }
252 if (!be_quiet && !found_needed) 214 if (!be_quiet && !*found_needed)
253 printf(" - "); 215 printf(" - ");
254 else if (found_needed) 216 else if (*found_needed)
255 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; \
256 } 233 }
257 234 SHOW_INTERP(32)
258 /* search the symbol table for a specified symbol */ 235 SHOW_INTERP(64)
259 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;
260 void *symtab_void, *strtab_void; 245 void *symtab_void, *strtab_void;
261 char *versioned_symname;
262 size_t len;
263 246
264 len = strlen(find_sym) + 1; 247 if (!find_sym) return;
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 248
272 symtab_void = elf_findsecbyname(elf, ".symtab"); 249 symtab_void = elf_findsecbyname(elf, ".symtab");
273 strtab_void = elf_findsecbyname(elf, ".strtab"); 250 strtab_void = elf_findsecbyname(elf, ".strtab");
274 251
275 if (symtab_void && strtab_void) { 252 if (symtab_void && strtab_void) {
276#define FIND_SYM(B) \ 253#define FIND_SYM(B) \
277 if (elf->elf_class == ELFCLASS ## B) { \ 254 if (elf->elf_class == ELFCLASS ## B) { \
278 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 255 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
279 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 256 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
280 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)); \
283 for (i = 0; i < cnt; ++i) { \ 260 for (i = 0; i < cnt; ++i) { \
284 if (sym->st_name) { \ 261 if (sym->st_name) { \
285 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)); \
286 if (*find_sym == '*') { \ 263 if (*find_sym == '*') { \
287 printf("%s(%s) %5lX %15s %s\n", \ 264 printf("%s(%s) %5lX %15s %s\n", \
288 ((found_sym == 0) ? "\n\t" : "\t"), \ 265 ((*found_sym == 0) ? "\n\t" : "\t"), \
289 (char *)basename(filename), \ 266 (char *)basename(filename), \
290 (long)sym->st_size, \ 267 (long)sym->st_size, \
291 (char *)get_elfstttype(sym->st_info), \ 268 (char *)get_elfstttype(sym->st_info), \
292 symname); \ 269 symname); \
293 found_sym = 1; \ 270 *found_sym = 1; \
294 } else if ((strcmp(find_sym, symname) == 0) || \ 271 } else if ((strcmp(find_sym, symname) == 0) || \
295 (strncmp(symname, versioned_symname, len) == 0)) \ 272 (strcmp(symname, versioned_symname) == 0)) \
296 found_sym++; \ 273 (*found_sym)++; \
297 } \ 274 } \
298 ++sym; \ 275 ++sym; \
299 } } 276 } }
300 FIND_SYM(32) 277 FIND_SYM(32)
301 FIND_SYM(64) 278 FIND_SYM(64)
302 } 279 }
303 free(versioned_symname);
304 if (*find_sym != '*') { 280 if (*find_sym != '*') {
305 if (found_sym) 281 if (*found_sym)
306 printf(" %s ", find_sym); 282 printf(" %s ", find_sym);
307 else if (!be_quiet) 283 else if (!be_quiet)
308 printf(" - "); 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 }
309 } 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 ");
310 } 352 }
353 if (!found_file) printf(" FILE");
354 printf("\n");
355 show_banner = 0;
356 }
311 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) {
312 if (!be_quiet || found_pax || found_stack || found_textrel || \ 392 if (!be_quiet || found_pax || found_stack || found_textrel || \
313 found_rpath || found_needed || found_sym) 393 found_rpath || found_needed || found_sym)
314 printf("%s\n", filename); 394 puts(filename);
395 } else {
396 printf("\n");
397 }
315 398
316 unreadelf(elf); 399 unreadelf(elf);
317} 400}
318 401
319/* 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 */
324 struct stat st_top, st; 407 struct stat st_top, st;
325 char buf[_POSIX_PATH_MAX]; 408 char buf[_POSIX_PATH_MAX];
326 size_t pathlen = 0, len = 0; 409 size_t pathlen = 0, len = 0;
327 410
328 /* make sure path exists */ 411 /* make sure path exists */
329 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);
330 return; 414 return;
415 }
331 416
332 /* 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 */
333 if (!S_ISDIR(st_top.st_mode)) { 418 if (!S_ISDIR(st_top.st_mode)) {
334 scanelf_file(path); 419 scanelf_file(path);
335 return; 420 return;
420} 505}
421 506
422 507
423 508
424/* usage / invocation handling functions */ 509/* usage / invocation handling functions */
425#define PARSE_FLAGS "plRmxetrns:aqvo:BhV" 510#define PARSE_FLAGS "plRmyxetrnis:aqvF:o:BhV"
426#define a_argument required_argument 511#define a_argument required_argument
427static struct option const long_opts[] = { 512static struct option const long_opts[] = {
428 {"path", no_argument, NULL, 'p'}, 513 {"path", no_argument, NULL, 'p'},
429 {"ldpath", no_argument, NULL, 'l'}, 514 {"ldpath", no_argument, NULL, 'l'},
430 {"recursive", no_argument, NULL, 'R'}, 515 {"recursive", no_argument, NULL, 'R'},
431 {"mount", no_argument, NULL, 'm'}, 516 {"mount", no_argument, NULL, 'm'},
517 {"symlink", no_argument, NULL, 'y'},
432 {"pax", no_argument, NULL, 'x'}, 518 {"pax", no_argument, NULL, 'x'},
433 {"header", no_argument, NULL, 'e'}, 519 {"header", no_argument, NULL, 'e'},
434 {"textrel", no_argument, NULL, 't'}, 520 {"textrel", no_argument, NULL, 't'},
435 {"rpath", no_argument, NULL, 'r'}, 521 {"rpath", no_argument, NULL, 'r'},
436 {"needed", no_argument, NULL, 'n'}, 522 {"needed", no_argument, NULL, 'n'},
523 {"interp", no_argument, NULL, 'i'},
437 {"symbol", a_argument, NULL, 's'}, 524 {"symbol", a_argument, NULL, 's'},
438 {"all", no_argument, NULL, 'a'}, 525 {"all", no_argument, NULL, 'a'},
439 {"quiet", no_argument, NULL, 'q'}, 526 {"quiet", no_argument, NULL, 'q'},
440 {"verbose", no_argument, NULL, 'v'}, 527 {"verbose", no_argument, NULL, 'v'},
528 {"format", a_argument, NULL, 'F'},
441 {"file", a_argument, NULL, 'o'}, 529 {"file", a_argument, NULL, 'o'},
442 {"nobanner", no_argument, NULL, 'B'}, 530 {"nobanner", no_argument, NULL, 'B'},
443 {"help", no_argument, NULL, 'h'}, 531 {"help", no_argument, NULL, 'h'},
444 {"version", no_argument, NULL, 'V'}, 532 {"version", no_argument, NULL, 'V'},
445 {NULL, no_argument, NULL, 0x0} 533 {NULL, no_argument, NULL, 0x0}
446}; 534};
447static char *opts_help[] = { 535static char *opts_help[] = {
448 "Scan all directories in PATH environment", 536 "Scan all directories in PATH environment",
449 "Scan all directories in /etc/ld.so.conf", 537 "Scan all directories in /etc/ld.so.conf",
450 "Scan directories recursively", 538 "Scan directories recursively",
451 "Don't recursively cross mount points\n", 539 "Don't recursively cross mount points",
540 "Don't scan symlinks\n",
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
467 558
468/* display usage and exit */ 559/* display usage and exit */
469static void usage(int status) 560static void usage(int status)
470{ 561{
471 int i; 562 int i;
472 printf(" Scan ELF binaries for stuff\n" 563 printf(" Scan ELF binaries for stuff\n\n"
473 "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0); 564 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0);
474 printf("Options:\n"); 565 printf("Options: -[%s]\n", PARSE_FLAGS);
475 for (i = 0; long_opts[i].name; ++i) 566 for (i = 0; long_opts[i].name; ++i)
476 if (long_opts[i].has_arg == no_argument) 567 if (long_opts[i].has_arg == no_argument)
477 printf(" -%c, --%-13s %s\n", long_opts[i].val, 568 printf(" -%c, --%-13s %s\n", long_opts[i].val,
478 long_opts[i].name, opts_help[i]); 569 long_opts[i].name, opts_help[i]);
479 else 570 else
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 }
512 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 }
628
629 case 'y': scan_symlink = 0; break;
513 case 'B': show_banner = 0; break; 630 case 'B': show_banner = 0; break;
514 case 'l': scan_ldpath = 1; break; 631 case 'l': scan_ldpath = 1; break;
515 case 'p': scan_envpath = 1; break; 632 case 'p': scan_envpath = 1; break;
516 case 'R': dir_recurse = 1; break; 633 case 'R': dir_recurse = 1; break;
517 case 'm': dir_crossmount = 0; break; 634 case 'm': dir_crossmount = 0; break;
518 case 'x': show_pax = 1; break; 635 case 'x': show_pax = 1; break;
519 case 'e': show_stack = 1; break; 636 case 'e': show_stack = 1; break;
520 case 't': show_textrel = 1; break; 637 case 't': show_textrel = 1; break;
521 case 'r': show_rpath = 1; break; 638 case 'r': show_rpath = 1; break;
522 case 'n': show_needed = 1; break; 639 case 'n': show_needed = 1; break;
640 case 'i': show_interp = 1; break;
523 case 'q': be_quiet = 1; break; 641 case 'q': be_quiet = 1; break;
524 case 'v': be_verbose = (be_verbose % 20) + 1; break; 642 case 'v': be_verbose = (be_verbose % 20) + 1; break;
525 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;
526 644
527 case ':': 645 case ':':
528 warn("Option missing parameter"); 646 warn("Option missing parameter\n");
529 usage(EXIT_FAILURE); 647 usage(EXIT_FAILURE);
530 break; 648 break;
531 case '?': 649 case '?':
532 warn("Unknown option"); 650 warn("Unknown option\n");
533 usage(EXIT_FAILURE); 651 usage(EXIT_FAILURE);
534 break; 652 break;
535 default: 653 default:
536 err("Unhandled option '%c'", flag); 654 err("Unhandled option '%c'", flag);
537 break; 655 break;
539 } 657 }
540 658
541 if (be_quiet && be_verbose) 659 if (be_quiet && be_verbose)
542 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");
543 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 */
544 if (scan_ldpath) scanelf_ldpath(); 686 if (scan_ldpath) scanelf_ldpath();
545 if (scan_envpath) scanelf_envpath(); 687 if (scan_envpath) scanelf_envpath();
546 if (optind == argc && !scan_ldpath && !scan_envpath) 688 if (optind == argc && !scan_ldpath && !scan_envpath)
547 err("Nothing to scan !?"); 689 err("Nothing to scan !?");
548 while (optind < argc) 690 while (optind < argc)
549 scanelf_dir(argv[optind++]); 691 scanelf_dir(argv[optind++]);
550 692
551 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);
552} 699}
553 700
554 701
555 702
556int main(int argc, char *argv[]) 703int main(int argc, char *argv[])

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

  ViewVC Help
Powered by ViewVC 1.1.20