# 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= size XLDADD= -lelf X XBINDIR= /usr/bin X X.include END-of-Makefile echo x - size.1 sed 's/^X//' >size.1 << 'END-of-size.1' X.\"- X.\" Copyright (c) 2008 Ed Schouten 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 PURPOSE X.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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, STRICT 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 format 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 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 PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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, STRICT 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 X#include X#include X#include X#include X#include X X#include X#include X Xstatic int sysvflg = -1; Xstatic int radixflg = -1; Xstatic int totalflg = 0; Xstatic int exitcode = 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 = 0, total_data = 0, total_bss = 0; Xstatic int header_printed = 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 = text + data + bss; X X if (!header_printed) { X printf(" text\t data\t bss\t %s\t hex\tfilename\n", X radixflg == 8 ? "oct" : "dec"); X header_printed = 1; X } X X /* Radix dependant fields */ X if (radixflg == 8) { X fmt = "%#7o\t%#7o\t%#7o\t%7o"; X } else if (radixflg == 16) { X fmt = "%#7x\t%#7x\t%#7x\t%7u"; X } else { X fmt = "%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 = 0, data = 0, bss = 0; X Elf_Scn *es; X GElf_Shdr hdr; X X if (elf_getshnum(e, &nsec) == 0) { X warnx("%s: Unable to obtain the number of sections: %s", X filename, elf_errmsg(-1)); X exitcode = 1; X return; X } X X for (i = 0; i < nsec; i++) { X /* Iterate all the section headers */ X es = elf_getscn(e, i); X if (es == NULL) { X warnx("%s: Unable to obtain section %u: %s", X filename, i, elf_errmsg(-1)); X exitcode = 1; X return; X } X X if (gelf_getshdr(es, &hdr) != &hdr) { X warnx("%s: Unable to obtain section header %u: %s", X filename, i, elf_errmsg(-1)); X exitcode = 1; X return; X } X X /* Skip fields that don't take space anyway */ X if ((hdr.sh_flags & SHF_ALLOC) == 0) X continue; X if (hdr.sh_flags & SHF_EXECINSTR || X ((hdr.sh_flags & SHF_WRITE) == 0)) { X /* Read-only data */ X text += hdr.sh_size; X } else if (hdr.sh_type == SHT_NOBITS) { X /* Fields that don't consume space in the binary */ X bss += hdr.sh_size; X } else { X /* Read/write data segments */ X data += hdr.sh_size; X } X } X X print_line_berkeley(text, data, bss, filename); X X total_text += text; X total_data += data; X total_bss += 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 = 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) == 0) { X warnx("%s: Unable to obtain the number of sections: %s", X filename, elf_errmsg(-1)); X exitcode = 1; X return; X } X X /* Locate the string table for the section names */ X if (elf_getshstrndx(e, &strndx) == 0) { X warnx("%s: Unable to locate the string index: %s", X filename, elf_errmsg(-1)); X exitcode = 1; X return; X } X es = elf_getscn(e, strndx); X if ((es = elf_getscn(e, strndx)) == NULL || X (sdata = elf_rawdata(es, NULL)) == NULL || X sdata->d_buf == NULL) { X warnx("%s: Unable to obtain string table: %s", X filename, elf_errmsg(-1)); X exitcode = 1; X return; X } X snames = sdata->d_buf; X X printf("%s :\nsection size addr\n", filename); X X for (i = 0; i < nsec; i++) { X /* Iterate all the section headers */ X es = elf_getscn(e, i); X if (es == NULL) { X warnx("%s: Unable to obtain section %u: %s", X filename, i, elf_errmsg(-1)); X exitcode = 1; X return; X } X X if (gelf_getshdr(es, &hdr) != &hdr) { X warnx("%s: Unable to obtain section header %u: %s", X filename, i, elf_errmsg(-1)); X exitcode = 1; X return; X } X X /* Skip fields that don't take space anyway */ X if (hdr.sh_type != SHT_PROGBITS && X (hdr.sh_flags & SHF_ALLOC) == 0) X continue; X X /* Make sure we don't overrun the buffer */ X if (hdr.sh_name >= sdata->d_size) { X warnx("%s: Invalid name offset: %u", X filename, hdr.sh_name); X exitcode = 1; X continue; X } X X total += hdr.sh_size; X X printf("%-16s ", snames + hdr.sh_name); X if (radixflg == 8) { X fmt = "%#7o %#10o\n"; X } else if (radixflg == 16) { X fmt = "%#7x %#10x\n"; X } else { X fmt = "%7u %10u\n"; X } X printf(fmt, (unsigned int)hdr.sh_size, 0xdeadc0de); X } X X fputs("Total ", stdout); X if (radixflg == 8) { X printf("%#18o", total); X } else if (radixflg == 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 = getopt(argc, argv, "ABdotx")) != -1) { X switch (ch) { X case 'A': X /* SysV style output */ X if (sysvflg == 0) X usage(); X sysvflg = 1; X break; X case 'B': X /* Berkeley style output */ X if (sysvflg == 1) X usage(); X sysvflg = 0; X break; X case 'd': X /* Decimal output */ X if (radixflg != -1 && radixflg != 10) X usage(); X radixflg = 10; X break; X case 'o': X /* Octal output */ X if (radixflg != -1 && radixflg != 8) X usage(); X radixflg = 8; X break; X case 'x': X /* Hexadecimal output */ X if (radixflg != -1 && radixflg != 8) X usage(); X radixflg = 16; X break; X case 't': X /* List sum of sizes */ X totalflg = 1; X break; X default: X usage(); X } X } X argc -= optind; X argv += optind; X X if (argc == 0) X usage(); X X if (elf_version(EV_CURRENT) == EV_NONE) { X errx(1, "ELF library initialization failed: %s", X elf_errmsg(-1)); X } X X X do { X /* X * Already parse the ELF file and hand it over to the print X * routines. X */ X fd = open(*argv, O_RDONLY); X if (fd < 0) { X warn("%s", *argv); X exitcode = 1; X continue; X } X X e = elf_begin(fd, ELF_C_READ, NULL); X if (e == NULL) { X warnx("%s: %s", *argv, elf_errmsg(-1)); X exitcode = 1; X continue; X } X X if (sysvflg == 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 != 0); X X if (sysvflg != 1) X print_footer_berkeley(); X X return (exitcode); X} END-of-size.c exit