authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-04-10 23:30:41+02:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-04-10 23:30:41+02:00
log60e2a04322cb3cb49fdc2c1b28060bc261754302
tree3e767c6c7110b222b2277368c6dd0b11f60281cf
parentaff2e47821aaad5cac74ed8a3cac2e72283b594b

Correct parsing of DWARF line_info section


1 files changed, 139 insertions(+), 151 deletions(-)

std/debug.zig+139-151
...@@ -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};
12191218
...@@ -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
17871786
1788fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {1787fn 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);
17901790
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;
17941792
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);
17971794
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;
18021799 }
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 }
18071801
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 51803 // 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;
18111805
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;
18141808
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;
18171811
1818 if (version >= 4) {1812 if (version >= 4) {
1819 // maximum_operations_per_instruction1813 // maximum_operations_per_instruction
1820 _ = try di.dwarf_in_stream.readByte();1814 _ = try di.dwarf_in_stream.readByte();
1821 }1815 }
18221816
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();
18251819
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;
18281822
1829 const opcode_base = try di.dwarf_in_stream.readByte();1823 const opcode_base = try di.dwarf_in_stream.readByte();
18301824
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);
18321826
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 }
18391833
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 }
18471841
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);
18501844
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 }
18641858
1865 try di.dwarf_seekable_stream.seekTo(prog_start_offset);1859 try di.dwarf_seekable_stream.seekTo(prog_start_offset);
18661860
1867 while (true) {1861 while (true) {
1868 const opcode = try di.dwarf_in_stream.readByte();1862 const opcode = try di.dwarf_in_stream.readByte();
18691863
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 opcodes1896 // 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 }
19581949
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
1962fn scanAllCompileUnits(di: *DwarfInfo) !void {1953fn 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;
19661956
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 });
20242013
2025 this_unit_offset += next_offset;2014 this_unit_offset += next_offset;
2026 cu_index += 1;
2027 }2015 }
2028}2016}
20292017