Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 3 Mar 2008 21:08:29 +0100
From:      Ed Schouten <ed@80386.nl>
To:        FreeBSD Current <freebsd-current@freebsd.org>
Subject:   Re: Yet another BSD licensed replacement: size(1)
Message-ID:  <20080303200829.GG80576@hoeg.nl>
In-Reply-To: <20080303200219.GF80576@hoeg.nl>
References:  <20080303200219.GF80576@hoeg.nl>

next in thread | previous in thread | raw e-mail | index | archive | help

--N8NGGaQn1mzfvaPg
Content-Type: multipart/mixed; boundary="ik0NlRzMGhMnxrMX"
Content-Disposition: inline


--ik0NlRzMGhMnxrMX
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

* Ed Schouten <ed@80386.nl> wrote:
> I've attached the code to this message.

Of course, Mailman ate the source file.

--=20
 Ed Schouten <ed@fxq.nl>
 WWW: http://g-rave.nl/

--ik0NlRzMGhMnxrMX
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="size.txt"
Content-Transfer-Encoding: quoted-printable

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	Makefile
#	size.1
#	size.c
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
XPROG=3D	size
XLDADD=3D	-lelf
X
XBINDIR=3D	/usr/bin
X
X.include <bsd.prog.mk>
END-of-Makefile
echo x - size.1
sed 's/^X//' >size.1 << 'END-of-size.1'
X.\"-
X.\" Copyright (c) 2008 Ed Schouten <ed@fxq.nl>
X.\" All rights reserved.
X.\"
X.\" Redistribution and use in source and binary forms, with or without
X.\" modification, are permitted provided that the following conditions
X.\" are met:
X.\" 1. Redistributions of source code must retain the above copyright
X.\"    notice, this list of conditions and the following disclaimer.
X.\" 2. Redistributions in binary form must reproduce the above copyright
X.\"    notice, this list of conditions and the following disclaimer in the
X.\"    documentation and/or other materials provided with the distribution.
X.\"
X.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PUR=
POSE
X.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUEN=
TIAL
X.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ST=
RICT
X.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY =
WAY
X.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X.\" SUCH DAMAGE.
X.\"
X.\" $FreeBSD$
X.\"
X.Dd March 3, 2008
X.Dt SIZE 1
X.Os
X.Sh NAME
X.Nm size
X.Nd list section sizes of ELF files
X.Sh SYNOPSIS
X.Nm
X.Op Fl A | B
X.Op Fl d | o | x
X.Op Fl t
X.Ar
X.Sh DESCRIPTION
XFor each operand,
X.Nm
Xdisplays the sizes of the read-only sections of the ELF file (text), the
Xread-write sections (data) and the zero-initialized sections (bss). This f=
ormat
Xis referred to as the Berkeley format, which is shown by default.
X.Pp
XThis version of
X.Nm
Xalso supports the System V format, which shows the sizes and load
Xaddresses of all sections within the ELF file.
X.Pp
XThe following options are available:
X.Bl -tag -width indent
X.It Fl A
XShow output using the System V format.
X.It Fl B
XShow output using the Berkeley format.
X.It Fl d
XDisplay sizes as decimal numbers.
X.It Fl o
XDisplay sizes as octal numbers. When enabled, the
X.Em dec
Xcolumn in the Berkeley format is replaced by a column which displays the
Xsize in octal.
X.It Fl x
XDisplay sizes as hexadecimal numbers.
X.It Fl t
XWhen using the Berkeley format, show the total size for all ELF files at
Xthe bottom.
X.Sh EXIT STATUS
X.Ex -std
X.Sh COMPATIBILITY
XThis utility implements most standard options that are implemented in
Xthe GNU
X.Nm
Xutility. Unlike the GNU version, this utility only supports decimal,
Xoctal and hexadecimal radices.
X.Sh SEE ALSO
X.Xr objdump 1 ,
X.Xr readelf 1 ,
X.Sh HISTORY
XIn
X.Fx 8.0 ,
X.An "Ed Schouten" Aq ed@80386.nl
Xreimplemented
X.Nm
Xusing the
X.Lb libelf .
END-of-size.1
echo x - size.c
sed 's/^X//' >size.c << 'END-of-size.c'
X/*-
X * Copyright (c) 2008 Ed Schouten <ed@fxq.nl>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP=
OSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENT=
IAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STR=
ICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY W=
AY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $FreeBSD$
X */
X
X#include <err.h>
X#include <fcntl.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <unistd.h>
X
X#include <gelf.h>
X#include <libelf.h>
X
Xstatic int sysvflg =3D -1;
Xstatic int radixflg =3D -1;
Xstatic int totalflg =3D 0;
Xstatic int exitcode =3D 0;
X
Xstatic void
Xusage(void)
X{
X	fprintf(stderr, "usage: size [-A | -B] [-d | -o | -x] [-t] file ...\n");
X	exit(1);
X}
X
Xstatic unsigned int total_text =3D 0, total_data =3D 0, total_bss =3D 0;
Xstatic int header_printed =3D 0;
X
Xstatic void
Xprint_line_berkeley(unsigned int text, unsigned int data,
X    unsigned int bss, const char *filename)
X{
X	const char *fmt;
X	unsigned int total;
X
X	total =3D text + data + bss;
X
X	if (!header_printed) {
X		printf("   text\t   data\t    bss\t    %s\t    hex\tfilename\n",
X		    radixflg =3D=3D 8 ? "oct" : "dec");
X		header_printed =3D 1;
X	}
X
X	/* Radix dependant fields */
X	if (radixflg =3D=3D 8) {
X		fmt =3D "%#7o\t%#7o\t%#7o\t%7o";
X	} else if (radixflg =3D=3D 16) {
X		fmt =3D "%#7x\t%#7x\t%#7x\t%7u";
X	} else {
X		fmt =3D "%7u\t%7u\t%7u\t%7u";
X	}
X	printf(fmt, text, data, bss, total);
X	/* Radix independant fields */
X	printf("\t%7x\t%s\n", total, filename);
X}
X
Xstatic void
Xprint_entry_berkeley(Elf *e, const char *filename)
X{
X	unsigned int i, nsec;
X	unsigned int text =3D 0, data =3D 0, bss =3D 0;
X	Elf_Scn *es;
X	GElf_Shdr hdr;
X
X	if (elf_getshnum(e, &nsec) =3D=3D 0) {
X		warnx("%s: Unable to obtain the number of sections: %s",
X		    filename, elf_errmsg(-1));
X		exitcode =3D 1;
X		return;
X	}
X
X	for (i =3D 0; i < nsec; i++) {
X		/* Iterate all the section headers */
X		es =3D elf_getscn(e, i);
X		if (es =3D=3D NULL) {
X			warnx("%s: Unable to obtain section %u: %s",
X			    filename, i, elf_errmsg(-1));
X			exitcode =3D 1;
X			return;
X		}
X
X		if (gelf_getshdr(es, &hdr) !=3D &hdr) {
X			warnx("%s: Unable to obtain section header %u: %s",
X			    filename, i, elf_errmsg(-1));
X			exitcode =3D 1;
X			return;
X		}
X
X		/* Skip fields that don't take space anyway */
X		if ((hdr.sh_flags & SHF_ALLOC) =3D=3D 0)
X			continue;
X		if (hdr.sh_flags & SHF_EXECINSTR ||
X		    ((hdr.sh_flags & SHF_WRITE) =3D=3D 0)) {
X		    	/* Read-only data */
X			text +=3D hdr.sh_size;
X		} else if (hdr.sh_type =3D=3D SHT_NOBITS) {
X			/* Fields that don't consume space in the binary */
X			bss +=3D hdr.sh_size;
X		} else {
X			/* Read/write data segments */
X			data +=3D hdr.sh_size;
X		}
X	}
X
X	print_line_berkeley(text, data, bss, filename);
X
X	total_text +=3D text;
X	total_data +=3D data;
X	total_bss +=3D bss;
X}
X
Xstatic void
Xprint_footer_berkeley(void)
X{
X	if (!header_printed || !totalflg)
X		return;
X
X	print_line_berkeley(total_text, total_data, total_bss, "(TOTALS)");
X}
X
Xstatic void
Xprint_entry_sysv(Elf *e, const char *filename)
X{
X	unsigned int i, nsec, total =3D 0;
X	size_t strndx;
X	const char *fmt;
X	Elf_Scn *es;
X	GElf_Shdr hdr;
X	Elf_Data *sdata;
X	const char *snames;
X
X	if (elf_getshnum(e, &nsec) =3D=3D 0) {
X		warnx("%s: Unable to obtain the number of sections: %s",
X		    filename, elf_errmsg(-1));
X		exitcode =3D 1;
X		return;
X	}
X
X	/* Locate the string table for the section names */
X	if (elf_getshstrndx(e, &strndx) =3D=3D 0) {
X		warnx("%s: Unable to locate the string index: %s",
X		    filename, elf_errmsg(-1));
X		exitcode =3D 1;
X		return;
X	}
X	es =3D elf_getscn(e, strndx);
X	if ((es =3D elf_getscn(e, strndx)) =3D=3D NULL ||
X	    (sdata =3D elf_rawdata(es, NULL)) =3D=3D NULL ||
X	    sdata->d_buf =3D=3D NULL) {
X		warnx("%s: Unable to obtain string table: %s",
X		    filename, elf_errmsg(-1));
X		exitcode =3D 1;
X		return;
X	}
X	snames =3D sdata->d_buf;
X
X	printf("%s  :\nsection             size       addr\n", filename);
X
X	for (i =3D 0; i < nsec; i++) {
X		/* Iterate all the section headers */
X		es =3D elf_getscn(e, i);
X		if (es =3D=3D NULL) {
X			warnx("%s: Unable to obtain section %u: %s",
X			    filename, i, elf_errmsg(-1));
X			exitcode =3D 1;
X			return;
X		}
X
X		if (gelf_getshdr(es, &hdr) !=3D &hdr) {
X			warnx("%s: Unable to obtain section header %u: %s",
X			    filename, i, elf_errmsg(-1));
X			exitcode =3D 1;
X			return;
X		}
X
X		/* Skip fields that don't take space anyway */
X		if (hdr.sh_type !=3D SHT_PROGBITS &&
X		    (hdr.sh_flags & SHF_ALLOC) =3D=3D 0)
X			continue;
X
X		/* Make sure we don't overrun the buffer */
X		if (hdr.sh_name >=3D sdata->d_size) {
X			warnx("%s: Invalid name offset: %u",
X			    filename, hdr.sh_name);
X			exitcode =3D 1;
X			continue;
X		}
X
X		total +=3D hdr.sh_size;
X
X		printf("%-16s ", snames + hdr.sh_name);
X		if (radixflg =3D=3D 8) {
X			fmt =3D "%#7o %#10o\n";
X		} else if (radixflg =3D=3D 16) {
X			fmt =3D "%#7x %#10x\n";
X		} else {
X			fmt =3D "%7u %10u\n";
X		}
X		printf(fmt, (unsigned int)hdr.sh_size, 0xdeadc0de);
X	}
X
X	fputs("Total ", stdout);
X	if (radixflg =3D=3D 8) {
X		printf("%#18o", total);
X	} else if (radixflg =3D=3D 16) {
X		printf("%#18x", total);
X	} else {
X		printf("%18d", total);
X	}
X	fputs("\n\n\n", stdout);
X}
X
Xint
Xmain(int argc, char *argv[])
X{
X	int ch, fd;
X	Elf *e;
X
X	while ((ch =3D getopt(argc, argv, "ABdotx")) !=3D -1) {
X		switch (ch) {
X		case 'A':
X			/* SysV style output */
X			if (sysvflg =3D=3D 0)
X				usage();
X			sysvflg =3D 1;
X			break;
X		case 'B':
X			/* Berkeley style output */
X			if (sysvflg =3D=3D 1)
X				usage();
X			sysvflg =3D 0;
X			break;
X		case 'd':
X			/* Decimal output */
X			if (radixflg !=3D -1 && radixflg !=3D 10)
X				usage();
X			radixflg =3D 10;
X			break;
X		case 'o':
X			/* Octal output */
X			if (radixflg !=3D -1 && radixflg !=3D 8)
X				usage();
X			radixflg =3D 8;
X			break;
X		case 'x':
X			/* Hexadecimal output */
X			if (radixflg !=3D -1 && radixflg !=3D 8)
X				usage();
X			radixflg =3D 16;
X			break;
X		case 't':
X			/* List sum of sizes */
X			totalflg =3D 1;
X			break;
X		default:
X			usage();
X		}
X	}
X	argc -=3D optind;
X	argv +=3D optind;
X
X	if (argc =3D=3D 0)
X		usage();
X=09
X	if (elf_version(EV_CURRENT) =3D=3D EV_NONE) {
X		errx(1, "ELF library initialization failed: %s",
X		    elf_errmsg(-1));
X	}
X=09
X
X	do {
X		/*
X		 * Already parse the ELF file and hand it over to the print
X		 * routines.
X		*/
X		fd =3D open(*argv, O_RDONLY);
X		if (fd < 0) {
X			warn("%s", *argv);
X			exitcode =3D 1;
X			continue;
X		}
X
X		e =3D elf_begin(fd, ELF_C_READ, NULL);
X		if (e =3D=3D NULL) {
X			warnx("%s: %s", *argv, elf_errmsg(-1));
X			exitcode =3D 1;
X			continue;
X		}
X
X		if (sysvflg =3D=3D 1)
X			print_entry_sysv(e, *argv);
X		else
X			print_entry_berkeley(e, *argv);
X
X		elf_end(e);
X		close(fd);
X	} while (argv++, --argc !=3D 0);
X
X	if (sysvflg !=3D 1)
X		print_footer_berkeley();
X
X	return (exitcode);
X}
END-of-size.c
exit


--ik0NlRzMGhMnxrMX--

--N8NGGaQn1mzfvaPg
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (FreeBSD)

iEYEARECAAYFAkfMWr0ACgkQ52SDGA2eCwUivgCeN7cDhT4p7vPC38YZKNOoxZUY
6QwAn0WvSom46tsGoj/MxJqffOowhPDZ
=MSvS
-----END PGP SIGNATURE-----

--N8NGGaQn1mzfvaPg--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080303200829.GG80576>