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 {
12131213 version: u16,
12141214 is_64: bool,
12151215 die: *Die,
1216 index: usize,
12171216 pc_range: ?PcRange,
12181217};
12191218
......@@ -1787,173 +1786,165 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
17871786
17881787fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {
17891788 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;
1792 var this_offset = di.debug_line.offset;
1793 var this_index: usize = 0;
1791 assert(line_info_offset < di.debug_line.size);
17941792
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);
17971794
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));
18071801
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;
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);
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;
18141808
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;
18171811
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 }
18221816
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();
18251819
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;
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 {
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();
18381831 }
1832 }
18391833
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 }
18471841
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);
18501844
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 }
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) {
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 },
19531946 }
19541947 }
1955
1956 this_offset += next_offset;
19571948 }
19581949
19591950 return error.MissingDebugInfo;
......@@ -1962,7 +1953,6 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
19621953fn scanAllCompileUnits(di: *DwarfInfo) !void {
19631954 const debug_info_end = di.debug_info.offset + di.debug_info.size;
19641955 var this_unit_offset = di.debug_info.offset;
1965 var cu_index: usize = 0;
19661956
19671957 while (this_unit_offset < debug_info_end) {
19681958 try di.dwarf_seekable_stream.seekTo(this_unit_offset);
......@@ -2019,11 +2009,9 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
20192009 .is_64 = is_64,
20202010 .pc_range = pc_range,
20212011 .die = compile_unit_die,
2022 .index = cu_index,
20232012 });
20242013
20252014 this_unit_offset += next_offset;
2026 cu_index += 1;
20272015 }
20282016}
20292017