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.
The route
Jump straight to the step you need, or tick off Done means at the end.
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
- No input supplied. GNU
sizefalls back toa.out, which often produces a confusing error on a modern project. Name the file explicitly. - Format detection fails. Inspect the file with a suitable Binutils tool first.
--target=BFDNAMEcan force a BFD object format, but guessing a target can produce misleading results. - Common symbols.
--commonreports their total size; in Berkeley and GNU formats it is already included in thebssvalue. Use it when common symbols matter to your build comparison. - Ignored flag.
-fis accepted but ignored by GNU Binutils. Do not add it assuming it changes the report. - Options files.
@filearguments are expanded recursively. Treat them as executable configuration: inspect their contents before use, especially in automated builds.
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
- Version recorded: you know the exact
sizeexecutable and version. - Sum checked: you read a named binary and confirmed
decis the section sum. - Format chosen: you selected Berkeley, GNU or System V output knowingly.
- Radix consistent: you used one radix and did not confuse section totals with runtime memory or file length.
- Comparison safe: you can compare several files or archive members without changing the originals.