| ... | @@ -1213,7 +1213,6 @@ const CompileUnit = struct { | ... | @@ -1213,7 +1213,6 @@ const CompileUnit = struct { |
| 1213 | version: u16, | 1213 | version: u16, |
| 1214 | is_64: bool, | 1214 | is_64: bool, |
| 1215 | die: *Die, | 1215 | die: *Die, |
| 1216 | index: usize, | | |
| 1217 | pc_range: ?PcRange, | 1216 | pc_range: ?PcRange, |
| 1218 | }; | 1217 | }; |
| 1219 | | 1218 | |
| ... | @@ -1787,173 +1786,165 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u | ... | @@ -1787,173 +1786,165 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1787 | | 1786 | |
| 1788 | fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo { | 1787 | fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo { |
| 1789 | const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir); | 1788 | const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir); |
| | 1789 | const line_info_offset = try compile_unit.die.getAttrSecOffset(DW.AT_stmt_list); |
| 1790 | | 1790 | |
| 1791 | const debug_line_end = di.debug_line.offset + di.debug_line.size; | 1791 | assert(line_info_offset < di.debug_line.size); |
| 1792 | var this_offset = di.debug_line.offset; | | |
| 1793 | var this_index: usize = 0; | | |
| 1794 | | 1792 | |
| 1795 | while (this_offset < debug_line_end) : (this_index += 1) { | 1793 | try di.dwarf_seekable_stream.seekTo(di.debug_line.offset + line_info_offset); |
| 1796 | try di.dwarf_seekable_stream.seekTo(this_offset); | | |
| 1797 | | 1794 | |
| 1798 | var is_64: bool = undefined; | 1795 | var is_64: bool = undefined; |
| 1799 | const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); | 1796 | const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); |
| 1800 | if (unit_length == 0) return error.MissingDebugInfo; | 1797 | if (unit_length == 0) { |
| 1801 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | 1798 | return error.MissingDebugInfo; |
| 1802 | | 1799 | } |
| 1803 | if (compile_unit.index != this_index) { | 1800 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); |
| 1804 | this_offset += next_offset; | | |
| 1805 | continue; | | |
| 1806 | } | | |
| 1807 | | 1801 | |
| 1808 | const version = try di.dwarf_in_stream.readInt(u16, di.endian); | 1802 | const version = try di.dwarf_in_stream.readInt(u16, di.endian); |
| 1809 | // TODO support 3 and 5 | 1803 | // TODO support 3 and 5 |
| 1810 | if (version != 2 and version != 4) return error.InvalidDebugInfo; | 1804 | if (version != 2 and version != 4) return error.InvalidDebugInfo; |
| 1811 | | 1805 | |
| 1812 | const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); | 1806 | const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); |
| 1813 | const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; | 1807 | const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; |
| 1814 | | 1808 | |
| 1815 | const minimum_instruction_length = try di.dwarf_in_stream.readByte(); | 1809 | const minimum_instruction_length = try di.dwarf_in_stream.readByte(); |
| 1816 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; | 1810 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; |
| 1817 | | 1811 | |
| 1818 | if (version >= 4) { | 1812 | if (version >= 4) { |
| 1819 | // maximum_operations_per_instruction | 1813 | // maximum_operations_per_instruction |
| 1820 | _ = try di.dwarf_in_stream.readByte(); | 1814 | _ = try di.dwarf_in_stream.readByte(); |
| 1821 | } | 1815 | } |
| 1822 | | 1816 | |
| 1823 | const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; | 1817 | const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; |
| 1824 | const line_base = try di.dwarf_in_stream.readByteSigned(); | 1818 | const line_base = try di.dwarf_in_stream.readByteSigned(); |
| 1825 | | 1819 | |
| 1826 | const line_range = try di.dwarf_in_stream.readByte(); | 1820 | const line_range = try di.dwarf_in_stream.readByte(); |
| 1827 | if (line_range == 0) return error.InvalidDebugInfo; | 1821 | if (line_range == 0) return error.InvalidDebugInfo; |
| 1828 | | 1822 | |
| 1829 | const opcode_base = try di.dwarf_in_stream.readByte(); | 1823 | const opcode_base = try di.dwarf_in_stream.readByte(); |
| 1830 | | 1824 | |
| 1831 | const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); | 1825 | const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); |
| 1832 | | 1826 | |
| 1833 | { | 1827 | { |
| 1834 | var i: usize = 0; | 1828 | var i: usize = 0; |
| 1835 | while (i < opcode_base - 1) : (i += 1) { | 1829 | while (i < opcode_base - 1) : (i += 1) { |
| 1836 | standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte(); | 1830 | standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte(); |
| 1837 | } | | |
| 1838 | } | 1831 | } |
| | 1832 | } |
| 1839 | | 1833 | |
| 1840 | var include_directories = ArrayList([]u8).init(di.allocator()); | 1834 | var include_directories = ArrayList([]u8).init(di.allocator()); |
| 1841 | try include_directories.append(compile_unit_cwd); | 1835 | try include_directories.append(compile_unit_cwd); |
| 1842 | while (true) { | 1836 | while (true) { |
| 1843 | const dir = try di.readString(); | 1837 | const dir = try di.readString(); |
| 1844 | if (dir.len == 0) break; | 1838 | if (dir.len == 0) break; |
| 1845 | try include_directories.append(dir); | 1839 | try include_directories.append(dir); |
| 1846 | } | 1840 | } |
| 1847 | | 1841 | |
| 1848 | var file_entries = ArrayList(FileEntry).init(di.allocator()); | 1842 | var file_entries = ArrayList(FileEntry).init(di.allocator()); |
| 1849 | var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address); | 1843 | var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address); |
| 1850 | | 1844 | |
| 1851 | while (true) { | 1845 | while (true) { |
| 1852 | const file_name = try di.readString(); | 1846 | const file_name = try di.readString(); |
| 1853 | if (file_name.len == 0) break; | 1847 | if (file_name.len == 0) break; |
| 1854 | const dir_index = try readULeb128(di.dwarf_in_stream); | 1848 | const dir_index = try readULeb128(di.dwarf_in_stream); |
| 1855 | const mtime = try readULeb128(di.dwarf_in_stream); | 1849 | const mtime = try readULeb128(di.dwarf_in_stream); |
| 1856 | const len_bytes = try readULeb128(di.dwarf_in_stream); | 1850 | const len_bytes = try readULeb128(di.dwarf_in_stream); |
| 1857 | try file_entries.append(FileEntry{ | 1851 | try file_entries.append(FileEntry{ |
| 1858 | .file_name = file_name, | 1852 | .file_name = file_name, |
| 1859 | .dir_index = dir_index, | 1853 | .dir_index = dir_index, |
| 1860 | .mtime = mtime, | 1854 | .mtime = mtime, |
| 1861 | .len_bytes = len_bytes, | 1855 | .len_bytes = len_bytes, |
| 1862 | }); | 1856 | }); |
| 1863 | } | 1857 | } |
| 1864 | | 1858 | |
| 1865 | try di.dwarf_seekable_stream.seekTo(prog_start_offset); | 1859 | try di.dwarf_seekable_stream.seekTo(prog_start_offset); |
| 1866 | | 1860 | |
| 1867 | while (true) { | 1861 | while (true) { |
| 1868 | const opcode = try di.dwarf_in_stream.readByte(); | 1862 | const opcode = try di.dwarf_in_stream.readByte(); |
| 1869 | | 1863 | |
| 1870 | if (opcode == DW.LNS_extended_op) { | 1864 | if (opcode == DW.LNS_extended_op) { |
| 1871 | const op_size = try readULeb128(di.dwarf_in_stream); | 1865 | const op_size = try readULeb128(di.dwarf_in_stream); |
| 1872 | if (op_size < 1) return error.InvalidDebugInfo; | 1866 | if (op_size < 1) return error.InvalidDebugInfo; |
| 1873 | var sub_op = try di.dwarf_in_stream.readByte(); | 1867 | var sub_op = try di.dwarf_in_stream.readByte(); |
| 1874 | switch (sub_op) { | 1868 | switch (sub_op) { |
| 1875 | DW.LNE_end_sequence => { | 1869 | DW.LNE_end_sequence => { |
| 1876 | prog.end_sequence = true; | 1870 | prog.end_sequence = true; |
| 1877 | if (try prog.checkLineMatch()) |info| return info; | 1871 | if (try prog.checkLineMatch()) |info| return info; |
| 1878 | return error.MissingDebugInfo; | 1872 | return error.MissingDebugInfo; |
| 1879 | }, | 1873 | }, |
| 1880 | DW.LNE_set_address => { | 1874 | DW.LNE_set_address => { |
| 1881 | const addr = try di.dwarf_in_stream.readInt(usize, di.endian); | 1875 | const addr = try di.dwarf_in_stream.readInt(usize, di.endian); |
| 1882 | prog.address = addr; | 1876 | prog.address = addr; |
| 1883 | }, | 1877 | }, |
| 1884 | DW.LNE_define_file => { | 1878 | DW.LNE_define_file => { |
| 1885 | const file_name = try di.readString(); | 1879 | const file_name = try di.readString(); |
| 1886 | const dir_index = try readULeb128(di.dwarf_in_stream); | 1880 | const dir_index = try readULeb128(di.dwarf_in_stream); |
| 1887 | const mtime = try readULeb128(di.dwarf_in_stream); | 1881 | const mtime = try readULeb128(di.dwarf_in_stream); |
| 1888 | const len_bytes = try readULeb128(di.dwarf_in_stream); | 1882 | const len_bytes = try readULeb128(di.dwarf_in_stream); |
| 1889 | try file_entries.append(FileEntry{ | 1883 | try file_entries.append(FileEntry{ |
| 1890 | .file_name = file_name, | 1884 | .file_name = file_name, |
| 1891 | .dir_index = dir_index, | 1885 | .dir_index = dir_index, |
| 1892 | .mtime = mtime, | 1886 | .mtime = mtime, |
| 1893 | .len_bytes = len_bytes, | 1887 | .len_bytes = len_bytes, |
| 1894 | }); | 1888 | }); |
| 1895 | }, | 1889 | }, |
| 1896 | else => { | 1890 | else => { |
| 1897 | const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; | 1891 | const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; |
| 1898 | try di.dwarf_seekable_stream.seekForward(fwd_amt); | 1892 | try di.dwarf_seekable_stream.seekForward(fwd_amt); |
| 1899 | }, | 1893 | }, |
| 1900 | } | 1894 | } |
| 1901 | } else if (opcode >= opcode_base) { | 1895 | } else if (opcode >= opcode_base) { |
| 1902 | // special opcodes | 1896 | // special opcodes |
| 1903 | const adjusted_opcode = opcode - opcode_base; | 1897 | const adjusted_opcode = opcode - opcode_base; |
| 1904 | const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range); | 1898 | const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range); |
| 1905 | const inc_line = i32(line_base) + i32(adjusted_opcode % line_range); | 1899 | const inc_line = i32(line_base) + i32(adjusted_opcode % line_range); |
| 1906 | prog.line += inc_line; | 1900 | prog.line += inc_line; |
| 1907 | prog.address += inc_addr; | 1901 | prog.address += inc_addr; |
| 1908 | if (try prog.checkLineMatch()) |info| return info; | 1902 | if (try prog.checkLineMatch()) |info| return info; |
| 1909 | prog.basic_block = false; | 1903 | prog.basic_block = false; |
| 1910 | } else { | 1904 | } else { |
| 1911 | switch (opcode) { | 1905 | switch (opcode) { |
| 1912 | DW.LNS_copy => { | 1906 | DW.LNS_copy => { |
| 1913 | if (try prog.checkLineMatch()) |info| return info; | 1907 | if (try prog.checkLineMatch()) |info| return info; |
| 1914 | prog.basic_block = false; | 1908 | prog.basic_block = false; |
| 1915 | }, | 1909 | }, |
| 1916 | DW.LNS_advance_pc => { | 1910 | DW.LNS_advance_pc => { |
| 1917 | const arg = try readULeb128(di.dwarf_in_stream); | 1911 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1918 | prog.address += arg * minimum_instruction_length; | 1912 | prog.address += arg * minimum_instruction_length; |
| 1919 | }, | 1913 | }, |
| 1920 | DW.LNS_advance_line => { | 1914 | DW.LNS_advance_line => { |
| 1921 | const arg = try readILeb128(di.dwarf_in_stream); | 1915 | const arg = try readILeb128(di.dwarf_in_stream); |
| 1922 | prog.line += arg; | 1916 | prog.line += arg; |
| 1923 | }, | 1917 | }, |
| 1924 | DW.LNS_set_file => { | 1918 | DW.LNS_set_file => { |
| 1925 | const arg = try readULeb128(di.dwarf_in_stream); | 1919 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1926 | prog.file = arg; | 1920 | prog.file = arg; |
| 1927 | }, | 1921 | }, |
| 1928 | DW.LNS_set_column => { | 1922 | DW.LNS_set_column => { |
| 1929 | const arg = try readULeb128(di.dwarf_in_stream); | 1923 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1930 | prog.column = arg; | 1924 | prog.column = arg; |
| 1931 | }, | 1925 | }, |
| 1932 | DW.LNS_negate_stmt => { | 1926 | DW.LNS_negate_stmt => { |
| 1933 | prog.is_stmt = !prog.is_stmt; | 1927 | prog.is_stmt = !prog.is_stmt; |
| 1934 | }, | 1928 | }, |
| 1935 | DW.LNS_set_basic_block => { | 1929 | DW.LNS_set_basic_block => { |
| 1936 | prog.basic_block = true; | 1930 | prog.basic_block = true; |
| 1937 | }, | 1931 | }, |
| 1938 | DW.LNS_const_add_pc => { | 1932 | DW.LNS_const_add_pc => { |
| 1939 | const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range); | 1933 | const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range); |
| 1940 | prog.address += inc_addr; | 1934 | prog.address += inc_addr; |
| 1941 | }, | 1935 | }, |
| 1942 | DW.LNS_fixed_advance_pc => { | 1936 | DW.LNS_fixed_advance_pc => { |
| 1943 | const arg = try di.dwarf_in_stream.readInt(u16, di.endian); | 1937 | const arg = try di.dwarf_in_stream.readInt(u16, di.endian); |
| 1944 | prog.address += arg; | 1938 | prog.address += arg; |
| 1945 | }, | 1939 | }, |
| 1946 | DW.LNS_set_prologue_end => {}, | 1940 | DW.LNS_set_prologue_end => {}, |
| 1947 | else => { | 1941 | else => { |
| 1948 | if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; | 1942 | if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; |
| 1949 | const len_bytes = standard_opcode_lengths[opcode - 1]; | 1943 | const len_bytes = standard_opcode_lengths[opcode - 1]; |
| 1950 | try di.dwarf_seekable_stream.seekForward(len_bytes); | 1944 | try di.dwarf_seekable_stream.seekForward(len_bytes); |
| 1951 | }, | 1945 | }, |
| 1952 | } | | |
| 1953 | } | 1946 | } |
| 1954 | } | 1947 | } |
| 1955 | | | |
| 1956 | this_offset += next_offset; | | |
| 1957 | } | 1948 | } |
| 1958 | | 1949 | |
| 1959 | return error.MissingDebugInfo; | 1950 | return error.MissingDebugInfo; |
| ... | @@ -1962,7 +1953,6 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr | ... | @@ -1962,7 +1953,6 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr |
| 1962 | fn scanAllCompileUnits(di: *DwarfInfo) !void { | 1953 | fn scanAllCompileUnits(di: *DwarfInfo) !void { |
| 1963 | const debug_info_end = di.debug_info.offset + di.debug_info.size; | 1954 | const debug_info_end = di.debug_info.offset + di.debug_info.size; |
| 1964 | var this_unit_offset = di.debug_info.offset; | 1955 | var this_unit_offset = di.debug_info.offset; |
| 1965 | var cu_index: usize = 0; | | |
| 1966 | | 1956 | |
| 1967 | while (this_unit_offset < debug_info_end) { | 1957 | while (this_unit_offset < debug_info_end) { |
| 1968 | try di.dwarf_seekable_stream.seekTo(this_unit_offset); | 1958 | try di.dwarf_seekable_stream.seekTo(this_unit_offset); |
| ... | @@ -2019,11 +2009,9 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void { | ... | @@ -2019,11 +2009,9 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void { |
| 2019 | .is_64 = is_64, | 2009 | .is_64 = is_64, |
| 2020 | .pc_range = pc_range, | 2010 | .pc_range = pc_range, |
| 2021 | .die = compile_unit_die, | 2011 | .die = compile_unit_die, |
| 2022 | .index = cu_index, | | |
| 2023 | }); | 2012 | }); |
| 2024 | | 2013 | |
| 2025 | this_unit_offset += next_offset; | 2014 | this_unit_offset += next_offset; |
| 2026 | cu_index += 1; | | |
| 2027 | } | 2015 | } |
| 2028 | } | 2016 | } |
| 2029 | | 2017 | |