xref: /illumos-gate/usr/src/cmd/sgs/size/common/main.c (revision efd4c9b63ad77503c101fc6c2ed8ba96c9d52964)
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
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
249 usagerr()
250 {
251 	(void) fprintf(stderr,
252 	"usage: %s [-%s] file(s)...\n", tool_name, OPTSTR);
253 	exitcode++;
254 }
255