Commit 6cd725c24b

Andrew Kelley <superjoe30@gmail.com>
2017-04-24 19:03:32
stack traces support compile units with no pc range
1 parent 245eed8
Changed files (1)
std/debug.zig
@@ -185,12 +185,17 @@ const ElfStackTrace = struct {
     }
 };
 
+const PcRange = struct {
+    start: u64,
+    end: u64,
+};
+
 const CompileUnit = struct {
+    version: u16,
     is_64: bool,
     die: &Die,
-    pc_start: u64,
-    pc_end: u64,
     index: usize,
+    pc_range: ?PcRange,
 };
 
 const AbbrevTable = List(AbbrevTableEntry);
@@ -259,7 +264,7 @@ const Die = struct {
     }
 
     fn getAttrAddr(self: &const Die, id: u64) -> %u64 {
-        const form_value = self.getAttr(id) ?? return error.InvalidDebugInfo;
+        const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
         return switch (*form_value) {
             FormValue.Address => |value| value,
             else => error.InvalidDebugInfo,
@@ -267,7 +272,7 @@ const Die = struct {
     }
 
     fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 {
-        const form_value = self.getAttr(id) ?? return error.InvalidDebugInfo;
+        const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
         return switch (*form_value) {
             FormValue.Const => |value| value.asUnsignedLe(),
             else => error.InvalidDebugInfo,
@@ -275,7 +280,7 @@ const Die = struct {
     }
 
     fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) -> %[]u8 {
-        const form_value = self.getAttr(id) ?? return error.InvalidDebugInfo;
+        const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
         return switch (*form_value) {
             FormValue.String => |value| value,
             FormValue.StrPtr => |offset| getString(st, offset),
@@ -794,7 +799,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
         const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
 
         const version = %return st.self_exe_stream.readInt(st.elf.is_big_endian, u16);
-        if (version != 4) return error.InvalidDebugInfo;
+        if (version < 2 or version > 5) return error.InvalidDebugInfo;
 
         const debug_abbrev_offset = if (is_64) {
             %return st.self_exe_stream.readInt(st.elf.is_big_endian, u64)
@@ -815,22 +820,36 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
 
         if (compile_unit_die.tag_id != DW.TAG_compile_unit)
             return error.InvalidDebugInfo;
-        const low_pc = %return compile_unit_die.getAttrAddr(DW.AT_low_pc);
 
-        const high_pc_value = compile_unit_die.getAttr(DW.AT_high_pc) ?? return error.MissingDebugInfo;
-        const pc_end = switch (*high_pc_value) {
-            FormValue.Address => |value| value,
-            FormValue.Const => |value| {
-                const offset = %return value.asUnsignedLe();
-                low_pc + offset
-            },
-            else => return error.InvalidDebugInfo,
+        const pc_range = {
+            try (compile_unit_die.getAttrAddr(DW.AT_low_pc)) |low_pc| {
+                test (compile_unit_die.getAttr(DW.AT_high_pc)) |high_pc_value| {
+                    const pc_end = switch (*high_pc_value) {
+                        FormValue.Address => |value| value,
+                        FormValue.Const => |value| {
+                            const offset = %return value.asUnsignedLe();
+                            low_pc + offset
+                        },
+                        else => return error.InvalidDebugInfo,
+                    };
+                    PcRange {
+                        .start = low_pc,
+                        .end = pc_end,
+                    }
+                } else {
+                    null
+                }
+            } else |err| {
+                if (err != error.MissingDebugInfo)
+                    return err;
+                null
+            }
         };
 
         %return st.compile_unit_list.append(CompileUnit {
+            .version = version,
             .is_64 = is_64,
-            .pc_start = low_pc,
-            .pc_end = pc_end,
+            .pc_range = pc_range,
             .die = compile_unit_die,
             .index = cu_index,
         });
@@ -842,8 +861,10 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
 
 fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> ?&const CompileUnit {
     for (st.compile_unit_list.toSlice()) |*compile_unit| {
-        if (target_address >= compile_unit.pc_start and target_address < compile_unit.pc_end)
-            return compile_unit;
+        test (compile_unit.pc_range) |range| {
+            if (target_address >= range.start and target_address < range.end)
+                return compile_unit;
+        }
     }
     return null;
 }