Measure ELF Section Sizes with GNU size

A binary got bigger for no obvious reason, and GNU size tells you whether the bloat sits in code, data, or uninitialised storage. You will read section sizes, compare several files, and inspect an archive without changing any input. Allow about ten minutes. You need a shell, GNU Binutils, and a readable ELF executable or object file; no elevated privileges are normally needed.

Tip: By the end, you should know which output format you used and what its total actually includes: that matters more than the raw numbers.

1. Check the command and version

This machine has GNU Binutils 2.42 in the installed binutils-common, binutils-aarch64-linux-gnu and binutils-x86-64-linux-gnu packages. The command found first in this shell is GNU Binutils 2.47.20260726, so record your own path and version before comparing numbers with another host.

$ command -v size
/home/linuxbrew/.linuxbrew/bin/size
$ size --version | head -n 2
GNU size (GNU Binutils) 2.47.20260726
Copyright (C) 2026 Free Software Foundation, Inc.

The architecture-prefixed aliases, such as aarch64-linux-gnu-size and x86_64-linux-gnu-size, use the same documented interface. Prefer the alias that matches the target toolchain when you need to make that choice explicit.

2. Read the default Berkeley-style summary

Give size one or more object files. The default is a one-line Berkeley-style report, with columns in bytes: text for code and read-only data as counted by this format, data for initialised writable data, and bss for zero-initialised storage. dec and hex are the sum of those three columns.

$ size /bin/true
   text   data    bss    dec    hex filename
  18383     900     16  19299   4b63 /bin/true

The exact numbers depend on the binary and build. This command only reads the file: it does not measure the executable's on-disk file length, memory mapping, shared-library footprint or peak runtime memory.

Checkpoint: Confirm that dec equals text + data + bss. If you need file length, use a separate command such as stat; do not treat dec as a disk-usage figure.

3. Pick a format before comparing results

GNU size supports Berkeley, GNU and System V layouts, and the difference is more than presentation. Berkeley places read-only data in text; GNU places it in data and calls the sum total. Use one format consistently in a report.

$ size --format=gnu /bin/true
      text       data        bss      total filename
     11946       7337         16      19299 /bin/true
$ size --format=sysv /bin/true | sed -n '1,8p'
/bin/true  :
section               size    addr
.interp                 28     792
.note.gnu.property      48     824
.note.gnu.build-id      36     872
.note.ABI-tag           32     908
.gnu.hash               36     944
.dynsym               1104     984

The short forms are -B for Berkeley, -G for GNU and -A for System V; the long forms are easier to audit in scripts. System V output lists individual sections and addresses, while Berkeley and GNU output are compact summaries.

4. Change the number base deliberately

Use --radix=10, --radix=8 or --radix=16, also available as -d, -o and -x. Only 8, 10 and 16 are accepted. With decimal or hexadecimal section output, the total stays available in decimal and hexadecimal; octal output uses octal and hexadecimal totals.

$ size --radix=16 /bin/true
   text   data    bss    dec    hex filename
  0x47cf  0x384  0x10  19299  4b63 /bin/true

Do not compare a hexadecimal section column with a decimal one by eye. Keep the selected radix in the command or report heading, and convert values when doing arithmetic outside the tool.

5. Compare files and request a grand total

List several files to get one row per file. Add --totals when you also need their combined section totals; this applies to Berkeley and GNU output modes, not to the System V section listing.

$ size --totals /bin/true /bin/false
   text   data    bss    dec    hex filename
  18383     900     16  19299   4b63 /bin/true
  18383     900     16  19299   4b63 /bin/false
  36766    1800     32  38598   96c6 (TOTALS)

Totals are a report over the files you named, not a prediction of the memory used when they run together. Shared libraries, loader behaviour and runtime allocations sit outside this calculation.

6. Inspect an archive without unpacking it

If the input is an archive, size reports each module in it, which is handy for spotting a large object before linking. The archive members below are copied from system binaries only to make a disposable test archive; this does not modify /bin/true or /bin/false.

$ workdir=$(mktemp -d /tmp/size-example.XXXXXX)
$ cp /bin/true "$workdir/true.o"
$ cp /bin/false "$workdir/false.o"
$ ar rcs "$workdir/sample.a" "$workdir/true.o" "$workdir/false.o"
$ size "$workdir/sample.a"
   text   data    bss    dec    hex filename
  18383     900     16  19299   4b63 true.o (ex /tmp/size-example.XXXXXX/sample.a)
  18383     900     16  19299   4b63 false.o (ex /tmp/size-example.XXXXXX/sample.a)

The random directory suffix in the displayed archive path will differ. When finished, remove only the disposable directory you created, for example with rm -rf -- "$workdir". Check the variable first: a mistaken destructive command can remove more than the test files. No sudo is needed for this example.

Common traps

If a report looks wrong, first run command -v size, size --version and file /path/to/binary. Compare the tool path, version, target format and selected output mode before comparing numbers. Reading a binary needs no elevated privilege; only use an administrator account if ordinary file permissions genuinely require it.

Done means