Measure PE Section Sizes with x86_64-w64-mingw32-size
You will finish with a repeatable way to inspect the text, data, BSS and total sizes of MinGW-w64 binaries, switch between the output formats, and add totals for several files. The command only reads object files, so the examples are ordinary unprivileged checks.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide uses GNU Binutils 2.41.90.20240122 from the installed binutils-mingw-w64-x86-64 package, version 2.41.90.20240122-1ubuntu1+11.4. The alias x86_64-w64-mingw32ucrt-size has the same installed behaviour here. Allow about ten minutes if you already have a PE file to inspect.
1. Check the installed command
Confirm the executable and package before relying on an example. This does not need sudo:
$ command -v x86_64-w64-mingw32-size
/usr/bin/x86_64-w64-mingw32-size
$ x86_64-w64-mingw32-size --version
GNU size (GNU Binutils) 2.41.90.20240122
$ dpkg-query -W -f='${Package} ${Version}\n' binutils-mingw-w64-x86-64
binutils-mingw-w64-x86-64 2.41.90.20240122-1ubuntu1+11.4
Checkpoint: if the path or version differs, keep the local command's help and output as the authority. Tool output can change between Binutils releases.
2. Measure one PE file
Pass the path to the executable or object file explicitly. Replace /path/to/program.exe with a readable file that you built for the target:
$ x86_64-w64-mingw32-size /path/to/program.exe
text data bss dec hex filename
9280 1536 384 11200 2bc0 /path/to/program.exe
The default is Berkeley-style output. Its first three numeric columns are text, data and BSS. The decimal total is text + data + bss, and the final total is hexadecimal. The precise values depend on the file, linker settings and whether debug sections are present.
Do not omit the filename unless you deliberately want to inspect a.out. With no input files, this version assumes a.out, which is a common distraction when a build produced a named .exe elsewhere.
3. Choose a format for the question you are asking
Use GNU format when you want a compact table with one total column:
$ x86_64-w64-mingw32-size --format=gnu /path/to/program.exe
text data bss total filename
9280 1536 384 11200 /path/to/program.exe
Use System V format when section names and addresses matter:
$ x86_64-w64-mingw32-size --format=sysv /path/to/program.exe
/path/to/program.exe :
section size addr
.text 5976 5368713216
.data 128 5368721408
.bss 384 5368737792
Total 82562
The System V view can contain many more sections than the three Berkeley columns. That is useful for finding where space went, but its Total includes the sections it lists and is not interchangeable with a simplistic reading of the Berkeley table.
-B or --format=berkeley selects the default explicitly. -A selects System V and -G selects GNU. Format names are easier to read in scripts and review notes, so prefer the long form when the command will be maintained.
4. Make the number base explicit
For a hexadecimal comparison with a linker map or debugger, request base 16:
$ x86_64-w64-mingw32-size --format=gnu --radix=16 /path/to/program.exe
text data bss total filename
0x2450 0x600 0x180 0x2bc0 /path/to/program.exe
--radix=10, --radix=16 and --radix=8 are the supported values. The short forms are -d, -x and -o. The total column uses paired bases according to the selected radix, so read the headings and do not paste a hexadecimal result into a decimal budget without converting it.
Checkpoint: verify a script's assumption with x86_64-w64-mingw32-size --help. A typo such as --radix=7 exits with status 1 and reports Invalid radix: 7; it does not silently choose a base.
5. Compare several files and add a grand total
Give several paths in one invocation to keep the output comparable:
$ x86_64-w64-mingw32-size --format=gnu --totals build/app.exe build/helper.exe
text data bss total filename
9280 1536 384 11200 build/app.exe
9280 1536 384 11200 build/helper.exe
18560 3072 768 22400 (TOTALS)
--totals, or -t, is available for Berkeley and GNU output. It sums the objects named on this command line. It does not scan a directory and it does not compare builds for you, so make the file list explicit in a review script.
6. Handle archives and common symbols carefully
If the input is an archive, the manual says the command reports one line for each module. This is useful for finding a large object inside a static library, but it is not the same as measuring the final linked executable. Measure both when link-time section layout is the question.
--common prints the total size of common symbols. In Berkeley and GNU formats those symbols are included in BSS. Use it when investigating uninitialised storage or legacy tentative definitions, and record whether the flag was present so two reports remain comparable.
--target=BFDNAME forces an object format when automatic recognition is not enough. The installed command reports supported targets in its help output. Try automatic recognition first; forcing the wrong target can turn a useful diagnostic into a format error.
7. Diagnose failures without changing the build
A missing or unreadable input is a path or permission problem, not a reason to run the size command as root:
$ test -r /path/to/program.exe && echo readable
$ x86_64-w64-mingw32-size /path/to/program.exe
x86_64-w64-mingw32-size: '/path/to/program.exe': No such file
If the first command prints nothing, check the path with ls -l and the build output directory. If the input is readable but still rejected, run file /path/to/program.exe and inspect the format with a suitable Binutils tool. Do not edit or overwrite the binary merely to make this read-only report succeed.
The -f option is accepted but ignored by this GNU version. It is not a switch for changing the input format. Likewise, the @file syntax reads whitespace-separated command-line options, including recursively nested option files. Treat an option file as executable configuration: inspect it before use, especially if it came from another build or user.
Done means
- You confirmed the installed Binutils version and command path.
- You passed the intended PE or archive explicitly, rather than relying on the
a.outdefault. - You can explain the difference between Berkeley, GNU and System V output.
- You selected decimal, hexadecimal or octal deliberately and checked the headings.
- You used
--totalsfor a stated list of files when comparing several objects. - You kept the inspection unprivileged and treated option files as trusted input.