diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-04-24 13:03:32 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-04-24 13:03:32 -0400 |
| commit | 6cd725c24b5744d67c36ccb3be9ef9e2fd69c74d (patch) | |
| tree | 15111a04e69ded0905d50ec92d1dee59a7edf6ed /std/debug.zig | |
| parent | 245eed8afee899cb0d0a2dac60c8a1edc6be654d (diff) | |
| download | zig-6cd725c24b5744d67c36ccb3be9ef9e2fd69c74d.tar.gz zig-6cd725c24b5744d67c36ccb3be9ef9e2fd69c74d.zip | |
stack traces support compile units with no pc range
Diffstat (limited to 'std/debug.zig')
| -rw-r--r-- | std/debug.zig | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/std/debug.zig b/std/debug.zig index 0d00931525..764cdc176d 100644 --- a/std/debug.zig +++ b/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; } |
