fix(dwarf): non-empty comp_dir so ld keeps the debug map (issue 0058)

A source path with no directory component (`sx build main.sx` from the
project dir — what the chess app does) made `diFileFor` emit a `DIFile`
with an empty `directory:`, so the compile unit's `DW_AT_comp_dir` was
"". Apple's ld then silently drops the *entire* object's debug map (0
N_OSO) and the binary is undebuggable — lldb resolves no sx source.
Builds whose path had any directory (`.sx-tmp/x.sx`, `examples/x.sx`)
were unaffected, which is why small repros + the stepping smoke passed
and only the bundled chess app hit it.

Fix: diFileFor falls back to "." (and "/" for a root-level file) when
the path has no directory component, so comp_dir is never empty.

Verified: chess (`sx build --target macos --emit-obj main.sx`) now
links with OSO=1 and lldb resolves `frame at main.sx:82:8`. Regression
guard added to the DWARF unit test (asserts `DIFile(... directory: ".")`
for a bare filename). Gates: zig build, zig build test, run_examples.sh
-> 291 passed, debug-stepping smoke ok.
This commit is contained in:
agra
2026-06-01 16:47:51 +03:00
parent b2ebf774bc
commit 0d7f786db2
3 changed files with 117 additions and 3 deletions

View File

@@ -989,7 +989,10 @@ test "emit: ERR E3.0 — DWARF debug info (compile unit + subprogram + per-inst
try std.testing.expect(std.mem.indexOf(u8, ir_str, "\"Debug Info Version\"") != null);
try std.testing.expect(std.mem.indexOf(u8, ir_str, "\"Dwarf Version\"") != null);
try std.testing.expect(std.mem.indexOf(u8, ir_str, "DICompileUnit") != null);
try std.testing.expect(std.mem.indexOf(u8, ir_str, "DIFile(filename: \"probe.sx\"") != null);
// Regression (issue 0058): a bare filename (no directory component) must
// still get a NON-EMPTY `directory:` — an empty `DW_AT_comp_dir` makes ld
// silently drop the whole debug map, so the binary becomes undebuggable.
try std.testing.expect(std.mem.indexOf(u8, ir_str, "DIFile(filename: \"probe.sx\", directory: \".\")") != null);
try std.testing.expect(std.mem.indexOf(u8, ir_str, "DISubprogram(name: \"main\"") != null);
try std.testing.expect(std.mem.indexOf(u8, ir_str, "DILocation(line: 3") != null);
}