/[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.26 Revision 1.35
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.26 2005/04/05 00:51:33 vapier Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.35 2005/04/14 00:17:30 solar Exp $
6 * 6 *
7 ******************************************************************** 7 ********************************************************************
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the 10 * published by the Free Software Foundation; either version 2 of the
22 */ 22 */
23 23
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <sys/types.h> 26#include <sys/types.h>
27#define __USE_GNU
27#include <string.h> 28#include <string.h>
28#include <errno.h> 29#include <errno.h>
29#include <unistd.h> 30#include <unistd.h>
30#include <sys/stat.h> 31#include <sys/stat.h>
31#include <dirent.h> 32#include <dirent.h>
32#include <getopt.h> 33#include <getopt.h>
33#include <assert.h> 34#include <assert.h>
34 35
35#include "paxelf.h" 36#include "paxelf.h"
36 37
37static const char *rcsid = "$Id: scanelf.c,v 1.26 2005/04/05 00:51:33 vapier Exp $"; 38static const char *rcsid = "$Id: scanelf.c,v 1.35 2005/04/14 00:17:30 solar Exp $";
38 39
39 40
40/* helper functions for showing errors */ 41/* helper functions for showing errors */
41#define argv0 "scanelf" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/ 42#define argv0 "scanelf" /*((*argv != NULL) ? argv[0] : __FILE__ "\b\b")*/
42#define warn(fmt, args...) \ 43#define warn(fmt, args...) \
65static char dir_crossmount = 1; 66static char dir_crossmount = 1;
66static char show_pax = 0; 67static char show_pax = 0;
67static char show_stack = 0; 68static char show_stack = 0;
68static char show_textrel = 0; 69static char show_textrel = 0;
69static char show_rpath = 0; 70static char show_rpath = 0;
71static char show_needed = 0;
70static char show_banner = 1; 72static char show_banner = 1;
71static char be_quiet = 0; 73static char be_quiet = 0;
72static char be_verbose = 0; 74static char be_verbose = 0;
75static char *find_sym = NULL;
73 76
74 77
75 78
76/* scan an elf file and show all the fun stuff */ 79/* scan an elf file and show all the fun stuff */
77static void scanelf_file(const char *filename) 80static void scanelf_file(const char *filename)
78{ 81{
79 int i; 82 int i;
80 char found_pax, found_stack, found_relro, found_textrel, found_rpath; 83 char found_pax, found_stack, found_relro, found_textrel,
84 found_rpath, found_needed, found_sym;
81 elfobj *elf; 85 elfobj *elf;
86 struct stat st;
82 87
88 /* make sure path exists */
89 if (lstat(filename, &st) == -1)
90 return;
91 if (!S_ISREG(st.st_mode))
92 return;
83 found_pax = found_stack = found_relro = found_textrel = found_rpath = 0; 93 found_pax = found_stack = found_relro = found_textrel = \
94 found_rpath = found_needed = found_sym = 0;
84 95
85 /* verify this is real ELF */ 96 /* verify this is real ELF */
86 if ((elf = readelf(filename)) == NULL) { 97 if ((elf = readelf(filename)) == NULL) {
87 if (be_verbose > 2) printf("%s: not an ELF\n", filename); 98 if (be_verbose > 2) printf("%s: not an ELF\n", filename);
88 return; 99 return;
95 else if (be_verbose) 106 else if (be_verbose)
96 printf("%s: scanning file\n", filename); 107 printf("%s: scanning file\n", filename);
97 108
98 /* show the header */ 109 /* show the header */
99 if (!be_quiet && show_banner) { 110 if (!be_quiet && show_banner) {
100 printf(" TYPE "); 111 printf(" TYPE ");
101 if (show_pax) printf(" PAX "); 112 if (show_pax) printf(" PAX ");
102 if (show_stack) printf(" STK/REL "); 113 if (show_stack) printf("STK/REL ");
103 if (show_textrel) printf("TEXTREL "); 114 if (show_textrel) printf("TEXTREL ");
104 if (show_rpath) printf("RPATH "); 115 if (show_rpath) printf("RPATH ");
116 if (show_needed) printf("NEEDED ");
105 printf(" FILE\n"); 117 printf(" FILE\n");
106 show_banner = 0; 118 show_banner = 0;
107 } 119 }
108 120
109 /* dump all the good stuff */ 121 /* dump all the good stuff */
154 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \ 166 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
155 while (EGET(dyn->d_tag) != DT_NULL) { \ 167 while (EGET(dyn->d_tag) != DT_NULL) { \
156 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \ 168 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
157 found_textrel = 1; \ 169 found_textrel = 1; \
158 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \ 170 /*if (dyn->d_un.d_val & DF_TEXTREL)*/ \
159 printf("TEXTREL "); \ 171 fputs("TEXTREL ", stdout); \
160 } \ 172 } \
161 ++dyn; \ 173 ++dyn; \
162 } \ 174 } \
163 } } 175 } }
164 SHOW_TEXTREL(32) 176 SHOW_TEXTREL(32)
165 SHOW_TEXTREL(64) 177 SHOW_TEXTREL(64)
166 if (!be_quiet && !found_textrel) printf("------- "); 178 if (!be_quiet && !found_textrel) fputs("------- ", stdout);
167 } 179 }
168 180
169 /* rpath fun */ 181 /* rpath fun */
170 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */ 182 /* TODO: if be_quiet, only output RPATH's which aren't in /etc/ld.so.conf */
171 if (show_rpath) { 183 if (show_rpath) {
208 printf("%-5s ", (runpath ? runpath : rpath)); 220 printf("%-5s ", (runpath ? runpath : rpath));
209 else if (!be_quiet && !found_rpath) 221 else if (!be_quiet && !found_rpath)
210 printf(" - "); 222 printf(" - ");
211 } 223 }
212 224
225 /* print out all the NEEDED entries */
226 if (show_needed) {
227 char *needed;
228 void *strtbl_void = elf_findsecbyname(elf, ".dynstr");
229
230 if (strtbl_void) {
231#define SHOW_NEEDED(B) \
232 if (elf->elf_class == ELFCLASS ## B) { \
233 Elf ## B ## _Dyn *dyn; \
234 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
235 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
236 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
237 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
238 if (be_verbose && EGET(phdr[i].p_type) == PT_INTERP) { \
239 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
240 printf("%s\n", elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr)); \
241 exit(0); \
242 } \
243 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
244 dyn = DYN ## B (elf->data + EGET(phdr[i].p_offset)); \
245 while (EGET(dyn->d_tag) != DT_NULL) { \
246 if (EGET(dyn->d_tag) == DT_NEEDED) { \
247 needed = elf->data + EGET(strtbl->sh_offset) + EGET(dyn->d_un.d_ptr); \
248 if (found_needed) printf(","); \
249 printf("%s", needed); \
250 found_needed = 1; \
251 } \
252 ++dyn; \
253 } \
254 } }
255 SHOW_NEEDED(32)
256 SHOW_NEEDED(64)
257 }
258 if (!be_quiet && !found_needed)
259 printf(" - ");
260 else if (found_needed)
261 printf(" ");
262 }
263
264 /* search the symbol table for a specified symbol */
265 if (find_sym) {
266 void *symtab_void, *strtab_void;
267 char *versioned_symname;
268 size_t len;
269
270 len = strlen(find_sym) + 1;
271 versioned_symname = (char *)malloc(sizeof(char) * (len+1));
272 if (!versioned_symname) {
273 warnf("Could not malloc() mem for sym scan");
274 return;
275 }
276 sprintf(versioned_symname, "%s@", find_sym);
277
278 symtab_void = elf_findsecbyname(elf, ".symtab");
279 strtab_void = elf_findsecbyname(elf, ".strtab");
280
281 if (symtab_void && strtab_void) {
282#define FIND_SYM(B) \
283 if (elf->elf_class == ELFCLASS ## B) { \
284 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
285 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
286 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
287 int cnt = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \
288 char *symname; \
289 for (i = 0; i < cnt; ++i) { \
290 if (sym->st_name) { \
291 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
292 if (*find_sym == '*') { \
293 printf("%s(%s) %5lX %15s %s\n", \
294 ((found_sym == 0) ? "\n\t" : "\t"), \
295 (char *)basename(filename), \
296 (long)sym->st_size, \
297 (char *)get_elfstttype(sym->st_info), \
298 symname); \
299 found_sym = 1; \
300 } else if ((strcmp(find_sym, symname) == 0) || \
301 (strncmp(symname, versioned_symname, len) == 0)) \
302 found_sym++; \
303 } \
304 ++sym; \
305 } }
306 FIND_SYM(32)
307 FIND_SYM(64)
308 }
309 free(versioned_symname);
310 if (*find_sym != '*') {
311 if (found_sym)
312 printf(" %s ", find_sym);
313 else if (!be_quiet)
314 fputs(" - ", stdout);
315 }
316 }
317
213 if (!be_quiet || found_pax || found_stack || found_textrel || found_rpath) 318 if (!be_quiet || found_pax || found_stack || found_textrel || \
319 found_rpath || found_needed || found_sym)
214 puts(filename); 320 puts(filename);
215 321
216 unreadelf(elf); 322 unreadelf(elf);
217} 323}
218 324
221{ 327{
222 register DIR *dir; 328 register DIR *dir;
223 register struct dirent *dentry; 329 register struct dirent *dentry;
224 struct stat st_top, st; 330 struct stat st_top, st;
225 char buf[_POSIX_PATH_MAX]; 331 char buf[_POSIX_PATH_MAX];
226 size_t len = 0; 332 size_t pathlen = 0, len = 0;
227 333
228 /* make sure path exists */ 334 /* make sure path exists */
229 if (lstat(path, &st_top) == -1) 335 if (lstat(path, &st_top) == -1)
230 return; 336 return;
231 337
240 warnf("could not opendir %s: %s", path, strerror(errno)); 346 warnf("could not opendir %s: %s", path, strerror(errno));
241 return; 347 return;
242 } 348 }
243 if (be_verbose) printf("%s: scanning dir\n", path); 349 if (be_verbose) printf("%s: scanning dir\n", path);
244 350
351 pathlen = strlen(path);
245 while ((dentry = readdir(dir))) { 352 while ((dentry = readdir(dir))) {
246 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) 353 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
247 continue; 354 continue;
248 len = (strlen(path) + 2 + strlen(dentry->d_name)); 355 len = (pathlen + 1 + strlen(dentry->d_name) + 1);
249 assert(len < sizeof(buf)); 356 if (len >= sizeof(buf)) {
250 strncpy(buf, path, len); 357 warnf("Skipping '%s': len > sizeof(buf); %d > %d\n", path, (int)len, (int)sizeof(buf));
251 strncat(buf, "/", len); 358 continue;
252 strncat(buf, dentry->d_name, len); 359 }
253 buf[sizeof(buf)] = 0; 360 sprintf(buf, "%s/%s", path, dentry->d_name);
254 if (lstat(buf, &st) != -1) { 361 if (lstat(buf, &st) != -1) {
255 if (S_ISREG(st.st_mode)) 362 if (S_ISREG(st.st_mode))
256 scanelf_file(buf); 363 scanelf_file(buf);
257 else if (dir_recurse && S_ISDIR(st.st_mode)) { 364 else if (dir_recurse && S_ISDIR(st.st_mode)) {
258 if (dir_crossmount || (st_top.st_dev == st.st_dev)) 365 if (dir_crossmount || (st_top.st_dev == st.st_dev))
273 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL) 380 if ((fp = fopen("/etc/ld.so.conf", "r")) == NULL)
274 err("Unable to open ld.so.conf: %s", strerror(errno)); 381 err("Unable to open ld.so.conf: %s", strerror(errno));
275 382
276 scan_l = scan_ul = scan_ull = 0; 383 scan_l = scan_ul = scan_ull = 0;
277 384
278 path = malloc(_POSIX_PATH_MAX); 385 if ((path = malloc(_POSIX_PATH_MAX)) == NULL) {
386 warn("Can not malloc() memory for ldpath scanning");
387 return;
388 }
279 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL) 389 while ((fgets(path, _POSIX_PATH_MAX, fp)) != NULL)
280 if (*path == '/') { 390 if (*path == '/') {
281 if ((p = strrchr(path, '\r')) != NULL) 391 if ((p = strrchr(path, '\r')) != NULL)
282 *p = 0; 392 *p = 0;
283 if ((p = strrchr(path, '\n')) != NULL) 393 if ((p = strrchr(path, '\n')) != NULL)
286 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1; 396 if (!scan_ul && !strcmp(path, "/usr/lib")) scan_ul = 1;
287 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1; 397 if (!scan_ull && !strcmp(path, "/usr/local/lib")) scan_ull = 1;
288 scanelf_dir(path); 398 scanelf_dir(path);
289 } 399 }
290 free(path); 400 free(path);
401 fclose(fp);
291 402
292 if (!scan_l) scanelf_dir("/lib"); 403 if (!scan_l) scanelf_dir("/lib");
293 if (!scan_ul) scanelf_dir("/usr/lib"); 404 if (!scan_ul) scanelf_dir("/usr/lib");
294 if (!scan_ull) scanelf_dir("/usr/local/lib"); 405 if (!scan_ull) scanelf_dir("/usr/local/lib");
295
296 fclose(fp);
297} 406}
298 407
299/* scan env PATH for paths */ 408/* scan env PATH for paths */
300static void scanelf_envpath() 409static void scanelf_envpath()
301{ 410{
304 path = getenv("PATH"); 413 path = getenv("PATH");
305 if (!path) 414 if (!path)
306 err("PATH is not set in your env !"); 415 err("PATH is not set in your env !");
307 416
308 if ((path = strdup(path)) == NULL) 417 if ((path = strdup(path)) == NULL)
309 err("stdup failed: %s", strerror(errno)); 418 err("strdup failed: %s", strerror(errno));
310 419
311 while ((p = strrchr(path, ':')) != NULL) { 420 while ((p = strrchr(path, ':')) != NULL) {
312 scanelf_dir(p + 1); 421 scanelf_dir(p + 1);
313 *p = 0; 422 *p = 0;
314 } 423 }
317} 426}
318 427
319 428
320 429
321/* usage / invocation handling functions */ 430/* usage / invocation handling functions */
322#define PARSE_FLAGS "plRmxetraqvo:BhV" 431#define PARSE_FLAGS "plRmxetrns:aqvo:BhV"
432#define a_argument required_argument
323static struct option const long_opts[] = { 433static struct option const long_opts[] = {
324 {"path", no_argument, NULL, 'p'}, 434 {"path", no_argument, NULL, 'p'},
325 {"ldpath", no_argument, NULL, 'l'}, 435 {"ldpath", no_argument, NULL, 'l'},
326 {"recursive", no_argument, NULL, 'R'}, 436 {"recursive", no_argument, NULL, 'R'},
327 {"mount", no_argument, NULL, 'm'}, 437 {"mount", no_argument, NULL, 'm'},
328 {"pax", no_argument, NULL, 'x'}, 438 {"pax", no_argument, NULL, 'x'},
329 {"header", no_argument, NULL, 'e'}, 439 {"header", no_argument, NULL, 'e'},
330 {"textrel", no_argument, NULL, 't'}, 440 {"textrel", no_argument, NULL, 't'},
331 {"rpath", no_argument, NULL, 'r'}, 441 {"rpath", no_argument, NULL, 'r'},
442 {"needed", no_argument, NULL, 'n'},
443 {"symbol", a_argument, NULL, 's'},
332 {"all", no_argument, NULL, 'a'}, 444 {"all", no_argument, NULL, 'a'},
333 {"quiet", no_argument, NULL, 'q'}, 445 {"quiet", no_argument, NULL, 'q'},
334 {"verbose", no_argument, NULL, 'v'}, 446 {"verbose", no_argument, NULL, 'v'},
335 {"file",required_argument, NULL, 'o'}, 447 {"file", a_argument, NULL, 'o'},
336 {"nobanner", no_argument, NULL, 'B'}, 448 {"nobanner", no_argument, NULL, 'B'},
337 {"help", no_argument, NULL, 'h'}, 449 {"help", no_argument, NULL, 'h'},
338 {"version", no_argument, NULL, 'V'}, 450 {"version", no_argument, NULL, 'V'},
339 {NULL, no_argument, NULL, 0x0} 451 {NULL, no_argument, NULL, 0x0}
340}; 452};
345 "Don't recursively cross mount points\n", 457 "Don't recursively cross mount points\n",
346 "Print PaX markings", 458 "Print PaX markings",
347 "Print GNU_STACK markings", 459 "Print GNU_STACK markings",
348 "Print TEXTREL information", 460 "Print TEXTREL information",
349 "Print RPATH information", 461 "Print RPATH information",
462 "Print NEEDED information",
463 "Find a specified symbol",
350 "Print all scanned info (-x -e -t -r)\n", 464 "Print all scanned info (-x -e -t -r)\n",
351 "Only output 'bad' things", 465 "Only output 'bad' things",
352 "Be verbose (can be specified more than once)", 466 "Be verbose (can be specified more than once)",
353 "Write output stream to a filename", 467 "Write output stream to a filename",
354 "Don't display the header", 468 "Don't display the header",
359 473
360/* display usage and exit */ 474/* display usage and exit */
361static void usage(int status) 475static void usage(int status)
362{ 476{
363 int i; 477 int i;
364 printf(" Scan ELF binaries for stuff\n\n" 478 printf(" Scan ELF binaries for stuff\n"
365 "Usage: %s [options] <dir1> [dir2 dirN ...]\n\n", argv0); 479 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0);
366 printf("Options:\n"); 480 printf("Options: -[%s]\n", PARSE_FLAGS);
367 for (i = 0; long_opts[i].name; ++i) 481 for (i = 0; long_opts[i].name; ++i)
482 if (long_opts[i].has_arg == no_argument)
368 printf(" -%c, --%-12s %s\n", long_opts[i].val, 483 printf(" -%c, --%-13s %s\n", long_opts[i].val,
369 long_opts[i].name, opts_help[i]); 484 long_opts[i].name, opts_help[i]);
370#ifdef MANLYPAGE 485 else
371 for (i = 0; long_opts[i].name; ++i) 486 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val,
372 printf(".TP\n\\fB\\-%c, \\-\\-%s\\fR\n%s\n", long_opts[i].val,
373 long_opts[i].name, opts_help[i]); 487 long_opts[i].name, opts_help[i]);
374#endif
375 exit(status); 488 exit(status);
376} 489}
377 490
378/* parse command line arguments and preform needed actions */ 491/* parse command line arguments and preform needed actions */
379static void parseargs(int argc, char *argv[]) 492static void parseargs(int argc, char *argv[])
388 printf("%s compiled %s\n%s\n" 501 printf("%s compiled %s\n%s\n"
389 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n", 502 "%s written for Gentoo Linux by <solar and vapier @ gentoo.org>\n",
390 __FILE__, __DATE__, rcsid, argv0); 503 __FILE__, __DATE__, rcsid, argv0);
391 exit(EXIT_SUCCESS); 504 exit(EXIT_SUCCESS);
392 break; 505 break;
393 case 's': /* reserved for -s, --symbol= */
394 case 'h': usage(EXIT_SUCCESS); break; 506 case 'h': usage(EXIT_SUCCESS); break;
395 507
396 case 'o': { 508 case 'o': {
397 FILE *fp = NULL; 509 FILE *fp = NULL;
398 fp = freopen(optarg, "w", stdout); 510 fp = freopen(optarg, "w", stdout);
399 if (fp == NULL) 511 if (fp == NULL)
400 err("Could not open output stream '%s': %s", optarg, strerror(errno)); 512 err("Could not open output stream '%s': %s", optarg, strerror(errno));
401 stdout = fp; 513 stdout = fp;
402 break; 514 break;
403 } 515 }
516
517 case 's': find_sym = strdup(optarg); break;
404 518
405 case 'B': show_banner = 0; break; 519 case 'B': show_banner = 0; break;
406 case 'l': scan_ldpath = 1; break; 520 case 'l': scan_ldpath = 1; break;
407 case 'p': scan_envpath = 1; break; 521 case 'p': scan_envpath = 1; break;
408 case 'R': dir_recurse = 1; break; 522 case 'R': dir_recurse = 1; break;
409 case 'm': dir_crossmount = 0; break; 523 case 'm': dir_crossmount = 0; break;
410 case 'x': show_pax = 1; break; 524 case 'x': show_pax = 1; break;
411 case 'e': show_stack = 1; break; 525 case 'e': show_stack = 1; break;
412 case 't': show_textrel = 1; break; 526 case 't': show_textrel = 1; break;
413 case 'r': show_rpath = 1; break; 527 case 'r': show_rpath = 1; break;
528 case 'n': show_needed = 1; break;
414 case 'q': be_quiet = 1; break; 529 case 'q': be_quiet = 1; break;
415 case 'v': be_verbose = (be_verbose % 20) + 1; break; 530 case 'v': be_verbose = (be_verbose % 20) + 1; break;
416 case 'a': show_pax = show_stack = show_textrel = show_rpath = 1; break; 531 case 'a': show_pax = show_stack = show_textrel = show_needed = show_rpath = 1; break;
417 532
418 case ':': 533 case ':':
419 warn("Option missing parameter"); 534 warn("Option missing parameter");
420 usage(EXIT_FAILURE); 535 usage(EXIT_FAILURE);
421 break; 536 break;
436 if (scan_envpath) scanelf_envpath(); 551 if (scan_envpath) scanelf_envpath();
437 if (optind == argc && !scan_ldpath && !scan_envpath) 552 if (optind == argc && !scan_ldpath && !scan_envpath)
438 err("Nothing to scan !?"); 553 err("Nothing to scan !?");
439 while (optind < argc) 554 while (optind < argc)
440 scanelf_dir(argv[optind++]); 555 scanelf_dir(argv[optind++]);
556
557 if (find_sym) free(find_sym);
441} 558}
442 559
443 560
444 561
445int main(int argc, char *argv[]) 562int main(int argc, char *argv[])

Legend:
Removed from v.1.26  
changed lines
  Added in v.1.35

  ViewVC Help
Powered by ViewVC 1.1.20