/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1988 AT&T
* Copyright (c) 1989 AT&T
* All Rights Reserved
*
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* UNIX HEADERS */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <libelf.h>
/* SIZE HEADER */
#include "defs.h"
/* RELEASE STRING */
#include "conv.h"
#include "sgs.h"
/* EXTERNAL VARIABLES DEFINED */
int fflag = 0, /* print full output if -f option is supplied */
Fflag = 0, /* print full output if -F option is supplied */
nflag = 0; /* include NOLOAD sections in size if -n */
/* option is supplied */
int numbase = DECIMAL;
static int errflag = 0; /* Global error flag */
int oneflag = 0;
int exitcode = 0; /* Global exit code */
char *fname;
char *archive;
int is_archive = 0;
static char *tool_name;
static void usagerr();
#define OPTSTR "VoxnfF" /* option string for usage error message */
#define GETOPTSTR "VoxnfF?" /* option string for getopt */
static Elf *elf;
static Elf_Arhdr *arhdr;
/*
* main(argc, argv)
*
* parses the command line
* opens, processes and closes each object file command line argument
*
* defines:
* - int numbase = HEX if the -x flag is in the command line
* = OCTAL if the -o flag is in the command line
* = DECIMAL if the -d flag is in the command line
*
* calls:
* - process(filename) to print the size information in the object file
* filename
*
* prints:
* - an error message if any unknown options appear on the command line
* - a usage message if no object file args appear on the command line
* - an error message if it can't open an object file
* or if the object file has the wrong magic number
*
* exits 1 - errors found, 0 - no errors
*/
int
main(int argc, char ** argv, char ** envp)
{
/* UNIX FUNCTIONS CALLED */
extern void error();
/* SIZE FUNCTIONS CALLED */
extern void process();
/* EXTERNAL VARIABLES USED */
extern int numbase;
extern int errflag;
extern int oneflag;
extern int optind;
extern char *fname;
int c;
static int fd;
extern char *archive;
Elf_Cmd cmd;
Elf *arf;
unsigned Vflag = 0;
/*
* Check for a binary that better fits this architecture.
*/
(void) conv_check_native(argv, envp);
tool_name = argv[0];
while ((c = getopt(argc, argv, GETOPTSTR)) != EOF) {
switch (c) {
case 'o':
if (numbase != HEX)
numbase = OCTAL;
else
(void) fprintf(stderr,
"size: -x set, -o ignored\n");
break;
case 'd':
numbase = DECIMAL;
break;
case 'x':
if (numbase != OCTAL)
numbase = HEX;
else
(void) fprintf(stderr,
"size: -o set, -x ignored\n");
break;
case 'f':
fflag++;
break;
case 'F':
Fflag++;
break;
case 'n':
nflag++;
break;
case 'V':
(void) fprintf(stderr, "size: %s %s\n",
(const char *)SGU_PKG,
(const char *)SGU_REL);
Vflag++;
break;
case '?':
errflag++;
break;
default:
break;
}
}
if (errflag || (optind >= argc)) {
if (!(Vflag && (argc == 2) && !errflag)) {
usagerr();
}
}
if ((argc - optind) == 1) {
oneflag++; /* only one file to process */
}
if (elf_version(EV_CURRENT) == EV_NONE) {
(void) fprintf(stderr, "size: Libelf is out of date");
exit(FATAL); /* library out of date */
}
for (; optind < argc; optind++) {
fname = argv[optind];
if ((fd = open(argv[optind], O_RDONLY)) == -1) {
error(fname, "cannot open");
} else {
cmd = ELF_C_READ;
arf = 0;
if ((arf = elf_begin(fd, cmd, arf)) == 0) {
/* error(fname, "cannot open"); */
(void) fprintf(stderr,
"size: %s: %s\n", fname, elf_errmsg(-1));
return (FATAL);
}
if (elf_kind(arf) == ELF_K_AR) {
archive = argv[optind];
} else {
archive = "";
}
while ((elf = elf_begin(fd, cmd, arf)) != 0) {
if ((arhdr = elf_getarhdr(elf)) == 0) {
if (elf_kind(arf) == ELF_K_NONE) {
/* BEGIN CSTYLED */
(void) fprintf(stderr,
"%s: %s: invalid file type\n",
tool_name, fname);
/* END CSTYLED */
exitcode++;
break;
} else {
process(elf);
}
} else if (arhdr->ar_name[0] != '/') {
fname = arhdr->ar_name;
if (elf_kind(arf) == ELF_K_NONE) {
/* BEGIN CSTYLED */
(void) fprintf(stderr,
"%s: %s[%s]: invalid file type\n",
tool_name, archive, fname);
/* END CSTYLED */
exitcode++;
break;
} else {
is_archive++;
process(elf);
}
}
cmd = elf_next(elf);
(void) elf_end(elf);
}
(void) elf_end(arf);
(void) close(fd);
}
}
if (exitcode)
exit(FATAL);
else
exit(0);
return (0);
}
static void
usagerr()
{
(void) fprintf(stderr,
"usage: %s [-%s] file(s)...\n", tool_name, OPTSTR);
exitcode++;
}