1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1988 AT&T
23 * Copyright (c) 1989 AT&T
24 * All Rights Reserved
25 *
26 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
29
30 /* UNIX HEADERS */
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <libelf.h>
36
37 /* SIZE HEADER */
38 #include "defs.h"
39
40 /* RELEASE STRING */
41 #include "conv.h"
42 #include "sgs.h"
43
44
45 /* EXTERNAL VARIABLES DEFINED */
46 int fflag = 0, /* print full output if -f option is supplied */
47 Fflag = 0, /* print full output if -F option is supplied */
48 nflag = 0; /* include NOLOAD sections in size if -n */
49 /* option is supplied */
50 int numbase = DECIMAL;
51 static int errflag = 0; /* Global error flag */
52 int oneflag = 0;
53 int exitcode = 0; /* Global exit code */
54 char *fname;
55 char *archive;
56 int is_archive = 0;
57
58 static char *tool_name;
59
60 static void usagerr();
61
62 #define OPTSTR "VoxnfF" /* option string for usage error message */
63 #define GETOPTSTR "VoxnfF?" /* option string for getopt */
64
65 static Elf *elf;
66 static Elf_Arhdr *arhdr;
67
68 /*
69 * main(argc, argv)
70 *
71 * parses the command line
72 * opens, processes and closes each object file command line argument
73 *
74 * defines:
75 * - int numbase = HEX if the -x flag is in the command line
76 * = OCTAL if the -o flag is in the command line
77 * = DECIMAL if the -d flag is in the command line
78 *
79 * calls:
80 * - process(filename) to print the size information in the object file
81 * filename
82 *
83 * prints:
84 * - an error message if any unknown options appear on the command line
85 * - a usage message if no object file args appear on the command line
86 * - an error message if it can't open an object file
87 * or if the object file has the wrong magic number
88 *
89 * exits 1 - errors found, 0 - no errors
90 */
91 int
main(int argc,char ** argv,char ** envp)92 main(int argc, char ** argv, char ** envp)
93 {
94 /* UNIX FUNCTIONS CALLED */
95 extern void error();
96
97 /* SIZE FUNCTIONS CALLED */
98 extern void process();
99
100 /* EXTERNAL VARIABLES USED */
101 extern int numbase;
102 extern int errflag;
103 extern int oneflag;
104 extern int optind;
105 extern char *fname;
106
107 int c;
108 static int fd;
109 extern char *archive;
110 Elf_Cmd cmd;
111 Elf *arf;
112 unsigned Vflag = 0;
113
114 tool_name = argv[0];
115
116 while ((c = getopt(argc, argv, GETOPTSTR)) != EOF) {
117 switch (c) {
118 case 'o':
119 if (numbase != HEX)
120 numbase = OCTAL;
121 else
122 (void) fprintf(stderr,
123 "size: -x set, -o ignored\n");
124 break;
125
126 case 'd':
127 numbase = DECIMAL;
128 break;
129
130 case 'x':
131 if (numbase != OCTAL)
132 numbase = HEX;
133 else
134 (void) fprintf(stderr,
135 "size: -o set, -x ignored\n");
136 break;
137
138 case 'f':
139 fflag++;
140 break;
141
142 case 'F':
143 Fflag++;
144 break;
145
146 case 'n':
147 nflag++;
148 break;
149 case 'V':
150 (void) fprintf(stderr, "size: %s %s\n",
151 (const char *)SGU_PKG,
152 (const char *)SGU_REL);
153 Vflag++;
154 break;
155 case '?':
156 errflag++;
157 break;
158 default:
159 break;
160 }
161 }
162 if (errflag || (optind >= argc)) {
163 if (!(Vflag && (argc == 2) && !errflag)) {
164 usagerr();
165 }
166 }
167 if ((argc - optind) == 1) {
168 oneflag++; /* only one file to process */
169 }
170
171 if (elf_version(EV_CURRENT) == EV_NONE) {
172 (void) fprintf(stderr, "size: Libelf is out of date");
173 exit(FATAL); /* library out of date */
174 }
175
176 for (; optind < argc; optind++) {
177 fname = argv[optind];
178 if ((fd = open(argv[optind], O_RDONLY)) == -1) {
179 error(fname, "cannot open");
180 } else {
181 cmd = ELF_C_READ;
182 arf = 0;
183
184 if ((arf = elf_begin(fd, cmd, arf)) == 0) {
185 /* error(fname, "cannot open"); */
186 (void) fprintf(stderr,
187 "size: %s: %s\n", fname, elf_errmsg(-1));
188 return (FATAL);
189 }
190
191 if (elf_kind(arf) == ELF_K_AR) {
192 archive = argv[optind];
193 } else {
194 archive = "";
195 }
196
197 while ((elf = elf_begin(fd, cmd, arf)) != 0) {
198 if ((arhdr = elf_getarhdr(elf)) == 0) {
199 if (elf_kind(arf) == ELF_K_NONE) {
200 /* BEGIN CSTYLED */
201 (void) fprintf(stderr,
202 "%s: %s: invalid file type\n",
203 tool_name, fname);
204 /* END CSTYLED */
205 exitcode++;
206 break;
207 } else {
208 process(elf);
209 }
210 } else if (arhdr->ar_name[0] != '/') {
211 fname = arhdr->ar_name;
212 if (elf_kind(arf) == ELF_K_NONE) {
213 /* BEGIN CSTYLED */
214 (void) fprintf(stderr,
215 "%s: %s[%s]: invalid file type\n",
216 tool_name, archive, fname);
217 /* END CSTYLED */
218 exitcode++;
219 break;
220 } else {
221 is_archive++;
222 process(elf);
223 }
224 }
225 cmd = elf_next(elf);
226 (void) elf_end(elf);
227 }
228 (void) elf_end(arf);
229 (void) close(fd);
230 }
231 }
232 if (exitcode)
233 exit(FATAL);
234 else
235 exit(0);
236 return (0);
237 }
238
239 static void
usagerr()240 usagerr()
241 {
242 (void) fprintf(stderr,
243 "usage: %s [-%s] file(s)...\n", tool_name, OPTSTR);
244 exitcode++;
245 }
246