/[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.46
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.46 2005/05/16 21:59:06 vapier Exp $
6 * 6 *
7 ******************************************************************** 7 ********************************************************************
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the 10 * published by the Free Software Foundation; either version 2 of the
33#include <getopt.h> 33#include <getopt.h>
34#include <assert.h> 34#include <assert.h>
35 35
36#include "paxelf.h" 36#include "paxelf.h"
37 37
38static const char *rcsid = "$Id: scanelf.c,v 1.40 2005/04/21 00:13:03 solar Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.46 2005/05/16 21:59:06 vapier Exp $";
39#define argv0 "scanelf" 39#define argv0 "scanelf"
40 40
41 41
42 42
43/* prototypes */ 43/* prototypes */
45static void scanelf_dir(const char *path); 45static void scanelf_dir(const char *path);
46static void scanelf_ldpath(); 46static void scanelf_ldpath();
47static void scanelf_envpath(); 47static void scanelf_envpath();
48static void usage(int status); 48static void usage(int status);
49static void parseargs(int argc, char *argv[]); 49static void parseargs(int argc, char *argv[]);
50static char *xstrdup(char *s);
51static void *xmalloc(size_t size);
52static void xstrcat(char **dst, const char *src, size_t *curr_len);
53static inline void xchrcat(char **dst, const char append, size_t *curr_len);
54static int xemptybuffer(const char *buff);
50 55
51/* variables to control behavior */ 56/* variables to control behavior */
52static char scan_ldpath = 0; 57static char scan_ldpath = 0;
53static char scan_envpath = 0; 58static char scan_envpath = 0;
54static char scan_symlink = 1; 59static char scan_symlink = 1;
67static char *out_format = NULL; 72static char *out_format = NULL;
68 73
69 74
70 75
71/* sub-funcs for scanelf_file() */ 76/* sub-funcs for scanelf_file() */
72static void scanelf_file_pax(elfobj *elf, char *found_pax) 77static char *scanelf_file_pax(elfobj *elf, char *found_pax)
73{ 78{
74 char *paxflags; 79 static char *paxflags;
80
75 if (!show_pax) return; 81 if (!show_pax) return NULL;
76 82
77 paxflags = pax_short_hf_flags(PAX_FLAGS(elf)); 83 paxflags = pax_short_hf_flags(PAX_FLAGS(elf));
78 if (!be_quiet || (be_quiet && strncmp(paxflags, "PeMRxS", 6))) { 84 if (!be_quiet || (be_quiet && strncmp(paxflags, "PeMRxS", 6))) {
79 *found_pax = 1; 85 *found_pax = 1;
80 printf("%s ", pax_short_hf_flags(PAX_FLAGS(elf))); 86 return paxflags;
81 } 87 }
88
89 return NULL;
82} 90}
83static void scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro) 91static char *scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro)
84{ 92{
85 int i; 93 static char ret[8];
94 char *found;
95 unsigned long i, off, shown;
96
86 if (!show_stack) return; 97 if (!show_stack) return NULL;
98
99 shown = 0;
100 strcpy(ret, "--- ---");
101
102 if (elf->phdr) {
87#define SHOW_STACK(B) \ 103#define SHOW_STACK(B) \
88 if (elf->elf_class == ELFCLASS ## B) { \ 104 if (elf->elf_class == ELFCLASS ## B) { \
89 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 105 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
90 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 106 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
91 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 107 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
92 if (EGET(phdr[i].p_type) != PT_GNU_STACK && \ 108 if (EGET(phdr[i].p_type) == PT_GNU_STACK) { \
109 found = found_stack; \
110 off = 0; \
93 EGET(phdr[i].p_type) != PT_GNU_RELRO) continue; \ 111 } else if (EGET(phdr[i].p_type) == PT_GNU_RELRO) { \
112 found = found_relro; \
113 off = 3; \
114 } else \
115 continue; \
94 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \ 116 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \
95 continue; \ 117 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))); \ 118 memcpy(ret+off, gnu_short_stack_flags(EGET(phdr[i].p_flags)), 3); \
119 *found = 1; \
120 ++shown; \
101 } \ 121 } \
102 } 122 }
103 SHOW_STACK(32) 123 SHOW_STACK(32)
104 SHOW_STACK(64) 124 SHOW_STACK(64)
105 if (!be_quiet && !*found_stack) printf("--- "); 125 }
106 if (!be_quiet && !*found_relro) printf("--- "); 126
127 if (be_quiet && !shown)
128 return NULL;
129 else
130 return ret;
107} 131}
108static void scanelf_file_textrel(elfobj *elf, char *found_textrel) 132static char *scanelf_file_textrel(elfobj *elf, char *found_textrel)
109{ 133{
110 int i; 134 static char *ret = "TEXTREL";
135 unsigned long i;
136
111 if (!show_textrel) return; 137 if (!show_textrel) return NULL;
138
139 if (elf->phdr) {
112#define SHOW_TEXTREL(B) \ 140#define SHOW_TEXTREL(B) \
113 if (elf->elf_class == ELFCLASS ## B) { \ 141 if (elf->elf_class == ELFCLASS ## B) { \
114 Elf ## B ## _Dyn *dyn; \ 142 Elf ## B ## _Dyn *dyn; \
115 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 143 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
116 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 144 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
145 Elf ## B ## _Off offset; \
117 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 146 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
118 if (phdr[i].p_type != PT_DYNAMIC) continue; \ 147 if (phdr[i].p_type != PT_DYNAMIC) continue; \
148 offset = EGET(phdr[i].p_offset); \
149 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
119 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 150 dyn = DYN ## B (elf->data + offset); \
120 while (EGET(dyn->d_tag) != DT_NULL) { \ 151 while (EGET(dyn->d_tag) != DT_NULL) { \
121 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \ 152 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
122 *found_textrel = 1; \ 153 *found_textrel = 1; \
123 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \ 154 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
124 printf("TEXTREL "); \ 155 return ret; \
125 } \ 156 } \
126 ++dyn; \ 157 ++dyn; \
127 } \ 158 } \
128 } } 159 } }
129 SHOW_TEXTREL(32) 160 SHOW_TEXTREL(32)
130 SHOW_TEXTREL(64) 161 SHOW_TEXTREL(64)
131 if (!be_quiet && !*found_textrel) printf("------- "); 162 }
163
164 if (be_quiet)
165 return NULL;
166 else
167 return " - ";
132} 168}
133static void scanelf_file_rpath(elfobj *elf, char *found_rpath) 169static void scanelf_file_rpath(elfobj *elf, char *found_rpath, char **ret, size_t *ret_len)
134{ 170{
135 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */ 171 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */
136 int i; 172 unsigned long i;
137 char *rpath, *runpath; 173 char *rpath, *runpath;
138 void *strtbl_void; 174 void *strtbl_void;
139 175
140 if (!show_rpath) return; 176 if (!show_rpath) return;
141 177
142 strtbl_void = elf_findsecbyname(elf, ".dynstr"); 178 strtbl_void = elf_findsecbyname(elf, ".dynstr");
143 rpath = runpath = NULL; 179 rpath = runpath = NULL;
144 180
145 if (strtbl_void) { 181 if (elf->phdr && strtbl_void) {
146#define SHOW_RPATH(B) \ 182#define SHOW_RPATH(B) \
147 if (elf->elf_class == ELFCLASS ## B) { \ 183 if (elf->elf_class == ELFCLASS ## B) { \
148 Elf ## B ## _Dyn *dyn; \ 184 Elf ## B ## _Dyn *dyn; \
149 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 185 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
150 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 186 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
151 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 187 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
188 Elf ## B ## _Off offset; \
152 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 189 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
153 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 190 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
191 offset = EGET(phdr[i].p_offset); \
192 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
154 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 193 dyn = DYN ## B (elf->data + offset); \
155 while (EGET(dyn->d_tag) != DT_NULL) { \ 194 while (EGET(dyn->d_tag) != DT_NULL) { \
156 if (EGET(dyn->d_tag) == DT_RPATH) { \ 195 if (EGET(dyn->d_tag) == DT_RPATH) { \
196 if (rpath) warn("ELF has multiple DT_RPATH's !?"); \
157 rpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 197 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
198 if (offset >= elf->len) continue; \
199 rpath = (char*)(elf->data + offset); \
158 *found_rpath = 1; \ 200 *found_rpath = 1; \
159 } else if (EGET(dyn->d_tag) == DT_RUNPATH) { \ 201 } else if (EGET(dyn->d_tag) == DT_RUNPATH) { \
202 if (runpath) warn("ELF has multiple DT_RUNPATH's !?"); \
160 runpath = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 203 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
204 if (offset >= elf->len) continue; \
205 runpath = (char*)(elf->data + offset); \
161 *found_rpath = 1; \ 206 *found_rpath = 1; \
162 } \ 207 } \
163 ++dyn; \ 208 ++dyn; \
164 } \ 209 } \
165 } } 210 } }
166 SHOW_RPATH(32) 211 SHOW_RPATH(32)
167 SHOW_RPATH(64) 212 SHOW_RPATH(64)
168 } 213 }
214
169 if (rpath && runpath) { 215 if (rpath && runpath) {
170 if (!strcmp(rpath, runpath)) 216 if (!strcmp(rpath, runpath)) {
171 printf("%-5s ", runpath); 217 xstrcat(ret, runpath, ret_len);
172 else { 218 } else {
173 fprintf(stderr, "RPATH [%s] != RUNPATH [%s]\n", rpath, runpath); 219 fprintf(stderr, "RPATH [%s] != RUNPATH [%s]\n", rpath, runpath);
174 printf("{%s,%s} ", rpath, runpath); 220 xchrcat(ret, '{', ret_len);
221 xstrcat(ret, rpath, ret_len);
222 xchrcat(ret, ',', ret_len);
223 xstrcat(ret, runpath, ret_len);
224 xchrcat(ret, '}', ret_len);
175 } 225 }
176 } else if (rpath || runpath) 226 } else if (rpath || runpath)
177 printf("%-5s ", (runpath ? runpath : rpath)); 227 xstrcat(ret, (runpath ? runpath : rpath), ret_len);
178 else if (!be_quiet && !*found_rpath) 228 else if (!be_quiet)
179 printf(" - "); 229 xstrcat(ret, " - ", ret_len);
180} 230}
181static void scanelf_file_needed(elfobj *elf, char *found_needed) 231static void scanelf_file_needed(elfobj *elf, char *found_needed, char **ret, size_t *ret_len)
182{ 232{
183 int i; 233 unsigned long i;
184 char *needed; 234 char *needed;
185 void *strtbl_void; 235 void *strtbl_void;
186 236
187 if (!show_needed) return; 237 if (!show_needed) return;
188 238
189 strtbl_void = elf_findsecbyname(elf, ".dynstr"); 239 strtbl_void = elf_findsecbyname(elf, ".dynstr");
190 240
191 if (strtbl_void) { 241 if (elf->phdr && strtbl_void) {
192#define SHOW_NEEDED(B) \ 242#define SHOW_NEEDED(B) \
193 if (elf->elf_class == ELFCLASS ## B) { \ 243 if (elf->elf_class == ELFCLASS ## B) { \
194 Elf ## B ## _Dyn *dyn; \ 244 Elf ## B ## _Dyn *dyn; \
195 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 245 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
196 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 246 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
197 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 247 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
248 Elf ## B ## _Off offset; \
198 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 249 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
199 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 250 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
251 offset = EGET(phdr[i].p_offset); \
252 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
200 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 253 dyn = DYN ## B (elf->data + offset); \
201 while (EGET(dyn->d_tag) != DT_NULL) { \ 254 while (EGET(dyn->d_tag) != DT_NULL) { \
202 if (EGET(dyn->d_tag) == DT_NEEDED) { \ 255 if (EGET(dyn->d_tag) == DT_NEEDED) { \
203 needed = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \ 256 offset = EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
204 if (*found_needed) printf(","); \ 257 if (offset >= elf->len) continue; \
205 printf("%s", needed); \ 258 needed = (char*)(elf->data + offset); \
259 if (*found_needed) xchrcat(ret, ',', ret_len); \
260 xstrcat(ret, needed, ret_len); \
206 *found_needed = 1; \ 261 *found_needed = 1; \
207 } \ 262 } \
208 ++dyn; \ 263 ++dyn; \
209 } \ 264 } \
210 } } 265 } }
211 SHOW_NEEDED(32) 266 SHOW_NEEDED(32)
212 SHOW_NEEDED(64) 267 SHOW_NEEDED(64)
213 } 268 }
214 if (!be_quiet && !*found_needed)
215 printf(" - ");
216 else if (*found_needed)
217 printf(" ");
218} 269}
219static void scanelf_file_interp(elfobj *elf, char *found_interp) 270static char *scanelf_file_interp(elfobj *elf, char *found_interp)
220{ 271{
221 void *strtbl_void; 272 void *strtbl_void;
222 273
223 if (!show_interp) return; 274 if (!show_interp) return NULL;
224 275
225 strtbl_void = elf_findsecbyname(elf, ".interp"); 276 strtbl_void = elf_findsecbyname(elf, ".interp");
226 277
227 if (strtbl_void) { 278 if (strtbl_void) {
228#define SHOW_INTERP(B) \ 279#define SHOW_INTERP(B) \
229 if (elf->elf_class == ELFCLASS ## B) { \ 280 if (elf->elf_class == ELFCLASS ## B) { \
230 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 281 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
231 printf("%s ", elf->data + EGET(strtbl->sh_offset)); \
232 *found_interp = 1; \ 282 *found_interp = 1; \
283 return elf->data + EGET(strtbl->sh_offset); \
233 } 284 }
234 SHOW_INTERP(32) 285 SHOW_INTERP(32)
235 SHOW_INTERP(64) 286 SHOW_INTERP(64)
236 } 287 }
237 if (!be_quiet && !*found_interp) 288 return NULL;
238 printf(" - ");
239 else if (*found_interp)
240 printf(" ");
241} 289}
242static void scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename) 290static char *scanelf_file_sym(elfobj *elf, char *found_sym, const char *filename)
243{ 291{
244 int i; 292 unsigned long i;
245 void *symtab_void, *strtab_void; 293 void *symtab_void, *strtab_void;
246 294
247 if (!find_sym) return; 295 if (!find_sym) return NULL;
248 296
249 symtab_void = elf_findsecbyname(elf, ".symtab"); 297 symtab_void = elf_findsecbyname(elf, ".symtab");
250 strtab_void = elf_findsecbyname(elf, ".strtab"); 298 strtab_void = elf_findsecbyname(elf, ".strtab");
251 299
252 if (symtab_void && strtab_void) { 300 if (symtab_void && strtab_void) {
253#define FIND_SYM(B) \ 301#define FIND_SYM(B) \
254 if (elf->elf_class == ELFCLASS ## B) { \ 302 if (elf->elf_class == ELFCLASS ## B) { \
255 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 303 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
256 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 304 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
257 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 305 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
258 int cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \ 306 unsigned long cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \
259 char *symname; \ 307 char *symname; \
260 for (i = 0; i < cnt; ++i) { \ 308 for (i = 0; i < cnt; ++i) { \
261 if (sym->st_name) { \ 309 if (sym->st_name) { \
262 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 310 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
263 if (*find_sym == '*') { \ 311 if (*find_sym == '*') { \
275 ++sym; \ 323 ++sym; \
276 } } 324 } }
277 FIND_SYM(32) 325 FIND_SYM(32)
278 FIND_SYM(64) 326 FIND_SYM(64)
279 } 327 }
280 if (*find_sym != '*') { 328 if (*find_sym != '*' && *found_sym)
281 if (*found_sym) 329 return find_sym;
282 printf(" %s ", find_sym);
283 else if (!be_quiet) 330 if (be_quiet)
284 printf(" - "); 331 return NULL;
285 } 332 else
333 return " - ";
286} 334}
287/* scan an elf file and show all the fun stuff */ 335/* scan an elf file and show all the fun stuff */
336#define prints(str) fputs(str, stdout)
288static void scanelf_file(const char *filename) 337static void scanelf_file(const char *filename)
289{ 338{
290 int i; 339 unsigned long i;
291 char found_pax, found_stack, found_relro, found_textrel, 340 char found_pax, found_stack, found_relro, found_textrel,
292 found_rpath, found_needed, found_interp, found_sym, 341 found_rpath, found_needed, found_interp, found_sym,
293 found_file; 342 found_file;
294 elfobj *elf; 343 elfobj *elf;
295 struct stat st; 344 struct stat st;
345 static char *out_buffer = NULL;
346 static size_t out_len;
296 347
297 /* make sure 'filename' exists */ 348 /* make sure 'filename' exists */
298 if (lstat(filename, &st) == -1) { 349 if (lstat(filename, &st) == -1) {
299 if (be_verbose > 2) printf("%s: does not exist\n", filename); 350 if (be_verbose > 2) printf("%s: does not exist\n", filename);
300 return; 351 return;
314 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 365 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
315 return; 366 return;
316 } 367 }
317 368
318 if (be_verbose > 1) 369 if (be_verbose > 1)
319 printf("%s: {%s,%s} scanning file\n", filename, 370 printf("%s: scanning file {%s,%s}\n", filename,
320 get_elfeitype(elf, EI_CLASS, elf->elf_class), 371 get_elfeitype(elf, EI_CLASS, elf->elf_class),
321 get_elfeitype(elf, EI_DATA, elf->data[EI_DATA])); 372 get_elfeitype(elf, EI_DATA, elf->data[EI_DATA]));
322 else if (be_verbose) 373 else if (be_verbose)
323 printf("%s: scanning file\n", filename); 374 printf("%s: scanning file\n", filename);
324 375
376 /* init output buffer */
377 if (!out_buffer) {
378 out_len = sizeof(char) * 80;
379 out_buffer = (char*)xmalloc(out_len);
380 }
381 *out_buffer = '\0';
382
325 /* show the header */ 383 /* show the header */
326 if (!be_quiet && show_banner) { 384 if (!be_quiet && show_banner) {
327 if (out_format) {
328 for (i=0; out_format[i]; ++i) { 385 for (i=0; out_format[i]; ++i) {
329 if (out_format[i] != '%') continue; 386 if (out_format[i] != '%') continue;
330 387
331 switch (out_format[++i]) { 388 switch (out_format[++i]) {
332 case '%': break; 389 case '%': break;
333 case 'F': printf("FILE "); break; 390 case 'F': prints("FILE "); break;
391 case 'o': prints(" TYPE "); break;
334 case 'x': printf(" PAX "); break; 392 case 'x': prints(" PAX "); break;
335 case 'e': printf("STK/REL "); break; 393 case 'e': prints("STK/REL "); break;
336 case 't': printf("TEXTREL "); break; 394 case 't': prints("TEXTREL "); break;
337 case 'r': printf("RPATH "); break; 395 case 'r': prints("RPATH "); break;
338 case 'n': printf("NEEDED "); break; 396 case 'n': prints("NEEDED "); break;
339 case 'i': printf("INTERP "); break; 397 case 'i': prints("INTERP "); break;
340 case 's': printf("SYM "); break; 398 case 's': prints("SYM "); break;
341 }
342 } 399 }
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 } 400 }
353 if (!found_file) printf(" FILE");
354 printf("\n"); 401 prints("\n");
355 show_banner = 0; 402 show_banner = 0;
356 } 403 }
357 404
358 /* dump all the good stuff */ 405 /* 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) { 406 for (i=0; out_format[i]; ++i) {
407 const char *out;
408
409 /* make sure we trim leading spaces in quiet mode */
410 if (be_quiet && *out_buffer == ' ' && !out_buffer[1])
411 *out_buffer = '\0';
412
364 if (out_format[i] != '%') { 413 if (out_format[i] != '%') {
365 printf("%c", out_format[i]); 414 xchrcat(&out_buffer, out_format[i], &out_len);
366 continue; 415 continue;
367 } 416 }
368 417
418 out = NULL;
369 switch (out_format[++i]) { 419 switch (out_format[++i]) {
370 case '%': printf("%%"); break; 420 case '%': xchrcat(&out_buffer, '%', &out_len); break;
371 case 'F': found_file = 1; printf("%s ", filename); break; 421 case 'F': found_file = 1; xstrcat(&out_buffer, filename, &out_len); break;
422 case 'o': out = get_elfetype(elf); break;
372 case 'x': scanelf_file_pax(elf, &found_pax); break; 423 case 'x': out = scanelf_file_pax(elf, &found_pax); break;
373 case 'e': scanelf_file_stack(elf, &found_stack, &found_relro); break; 424 case 'e': out = scanelf_file_stack(elf, &found_stack, &found_relro); break;
374 case 't': scanelf_file_textrel(elf, &found_textrel); break; 425 case 't': out = scanelf_file_textrel(elf, &found_textrel); break;
375 case 'r': scanelf_file_rpath(elf, &found_rpath); break; 426 case 'r': scanelf_file_rpath(elf, &found_rpath, &out_buffer, &out_len); break;
376 case 'n': scanelf_file_needed(elf, &found_needed); break; 427 case 'n': scanelf_file_needed(elf, &found_needed, &out_buffer, &out_len); break;
377 case 'i': scanelf_file_interp(elf, &found_interp); break; 428 case 'i': out = scanelf_file_interp(elf, &found_interp); break;
378 case 's': scanelf_file_sym(elf, &found_sym, filename); break; 429 case 's': out = scanelf_file_sym(elf, &found_sym, filename); break;
379 } 430 }
380 } 431 if (out) xstrcat(&out_buffer, out, &out_len);
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 } 432 }
390 433
391 if (!found_file) { 434 if (!found_file) {
392 if (!be_quiet || found_pax || found_stack || found_textrel || \ 435 if (!be_quiet || found_pax || found_stack || found_textrel || \
393 found_rpath || found_needed || found_sym) 436 found_rpath || found_needed || found_interp || found_sym)
394 puts(filename); 437 xstrcat(&out_buffer, filename, &out_len);
395 } else {
396 printf("\n");
397 } 438 }
439 if (!(be_quiet && xemptybuffer(out_buffer)))
440 puts(out_buffer);
398 441
399 unreadelf(elf); 442 unreadelf(elf);
400} 443}
401 444
402/* scan a directory for ET_EXEC files and print when we find one */ 445/* scan a directory for ET_EXEC files and print when we find one */
447 } 490 }
448 } 491 }
449 closedir(dir); 492 closedir(dir);
450} 493}
451 494
495int scanelf_from_file(char *filename) {
496 FILE *fp = NULL;
497 char *p;
498 char path[_POSIX_PATH_MAX];
499
500 if (((strcmp(filename, "-")) == 0) && (ttyname(0) == NULL))
501 fp = stdin;
502 else if ((fp = fopen(filename, "r")) == NULL)
503 return 1;
504
505 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) {
506 if ((p = strchr(path, '\n')) != NULL)
507 *p = 0;
508 scanelf_dir(path);
509 }
510 if (fp != stdin)
511 fclose(fp);
512 return 0;
513}
514
452/* scan /etc/ld.so.conf for paths */ 515/* scan /etc/ld.so.conf for paths */
453static void scanelf_ldpath() 516static void scanelf_ldpath()
454{ 517{
455 char scan_l, scan_ul, scan_ull; 518 char scan_l, scan_ul, scan_ull;
456 char *path, *p; 519 char *path, *p;
459 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 522 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
460 err("Unable to open ld.so.conf: %s", strerror(errno)); 523 err("Unable to open ld.so.conf: %s", strerror(errno));
461 524
462 scan_l = scan_ul = scan_ull = 0; 525 scan_l = scan_ul = scan_ull = 0;
463 526
464 if ((path = malloc(_POSIX_PATH_MAX)) == NULL) { 527 path = (char*)xmalloc(_POSIX_PATH_MAX);
465 warn("Can not malloc() memory for ldpath scanning");
466 return;
467 }
468 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) 528 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
469 if (*path == '/') { 529 if (*path == '/') {
470 if ((p = strrchr(path, '\r')) != NULL) 530 if ((p = strrchr(path, '\r')) != NULL)
471 *p = 0; 531 *p = 0;
472 if ((p = strrchr(path, '\n')) != NULL) 532 if ((p = strrchr(path, '\n')) != NULL)
490 char *path, *p; 550 char *path, *p;
491 551
492 path = getenv("PATH"); 552 path = getenv("PATH");
493 if (!path) 553 if (!path)
494 err("PATH is not set in your env !"); 554 err("PATH is not set in your env !");
495 555 path = xstrdup(path);
496 if ((path = strdup(path)) == NULL)
497 err("strdup failed: %s", strerror(errno));
498 556
499 while ((p = strrchr(path, ':')) != NULL) { 557 while ((p = strrchr(path, ':')) != NULL) {
500 scanelf_dir(p + 1); 558 scanelf_dir(p + 1);
501 *p = 0; 559 *p = 0;
502 } 560 }
505} 563}
506 564
507 565
508 566
509/* usage / invocation handling functions */ 567/* usage / invocation handling functions */
510#define PARSE_FLAGS "plRmyxetrnis:aqvF:o:BhV" 568#define PARSE_FLAGS "plRmyxetrnis:aqvF:f:o:BhV"
511#define a_argument required_argument 569#define a_argument required_argument
512static struct option const long_opts[] = { 570static struct option const long_opts[] = {
513 {"path", no_argument, NULL, 'p'}, 571 {"path", no_argument, NULL, 'p'},
514 {"ldpath", no_argument, NULL, 'l'}, 572 {"ldpath", no_argument, NULL, 'l'},
515 {"recursive", no_argument, NULL, 'R'}, 573 {"recursive", no_argument, NULL, 'R'},
524 {"symbol", a_argument, NULL, 's'}, 582 {"symbol", a_argument, NULL, 's'},
525 {"all", no_argument, NULL, 'a'}, 583 {"all", no_argument, NULL, 'a'},
526 {"quiet", no_argument, NULL, 'q'}, 584 {"quiet", no_argument, NULL, 'q'},
527 {"verbose", no_argument, NULL, 'v'}, 585 {"verbose", no_argument, NULL, 'v'},
528 {"format", a_argument, NULL, 'F'}, 586 {"format", a_argument, NULL, 'F'},
587 {"from", a_argument, NULL, 'f'},
529 {"file", a_argument, NULL, 'o'}, 588 {"file", a_argument, NULL, 'o'},
530 {"nobanner", no_argument, NULL, 'B'}, 589 {"nobanner", no_argument, NULL, 'B'},
531 {"help", no_argument, NULL, 'h'}, 590 {"help", no_argument, NULL, 'h'},
532 {"version", no_argument, NULL, 'V'}, 591 {"version", no_argument, NULL, 'V'},
533 {NULL, no_argument, NULL, 0x0} 592 {NULL, no_argument, NULL, 0x0}
543 "Print TEXTREL information", 602 "Print TEXTREL information",
544 "Print RPATH information", 603 "Print RPATH information",
545 "Print NEEDED information", 604 "Print NEEDED information",
546 "Print INTERP information", 605 "Print INTERP information",
547 "Find a specified symbol", 606 "Find a specified symbol",
548 "Print all scanned info (-x -e -t -r)\n", 607 "Print all scanned info (-x -e -t -r -n -i)\n",
549 "Only output 'bad' things", 608 "Only output 'bad' things",
550 "Be verbose (can be specified more than once)", 609 "Be verbose (can be specified more than once)",
551 "Use specified format for output", 610 "Use specified format for output",
611 "Read input stream from a filename",
552 "Write output stream to a filename", 612 "Write output stream to a filename",
553 "Don't display the header", 613 "Don't display the header",
554 "Print this help and exit", 614 "Print this help and exit",
555 "Print version and exit", 615 "Print version and exit",
556 NULL 616 NULL
557}; 617};
558 618
559/* display usage and exit */ 619/* display usage and exit */
560static void usage(int status) 620static void usage(int status)
561{ 621{
562 int i; 622 unsigned long i;
563 printf(" Scan ELF binaries for stuff\n\n" 623 printf(" Scan ELF binaries for stuff\n\n"
564 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0); 624 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0);
565 printf("Options: -[%s]\n", PARSE_FLAGS); 625 printf("Options: -[%s]\n", PARSE_FLAGS);
566 for (i = 0; long_opts[i].name; ++i) 626 for (i = 0; long_opts[i].name; ++i)
567 if (long_opts[i].has_arg == no_argument) 627 if (long_opts[i].has_arg == no_argument)
568 printf(" -%c, --%-13s %s\n", long_opts[i].val, 628 printf(" -%c, --%-13s %s\n", long_opts[i].val,
569 long_opts[i].name, opts_help[i]); 629 long_opts[i].name, opts_help[i]);
570 else 630 else
571 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val, 631 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val,
572 long_opts[i].name, opts_help[i]); 632 long_opts[i].name, opts_help[i]);
633
634 if (status != EXIT_SUCCESS)
635 exit(status);
636
637 puts("\nThe format modifiers for the -F option are:");
638 puts(" %F Filename \t%x PaX Flags \t%e STACK/RELRO");
639 puts(" %t TEXTREL \t%r RPATH \t%n NEEDED");
640 puts(" %i INTERP \t%s symbol");
641
573 exit(status); 642 exit(status);
574} 643}
575 644
576/* parse command line arguments and preform needed actions */ 645/* parse command line arguments and preform needed actions */
577static void parseargs(int argc, char *argv[]) 646static void parseargs(int argc, char *argv[])
578{ 647{
579 int flag; 648 int flag;
649 char *from_file = NULL;
580 650
581 opterr = 0; 651 opterr = 0;
582 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) { 652 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
583 switch (flag) { 653 switch (flag) {
584 654
587 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n", 657 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n",
588 __FILE__, __DATE__, rcsid, argv0); 658 __FILE__, __DATE__, rcsid, argv0);
589 exit(EXIT_SUCCESS); 659 exit(EXIT_SUCCESS);
590 break; 660 break;
591 case 'h': usage(EXIT_SUCCESS); break; 661 case 'h': usage(EXIT_SUCCESS); break;
592 662 case 'f':
663 if (from_file == NULL)
664 from_file = xstrdup(optarg);
665 break;
593 case 'o': { 666 case 'o': {
594 FILE *fp = NULL; 667 FILE *fp = NULL;
595 fp = freopen(optarg, "w", stdout); 668 fp = freopen(optarg, "w", stdout);
596 if (fp == NULL) 669 if (fp == NULL)
597 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 670 err("Could not open output stream '%s': %s", optarg, strerror(errno));
599 break; 672 break;
600 } 673 }
601 674
602 case 's': { 675 case 's': {
603 size_t len; 676 size_t len;
604 find_sym = strdup(optarg); 677 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; 678 len = strlen(find_sym) + 1;
611 versioned_symname = (char *)malloc(sizeof(char) * (len+1)); 679 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); 680 sprintf(versioned_symname, "%s@", find_sym);
619 break; 681 break;
620 } 682 }
621 683
622 case 'F': { 684 case 'F': {
623 out_format = strdup(optarg); 685 out_format = xstrdup(optarg);
624 if (!out_format)
625 err("Could not malloc() mem for output format");
626 break; 686 break;
627 } 687 }
628 688
629 case 'y': scan_symlink = 0; break; 689 case 'y': scan_symlink = 0; break;
630 case 'B': show_banner = 0; break; 690 case 'B': show_banner = 0; break;
667 727
668 switch (out_format[++flag]) { 728 switch (out_format[++flag]) {
669 case '%': break; 729 case '%': break;
670 case 'F': break; 730 case 'F': break;
671 case 's': break; 731 case 's': break;
732 case 'o': break;
672 case 'x': show_pax = 1; break; 733 case 'x': show_pax = 1; break;
673 case 'e': show_stack = 1; break; 734 case 'e': show_stack = 1; break;
674 case 't': show_textrel = 1; break; 735 case 't': show_textrel = 1; break;
675 case 'r': show_rpath = 1; break; 736 case 'r': show_rpath = 1; break;
676 case 'n': show_needed = 1; break; 737 case 'n': show_needed = 1; break;
678 default: 739 default:
679 err("Invalid format specifier '%c' (byte %i)", 740 err("Invalid format specifier '%c' (byte %i)",
680 out_format[flag], flag+1); 741 out_format[flag], flag+1);
681 } 742 }
682 } 743 }
744
745 /* construct our default format */
746 } else {
747 size_t fmt_len = 30;
748 out_format = (char*)xmalloc(sizeof(char) * fmt_len);
749 if (!be_quiet) xstrcat(&out_format, "%o ", &fmt_len);
750 if (show_pax) xstrcat(&out_format, "%x ", &fmt_len);
751 if (show_stack) xstrcat(&out_format, "%e ", &fmt_len);
752 if (show_textrel) xstrcat(&out_format, "%t ", &fmt_len);
753 if (show_rpath) xstrcat(&out_format, "%r ", &fmt_len);
754 if (show_needed) xstrcat(&out_format, "%n ", &fmt_len);
755 if (show_interp) xstrcat(&out_format, "%i ", &fmt_len);
756 if (find_sym) xstrcat(&out_format, "%s ", &fmt_len);
757 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
683 } 758 }
759 if (be_verbose > 2) printf("Format: %s\n", out_format);
684 760
685 /* now lets actually do the scanning */ 761 /* now lets actually do the scanning */
686 if (scan_ldpath) scanelf_ldpath(); 762 if (scan_ldpath) scanelf_ldpath();
687 if (scan_envpath) scanelf_envpath(); 763 if (scan_envpath) scanelf_envpath();
764 if (from_file) {
765 scanelf_from_file(from_file);
766 free(from_file);
767 from_file = *argv;
768 }
688 if (optind == argc && !scan_ldpath && !scan_envpath) 769 if (optind == argc && !scan_ldpath && !scan_envpath && !from_file)
689 err("Nothing to scan !?"); 770 err("Nothing to scan !?");
690 while (optind < argc) 771 while (optind < argc)
691 scanelf_dir(argv[optind++]); 772 scanelf_dir(argv[optind++]);
692 773
693 /* clean up */ 774 /* clean up */
694 if (find_sym) { 775 if (find_sym) {
695 free(find_sym); 776 free(find_sym);
696 free(versioned_symname); 777 free(versioned_symname);
697 } 778 }
698 if (out_format) free(out_format); 779 if (out_format) free(out_format);
780}
781
782
783
784/* utility funcs */
785static char *xstrdup(char *s)
786{
787 char *ret = strdup(s);
788 if (!ret) err("Could not strdup(): %s", strerror(errno));
789 return ret;
790}
791static void *xmalloc(size_t size)
792{
793 void *ret = malloc(size);
794 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size);
795 return ret;
796}
797static void xstrcat(char **dst, const char *src, size_t *curr_len)
798{
799 long new_len;
800
801 new_len = strlen(*dst) + strlen(src);
802 if (*curr_len <= new_len) {
803 *curr_len = new_len + (*curr_len / 2);
804 *dst = realloc(*dst, *curr_len);
805 if (!*dst)
806 err("could not realloc %li bytes", (unsigned long)*curr_len);
807 }
808
809 strcat(*dst, src);
810}
811static inline void xchrcat(char **dst, const char append, size_t *curr_len)
812{
813 static char my_app[2];
814 my_app[0] = append;
815 my_app[1] = '\0';
816 xstrcat(dst, my_app, curr_len);
817}
818static int xemptybuffer(const char *buff)
819{
820 long i;
821 for (i=0; buff[i]; ++i)
822 if (buff[i] != ' ')
823 return 0;
824 return 1;
699} 825}
700 826
701 827
702 828
703int main(int argc, char *argv[]) 829int main(int argc, char *argv[])

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

  ViewVC Help
Powered by ViewVC 1.1.20