kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit cb8e08d7d89c0ce544883b60d2d04a5c883df51e
parent 8b8960344ffcc9a12161a218fece7e8bf2beaf8b
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sat,  6 Jun 2026 04:41:35 -0700

Fix -no-pie overriding explicit PIE

Diffstat:
Mdoc/plan/TODO.md | 11-----------
Mdriver/cmd/build.c | 1+
Mdriver/cmd/cc.c | 1+
Mdriver/cmd/ld.c | 1+
Mtest/buildcmds/run.sh | 11+++++++++++
Mtest/driver/run.sh | 35+++++++++++++++++++++++++++++++++++
6 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/doc/plan/TODO.md b/doc/plan/TODO.md @@ -5,17 +5,6 @@ fixed, remove it instead of checking it off or keeping a closed entry. Add new deferred fixes below as they are discovered. -## `-no-pie` does not produce a non-PIE (ET_EXEC) executable - -`-no-pie` sets `o->target.pic = KIT_PIC_NONE` (`driver/cmd/cc.c:1185`) but does -not clear `o->pie`, which is what feeds the linker's e_type decision -(`driver/cmd/cc.c:2494`). So `kit cc -no-pie -static foo.c -o exe` still emits an -ET_DYN (static-PIE) image — `readelf`/`file` report "shared object", and the -program loads at an ASLR base, so captured code addresses don't match link-time -addresses without computing the load slide. `-no-pie` should clear `o->pie` (and -ideally `-static` without `-pie` should default to non-PIE). Found while making a -backtrace demo's addresses line up with `kit addr2line`. - ## ASan host build: some fatal diagnostics SEGV during `compiler_panic` recovery While reproducing the former x64 inline-asm fatal on the ASan host build, the diff --git a/driver/cmd/build.c b/driver/cmd/build.c @@ -798,6 +798,7 @@ static int build_parse(int argc, char** argv, BuildOptions* o) { } if (driver_streq(a, "-no-pie")) { o->target.pic = KIT_PIC_NONE; + o->pie = 0; continue; } diff --git a/driver/cmd/cc.c b/driver/cmd/cc.c @@ -1184,6 +1184,7 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { } if (driver_streq(a, "-no-pie")) { o->target.pic = KIT_PIC_NONE; + o->pie = 0; continue; } if (driver_streq(a, "-Bstatic")) { diff --git a/driver/cmd/ld.c b/driver/cmd/ld.c @@ -1018,6 +1018,7 @@ static int ld_parse(int argc, char** argv, LdOptions* o) { } if (driver_streq(a, "-no-pie")) { o->target.pic = KIT_PIC_NONE; + o->pie = 0; o->pic_explicit = 1; continue; } diff --git a/test/buildcmds/run.sh b/test/buildcmds/run.sh @@ -169,6 +169,17 @@ contains be-neg-shared-diag "$work/be-neg-shared.err" "shared" run_ok be-default-name "$KIT" build-exe -lc -Iinc hello.c helper.c assert_file_exists be-default-name-file a.out +# -no-pie must cancel an earlier -pie for build-exe's link state. +printf 'void _start(void) { for (;;) {} }\n' > no_pie_start.c +run_ok be-no-pie "$KIT" build-exe -target x86_64-linux -nostdlib \ + -pie -no-pie no_pie_start.c -o no-pie-exe +e_type=$(od -An -tx1 -j 16 -N 2 no-pie-exe | tr -d ' \n') +if [ "$e_type" = "0200" ]; then ok be-no-pie-et-exec; else + printf 'e_type bytes=%s want=0200\n' "$e_type" \ + > "$work/be-no-pie-et-exec.diag" + not_ok be-no-pie-et-exec "$work/be-no-pie-et-exec.diag" +fi + # --group scoping is observable through the program's exit code: the bare TU # sees -DRET=0 (global), the grouped TU overrides it to a non-zero value. printf '#ifndef RET\n#define RET 7\n#endif\nint ret_val(void){return RET;}\n' > rv.c diff --git a/test/driver/run.sh b/test/driver/run.sh @@ -465,6 +465,41 @@ else "$work/ld-static-pie-setup.diag" fi +# ---- ld -no-pie cancels an earlier -pie and emits ET_EXEC ---- +if "$KIT" ld -pie -no-pie -nostdlib "$work/ld-static-pie.o" \ + -o "$work/ld-no-pie" > "$work/ld-no-pie.out" \ + 2> "$work/ld-no-pie.err"; then + e_type=$(od -An -tx1 -j 16 -N 2 "$work/ld-no-pie" | tr -d ' \n') + if [ "$e_type" = "0200" ]; then + ok "ld-no-pie-cancels-pie" + else + printf 'e_type bytes=%s want=0200\n' "$e_type" \ + > "$work/ld-no-pie.diag" + not_ok "ld-no-pie-cancels-pie" "$work/ld-no-pie.diag" + fi +else + not_ok "ld-no-pie-cancels-pie" "$work/ld-no-pie.err" +fi + +# ---- -no-pie cancels an earlier -pie and emits ET_EXEC ---- +cat > "$work/cc-no-pie.c" <<'SRC' +void _start(void) { for (;;) {} } +SRC +if "$KIT" cc -target x86_64-linux -nostdlib -pie -no-pie \ + "$work/cc-no-pie.c" -o "$work/cc-no-pie" \ + > "$work/cc-no-pie.out" 2> "$work/cc-no-pie.err"; then + e_type=$(od -An -tx1 -j 16 -N 2 "$work/cc-no-pie" | tr -d ' \n') + if [ "$e_type" = "0200" ]; then + ok "cc-no-pie-cancels-pie" + else + printf 'e_type bytes=%s want=0200\n' "$e_type" \ + > "$work/cc-no-pie.diag" + not_ok "cc-no-pie-cancels-pie" "$work/cc-no-pie.diag" + fi +else + not_ok "cc-no-pie-cancels-pie" "$work/cc-no-pie.err" +fi + # ---- objdump -x aggregate (sections + symbol table) ---- if "$KIT" objdump -x "$work/main.o" \ > "$work/objdump-x.out" 2> "$work/objdump-x.err" &&