| ... | ... | @@ -26,7 +26,6 @@ const cast = std.math.cast; |
| 26 | 26 | const maxInt = std.math.maxInt; |
| 27 | 27 | const MemoryAccessor = std.debug.MemoryAccessor; |
| 28 | 28 | const Path = std.Build.Cache.Path; |
| 29 | | |
| 30 | 29 | const FixedBufferReader = std.debug.FixedBufferReader; |
| 31 | 30 | |
| 32 | 31 | const Dwarf = @This(); |
| ... | ... | @@ -35,6 +34,9 @@ pub const expression = @import("Dwarf/expression.zig"); |
| 35 | 34 | pub const abi = @import("Dwarf/abi.zig"); |
| 36 | 35 | pub const call_frame = @import("Dwarf/call_frame.zig"); |
| 37 | 36 | |
| 37 | /// Useful to temporarily enable while working on this file. |
| 38 | const debug_debug_mode = false; |
| 39 | |
| 38 | 40 | endian: std.builtin.Endian, |
| 39 | 41 | sections: SectionArray = null_section_array, |
| 40 | 42 | is_macho: bool, |
| ... | ... | @@ -165,6 +167,16 @@ pub const CompileUnit = struct { |
| 165 | 167 | column: u32, |
| 166 | 168 | /// Offset by 1 depending on whether Dwarf version is >= 5. |
| 167 | 169 | file: u32, |
| 170 | |
| 171 | pub const invalid: LineEntry = .{ |
| 172 | .line = undefined, |
| 173 | .column = undefined, |
| 174 | .file = std.math.maxInt(u32), |
| 175 | }; |
| 176 | |
| 177 | pub fn isInvalid(le: LineEntry) bool { |
| 178 | return le.file == invalid.file; |
| 179 | } |
| 168 | 180 | }; |
| 169 | 181 | |
| 170 | 182 | pub fn findSource(slc: *const SrcLocCache, address: u64) !LineEntry { |
| ... | ... | @@ -1400,6 +1412,7 @@ fn parseDie( |
| 1400 | 1412 | }; |
| 1401 | 1413 | } |
| 1402 | 1414 | |
| 1415 | /// Ensures that addresses in the returned LineTable are monotonically increasing. |
| 1403 | 1416 | fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !CompileUnit.SrcLocCache { |
| 1404 | 1417 | const compile_unit_cwd = try compile_unit.die.getAttrString(d, AT.comp_dir, d.section(.debug_line_str), compile_unit.*); |
| 1405 | 1418 | const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list); |
| ... | ... | @@ -1575,8 +1588,19 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) ! |
| 1575 | 1588 | const sub_op = try fbr.readByte(); |
| 1576 | 1589 | switch (sub_op) { |
| 1577 | 1590 | DW.LNE.end_sequence => { |
| 1578 | | prog.end_sequence = true; |
| 1579 | | try prog.addRow(gpa, &line_table); |
| 1591 | // The row being added here is an "end" address, meaning |
| 1592 | // that it does not map to the source location here - |
| 1593 | // rather it marks the previous address as the last address |
| 1594 | // that maps to this source location. |
| 1595 | |
| 1596 | // In this implementation we don't mark end of addresses. |
| 1597 | // This is a performance optimization based on the fact |
| 1598 | // that we don't need to know if an address is missing |
| 1599 | // source location info; we are only interested in being |
| 1600 | // able to look up source location info for addresses that |
| 1601 | // are known to have debug info. |
| 1602 | //if (debug_debug_mode) assert(!line_table.contains(prog.address)); |
| 1603 | //try line_table.put(gpa, prog.address, CompileUnit.SrcLocCache.LineEntry.invalid); |
| 1580 | 1604 | prog.reset(); |
| 1581 | 1605 | }, |
| 1582 | 1606 | DW.LNE.set_address => { |
| ... | ... | @@ -1651,6 +1675,17 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) ! |
| 1651 | 1675 | } |
| 1652 | 1676 | } |
| 1653 | 1677 | |
| 1678 | // Dwarf standard v5, 6.2.5 says |
| 1679 | // > Within a sequence, addresses and operation pointers may only increase. |
| 1680 | // However, this is empirically not the case in reality, so we sort here. |
| 1681 | line_table.sortUnstable(struct { |
| 1682 | keys: []const u64, |
| 1683 | |
| 1684 | pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool { |
| 1685 | return ctx.keys[a_index] < ctx.keys[b_index]; |
| 1686 | } |
| 1687 | }{ .keys = line_table.keys() }); |
| 1688 | |
| 1654 | 1689 | return .{ |
| 1655 | 1690 | .line_table = line_table, |
| 1656 | 1691 | .directories = try directories.toOwnedSlice(gpa), |
| ... | ... | @@ -1895,7 +1930,6 @@ const LineNumberProgram = struct { |
| 1895 | 1930 | version: u16, |
| 1896 | 1931 | is_stmt: bool, |
| 1897 | 1932 | basic_block: bool, |
| 1898 | | end_sequence: bool, |
| 1899 | 1933 | |
| 1900 | 1934 | default_is_stmt: bool, |
| 1901 | 1935 | |
| ... | ... | @@ -1907,7 +1941,6 @@ const LineNumberProgram = struct { |
| 1907 | 1941 | self.column = 0; |
| 1908 | 1942 | self.is_stmt = self.default_is_stmt; |
| 1909 | 1943 | self.basic_block = false; |
| 1910 | | self.end_sequence = false; |
| 1911 | 1944 | } |
| 1912 | 1945 | |
| 1913 | 1946 | pub fn init(is_stmt: bool, version: u16) LineNumberProgram { |
| ... | ... | @@ -1919,13 +1952,16 @@ const LineNumberProgram = struct { |
| 1919 | 1952 | .version = version, |
| 1920 | 1953 | .is_stmt = is_stmt, |
| 1921 | 1954 | .basic_block = false, |
| 1922 | | .end_sequence = false, |
| 1923 | 1955 | .default_is_stmt = is_stmt, |
| 1924 | 1956 | }; |
| 1925 | 1957 | } |
| 1926 | 1958 | |
| 1927 | 1959 | pub fn addRow(prog: *LineNumberProgram, gpa: Allocator, table: *CompileUnit.SrcLocCache.LineTable) !void { |
| 1928 | | if (prog.line == 0) return; // garbage data |
| 1960 | if (prog.line == 0) { |
| 1961 | //if (debug_debug_mode) @panic("garbage line data"); |
| 1962 | return; |
| 1963 | } |
| 1964 | if (debug_debug_mode) assert(!table.contains(prog.address)); |
| 1929 | 1965 | try table.put(gpa, prog.address, .{ |
| 1930 | 1966 | .line = cast(u32, prog.line) orelse maxInt(u32), |
| 1931 | 1967 | .column = cast(u32, prog.column) orelse maxInt(u32), |
| ... | ... | @@ -1972,12 +2008,12 @@ pub fn compactUnwindToDwarfRegNumber(unwind_reg_number: u3) !u8 { |
| 1972 | 2008 | /// This function is to make it handy to comment out the return and make it |
| 1973 | 2009 | /// into a crash when working on this file. |
| 1974 | 2010 | pub fn bad() error{InvalidDebugInfo} { |
| 1975 | | //if (true) @panic("bad dwarf"); // can be handy to uncomment when working on this file |
| 2011 | if (debug_debug_mode) @panic("bad dwarf"); |
| 1976 | 2012 | return error.InvalidDebugInfo; |
| 1977 | 2013 | } |
| 1978 | 2014 | |
| 1979 | 2015 | fn missing() error{MissingDebugInfo} { |
| 1980 | | //if (true) @panic("missing dwarf"); // can be handy to uncomment when working on this file |
| 2016 | if (debug_debug_mode) @panic("missing dwarf"); |
| 1981 | 2017 | return error.MissingDebugInfo; |
| 1982 | 2018 | } |
| 1983 | 2019 | |