1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* $OpenBSD: size.c,v 1.6 1997/01/28 07:12:27 deraadt Exp $ */ 24/* $NetBSD: size.c,v 1.7 1996/01/14 23:07:12 pk Exp $ */ 25 26/* 27 * Copyright (c) 1988, 1993 28 * The Regents of the University of California. All rights reserved. 29 * 30 * Redistribution and use in source and binary forms, with or without 31 * modification, are permitted provided that the following conditions 32 * are met: 33 * 1. Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * 2. Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in the 37 * documentation and/or other materials provided with the distribution. 38 * 3. All advertising materials mentioning features or use of this software 39 * must display the following acknowledgement: 40 * This product includes software developed by the University of 41 * California, Berkeley and its contributors. 42 * 4. Neither the name of the University nor the names of its contributors 43 * may be used to endorse or promote products derived from this software 44 * without specific prior written permission. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 56 * SUCH DAMAGE. 57 */ 58/* 59 * The NeXT Computer, Inc. size(1) program that handles fat files, archives and 60 * Mach-O objects files (no BSD a.out files). A few lines of code were taken 61 * and adapted from the BSD release. 62 */ 63#include <stdio.h> 64#include <stdlib.h> 65#include <string.h> 66#include "stuff/bool.h" 67#include "stuff/ofile.h" 68#include "stuff/errors.h" 69#include "stuff/allocate.h" 70 71char *progname = NULL; 72 73struct flags { 74 uint32_t nfiles; 75 enum bool m; 76 enum bool l; 77 enum bool x; 78}; 79 80static void usage( 81 void); 82static void size( 83 struct ofile *ofile, 84 char *arch_name, 85 void *cookie); 86 87/* apple_version is created by the libstuff/Makefile */ 88extern char apple_version[]; 89char *version = apple_version; 90 91int 92main( 93int argc, 94char **argv, 95char **envp) 96{ 97 int i; 98 enum bool args_left; 99 struct flags flag; 100 struct arch_flag *arch_flags; 101 uint32_t narch_flags; 102 enum bool all_archs; 103 104 progname = argv[0]; 105 arch_flags = NULL; 106 narch_flags = 0; 107 all_archs = FALSE; 108 109 flag.nfiles = 0; 110 flag.m = FALSE; 111 flag.l = FALSE; 112 flag.x = FALSE; 113 114 for(i = 1; i < argc; i++){ 115 if(argv[i][0] == '-'){ 116 if(argv[i][1] == '\0'){ 117 flag.nfiles += argc - i - 1; 118 break; 119 } 120 if(strcmp(argv[i], "-m") == 0){ 121 flag.m = TRUE; 122 continue; 123 } 124 if(strcmp(argv[i], "-l") == 0){ 125 flag.l = TRUE; 126 flag.m = TRUE; 127 continue; 128 } 129 if(strcmp(argv[i], "-x") == 0){ 130 flag.x = TRUE; 131 flag.m = TRUE; 132 continue; 133 } 134 if(strcmp(argv[i], "-arch") == 0){ 135 if(i + 1 == argc){ 136 error("missing argument(s) to %s option", argv[i]); 137 usage(); 138 } 139 if(strcmp("all", argv[i+1]) == 0){ 140 all_archs = TRUE; 141 } 142 else{ 143 arch_flags = reallocate(arch_flags, 144 (narch_flags + 1) * sizeof(struct arch_flag)); 145 if(get_arch_from_flag(argv[i+1], 146 arch_flags + narch_flags) == 0){ 147 error("unknown architecture specification flag: " 148 "%s %s", argv[i], argv[i+1]); 149 arch_usage(); 150 usage(); 151 } 152 narch_flags++; 153 } 154 i++; 155 continue; 156 } 157 } 158 flag.nfiles++; 159 } 160 161 if(flag.m == FALSE) 162 printf("__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n"); 163 164 args_left = TRUE; 165 for (i = 1; i < argc; i++) { 166 if(args_left == TRUE && argv[i][0] == '-'){ 167 if(argv[i][1] == '\0'){ 168 args_left = FALSE; 169 continue; 170 } 171 if(strcmp(argv[i], "-m") == 0) 172 continue; 173 if(strcmp(argv[i], "-l") == 0) 174 continue; 175 if(strcmp(argv[i], "-x") == 0) 176 continue; 177 if(strcmp(argv[i], "-arch") == 0){ 178 i++; 179 continue; 180 } 181 } 182 ofile_process(argv[i], arch_flags, narch_flags, all_archs, FALSE, 183 TRUE, TRUE, size, &flag); 184 } 185 if(flag.nfiles == 0) 186 ofile_process("a.out", arch_flags, narch_flags, all_archs, FALSE, 187 TRUE, TRUE, size, &flag); 188 if(errors == 0) 189 return(EXIT_SUCCESS); 190 else 191 return(EXIT_FAILURE); 192} 193 194/* 195 * usage() prints the current usage message and exits indicating failure. 196 */ 197static 198void 199usage( 200void) 201{ 202 fprintf(stderr, "Usage: %s [-m] [-l] [-x] [--] " 203 "[[-arch <arch_flag>] ...] [file ...]\n", progname); 204 exit(EXIT_FAILURE); 205} 206 207/* 208 * size() is the routine that gets called by ofile_process() to process single 209 * object files. 210 */ 211static 212void 213size( 214struct ofile *ofile, 215char *arch_name, 216void *cookie) 217{ 218 struct flags *flag; 219 uint64_t seg_sum, sect_sum; 220 uint32_t i, j; 221 struct load_command *lc; 222 struct segment_command *sg; 223 struct segment_command_64 *sg64; 224 struct section *s; 225 struct section_64 *s64; 226 uint64_t text, data, objc, others, sum; 227 uint32_t ncmds; 228 229 flag = (struct flags *)cookie; 230 if(ofile->mh != NULL) 231 ncmds = ofile->mh->ncmds; 232 else 233 ncmds = ofile->mh64->ncmds; 234 if(flag->m == TRUE){ 235 if(flag->nfiles > 1 || ofile->member_ar_hdr != NULL || 236 arch_name != NULL){ 237 if(ofile->member_ar_hdr != NULL){ 238 printf("%s(%.*s)", ofile->file_name, 239 (int)ofile->member_name_size, 240 ofile->member_name); 241 } 242 else{ 243 printf("%s", ofile->file_name); 244 } 245 if(arch_name != NULL) 246 printf(" (for architecture %s):\n", arch_name); 247 else 248 printf(":\n"); 249 } 250 lc = ofile->load_commands; 251 seg_sum = 0; 252 for(i = 0; i < ncmds; i++){ 253 if(lc->cmd == LC_SEGMENT){ 254 sg = (struct segment_command *)lc; 255 printf("Segment %.16s: ", sg->segname); 256 if(flag->x == TRUE) 257 printf("0x%x", (unsigned int)sg->vmsize); 258 else 259 printf("%u", sg->vmsize); 260 if(sg->flags & SG_FVMLIB) 261 printf(" (fixed vm library segment)\n"); 262 else{ 263 if(flag->l == TRUE) 264 printf(" (vmaddr 0x%x fileoff %u)\n", 265 (unsigned int)sg->vmaddr, sg->fileoff); 266 else 267 printf("\n"); 268 } 269 seg_sum += sg->vmsize; 270 s = (struct section *)((char *)sg + 271 sizeof(struct segment_command)); 272 sect_sum = 0; 273 for(j = 0; j < sg->nsects; j++){ 274 if(ofile->mh_filetype == MH_OBJECT) 275 printf("\tSection (%.16s, %.16s): ", 276 s->segname, s->sectname); 277 else 278 printf("\tSection %.16s: ", s->sectname); 279 if(flag->x == TRUE) 280 printf("0x%x", (unsigned int)s->size); 281 else 282 printf("%u", s->size); 283 if(flag->l == TRUE) 284 printf(" (addr 0x%x offset %u)\n", 285 (unsigned int)s->addr, s->offset); 286 else 287 printf("\n"); 288 sect_sum += s->size; 289 s++; 290 } 291 if(sg->nsects > 0){ 292 if(flag->x == TRUE) 293 printf("\ttotal 0x%llx\n", sect_sum); 294 else 295 printf("\ttotal %llu\n", sect_sum); 296 } 297 } 298 else if(lc->cmd == LC_SEGMENT_64){ 299 sg64 = (struct segment_command_64 *)lc; 300 printf("Segment %.16s: ", sg64->segname); 301 if(flag->x == TRUE) 302 printf("0x%llx", sg64->vmsize); 303 else 304 printf("%llu", sg64->vmsize); 305 if(sg64->flags & SG_FVMLIB) 306 printf(" (fixed vm library segment)\n"); 307 else{ 308 if(flag->l == TRUE) 309 printf(" (vmaddr 0x%llx fileoff %llu)\n", 310 sg64->vmaddr, sg64->fileoff); 311 else 312 printf("\n"); 313 } 314 seg_sum += sg64->vmsize; 315 s64 = (struct section_64 *)((char *)sg64 + 316 sizeof(struct segment_command_64)); 317 sect_sum = 0; 318 for(j = 0; j < sg64->nsects; j++){ 319 if(ofile->mh_filetype == MH_OBJECT) 320 printf("\tSection (%.16s, %.16s): ", 321 s64->segname, s64->sectname); 322 else 323 printf("\tSection %.16s: ", s64->sectname); 324 if(flag->x == TRUE) 325 printf("0x%llx", s64->size); 326 else 327 printf("%llu", s64->size); 328 if(flag->l == TRUE) 329 printf(" (addr 0x%llx offset %u)\n", 330 s64->addr, 331 s64->offset); 332 else 333 printf("\n"); 334 sect_sum += s64->size; 335 s64++; 336 } 337 if(sg64->nsects > 0){ 338 if(flag->x == TRUE) 339 printf("\ttotal 0x%llx\n", sect_sum); 340 else 341 printf("\ttotal %llu\n", sect_sum); 342 } 343 } 344 lc = (struct load_command *)((char *)lc + lc->cmdsize); 345 } 346 if(flag->x == TRUE) 347 printf("total 0x%llx\n", seg_sum); 348 else 349 printf("total %llu\n", seg_sum); 350 } 351 else{ 352 text = 0; 353 data = 0; 354 objc = 0; 355 others = 0; 356 lc = ofile->load_commands; 357 for(i = 0; i < ncmds; i++){ 358 if(lc->cmd == LC_SEGMENT){ 359 sg = (struct segment_command *)lc; 360 if(ofile->mh_filetype == MH_OBJECT){ 361 s = (struct section *)((char *)sg + 362 sizeof(struct segment_command)); 363 for(j = 0; j < sg->nsects; j++){ 364 if(strcmp(s->segname, SEG_TEXT) == 0) 365 text += s->size; 366 else if(strcmp(s->segname, SEG_DATA) == 0) 367 data += s->size; 368 else if(strcmp(s->segname, SEG_OBJC) == 0) 369 objc += s->size; 370 else 371 others += s->size; 372 s++; 373 } 374 } 375 else{ 376 if(strcmp(sg->segname, SEG_TEXT) == 0) 377 text += sg->vmsize; 378 else if(strcmp(sg->segname, SEG_DATA) == 0) 379 data += sg->vmsize; 380 else if(strcmp(sg->segname, SEG_OBJC) == 0) 381 objc += sg->vmsize; 382 else 383 others += sg->vmsize; 384 } 385 } 386 else if(lc->cmd == LC_SEGMENT_64){ 387 sg64 = (struct segment_command_64 *)lc; 388 if(ofile->mh_filetype == MH_OBJECT){ 389 s64 = (struct section_64 *)((char *)sg64 + 390 sizeof(struct segment_command_64)); 391 for(j = 0; j < sg64->nsects; j++){ 392 if(strcmp(s64->segname, SEG_TEXT) == 0) 393 text += s64->size; 394 else if(strcmp(s64->segname, SEG_DATA) == 0) 395 data += s64->size; 396 else if(strcmp(s64->segname, SEG_OBJC) == 0) 397 objc += s64->size; 398 else 399 others += s64->size; 400 s64++; 401 } 402 } 403 else{ 404 if(strcmp(sg64->segname, SEG_TEXT) == 0) 405 text += sg64->vmsize; 406 else if(strcmp(sg64->segname, SEG_DATA) == 0) 407 data += sg64->vmsize; 408 else if(strcmp(sg64->segname, SEG_OBJC) == 0) 409 objc += sg64->vmsize; 410 else 411 others += sg64->vmsize; 412 } 413 } 414 lc = (struct load_command *)((char *)lc + lc->cmdsize); 415 } 416 printf("%llu\t%llu\t%llu\t%llu\t", text, data, objc, others); 417 sum = text + data + objc + others; 418 printf("%llu\t%llx", sum, sum); 419 if(flag->nfiles > 1 || ofile->member_ar_hdr != NULL || 420 arch_name != NULL){ 421 if(ofile->member_ar_hdr != NULL){ 422 printf("\t%s(%.*s)", ofile->file_name, 423 (int)ofile->member_name_size, 424 ofile->member_name); 425 } 426 else{ 427 printf("\t%s", ofile->file_name); 428 } 429 if(arch_name != NULL) 430 printf(" (for architecture %s)", arch_name); 431 } 432 printf("\n"); 433 } 434} 435