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 *
27 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30
31 #pragma ident "%Z%%M% %I% %E% SMI"
32
33 /* UNIX HEADERS */
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <libelf.h>
39
40
41 /* SIZE HEADER */
42 #include "defs.h"
43
44 /* RELEASE STRING */
45 #include "conv.h"
46 #include "sgs.h"
47
48
49 /* EXTERNAL VARIABLES DEFINED */
50 int fflag = 0, /* print full output if -f option is supplied */
51 Fflag = 0, /* print full output if -F option is supplied */
52 nflag = 0; /* include NOLOAD sections in size if -n */
53 /* option is supplied */
54 int numbase = DECIMAL;
55 static int errflag = 0; /* Global error flag */
56 int oneflag = 0;
57 int exitcode = 0; /* Global exit code */
58 char *fname;
59 char *archive;
60 int is_archive = 0;
61
62 static char *tool_name;
63
64 static void usagerr();
65
66 #define OPTSTR "VoxnfF" /* option string for usage error message */
67 #define GETOPTSTR "VoxnfF?" /* option string for getopt */
68
69 static Elf *elf;
70 static Elf_Arhdr *arhdr;
71
72 /*
73 * main(argc, argv)
74 *
75 * parses the command line
76 * opens, processes and closes each object file command line argument
77 *
78 * defines:
79 * - int numbase = HEX if the -x flag is in the command line
80 * = OCTAL if the -o flag is in the command line
81 * = DECIMAL if the -d flag is in the command line
82 *
83 * calls:
84 * - process(filename) to print the size information in the object file
85 * filename
86 *
87 * prints:
88 * - an error message if any unknown options appear on the command line
89 * - a usage message if no object file args appear on the command line
90 * - an error message if it can't open an object file
91 * or if the object file has the wrong magic number
92 *
93 * exits 1 - errors found, 0 - no errors
94 */
95 int
main(int argc,char ** argv,char ** envp)96 main(int argc, char ** argv, char ** envp)
97 {
98 /* UNIX FUNCTIONS CALLED */
99 extern void error();
100
101 /* SIZE FUNCTIONS CALLED */
102 extern void process();
103
104 /* EXTERNAL VARIABLES USED */
105 extern int numbase;
106 extern int errflag;
107 extern int oneflag;
108 extern int optind;
109 extern char *fname;
110
111 int c;
112 static int fd;
113 extern char *archive;
114 Elf_Cmd cmd;
115 Elf *arf;
116 unsigned Vflag = 0;
117
118 /*
119 * Check for a binary that better fits this architecture.
120 */
121 (void) conv_check_native(argv, envp);
122
123 tool_name = argv[0];
124
125 while ((c = getopt(argc, argv, GETOPTSTR)) != EOF) {
126 switch (c) {
127 case 'o':
128 if (numbase != HEX)
129 numbase = OCTAL;
130 else
131 (void) fprintf(stderr,
132 "size: -x set, -o ignored\n");
133 break;
134
135 case 'd':
136 numbase = DECIMAL;
137 break;
138
139 case 'x':
140 if (numbase != OCTAL)
141 numbase = HEX;
142 else
143 (void) fprintf(stderr,
144 "size: -o set, -x ignored\n");
145 break;
146
147 case 'f':
148 fflag++;
149 break;
150
151 case 'F':
152 Fflag++;
153 break;
154
155 case 'n':
156 nflag++;
157 break;
158 case 'V':
159 (void) fprintf(stderr, "size: %s %s\n",
160 (const char *)SGU_PKG,
161 (const char *)SGU_REL);
162 Vflag++;
163 break;
164 case '?':
165 errflag++;
166 break;
167 default:
168 break;
169 }
170 }
171 if (errflag || (optind >= argc)) {
172 if (!(Vflag && (argc == 2) && !errflag)) {
173 usagerr();
174 }
175 }
176 if ((argc - optind) == 1) {
177 oneflag++; /* only one file to process */
178 }
179
180 if (elf_version(EV_CURRENT) == EV_NONE) {
181 (void) fprintf(stderr, "size: Libelf is out of date");
182 exit(FATAL); /* library out of date */
183 }
184
185 for (; optind < argc; optind++) {
186 fname = argv[optind];
187 if ((fd = open(argv[optind], O_RDONLY)) == -1) {
188 error(fname, "cannot open");
189 } else {
190 cmd = ELF_C_READ;
191 arf = 0;
192
193 if ((arf = elf_begin(fd, cmd, arf)) == 0) {
194 /* error(fname, "cannot open"); */
195 (void) fprintf(stderr,
196 "size: %s: %s\n", fname, elf_errmsg(-1));
197 return (FATAL);
198 }
199
200 if (elf_kind(arf) == ELF_K_AR) {
201 archive = argv[optind];
202 } else {
203 archive = "";
204 }
205
206 while ((elf = elf_begin(fd, cmd, arf)) != 0) {
207 if ((arhdr = elf_getarhdr(elf)) == 0) {
208 if (elf_kind(arf) == ELF_K_NONE) {
209 /* BEGIN CSTYLED */
210 (void) fprintf(stderr,
211 "%s: %s: invalid file type\n",
212 tool_name, fname);
213 /* END CSTYLED */
214 exitcode++;
215 break;
216 } else {
217 process(elf);
218 }
219 } else if (arhdr->ar_name[0] != '/') {
220 fname = arhdr->ar_name;
221 if (elf_kind(arf) == ELF_K_NONE) {
222 /* BEGIN CSTYLED */
223 (void) fprintf(stderr,
224 "%s: %s[%s]: invalid file type\n",
225 tool_name, archive, fname);
226 /* END CSTYLED */
227 exitcode++;
228 break;
229 } else {
230 is_archive++;
231 process(elf);
232 }
233 }
234 cmd = elf_next(elf);
235 (void) elf_end(elf);
236 }
237 (void) elf_end(arf);
238 (void) close(fd);
239 }
240 }
241 if (exitcode)
242 exit(FATAL);
243 else
244 exit(0);
245 return (0);
246 }
247
248 static void
usagerr()249 usagerr()
250 {
251 (void) fprintf(stderr,
252 "usage: %s [-%s] file(s)...\n", tool_name, OPTSTR);
253 exitcode++;
254 }
255