Commit 0769afbb0f

Jakub Konka <kubkon@jakubkonka.com>
2024-10-16 13:20:19
macho: refactors errors from parsing DWARF
Currently we don't report any errors to the user due to a bug in self-hosted x86_64-macos backend.
1 parent c824b35
Changed files (2)
src
src/link/MachO/Dwarf.zig
@@ -29,8 +29,7 @@ pub const InfoReader = struct {
         return p.ctx.debug_info;
     }
 
-    pub fn readCompileUnitHeader(p: *InfoReader, macho_file: *MachO) !CompileUnitHeader {
-        _ = macho_file;
+    pub fn readCompileUnitHeader(p: *InfoReader) !CompileUnitHeader {
         var length: u64 = try p.readInt(u32);
         const is_64bit = length == 0xffffffff;
         if (is_64bit) {
@@ -67,7 +66,7 @@ pub const InfoReader = struct {
         };
     }
 
-    pub fn seekToDie(p: *InfoReader, code: Code, cuh: CompileUnitHeader, abbrev_reader: *AbbrevReader, macho_file: *MachO) !void {
+    pub fn seekToDie(p: *InfoReader, code: Code, cuh: CompileUnitHeader, abbrev_reader: *AbbrevReader) !void {
         const cuh_length = math.cast(usize, cuh.length) orelse return error.Overflow;
         const end_pos = p.pos + switch (cuh.format) {
             .dwarf32 => @as(usize, 4),
@@ -79,7 +78,7 @@ pub const InfoReader = struct {
             if (di_code == code) return;
 
             while (try abbrev_reader.readAttr()) |attr| {
-                try p.skip(attr.form, cuh, macho_file);
+                try p.skip(attr.form, cuh);
             }
         }
         return error.UnexpectedEndOfFile;
@@ -87,8 +86,7 @@ pub const InfoReader = struct {
 
     /// When skipping attributes, we don't really need to be able to handle them all
     /// since we only ever care about the DW_TAG_compile_unit.
-    pub fn skip(p: *InfoReader, form: Form, cuh: CompileUnitHeader, macho_file: *MachO) !void {
-        _ = macho_file;
+    pub fn skip(p: *InfoReader, form: Form, cuh: CompileUnitHeader) !void {
         switch (form) {
             dw.FORM.sec_offset,
             dw.FORM.ref_addr,
@@ -158,8 +156,8 @@ pub const InfoReader = struct {
                     _ = try p.readIndex(form);
                 },
 
-                else => return error.UnknownForm,
-            } else return error.UnknownForm,
+                else => return error.UnhandledForm,
+            } else return error.UnhandledForm,
         }
     }
 
@@ -195,7 +193,7 @@ pub const InfoReader = struct {
         return switch (form) {
             dw.FORM.strx1, dw.FORM.addrx1 => try p.readByte(),
             dw.FORM.strx2, dw.FORM.addrx2 => try p.readInt(u16),
-            dw.FORM.strx3, dw.FORM.addrx3 => error.UnhandledDwForm,
+            dw.FORM.strx3, dw.FORM.addrx3 => error.UnhandledForm,
             dw.FORM.strx4, dw.FORM.addrx4 => try p.readInt(u32),
             dw.FORM.strx, dw.FORM.addrx => try p.readUleb128(u64),
             else => return error.UnhandledIndexForm,
src/link/MachO/Object.zig
@@ -1362,6 +1362,8 @@ fn parseDebugInfo(self: *Object, macho_file: *MachO) !void {
         if (mem.eql(u8, sect.sectName(), "__debug_str")) {
             dwarf.debug_str = try self.readSectionData(gpa, file, n_sect);
         }
+        // __debug_str_offs[ets] section is a new addition in DWARFv5 and is generally
+        // required in order to correctly parse strings.
         if (mem.eql(u8, sect.sectName(), "__debug_str_offs")) {
             dwarf.debug_str_offsets = try self.readSectionData(gpa, file, n_sect);
         }
@@ -1369,20 +1371,22 @@ fn parseDebugInfo(self: *Object, macho_file: *MachO) !void {
 
     if (dwarf.debug_info.len == 0) return;
 
-    self.compile_unit = try self.findCompileUnit(gpa, dwarf, macho_file);
+    // TODO return error once we fix emitting DWARF in self-hosted backend.
+    // https://github.com/ziglang/zig/issues/21719
+    self.compile_unit = self.findCompileUnit(gpa, dwarf) catch null;
 }
 
-fn findCompileUnit(self: *Object, gpa: Allocator, ctx: Dwarf, macho_file: *MachO) !CompileUnit {
+fn findCompileUnit(self: *Object, gpa: Allocator, ctx: Dwarf) !CompileUnit {
     var info_reader = Dwarf.InfoReader{ .ctx = ctx };
     var abbrev_reader = Dwarf.AbbrevReader{ .ctx = ctx };
 
-    const cuh = try info_reader.readCompileUnitHeader(macho_file);
+    const cuh = try info_reader.readCompileUnitHeader();
     try abbrev_reader.seekTo(cuh.debug_abbrev_offset);
 
     const cu_decl = (try abbrev_reader.readDecl()) orelse return error.UnexpectedEndOfFile;
     if (cu_decl.tag != Dwarf.TAG.compile_unit) return error.UnexpectedTag;
 
-    try info_reader.seekToDie(cu_decl.code, cuh, &abbrev_reader, macho_file);
+    try info_reader.seekToDie(cu_decl.code, cuh, &abbrev_reader);
 
     const Pos = struct {
         pos: usize,
@@ -1405,10 +1409,10 @@ fn findCompileUnit(self: *Object, gpa: Allocator, ctx: Dwarf, macho_file: *MachO
             Dwarf.AT.str_offsets_base => saved.str_offsets_base = pos,
             else => {},
         }
-        try info_reader.skip(attr.form, cuh, macho_file);
+        try info_reader.skip(attr.form, cuh);
     }
 
-    if (saved.comp_dir == null) return error.MissingCompDir;
+    if (saved.comp_dir == null) return error.MissingCompileDir;
     if (saved.tu_name == null) return error.MissingTuName;
 
     const str_offsets_base: ?u64 = if (saved.str_offsets_base) |str_offsets_base| str_offsets_base: {
@@ -1433,7 +1437,7 @@ fn findCompileUnit(self: *Object, gpa: Allocator, ctx: Dwarf, macho_file: *MachO
             Dwarf.FORM.strx3,
             Dwarf.FORM.strx4,
             => blk: {
-                const base = str_offsets_base orelse return error.MalformedDwarf;
+                const base = str_offsets_base orelse return error.MissingStrOffsetsBase;
                 break :blk try self.addString(gpa, try info_reader.readStringIndexed(pos.form, cuh, base));
             },
             else => return error.InvalidForm,