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:
@@ -394,11 +394,15 @@ pub const LLVMEmitter = struct {
|
||||
}
|
||||
|
||||
/// The `DIFile` for `path`, created once and cached. Splits the path
|
||||
/// into basename + directory as DWARF expects.
|
||||
/// into basename + directory as DWARF expects. The directory MUST be
|
||||
/// non-empty: an empty `DW_AT_comp_dir` makes Apple's `ld` silently drop
|
||||
/// the whole object's debug map (no `N_OSO`), so a binary built from a
|
||||
/// bare filename (e.g. `sx build main.sx`) becomes undebuggable. Fall back
|
||||
/// to "." when the path has no directory component.
|
||||
fn diFileFor(self: *LLVMEmitter, path: []const u8) c.LLVMMetadataRef {
|
||||
if (self.di_files.get(path)) |f| return f;
|
||||
const slash = std.mem.lastIndexOfScalar(u8, path, '/');
|
||||
const dir = if (slash) |s| path[0..s] else "";
|
||||
const dir = if (slash) |s| (if (s == 0) "/" else path[0..s]) else ".";
|
||||
const base = if (slash) |s| path[s + 1 ..] else path;
|
||||
const f = c.LLVMDIBuilderCreateFile(self.di_builder, base.ptr, base.len, dir.ptr, dir.len);
|
||||
self.di_files.put(path, f) catch {};
|
||||
|
||||
Reference in New Issue
Block a user