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