Documentation
¶
Overview ¶
Command normalize-elf normalizes an ELF shared library for reproducible builds by zeroing non-deterministic content.
It performs two categories of normalization:
Go build info: gomobile embeds a `replace` directive with the local filesystem path in the Go build info stored in .rodata. This path varies between build environments and breaks reproducible builds. The tool finds the serialised build info strings (starting with "path\tgobind" or "mod\tgobind") within the .rodata section and overwrites them with null bytes. The search is constrained to .rodata to avoid corrupting other sections (e.g. .gopclntab, .text) that could coincidentally contain the same byte pattern.
Linker-generated sections: the NDK linker produces subtly different .relro_padding depending on the host environment. This section resides inside a LOAD segment, so llvm-objcopy --remove-section cannot safely remove it (doing so re-lays out the LOAD segment and corrupts Go's .gopclntab PC tables). This tool zeros its content in-place, preserving the binary layout.
ELF entry point: shared libraries have a non-deterministic e_entry value that differs between environments. Since the dynamic linker uses DT_INIT/DT_INIT_ARRAY (not e_entry) for shared libraries, zeroing it is safe.
Usage: go run ./cmd/normalize-elf <path-to-libgojni.so>