xref: /illumos-gate/usr/src/cmd/sgs/size/common/main.c (revision fc910014e8a32a65612105835a10995f2c13d942)
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
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
240 usagerr()
241 {
242 	(void) fprintf(stderr,
243 	"usage: %s [-%s] file(s)...\n", tool_name, OPTSTR);
244 	exitcode++;
245 }
246