On ELF binaries that have no PT_NOTE program header (e.g. those built with a toolchain that doesn't pass --build-id to ld), postject currently:
- Prints
💉 Injection done! and exits 0
- Doesn't actually modify the binary (file size and content are byte-identical before/after)
- Produces a binary where
postject_find_resource() returns NULL at runtime
This makes downstream failures (SEGV in BlobDeserializer, "resource not found" errors in user code) look unrelated to postject and was the single biggest time-sink in diagnosing nodejs/unofficial-builds#200.
Reproduction
Using a musl-cross-make-built aarch64-linux-musl-gcc (or any toolchain that doesn't pass --build-id by default):
// test.c
#include <stdio.h>
#define POSTJECT_SENTINEL_FUSE "NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2"
#include "postject-api.h"
int main(void) {
size_t size; const void* p = postject_find_resource("FOO", &size, NULL);
return p == NULL ? 2 : 0;
}
gcc test.c -o test # no --build-id by default on this toolchain
readelf -lW test | grep '^[[:space:]]*NOTE' # (no output — no PT_NOTE)
ls -la test # 8848 bytes
npx postject test FOO some.txt \
--sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
# → 💉 Injection done! (exit 0)
ls -la test # 8848 bytes (unchanged!)
./test # exit 2 (find_resource returned NULL)
Same source built with -Wl,--build-id=sha1 → postject grows the binary (8848 → 67408 bytes) and ./test returns 0.
Suggested fix
In inject_into_elf (src/postject.cpp), if the parsed ELF has no PT_NOTE segment, either:
- Return
InjectResult::kError and surface a clear error from the JS wrapper (e.g. "target has no PT_NOTE program header — rebuild with -Wl,--build-id or equivalent"), or
- Have LIEF synthesize a PT_NOTE segment so the injection actually succeeds
Either is better than the current "exit 0, do nothing, produce broken downstream binary" behavior.
Context
Hit while diagnosing nodejs/unofficial-builds#200 (unofficial-builds arm64-musl tarball ships a binary with no PT_NOTE). Root-cause fix for that at nodejs/unofficial-builds#233. The silent-no-op behavior here was load-bearing in masking the actual problem during diagnosis.
On ELF binaries that have no
PT_NOTEprogram header (e.g. those built with a toolchain that doesn't pass--build-idto ld),postjectcurrently:💉 Injection done!and exits 0postject_find_resource()returns NULL at runtimeThis makes downstream failures (SEGV in
BlobDeserializer, "resource not found" errors in user code) look unrelated to postject and was the single biggest time-sink in diagnosing nodejs/unofficial-builds#200.Reproduction
Using a musl-cross-make-built
aarch64-linux-musl-gcc(or any toolchain that doesn't pass--build-idby default):Same source built with
-Wl,--build-id=sha1→ postject grows the binary (8848 → 67408 bytes) and./testreturns 0.Suggested fix
In
inject_into_elf(src/postject.cpp), if the parsed ELF has no PT_NOTE segment, either:InjectResult::kErrorand surface a clear error from the JS wrapper (e.g. "target has no PT_NOTE program header — rebuild with-Wl,--build-idor equivalent"), orEither is better than the current "exit 0, do nothing, produce broken downstream binary" behavior.
Context
Hit while diagnosing nodejs/unofficial-builds#200 (unofficial-builds arm64-musl tarball ships a binary with no PT_NOTE). Root-cause fix for that at nodejs/unofficial-builds#233. The silent-no-op behavior here was load-bearing in masking the actual problem during diagnosis.