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