Makefile: add verify-dce target, use it in CI

Calling reflect.Value.Method or reflect.Value.MethodByName with a
non-constant argument (directly, or indirectly via e.g. text/template)
disables the linker's dead code elimination of exported methods,
noticeably increasing the binary size.

Add verify-dce target to make sure this does not happen again, and run
it from CI. To make sure the check itself works, also run it against
a small program which disables DCE, and expect it to fail.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin committed 2026-10-03 03:20:56 -07:00
1 parent 0774e1d04b
commit 1a187e899b
3 files changed
+34

No files matched your search

+2
View File
@@ -91,6 +91,8 @@ jobs:
run: make BUILDTAGS=""
- name: compile with runc_nocriu build tag
run: make RUNC_BUILDTAGS="runc_nocriu"
- name: verify linker dead code elimination is not disabled
run: make verify-dce
codespell:
runs-on: ubuntu-24.04
+14
View File
@@ -249,6 +249,20 @@ verify-dependencies: vendor
|| (echo -e "git status:\n $$(git status -- go.mod go.sum vendor/)\nerror: vendor/, go.mod and/or go.sum not up to date. Run \"make vendor\" to update"; exit 1) \
&& echo "all vendor files are up to date."
# Check that nothing disables the linker's dead code elimination of
# exported methods, which noticeably increases the binary size. This is
# caused by calling reflect.Value.Method or reflect.Value.MethodByName
# with a non-constant argument, including indirectly (e.g. text/template).
# The check itself is verified using tests/dce-canary, which disables DCE.
.PHONY: verify-dce
verify-dce:
$(GO) build -o /dev/null -ldflags=-dumpdep ./tests/dce-canary 2>&1 \
| grep -q '<ReflectMethod>' \
|| { echo "error: verify-dce self-check failed (tests/dce-canary not detected)"; exit 1; }
set -o pipefail; $(GO_BUILD) -o /dev/null -ldflags=-dumpdep . 2>&1 \
| { ! grep -q '<ReflectMethod>' \
|| { echo "error: linker dead code elimination is disabled; use github.com/aarzilli/whydeadcode to find out why"; exit 1; }; }
.PHONY: validate-keyring
validate-keyring:
script/keyring_validate.sh
+18
View File
@@ -0,0 +1,18 @@
// dce-canary is a positive control for "make verify-dce". It calls
// reflect.Value.MethodByName with a non-constant argument, which makes
// the linker disable dead code elimination of exported methods, so
// "verify-dce" must detect it. If it does not, the check is broken.
package main
import (
"os"
"reflect"
)
type t struct{}
func (t) Foo() {}
func main() {
reflect.ValueOf(t{}).MethodByName(os.Args[0])
}