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