/[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.49 Revision 1.61
1/* 1/*
2 * Copyright 2003 Ned Ludd <solar@gentoo.org> 2 * Copyright 2003 Ned Ludd <solar@gentoo.org>
3 * Copyright 1999-2005 Gentoo Foundation 3 * Copyright 1999-2005 Gentoo Foundation
4 * Distributed under the terms of the GNU General Public License v2 4 * Distributed under the terms of the GNU General Public License v2
5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.49 2005/05/18 04:08:30 vapier Exp $ 5 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanelf.c,v 1.61 2005/05/28 22:09:36 solar Exp $
6 * 6 *
7 ******************************************************************** 7 ********************************************************************
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the 10 * published by the Free Software Foundation; either version 2 of the
22 */ 22 */
23 23
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <sys/types.h> 26#include <sys/types.h>
27#include <libgen.h>
28#include <limits.h>
27#define __USE_GNU 29#define __USE_GNU
28#include <string.h> 30#include <string.h>
29#include <errno.h> 31#include <errno.h>
30#include <unistd.h> 32#include <unistd.h>
31#include <sys/stat.h> 33#include <sys/stat.h>
32#include <dirent.h> 34#include <dirent.h>
33#include <getopt.h> 35#include <getopt.h>
34#include <assert.h> 36#include <assert.h>
35
36#include "paxelf.h" 37#include "paxelf.h"
37 38
38static const char *rcsid = "$Id: scanelf.c,v 1.49 2005/05/18 04:08:30 vapier Exp $"; 39static const char *rcsid = "$Id: scanelf.c,v 1.61 2005/05/28 22:09:36 solar Exp $";
39#define argv0 "scanelf" 40#define argv0 "scanelf"
40 41
41 42
42 43
43/* prototypes */ 44/* prototypes */
45static void scanelf_dir(const char *path); 46static void scanelf_dir(const char *path);
46static void scanelf_ldpath(); 47static void scanelf_ldpath();
47static void scanelf_envpath(); 48static void scanelf_envpath();
48static void usage(int status); 49static void usage(int status);
49static void parseargs(int argc, char *argv[]); 50static void parseargs(int argc, char *argv[]);
50static char *xstrdup(char *s); 51static char *xstrdup(const char *s);
51static void *xmalloc(size_t size); 52static void *xmalloc(size_t size);
52static void xstrcat(char **dst, const char *src, size_t *curr_len); 53static 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 inline void xchrcat(char **dst, const char append, size_t *curr_len);
54static int xemptybuffer(const char *buff);
55 55
56/* variables to control behavior */ 56/* variables to control behavior */
57static char *ldpaths[256]; 57static char *ldpaths[256];
58static char scan_ldpath = 0; 58static char scan_ldpath = 0;
59static char scan_envpath = 0; 59static char scan_envpath = 0;
72static char be_verbose = 0; 72static char be_verbose = 0;
73static char *find_sym = NULL, *versioned_symname = NULL; 73static char *find_sym = NULL, *versioned_symname = NULL;
74static char *out_format = NULL; 74static char *out_format = NULL;
75 75
76 76
77
78/* sub-funcs for scanelf_file() */ 77/* sub-funcs for scanelf_file() */
79static char *scanelf_file_pax(elfobj *elf, char *found_pax) 78static char *scanelf_file_pax(elfobj *elf, char *found_pax)
80{ 79{
81 static char *paxflags; 80 static char *paxflags;
81 static char ret[7];
82 unsigned long i, shown;
83
82 84
83 if (!show_pax) return NULL; 85 if (!show_pax) return NULL;
84 86
87 shown = 0;
88 memset(&ret, 0, sizeof(ret));
89
90 if (elf->phdr) {
91#define SHOW_PAX(B) \
92 if (elf->elf_class == ELFCLASS ## B) { \
93 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
94 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
95 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
96 if (EGET(phdr[i].p_type) != PT_PAX_FLAGS) \
97 continue; \
98 if (be_quiet && (EGET(phdr[i].p_flags) == 10240)) \
99 continue; \
100 memcpy(ret, pax_short_pf_flags(EGET(phdr[i].p_flags)), 6); \
101 *found_pax = 1; \
102 ++shown; \
103 break; \
104 } \
105 }
106 SHOW_PAX(32)
107 SHOW_PAX(64)
108 }
109
110 /* fall back to EI_PAX if no PT_PAX was found */
111 if (!*ret) {
85 paxflags = pax_short_hf_flags(PAX_FLAGS(elf)); 112 paxflags = pax_short_hf_flags(EI_PAX_FLAGS(elf));
86 if (!be_quiet || (be_quiet && strncmp(paxflags, "PeMRxS", 6))) { 113 if (!be_quiet || (be_quiet && EI_PAX_FLAGS(elf))) {
87 *found_pax = 1; 114 *found_pax = 1;
88 return paxflags; 115 return paxflags;
89 } 116 }
117 strncpy(ret, paxflags, sizeof(ret));
118 // ++shown;
119 }
90 120
121 if (be_quiet && !shown)
91 return NULL; 122 return NULL;
123 return ret;
124
92} 125}
93static char *scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro) 126static char *scanelf_file_stack(elfobj *elf, char *found_stack, char *found_relro)
94{ 127{
95 static char ret[8]; 128 static char ret[8] = "--- ---";
96 char *found; 129 char *found;
97 unsigned long i, off, shown; 130 unsigned long i, off, shown;
98 131
99 if (!show_stack) return NULL; 132 if (!show_stack) return NULL;
100 133
101 shown = 0; 134 shown = 0;
102 strcpy(ret, "--- ---");
103 135
104 if (elf->phdr) { 136 if (elf->phdr) {
105#define SHOW_STACK(B) \ 137#define SHOW_STACK(B) \
106 if (elf->elf_class == ELFCLASS ## B) { \ 138 if (elf->elf_class == ELFCLASS ## B) { \
107 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 139 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
110 if (EGET(phdr[i].p_type) == PT_GNU_STACK) { \ 142 if (EGET(phdr[i].p_type) == PT_GNU_STACK) { \
111 found = found_stack; \ 143 found = found_stack; \
112 off = 0; \ 144 off = 0; \
113 } else if (EGET(phdr[i].p_type) == PT_GNU_RELRO) { \ 145 } else if (EGET(phdr[i].p_type) == PT_GNU_RELRO) { \
114 found = found_relro; \ 146 found = found_relro; \
115 off = 3; \ 147 off = 4; \
116 } else \ 148 } else \
117 continue; \ 149 continue; \
118 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \ 150 if (be_quiet && !(EGET(phdr[i].p_flags) & PF_X)) \
119 continue; \ 151 continue; \
120 memcpy(ret+off, gnu_short_stack_flags(EGET(phdr[i].p_flags)), 3); \ 152 memcpy(ret+off, gnu_short_stack_flags(EGET(phdr[i].p_flags)), 3); \
144 Elf ## B ## _Dyn *dyn; \ 176 Elf ## B ## _Dyn *dyn; \
145 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 177 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
146 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 178 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
147 Elf ## B ## _Off offset; \ 179 Elf ## B ## _Off offset; \
148 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 180 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
149 if (phdr[i].p_type != PT_DYNAMIC) continue; \ 181 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
150 offset = EGET(phdr[i].p_offset); \ 182 offset = EGET(phdr[i].p_offset); \
151 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \ 183 if (offset >= elf->len - sizeof(Elf ## B ## _Dyn)) continue; \
152 dyn = DYN ## B (elf->data + offset); \ 184 dyn = DYN ## B (elf->data + offset); \
153 while (EGET(dyn->d_tag) != DT_NULL) { \ 185 while (EGET(dyn->d_tag) != DT_NULL) { \
154 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \ 186 if (EGET(dyn->d_tag) == DT_TEXTREL) { /*dyn->d_tag != DT_FLAGS)*/ \
186 Elf ## B ## _Dyn *dyn; \ 218 Elf ## B ## _Dyn *dyn; \
187 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 219 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
188 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \ 220 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
189 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \ 221 Elf ## B ## _Shdr *strtbl = SHDR ## B (strtbl_void); \
190 Elf ## B ## _Off offset; \ 222 Elf ## B ## _Off offset; \
191 Elf ## B ## _Sxword word; \ 223 Elf ## B ## _Xword word; \
192 /* Scan all the program headers */ \ 224 /* Scan all the program headers */ \
193 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \ 225 for (i = 0; i < EGET(ehdr->e_phnum); i++) { \
194 /* Just scan dynamic headers */ \ 226 /* Just scan dynamic headers */ \
195 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \ 227 if (EGET(phdr[i].p_type) != PT_DYNAMIC) continue; \
196 offset = EGET(phdr[i].p_offset); \ 228 offset = EGET(phdr[i].p_offset); \
309{ 341{
310 unsigned long i; 342 unsigned long i;
311 struct stat s; 343 struct stat s;
312 344
313 if (!show_bind) return NULL; 345 if (!show_bind) return NULL;
346 if (!elf->phdr) return NULL;
314 347
315#define SHOW_BIND(B) \ 348#define SHOW_BIND(B) \
316 if (elf->elf_class == ELFCLASS ## B) { \ 349 if (elf->elf_class == ELFCLASS ## B) { \
317 Elf ## B ## _Dyn *dyn; \ 350 Elf ## B ## _Dyn *dyn; \
318 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ 351 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
336 } \ 369 } \
337 } 370 }
338 SHOW_BIND(32) 371 SHOW_BIND(32)
339 SHOW_BIND(64) 372 SHOW_BIND(64)
340 373
341 fstat(elf->fd, &s);
342 if (be_quiet && !(s.st_mode & S_ISUID || s.st_mode & S_ISGID)) { 374 if (be_quiet && !fstat(elf->fd, &s) && !(s.st_mode & S_ISUID || s.st_mode & S_ISGID)) {
343 return NULL; 375 return NULL;
344 } else { 376 } else {
345 *found_bind = 1; 377 *found_bind = 1;
346 return "LAZY"; 378 return "LAZY";
347 } 379 }
355 387
356 symtab_void = elf_findsecbyname(elf, ".symtab"); 388 symtab_void = elf_findsecbyname(elf, ".symtab");
357 strtab_void = elf_findsecbyname(elf, ".strtab"); 389 strtab_void = elf_findsecbyname(elf, ".strtab");
358 390
359 if (symtab_void && strtab_void) { 391 if (symtab_void && strtab_void) {
392 char *base, *basemem;
393 basemem = xstrdup(filename);
394 base = basename(basemem);
360#define FIND_SYM(B) \ 395#define FIND_SYM(B) \
361 if (elf->elf_class == ELFCLASS ## B) { \ 396 if (elf->elf_class == ELFCLASS ## B) { \
362 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ 397 Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \
363 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ 398 Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \
364 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \ 399 Elf ## B ## _Sym *sym = SYM ## B (elf->data + EGET(symtab->sh_offset)); \
368 if (sym->st_name) { \ 403 if (sym->st_name) { \
369 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ 404 symname = (char *)(elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \
370 if (*find_sym == '*') { \ 405 if (*find_sym == '*') { \
371 printf("%s(%s) %5lX %15s %s\n", \ 406 printf("%s(%s) %5lX %15s %s\n", \
372 ((*found_sym == 0) ? "\n\t" : "\t"), \ 407 ((*found_sym == 0) ? "\n\t" : "\t"), \
373 (char *)basename(filename), \ 408 base, \
374 (long)sym->st_size, \ 409 (long)sym->st_size, \
375 (char *)get_elfstttype(sym->st_info), \ 410 (char *)get_elfstttype(sym->st_info), \
376 symname); \ 411 symname); \
377 *found_sym = 1; \ 412 *found_sym = 1; \
378 } else if ((strcmp(find_sym, symname) == 0) || \ 413 } else if ((strcmp(find_sym, symname) == 0) || \
381 } \ 416 } \
382 ++sym; \ 417 ++sym; \
383 } } 418 } }
384 FIND_SYM(32) 419 FIND_SYM(32)
385 FIND_SYM(64) 420 FIND_SYM(64)
421 free(basemem);
386 } 422 }
387 if (*find_sym != '*' && *found_sym) 423 if (*find_sym != '*' && *found_sym)
388 return find_sym; 424 return find_sym;
389 if (be_quiet) 425 if (be_quiet)
390 return NULL; 426 return NULL;
391 else 427 else
392 return " - "; 428 return " - ";
393} 429}
394/* scan an elf file and show all the fun stuff */ 430/* scan an elf file and show all the fun stuff */
395#define prints(str) fputs(str, stdout) 431// #define prints(str) fputs(str, stdout)
432#define prints(str) write(fileno(stdout), str, strlen(str))
396static void scanelf_file(const char *filename) 433static void scanelf_file(const char *filename)
397{ 434{
398 unsigned long i; 435 unsigned long i;
399 char found_pax, found_stack, found_relro, found_textrel, 436 char found_pax, found_stack, found_relro, found_textrel,
400 found_rpath, found_needed, found_interp, found_bind, 437 found_rpath, found_needed, found_interp, found_bind,
408 if (lstat(filename, &st) == -1) { 445 if (lstat(filename, &st) == -1) {
409 if (be_verbose > 2) printf("%s: does not exist\n", filename); 446 if (be_verbose > 2) printf("%s: does not exist\n", filename);
410 return; 447 return;
411 } 448 }
412 /* always handle regular files and handle symlinked files if no -y */ 449 /* always handle regular files and handle symlinked files if no -y */
413 if (!(S_ISREG(st.st_mode) || (S_ISLNK(st.st_mode) && scan_symlink))) { 450 if (S_ISLNK(st.st_mode)) {
451 if (!scan_symlink) return;
452 stat(filename, &st);
453 }
454 if (!S_ISREG(st.st_mode)) {
414 if (be_verbose > 2) printf("%s: skipping non-file\n", filename); 455 if (be_verbose > 2) printf("%s: skipping non-file\n", filename);
415 return; 456 return;
416 } 457 }
417 458
418 found_pax = found_stack = found_relro = found_textrel = \ 459 found_pax = found_stack = found_relro = found_textrel = \
492 case 's': out = scanelf_file_sym(elf, &found_sym, filename); break; 533 case 's': out = scanelf_file_sym(elf, &found_sym, filename); break;
493 } 534 }
494 if (out) xstrcat(&out_buffer, out, &out_len); 535 if (out) xstrcat(&out_buffer, out, &out_len);
495 } 536 }
496 537
497 if (!found_file) { 538#define FOUND_SOMETHING() \
498 if (!be_quiet || found_pax || found_stack || found_textrel || \ 539 (found_pax || found_stack || found_textrel || found_rpath || \
499 found_rpath || found_needed || found_interp || found_bind || \ 540 found_needed || found_interp || found_bind || found_sym)
500 found_sym) 541
501 { 542 if (!found_file && (!be_quiet || (be_quiet && FOUND_SOMETHING()))) {
502 xchrcat(&out_buffer, ' ', &out_len); 543 xchrcat(&out_buffer, ' ', &out_len);
503 xstrcat(&out_buffer, filename, &out_len); 544 xstrcat(&out_buffer, filename, &out_len);
504 } 545 }
505 } 546 if (!be_quiet || (be_quiet && FOUND_SOMETHING()))
506 if (!(be_quiet && xemptybuffer(out_buffer)))
507 puts(out_buffer); 547 puts(out_buffer);
508 548
509 unreadelf(elf); 549 unreadelf(elf);
510} 550}
511 551
679 {"nobanner", no_argument, NULL, 'B'}, 719 {"nobanner", no_argument, NULL, 'B'},
680 {"help", no_argument, NULL, 'h'}, 720 {"help", no_argument, NULL, 'h'},
681 {"version", no_argument, NULL, 'V'}, 721 {"version", no_argument, NULL, 'V'},
682 {NULL, no_argument, NULL, 0x0} 722 {NULL, no_argument, NULL, 0x0}
683}; 723};
724
684static char *opts_help[] = { 725static char *opts_help[] = {
685 "Scan all directories in PATH environment", 726 "Scan all directories in PATH environment",
686 "Scan all directories in /etc/ld.so.conf", 727 "Scan all directories in /etc/ld.so.conf",
687 "Scan directories recursively", 728 "Scan directories recursively",
688 "Don't recursively cross mount points", 729 "Don't recursively cross mount points",
693 "Print RPATH information", 734 "Print RPATH information",
694 "Print NEEDED information", 735 "Print NEEDED information",
695 "Print INTERP information", 736 "Print INTERP information",
696 "Print BIND information", 737 "Print BIND information",
697 "Find a specified symbol", 738 "Find a specified symbol",
698 "Print all scanned info (-x -e -t -r -n -i)\n", 739 "Print all scanned info (-x -e -t -r -n -i -b)\n",
699 "Only output 'bad' things", 740 "Only output 'bad' things",
700 "Be verbose (can be specified more than once)", 741 "Be verbose (can be specified more than once)",
701 "Use specified format for output", 742 "Use specified format for output",
702 "Read input stream from a filename", 743 "Read input stream from a filename",
703 "Write output stream to a filename", 744 "Write output stream to a filename",
709 750
710/* display usage and exit */ 751/* display usage and exit */
711static void usage(int status) 752static void usage(int status)
712{ 753{
713 unsigned long i; 754 unsigned long i;
714 printf(" Scan ELF binaries for stuff\n\n" 755 printf("* Scan ELF binaries for stuff\n\n"
715 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0); 756 "Usage: %s [options] <dir1/file1> [dir2 dirN fileN ...]\n\n", argv0);
716 printf("Options: -[%s]\n", PARSE_FLAGS); 757 printf("Options: -[%s]\n", PARSE_FLAGS);
717 for (i = 0; long_opts[i].name; ++i) 758 for (i = 0; long_opts[i].name; ++i)
718 if (long_opts[i].has_arg == no_argument) 759 if (long_opts[i].has_arg == no_argument)
719 printf(" -%c, --%-13s %s\n", long_opts[i].val, 760 printf(" -%c, --%-13s* %s\n", long_opts[i].val,
720 long_opts[i].name, opts_help[i]); 761 long_opts[i].name, opts_help[i]);
721 else 762 else
722 printf(" -%c, --%-6s <arg> %s\n", long_opts[i].val, 763 printf(" -%c, --%-6s <arg> * %s\n", long_opts[i].val,
723 long_opts[i].name, opts_help[i]); 764 long_opts[i].name, opts_help[i]);
724 765
725 if (status != EXIT_SUCCESS) 766 if (status != EXIT_SUCCESS)
726 exit(status); 767 exit(status);
727 768
771 sprintf(versioned_symname, "%s@", find_sym); 812 sprintf(versioned_symname, "%s@", find_sym);
772 break; 813 break;
773 } 814 }
774 815
775 case 'F': { 816 case 'F': {
817 if (!out_format)
776 out_format = xstrdup(optarg); 818 out_format = xstrdup(optarg);
777 break; 819 break;
778 } 820 }
779 821
780 case 'y': scan_symlink = 0; break; 822 case 'y': scan_symlink = 0; break;
781 case 'B': show_banner = 0; break; 823 case 'B': show_banner = 0; break;
790 case 'n': show_needed = 1; break; 832 case 'n': show_needed = 1; break;
791 case 'i': show_interp = 1; break; 833 case 'i': show_interp = 1; break;
792 case 'b': show_bind = 1; break; 834 case 'b': show_bind = 1; break;
793 case 'q': be_quiet = 1; break; 835 case 'q': be_quiet = 1; break;
794 case 'v': be_verbose = (be_verbose % 20) + 1; break; 836 case 'v': be_verbose = (be_verbose % 20) + 1; break;
795 case 'a': show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 1; break; 837 case 'a': show_pax = show_stack = show_textrel = show_rpath = \
838 show_needed = show_interp = show_bind = 1; break;
796 839
797 case ':': 840 case ':':
798 err("Option missing parameter\n"); 841 err("Option missing parameter\n");
799 case '?': 842 case '?':
800 err("Unknown option\n"); 843 err("Unknown option\n");
803 } 846 }
804 } 847 }
805 848
806 /* let the format option override all other options */ 849 /* let the format option override all other options */
807 if (out_format) { 850 if (out_format) {
808 show_pax = show_stack = show_textrel = show_rpath = show_needed = show_interp = 0; 851 show_pax = show_stack = show_textrel = show_rpath = \
852 show_needed = show_interp = show_bind = 0;
809 for (i = 0; out_format[i]; ++i) { 853 for (i = 0; out_format[i]; ++i) {
810 if (out_format[i] != '%') continue; 854 if (out_format[i] != '%') continue;
811 855
812 switch (out_format[++i]) { 856 switch (out_format[++i]) {
813 case '%': break; 857 case '%': break;
870} 914}
871 915
872 916
873 917
874/* utility funcs */ 918/* utility funcs */
875static char *xstrdup(char *s) 919static char *xstrdup(const char *s)
876{ 920{
877 char *ret = strdup(s); 921 char *ret = strdup(s);
878 if (!ret) err("Could not strdup(): %s", strerror(errno)); 922 if (!ret) err("Could not strdup(): %s", strerror(errno));
879 return ret; 923 return ret;
880} 924}
925
881static void *xmalloc(size_t size) 926static void *xmalloc(size_t size)
882{ 927{
883 void *ret = malloc(size); 928 void *ret = malloc(size);
884 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size); 929 if (!ret) err("Could not malloc() %li bytes", (unsigned long)size);
885 return ret; 930 return ret;
886} 931}
932
887static void xstrcat(char **dst, const char *src, size_t *curr_len) 933static void xstrcat(char **dst, const char *src, size_t *curr_len)
888{ 934{
889 long new_len; 935 long new_len;
890 936
891 new_len = strlen(*dst) + strlen(src); 937 new_len = strlen(*dst) + strlen(src);
896 err("could not realloc %li bytes", (unsigned long)*curr_len); 942 err("could not realloc %li bytes", (unsigned long)*curr_len);
897 } 943 }
898 944
899 strcat(*dst, src); 945 strcat(*dst, src);
900} 946}
947
901static inline void xchrcat(char **dst, const char append, size_t *curr_len) 948static inline void xchrcat(char **dst, const char append, size_t *curr_len)
902{ 949{
903 static char my_app[2]; 950 static char my_app[2];
904 my_app[0] = append; 951 my_app[0] = append;
905 my_app[1] = '\0'; 952 my_app[1] = '\0';
906 xstrcat(dst, my_app, curr_len); 953 xstrcat(dst, my_app, curr_len);
907} 954}
908static int xemptybuffer(const char *buff)
909{
910 long i;
911 for (i = 0; buff[i]; ++i)
912 if (buff[i] != ' ')
913 return 0;
914 return 1;
915}
916
917 955
918 956
919int main(int argc, char *argv[]) 957int main(int argc, char *argv[])
920{ 958{
921 if (argc < 2) 959 if (argc < 2)
922 usage(EXIT_FAILURE); 960 usage(EXIT_FAILURE);
923 parseargs(argc, argv); 961 parseargs(argc, argv);
924 fclose(stdout); 962 fclose(stdout);
963#ifdef __BOUNDS_CHECKING_ON
964 warn("The calls to add/delete heap should be off by 1 due to the out_buffer not being freed in scanelf_file()");
965#endif
925 return EXIT_SUCCESS; 966 return EXIT_SUCCESS;
926} 967}

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

  ViewVC Help
Powered by ViewVC 1.1.20