Annotation of src/usr.bin/size/size.c, Revision 1.19
1.19 ! deraadt 1: /* $OpenBSD: size.c,v 1.18 2003/06/03 02:56:16 millert Exp $ */
1.2 deraadt 2: /* $NetBSD: size.c,v 1.7 1996/01/14 23:07:12 pk Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1988, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.18 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: static char copyright[] =
35: "@(#) Copyright (c) 1988, 1993\n\
36: The Regents of the University of California. All rights reserved.\n";
37: #endif /* not lint */
38:
39: #ifndef lint
40: #if 0
41: static char sccsid[] = "@(#)size.c 8.2 (Berkeley) 12/9/93";
42: #endif
1.19 ! deraadt 43: static char rcsid[] = "$OpenBSD: size.c,v 1.18 2003/06/03 02:56:16 millert Exp $";
1.1 deraadt 44: #endif /* not lint */
45:
46: #include <sys/param.h>
47: #include <sys/file.h>
48: #include <a.out.h>
1.2 deraadt 49: #include <ar.h>
50: #include <ranlib.h>
1.1 deraadt 51: #include <unistd.h>
52: #include <stdlib.h>
53: #include <stdio.h>
1.8 deraadt 54: #include <string.h>
55: #include <ctype.h>
1.1 deraadt 56: #include <err.h>
1.11 espie 57: #include "byte.c"
1.9 niklas 58:
59: #ifdef MID_MACHINE_OVERRIDE
60: #undef MID_MACHINE
61: #define MID_MACHINE MID_MACHINE_OVERRIDE
62: #endif
1.1 deraadt 63:
1.6 deraadt 64: unsigned long total_text, total_data, total_bss, total_total;
1.2 deraadt 65: int ignore_bad_archive_entries = 1;
1.6 deraadt 66: int print_totals = 0;
1.2 deraadt 67:
1.14 millert 68: int process_file(int, char *);
69: int show_archive(int, char *, FILE *);
70: int show_objfile(int, char *, FILE *);
71: void usage(void);
1.1 deraadt 72:
73: int
1.19 ! deraadt 74: main(int argc, char *argv[])
1.1 deraadt 75: {
76: int ch, eval;
77:
1.6 deraadt 78: while ((ch = getopt(argc, argv, "wt")) != -1)
1.1 deraadt 79: switch(ch) {
1.2 deraadt 80: case 'w':
81: ignore_bad_archive_entries = 0;
82: break;
1.6 deraadt 83: case 't':
84: print_totals = 1;
85: break;
1.1 deraadt 86: case '?':
87: default:
88: usage();
89: }
90: argc -= optind;
91: argv += optind;
92:
93: eval = 0;
94: if (*argv)
95: do {
1.2 deraadt 96: eval |= process_file(argc, *argv);
1.1 deraadt 97: } while (*++argv);
98: else
1.2 deraadt 99: eval |= process_file(1, "a.out");
1.6 deraadt 100:
101: if (print_totals)
102: (void)printf("\n%lu\t%lu\t%lu\t%lu\t%lx\tTOTAL\n",
103: total_text, total_data, total_bss,
104: total_total, total_total);
1.1 deraadt 105: exit(eval);
106: }
107:
1.2 deraadt 108: /*
109: * process_file()
110: * show symbols in the file given as an argument. Accepts archive and
111: * object files as input.
112: */
113: int
1.19 ! deraadt 114: process_file(int count, char *fname)
1.2 deraadt 115: {
116: struct exec exec_head;
117: FILE *fp;
118: int retval;
119: char magic[SARMAG];
1.6 deraadt 120:
1.2 deraadt 121: if (!(fp = fopen(fname, "r"))) {
122: warnx("cannot read %s", fname);
123: return(1);
124: }
125:
126: /*
127: * first check whether this is an object file - read a object
128: * header, and skip back to the beginning
129: */
130: if (fread((char *)&exec_head, sizeof(exec_head), (size_t)1, fp) != 1) {
131: warnx("%s: bad format", fname);
132: (void)fclose(fp);
133: return(1);
134: }
135: rewind(fp);
136:
137: /* this could be an archive */
138: if (N_BADMAG(exec_head)) {
139: if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||
140: strncmp(magic, ARMAG, SARMAG)) {
141: warnx("%s: not object file or archive", fname);
142: (void)fclose(fp);
143: return(1);
144: }
145: retval = show_archive(count, fname, fp);
146: } else
147: retval = show_objfile(count, fname, fp);
148: (void)fclose(fp);
149: return(retval);
150: }
151:
152: /*
153: * show_archive()
154: * show symbols in the given archive file
155: */
1.1 deraadt 156: int
1.19 ! deraadt 157: show_archive(int count, char *fname, FILE *fp)
1.2 deraadt 158: {
159: struct ar_hdr ar_head;
160: struct exec exec_head;
161: int i, rval;
162: long last_ar_off;
163: char *p, *name;
164: int baselen, namelen;
165:
166: baselen = strlen(fname) + 3;
167: namelen = sizeof(ar_head.ar_name);
1.12 smart 168: if ((name = malloc(baselen + namelen)) == NULL)
169: err(1, NULL);
1.2 deraadt 170:
171: rval = 0;
172:
173: /* while there are more entries in the archive */
174: while (fread((char *)&ar_head, sizeof(ar_head), (size_t)1, fp) == 1) {
175: /* bad archive entry - stop processing this archive */
176: if (strncmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
177: warnx("%s: bad format archive header", fname);
178: (void)free(name);
179: return(1);
180: }
181:
182: /* remember start position of current archive object */
183: last_ar_off = ftell(fp);
184:
185: /* skip ranlib entries */
186: if (!strncmp(ar_head.ar_name, RANLIBMAG, sizeof(RANLIBMAG) - 1))
187: goto skip;
188:
189: /*
190: * construct a name of the form "archive.a:obj.o:" for the
191: * current archive entry if the object name is to be printed
192: * on each output line
193: */
194: p = name;
1.17 deraadt 195: if (count > 1) {
196: snprintf(name, baselen - 1, "%s:", fname);
197: p += strlen(name);
198: }
1.2 deraadt 199: #ifdef AR_EFMT1
200: /*
201: * BSD 4.4 extended AR format: #1/<namelen>, with name as the
202: * first <namelen> bytes of the file
203: */
1.15 deraadt 204: if ((ar_head.ar_name[0] == '#') &&
205: (ar_head.ar_name[1] == '1') &&
206: (ar_head.ar_name[2] == '/') &&
207: (isdigit(ar_head.ar_name[3]))) {
208: int len = atoi(&ar_head.ar_name[3]);
1.2 deraadt 209:
210: if (len > namelen) {
211: p -= (long)name;
1.12 smart 212: if ((name = realloc(name, baselen+len)) == NULL)
213: err(1, NULL);
1.2 deraadt 214: namelen = len;
215: p += (long)name;
216: }
217: if (fread(p, len, 1, fp) != 1) {
1.12 smart 218: warnx("%s: premature EOF", name);
1.2 deraadt 219: (void)free(name);
1.12 smart 220: return(1);
1.2 deraadt 221: }
222: p += len;
223: } else
224: #endif
225: for (i = 0; i < sizeof(ar_head.ar_name); ++i)
226: if (ar_head.ar_name[i] && ar_head.ar_name[i] != ' ')
227: *p++ = ar_head.ar_name[i];
228: *p++ = '\0';
229:
230: /* get and check current object's header */
231: if (fread((char *)&exec_head, sizeof(exec_head),
232: (size_t)1, fp) != 1) {
233: warnx("%s: premature EOF", name);
234: (void)free(name);
235: return(1);
236: }
237:
1.11 espie 238: if (BAD_OBJECT(exec_head)) {
1.2 deraadt 239: if (!ignore_bad_archive_entries) {
240: warnx("%s: bad format", name);
241: rval = 1;
242: }
243: } else {
244: (void)fseek(fp, (long)-sizeof(exec_head),
245: SEEK_CUR);
246: rval |= show_objfile(2, name, fp);
247: }
248:
249: /*
250: * skip to next archive object - it starts at the next
251: * even byte boundary
252: */
253: #define even(x) (((x) + 1) & ~1)
254: skip: if (fseek(fp, last_ar_off + even(atol(ar_head.ar_size)),
255: SEEK_SET)) {
256: warn("%s", fname);
257: (void)free(name);
258: return(1);
259: }
260: }
261: (void)free(name);
262: return(rval);
263: }
264:
265: int
1.19 ! deraadt 266: show_objfile(int count, char *name, FILE *fp)
1.1 deraadt 267: {
268: static int first = 1;
269: struct exec head;
270: u_long total;
271:
1.2 deraadt 272: if (fread((char *)&head, sizeof(head), (size_t)1, fp) != 1) {
273: warnx("%s: cannot read header", name);
274: return(1);
275: }
276:
1.11 espie 277: if (BAD_OBJECT(head)) {
1.2 deraadt 278: warnx("%s: bad format", name);
1.4 deraadt 279: return(1);
280: }
281:
1.11 espie 282: fix_header_order(&head);
1.1 deraadt 283:
284: if (first) {
285: first = 0;
286: (void)printf("text\tdata\tbss\tdec\thex\n");
287: }
288: total = head.a_text + head.a_data + head.a_bss;
1.13 pvalchev 289: (void)printf("%lu\t%lu\t%lu\t%lu\t%lx", (unsigned long)head.a_text,
290: (unsigned long)head.a_data, (unsigned long)head.a_bss, total, total);
1.1 deraadt 291: if (count > 1)
292: (void)printf("\t%s", name);
1.6 deraadt 293:
294: total_text += head.a_text;
295: total_data += head.a_data;
296: total_bss += head.a_bss;
297: total_total += total;
298:
1.1 deraadt 299: (void)printf("\n");
300: return (0);
1.2 deraadt 301: }
302:
1.1 deraadt 303: void
1.19 ! deraadt 304: usage(void)
1.1 deraadt 305: {
1.7 mickey 306: (void)fprintf(stderr, "usage: size [-tw] [file ...]\n");
1.1 deraadt 307: exit(1);
308: }