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