Skip to content

BUILD/MINOR: strip the symbol table and trim the build path from the binary - #845

Open
PixiBixi wants to merge 1 commit into
haproxytech:masterfrom
PixiBixi:build/strip-binaries
Open

BUILD/MINOR: strip the symbol table and trim the build path from the binary#845
PixiBixi wants to merge 1 commit into
haproxytech:masterfrom
PixiBixi:build/strip-binaries

Conversation

@PixiBixi

@PixiBixi PixiBixi commented Aug 26, 2026

Copy link
Copy Markdown

Neither build path passes -s -w: not .goreleaser.yml, not build/Dockerfile:53. Both
ship the symbol table and the DWARF data.

Measured

linux/amd64, same commit, same CGO_ENABLED=0:

build size
as today 98.7 MB
-ldflags "-s" 69.7 MB −29.4%
+ -trimpath 69.5 MB −29.5%

Close to 30 MB per image, pulled on every node of every cluster.

Stack traces are not what is lost

This is the usual objection, and it does not hold. A Go stack trace is read from the
pclntab, which the linker keeps whatever the flags are: -s drops the symbol table and
the DWARF data, and touches neither the pclntab. Same panic, two binaries:

### without -s                      ### with -s
panic: index out of range [1]       panic: index out of range [1]

goroutine 1 [running]:              goroutine 1 [running]:
main.explode(...)                   main.explode(...)
	/…/main.go:3                       /…/main.go:3
main.main()                         main.main()

Identical. net/http/pprof is unaffected for the same reason: symbolisation happens in
the runtime, from the pclntab, not from the symbol table.

-w is deliberately not passed alongside -s. See the discussion below.

What is genuinely lost: source-level debugging with delve on a live process, go tool nm,
and core dump analysis under gdb. For a controller that is reached over the network and
observed through its logs and its pprof endpoint, none of those is how anyone works on it.

I would not sell this as hardening. -s does not meaningfully impede reverse
engineering; it is a size change.

-trimpath

Almost free in size (0.2 MB) but worth its own line. It keeps the build machine's path out
of the binary, which today is 4470 occurrences of a build directory in the
linux/amd64 build, and it is one of the conditions for two builds of the same commit to
produce the same bytes.

Verified

The -X version stamping still applies with -s in the same -ldflags string, checked
on a build carrying both.

@PixiBixi
PixiBixi force-pushed the build/strip-binaries branch from 0910439 to d2bdbd4 Compare August 26, 2026 22:28
@oktalz

oktalz commented Aug 27, 2026

Copy link
Copy Markdown
Member

@PixiBixi this seems like a good change, but
-w is not needed at all if -s is used, could you remove it ?
also I fail to see how this is related to other linked issues

…binary

Neither the goreleaser build nor the one in build/Dockerfile passes -s, so
both ship the symbol table and the DWARF data. On linux/amd64 that is
98.7 MB where 69.5 MB is enough, close to 30 MB carried by every image on
every node.

-w is not passed with it. The linker derives it from -s unless it is given
explicitly, so the two produce the same binary, and naming only -s says
what is being asked for.

The symbol table is not what a stack trace is read from. Go keeps the
pclntab whatever the linker flags are, and -s does not touch it, so a panic
still prints the function names and the line numbers, and pprof still
symbolises. Measured on the same panic with and without the flag, the two
traces are identical. What is lost is source level debugging with delve, go
tool nm, and core dump analysis under gdb, none of which is a way anyone
works on a running ingress controller.

-trimpath goes with it. It keeps the path of the machine that built the
binary out of the result, which is 4470 occurrences of a build directory in
the current linux/amd64 build, and it is one of the conditions for two
builds of the same commit to produce the same bytes.

The -X stamping of the version is not affected. It is verified in the same
build as these flags.
@PixiBixi
PixiBixi force-pushed the build/strip-binaries branch from d2bdbd4 to 5a2facf Compare August 27, 2026 07:23
@PixiBixi

Copy link
Copy Markdown
Author

You are right on both counts, thanks.

-w: removed, -s alone now. I had carried it over out of habit without checking.
It is not just redundant, it is derived: cmd/link/internal/ld/main.go:274 does

*FlagW = *FlagS // -s implies -w if not explicitly set

Measured on this tree, linux/amd64, -trimpath on all four:

ldflags size .symtab .debug* sections
none 103,276,329 yes 8
-s 72,913,056 no 0
-w 83,023,367 yes 0
-s -w 72,913,056 no 0

-s and -s -w are the same size to the byte and carry the same sections. Naming only
-s also says what is being asked for, rather than implying the two do different work
here.

The linked issues: fair, they do not belong. They came from the same pass over the
repository, which is not a relation from a reviewer's point of view. Removed from the
description.

The commit message is updated too, so the reasoning for dropping -w is in the history
rather than only in this thread.

PixiBixi added a commit to PixiBixi/pixibixi.github.io that referenced this pull request Aug 27, 2026
The article listed -s and -w as two flags doing two jobs. The linker derives
-w from -s unless -w is passed explicitly, so -s -w and -s produce the same
binary: cmd/link/internal/ld/main.go carries the rule as a one-liner.

Adds the measurement behind it, the four ldflags combinations with their
size and their ELF sections, plus what stripping actually costs. The stack
trace objection is the one that keeps -s out of projects that would benefit
from it, and it is wrong: the pclntab survives, so traces and pprof are
untouched. Says plainly that this is not a hardening measure, since selling
it as one leads to bad calls elsewhere.

Reported by a HAProxy maintainer on
haproxytech/kubernetes-ingress#845, where the same -s -w had been proposed.
@PixiBixi

Copy link
Copy Markdown
Author

@oktalz any update for it? Not a big change at all 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants