| ... | ... | @@ -138,6 +138,29 @@ pub const CompileUnit = struct { |
| 138 | 138 | rnglists_base: usize, |
| 139 | 139 | loclists_base: usize, |
| 140 | 140 | frame_base: ?*const FormValue, |
| 141 | |
| 142 | src_loc_cache: ?SrcLocCache, |
| 143 | |
| 144 | pub const SrcLocCache = struct { |
| 145 | line_table: LineTable, |
| 146 | directories: []const FileEntry, |
| 147 | files: []FileEntry, |
| 148 | version: u16, |
| 149 | |
| 150 | pub const LineTable = std.AutoArrayHashMapUnmanaged(u64, LineEntry); |
| 151 | |
| 152 | pub const LineEntry = struct { |
| 153 | line: u32, |
| 154 | column: u32, |
| 155 | file: u32, |
| 156 | }; |
| 157 | |
| 158 | pub fn findSource(slc: *const SrcLocCache, address: u64) !LineEntry { |
| 159 | const index = std.sort.upperBound(u64, address, slc.line_table.keys(), {}, std.sort.asc(u64)); |
| 160 | if (index == 0) return missing(); |
| 161 | return slc.line_table.values()[index - 1]; |
| 162 | } |
| 163 | }; |
| 141 | 164 | }; |
| 142 | 165 | |
| 143 | 166 | pub const FormValue = union(enum) { |
| ... | ... | @@ -760,6 +783,11 @@ pub fn deinit(di: *Dwarf, gpa: Allocator) void { |
| 760 | 783 | } |
| 761 | 784 | di.abbrev_table_list.deinit(gpa); |
| 762 | 785 | for (di.compile_unit_list.items) |*cu| { |
| 786 | if (cu.src_loc_cache) |*slc| { |
| 787 | slc.line_table.deinit(gpa); |
| 788 | gpa.free(slc.directories); |
| 789 | gpa.free(slc.files); |
| 790 | } |
| 763 | 791 | cu.die.deinit(gpa); |
| 764 | 792 | } |
| 765 | 793 | di.compile_unit_list.deinit(gpa); |
| ... | ... | @@ -846,6 +874,7 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void { |
| 846 | 874 | .rnglists_base = 0, |
| 847 | 875 | .loclists_base = 0, |
| 848 | 876 | .frame_base = null, |
| 877 | .src_loc_cache = null, |
| 849 | 878 | }; |
| 850 | 879 | |
| 851 | 880 | while (true) { |
| ... | ... | @@ -1032,6 +1061,7 @@ fn scanAllCompileUnits(di: *Dwarf, allocator: Allocator) ScanError!void { |
| 1032 | 1061 | .rnglists_base = if (compile_unit_die.getAttr(AT.rnglists_base)) |fv| try fv.getUInt(usize) else 0, |
| 1033 | 1062 | .loclists_base = if (compile_unit_die.getAttr(AT.loclists_base)) |fv| try fv.getUInt(usize) else 0, |
| 1034 | 1063 | .frame_base = compile_unit_die.getAttr(AT.frame_base), |
| 1064 | .src_loc_cache = null, |
| 1035 | 1065 | }; |
| 1036 | 1066 | |
| 1037 | 1067 | compile_unit.pc_range = x: { |
| ... | ... | @@ -1242,7 +1272,7 @@ const DebugRangeIterator = struct { |
| 1242 | 1272 | }; |
| 1243 | 1273 | |
| 1244 | 1274 | /// TODO: change this to binary searching the sorted compile unit list |
| 1245 | | pub fn findCompileUnit(di: *const Dwarf, target_address: u64) !*const CompileUnit { |
| 1275 | pub fn findCompileUnit(di: *const Dwarf, target_address: u64) !*CompileUnit { |
| 1246 | 1276 | for (di.compile_unit_list.items) |*compile_unit| { |
| 1247 | 1277 | if (compile_unit.pc_range) |range| { |
| 1248 | 1278 | if (target_address >= range.start and target_address < range.end) return compile_unit; |
| ... | ... | @@ -1352,34 +1382,36 @@ fn parseDie( |
| 1352 | 1382 | }; |
| 1353 | 1383 | } |
| 1354 | 1384 | |
| 1355 | | pub fn getLineNumberInfo( |
| 1356 | | di: *Dwarf, |
| 1357 | | allocator: Allocator, |
| 1358 | | compile_unit: CompileUnit, |
| 1359 | | target_address: u64, |
| 1360 | | ) !std.debug.SourceLocation { |
| 1361 | | const compile_unit_cwd = try compile_unit.die.getAttrString(di, AT.comp_dir, di.section(.debug_line_str), compile_unit); |
| 1385 | fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !CompileUnit.SrcLocCache { |
| 1386 | const compile_unit_cwd = try compile_unit.die.getAttrString(d, AT.comp_dir, d.section(.debug_line_str), compile_unit.*); |
| 1362 | 1387 | const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list); |
| 1363 | 1388 | |
| 1364 | | var fbr: FixedBufferReader = .{ .buf = di.section(.debug_line).?, .endian = di.endian }; |
| 1389 | var fbr: FixedBufferReader = .{ |
| 1390 | .buf = d.section(.debug_line).?, |
| 1391 | .endian = d.endian, |
| 1392 | }; |
| 1365 | 1393 | try fbr.seekTo(line_info_offset); |
| 1366 | 1394 | |
| 1367 | 1395 | const unit_header = try readUnitHeader(&fbr, null); |
| 1368 | 1396 | if (unit_header.unit_length == 0) return missing(); |
| 1397 | |
| 1369 | 1398 | const next_offset = unit_header.header_length + unit_header.unit_length; |
| 1370 | 1399 | |
| 1371 | 1400 | const version = try fbr.readInt(u16); |
| 1372 | 1401 | if (version < 2) return bad(); |
| 1373 | 1402 | |
| 1374 | | var addr_size: u8 = switch (unit_header.format) { |
| 1375 | | .@"32" => 4, |
| 1376 | | .@"64" => 8, |
| 1403 | const addr_size: u8, const seg_size: u8 = if (version >= 5) .{ |
| 1404 | try fbr.readByte(), |
| 1405 | try fbr.readByte(), |
| 1406 | } else .{ |
| 1407 | switch (unit_header.format) { |
| 1408 | .@"32" => 4, |
| 1409 | .@"64" => 8, |
| 1410 | }, |
| 1411 | 0, |
| 1377 | 1412 | }; |
| 1378 | | var seg_size: u8 = 0; |
| 1379 | | if (version >= 5) { |
| 1380 | | addr_size = try fbr.readByte(); |
| 1381 | | seg_size = try fbr.readByte(); |
| 1382 | | } |
| 1413 | _ = addr_size; |
| 1414 | _ = seg_size; |
| 1383 | 1415 | |
| 1384 | 1416 | const prologue_length = try fbr.readAddress(unit_header.format); |
| 1385 | 1417 | const prog_start_offset = fbr.pos + prologue_length; |
| ... | ... | @@ -1388,8 +1420,8 @@ pub fn getLineNumberInfo( |
| 1388 | 1420 | if (minimum_instruction_length == 0) return bad(); |
| 1389 | 1421 | |
| 1390 | 1422 | if (version >= 4) { |
| 1391 | | // maximum_operations_per_instruction |
| 1392 | | _ = try fbr.readByte(); |
| 1423 | const maximum_operations_per_instruction = try fbr.readByte(); |
| 1424 | _ = maximum_operations_per_instruction; |
| 1393 | 1425 | } |
| 1394 | 1426 | |
| 1395 | 1427 | const default_is_stmt = (try fbr.readByte()) != 0; |
| ... | ... | @@ -1402,18 +1434,18 @@ pub fn getLineNumberInfo( |
| 1402 | 1434 | |
| 1403 | 1435 | const standard_opcode_lengths = try fbr.readBytes(opcode_base - 1); |
| 1404 | 1436 | |
| 1405 | | var include_directories = std.ArrayList(FileEntry).init(allocator); |
| 1406 | | defer include_directories.deinit(); |
| 1407 | | var file_entries = std.ArrayList(FileEntry).init(allocator); |
| 1408 | | defer file_entries.deinit(); |
| 1437 | var directories: std.ArrayListUnmanaged(FileEntry) = .{}; |
| 1438 | defer directories.deinit(gpa); |
| 1439 | var file_entries: std.ArrayListUnmanaged(FileEntry) = .{}; |
| 1440 | defer file_entries.deinit(gpa); |
| 1409 | 1441 | |
| 1410 | 1442 | if (version < 5) { |
| 1411 | | try include_directories.append(.{ .path = compile_unit_cwd }); |
| 1443 | try directories.append(gpa, .{ .path = compile_unit_cwd }); |
| 1412 | 1444 | |
| 1413 | 1445 | while (true) { |
| 1414 | 1446 | const dir = try fbr.readBytesTo(0); |
| 1415 | 1447 | if (dir.len == 0) break; |
| 1416 | | try include_directories.append(.{ .path = dir }); |
| 1448 | try directories.append(gpa, .{ .path = dir }); |
| 1417 | 1449 | } |
| 1418 | 1450 | |
| 1419 | 1451 | while (true) { |
| ... | ... | @@ -1422,7 +1454,7 @@ pub fn getLineNumberInfo( |
| 1422 | 1454 | const dir_index = try fbr.readUleb128(u32); |
| 1423 | 1455 | const mtime = try fbr.readUleb128(u64); |
| 1424 | 1456 | const size = try fbr.readUleb128(u64); |
| 1425 | | try file_entries.append(.{ |
| 1457 | try file_entries.append(gpa, .{ |
| 1426 | 1458 | .path = file_name, |
| 1427 | 1459 | .dir_index = dir_index, |
| 1428 | 1460 | .mtime = mtime, |
| ... | ... | @@ -1446,52 +1478,10 @@ pub fn getLineNumberInfo( |
| 1446 | 1478 | } |
| 1447 | 1479 | |
| 1448 | 1480 | const directories_count = try fbr.readUleb128(usize); |
| 1449 | | try include_directories.ensureUnusedCapacity(directories_count); |
| 1450 | | { |
| 1451 | | var i: usize = 0; |
| 1452 | | while (i < directories_count) : (i += 1) { |
| 1453 | | var e: FileEntry = .{ .path = &.{} }; |
| 1454 | | for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| { |
| 1455 | | const form_value = try parseFormValue( |
| 1456 | | &fbr, |
| 1457 | | ent_fmt.form_code, |
| 1458 | | unit_header.format, |
| 1459 | | null, |
| 1460 | | ); |
| 1461 | | switch (ent_fmt.content_type_code) { |
| 1462 | | DW.LNCT.path => e.path = try form_value.getString(di.*), |
| 1463 | | DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32), |
| 1464 | | DW.LNCT.timestamp => e.mtime = try form_value.getUInt(u64), |
| 1465 | | DW.LNCT.size => e.size = try form_value.getUInt(u64), |
| 1466 | | DW.LNCT.MD5 => e.md5 = switch (form_value) { |
| 1467 | | .data16 => |data16| data16.*, |
| 1468 | | else => return bad(), |
| 1469 | | }, |
| 1470 | | else => continue, |
| 1471 | | } |
| 1472 | | } |
| 1473 | | include_directories.appendAssumeCapacity(e); |
| 1474 | | } |
| 1475 | | } |
| 1476 | | } |
| 1477 | 1481 | |
| 1478 | | var file_ent_fmt_buf: [10]FileEntFmt = undefined; |
| 1479 | | const file_name_entry_format_count = try fbr.readByte(); |
| 1480 | | if (file_name_entry_format_count > file_ent_fmt_buf.len) return bad(); |
| 1481 | | for (file_ent_fmt_buf[0..file_name_entry_format_count]) |*ent_fmt| { |
| 1482 | | ent_fmt.* = .{ |
| 1483 | | .content_type_code = try fbr.readUleb128(u8), |
| 1484 | | .form_code = try fbr.readUleb128(u16), |
| 1485 | | }; |
| 1486 | | } |
| 1487 | | |
| 1488 | | const file_names_count = try fbr.readUleb128(usize); |
| 1489 | | try file_entries.ensureUnusedCapacity(file_names_count); |
| 1490 | | { |
| 1491 | | var i: usize = 0; |
| 1492 | | while (i < file_names_count) : (i += 1) { |
| 1493 | | var e: FileEntry = .{ .path = &.{} }; |
| 1494 | | for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| { |
| 1482 | for (try directories.addManyAsSlice(gpa, directories_count)) |*e| { |
| 1483 | e.* = .{ .path = &.{} }; |
| 1484 | for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| { |
| 1495 | 1485 | const form_value = try parseFormValue( |
| 1496 | 1486 | &fbr, |
| 1497 | 1487 | ent_fmt.form_code, |
| ... | ... | @@ -1499,7 +1489,7 @@ pub fn getLineNumberInfo( |
| 1499 | 1489 | null, |
| 1500 | 1490 | ); |
| 1501 | 1491 | switch (ent_fmt.content_type_code) { |
| 1502 | | DW.LNCT.path => e.path = try form_value.getString(di.*), |
| 1492 | DW.LNCT.path => e.path = try form_value.getString(d.*), |
| 1503 | 1493 | DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32), |
| 1504 | 1494 | DW.LNCT.timestamp => e.mtime = try form_value.getUInt(u64), |
| 1505 | 1495 | DW.LNCT.size => e.size = try form_value.getUInt(u64), |
| ... | ... | @@ -1510,17 +1500,49 @@ pub fn getLineNumberInfo( |
| 1510 | 1500 | else => continue, |
| 1511 | 1501 | } |
| 1512 | 1502 | } |
| 1513 | | file_entries.appendAssumeCapacity(e); |
| 1503 | } |
| 1504 | } |
| 1505 | |
| 1506 | var file_ent_fmt_buf: [10]FileEntFmt = undefined; |
| 1507 | const file_name_entry_format_count = try fbr.readByte(); |
| 1508 | if (file_name_entry_format_count > file_ent_fmt_buf.len) return bad(); |
| 1509 | for (file_ent_fmt_buf[0..file_name_entry_format_count]) |*ent_fmt| { |
| 1510 | ent_fmt.* = .{ |
| 1511 | .content_type_code = try fbr.readUleb128(u8), |
| 1512 | .form_code = try fbr.readUleb128(u16), |
| 1513 | }; |
| 1514 | } |
| 1515 | |
| 1516 | const file_names_count = try fbr.readUleb128(usize); |
| 1517 | try file_entries.ensureUnusedCapacity(gpa, file_names_count); |
| 1518 | |
| 1519 | for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| { |
| 1520 | e.* = .{ .path = &.{} }; |
| 1521 | for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| { |
| 1522 | const form_value = try parseFormValue( |
| 1523 | &fbr, |
| 1524 | ent_fmt.form_code, |
| 1525 | unit_header.format, |
| 1526 | null, |
| 1527 | ); |
| 1528 | switch (ent_fmt.content_type_code) { |
| 1529 | DW.LNCT.path => e.path = try form_value.getString(d.*), |
| 1530 | DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32), |
| 1531 | DW.LNCT.timestamp => e.mtime = try form_value.getUInt(u64), |
| 1532 | DW.LNCT.size => e.size = try form_value.getUInt(u64), |
| 1533 | DW.LNCT.MD5 => e.md5 = switch (form_value) { |
| 1534 | .data16 => |data16| data16.*, |
| 1535 | else => return bad(), |
| 1536 | }, |
| 1537 | else => continue, |
| 1538 | } |
| 1514 | 1539 | } |
| 1515 | 1540 | } |
| 1516 | 1541 | } |
| 1517 | 1542 | |
| 1518 | | var prog = LineNumberProgram.init( |
| 1519 | | default_is_stmt, |
| 1520 | | include_directories.items, |
| 1521 | | target_address, |
| 1522 | | version, |
| 1523 | | ); |
| 1543 | var prog = LineNumberProgram.init(default_is_stmt, version); |
| 1544 | var line_table: CompileUnit.SrcLocCache.LineTable = .{}; |
| 1545 | errdefer line_table.deinit(gpa); |
| 1524 | 1546 | |
| 1525 | 1547 | try fbr.seekTo(prog_start_offset); |
| 1526 | 1548 | |
| ... | ... | @@ -1536,7 +1558,7 @@ pub fn getLineNumberInfo( |
| 1536 | 1558 | switch (sub_op) { |
| 1537 | 1559 | DW.LNE.end_sequence => { |
| 1538 | 1560 | prog.end_sequence = true; |
| 1539 | | if (try prog.checkLineMatch(allocator, file_entries.items)) |info| return info; |
| 1561 | try prog.addRow(gpa, &line_table); |
| 1540 | 1562 | prog.reset(); |
| 1541 | 1563 | }, |
| 1542 | 1564 | DW.LNE.set_address => { |
| ... | ... | @@ -1548,7 +1570,7 @@ pub fn getLineNumberInfo( |
| 1548 | 1570 | const dir_index = try fbr.readUleb128(u32); |
| 1549 | 1571 | const mtime = try fbr.readUleb128(u64); |
| 1550 | 1572 | const size = try fbr.readUleb128(u64); |
| 1551 | | try file_entries.append(.{ |
| 1573 | try file_entries.append(gpa, .{ |
| 1552 | 1574 | .path = path, |
| 1553 | 1575 | .dir_index = dir_index, |
| 1554 | 1576 | .mtime = mtime, |
| ... | ... | @@ -1564,12 +1586,12 @@ pub fn getLineNumberInfo( |
| 1564 | 1586 | const inc_line = @as(i32, line_base) + @as(i32, adjusted_opcode % line_range); |
| 1565 | 1587 | prog.line += inc_line; |
| 1566 | 1588 | prog.address += inc_addr; |
| 1567 | | if (try prog.checkLineMatch(allocator, file_entries.items)) |info| return info; |
| 1589 | try prog.addRow(gpa, &line_table); |
| 1568 | 1590 | prog.basic_block = false; |
| 1569 | 1591 | } else { |
| 1570 | 1592 | switch (opcode) { |
| 1571 | 1593 | DW.LNS.copy => { |
| 1572 | | if (try prog.checkLineMatch(allocator, file_entries.items)) |info| return info; |
| 1594 | try prog.addRow(gpa, &line_table); |
| 1573 | 1595 | prog.basic_block = false; |
| 1574 | 1596 | }, |
| 1575 | 1597 | DW.LNS.advance_pc => { |
| ... | ... | @@ -1611,7 +1633,35 @@ pub fn getLineNumberInfo( |
| 1611 | 1633 | } |
| 1612 | 1634 | } |
| 1613 | 1635 | |
| 1614 | | return missing(); |
| 1636 | return .{ |
| 1637 | .line_table = line_table, |
| 1638 | .directories = try directories.toOwnedSlice(gpa), |
| 1639 | .files = try file_entries.toOwnedSlice(gpa), |
| 1640 | .version = version, |
| 1641 | }; |
| 1642 | } |
| 1643 | |
| 1644 | pub fn getLineNumberInfo( |
| 1645 | d: *Dwarf, |
| 1646 | gpa: Allocator, |
| 1647 | compile_unit: *CompileUnit, |
| 1648 | target_address: u64, |
| 1649 | ) !std.debug.SourceLocation { |
| 1650 | if (compile_unit.src_loc_cache == null) |
| 1651 | compile_unit.src_loc_cache = try runLineNumberProgram(d, gpa, compile_unit); |
| 1652 | const slc = &compile_unit.src_loc_cache.?; |
| 1653 | const entry = try slc.findSource(target_address); |
| 1654 | const file_index = entry.file - @intFromBool(slc.version < 5); |
| 1655 | if (file_index >= slc.files.len) return bad(); |
| 1656 | const file_entry = &slc.files[file_index]; |
| 1657 | if (file_entry.dir_index >= slc.directories.len) return bad(); |
| 1658 | const dir_name = slc.directories[file_entry.dir_index].path; |
| 1659 | const file_name = try std.fs.path.join(gpa, &.{ dir_name, file_entry.path }); |
| 1660 | return .{ |
| 1661 | .line = entry.line, |
| 1662 | .column = entry.column, |
| 1663 | .file_name = file_name, |
| 1664 | }; |
| 1615 | 1665 | } |
| 1616 | 1666 | |
| 1617 | 1667 | fn getString(di: Dwarf, offset: u64) ![:0]const u8 { |
| ... | ... | @@ -1826,17 +1876,6 @@ const LineNumberProgram = struct { |
| 1826 | 1876 | end_sequence: bool, |
| 1827 | 1877 | |
| 1828 | 1878 | default_is_stmt: bool, |
| 1829 | | target_address: u64, |
| 1830 | | include_dirs: []const FileEntry, |
| 1831 | | |
| 1832 | | prev_valid: bool, |
| 1833 | | prev_address: u64, |
| 1834 | | prev_file: usize, |
| 1835 | | prev_line: i64, |
| 1836 | | prev_column: u64, |
| 1837 | | prev_is_stmt: bool, |
| 1838 | | prev_basic_block: bool, |
| 1839 | | prev_end_sequence: bool, |
| 1840 | 1879 | |
| 1841 | 1880 | // Reset the state machine following the DWARF specification |
| 1842 | 1881 | pub fn reset(self: *LineNumberProgram) void { |
| ... | ... | @@ -1847,24 +1886,10 @@ const LineNumberProgram = struct { |
| 1847 | 1886 | self.is_stmt = self.default_is_stmt; |
| 1848 | 1887 | self.basic_block = false; |
| 1849 | 1888 | self.end_sequence = false; |
| 1850 | | // Invalidate all the remaining fields |
| 1851 | | self.prev_valid = false; |
| 1852 | | self.prev_address = 0; |
| 1853 | | self.prev_file = undefined; |
| 1854 | | self.prev_line = undefined; |
| 1855 | | self.prev_column = undefined; |
| 1856 | | self.prev_is_stmt = undefined; |
| 1857 | | self.prev_basic_block = undefined; |
| 1858 | | self.prev_end_sequence = undefined; |
| 1859 | 1889 | } |
| 1860 | 1890 | |
| 1861 | | pub fn init( |
| 1862 | | is_stmt: bool, |
| 1863 | | include_dirs: []const FileEntry, |
| 1864 | | target_address: u64, |
| 1865 | | version: u16, |
| 1866 | | ) LineNumberProgram { |
| 1867 | | return LineNumberProgram{ |
| 1891 | pub fn init(is_stmt: bool, version: u16) LineNumberProgram { |
| 1892 | return .{ |
| 1868 | 1893 | .address = 0, |
| 1869 | 1894 | .file = 1, |
| 1870 | 1895 | .line = 1, |
| ... | ... | @@ -1873,60 +1898,17 @@ const LineNumberProgram = struct { |
| 1873 | 1898 | .is_stmt = is_stmt, |
| 1874 | 1899 | .basic_block = false, |
| 1875 | 1900 | .end_sequence = false, |
| 1876 | | .include_dirs = include_dirs, |
| 1877 | 1901 | .default_is_stmt = is_stmt, |
| 1878 | | .target_address = target_address, |
| 1879 | | .prev_valid = false, |
| 1880 | | .prev_address = 0, |
| 1881 | | .prev_file = undefined, |
| 1882 | | .prev_line = undefined, |
| 1883 | | .prev_column = undefined, |
| 1884 | | .prev_is_stmt = undefined, |
| 1885 | | .prev_basic_block = undefined, |
| 1886 | | .prev_end_sequence = undefined, |
| 1887 | 1902 | }; |
| 1888 | 1903 | } |
| 1889 | 1904 | |
| 1890 | | pub fn checkLineMatch( |
| 1891 | | self: *LineNumberProgram, |
| 1892 | | allocator: Allocator, |
| 1893 | | file_entries: []const FileEntry, |
| 1894 | | ) !?std.debug.SourceLocation { |
| 1895 | | if (self.prev_valid and |
| 1896 | | self.target_address >= self.prev_address and |
| 1897 | | self.target_address < self.address) |
| 1898 | | { |
| 1899 | | const file_index = if (self.version >= 5) self.prev_file else i: { |
| 1900 | | if (self.prev_file == 0) return missing(); |
| 1901 | | break :i self.prev_file - 1; |
| 1902 | | }; |
| 1903 | | |
| 1904 | | if (file_index >= file_entries.len) return bad(); |
| 1905 | | const file_entry = &file_entries[file_index]; |
| 1906 | | |
| 1907 | | if (file_entry.dir_index >= self.include_dirs.len) return bad(); |
| 1908 | | const dir_name = self.include_dirs[file_entry.dir_index].path; |
| 1909 | | |
| 1910 | | const file_name = try std.fs.path.join(allocator, &[_][]const u8{ |
| 1911 | | dir_name, file_entry.path, |
| 1912 | | }); |
| 1913 | | |
| 1914 | | return std.debug.SourceLocation{ |
| 1915 | | .line = if (self.prev_line >= 0) @as(u64, @intCast(self.prev_line)) else 0, |
| 1916 | | .column = self.prev_column, |
| 1917 | | .file_name = file_name, |
| 1918 | | }; |
| 1919 | | } |
| 1920 | | |
| 1921 | | self.prev_valid = true; |
| 1922 | | self.prev_address = self.address; |
| 1923 | | self.prev_file = self.file; |
| 1924 | | self.prev_line = self.line; |
| 1925 | | self.prev_column = self.column; |
| 1926 | | self.prev_is_stmt = self.is_stmt; |
| 1927 | | self.prev_basic_block = self.basic_block; |
| 1928 | | self.prev_end_sequence = self.end_sequence; |
| 1929 | | return null; |
| 1905 | pub fn addRow(prog: *LineNumberProgram, gpa: Allocator, table: *CompileUnit.SrcLocCache.LineTable) !void { |
| 1906 | if (prog.line == 0) return; // garbage data |
| 1907 | try table.put(gpa, prog.address, .{ |
| 1908 | .line = cast(u32, prog.line) orelse maxInt(u32), |
| 1909 | .column = cast(u32, prog.column) orelse maxInt(u32), |
| 1910 | .file = cast(u32, prog.file) orelse return bad(), |
| 1911 | }); |
| 1930 | 1912 | } |
| 1931 | 1913 | }; |
| 1932 | 1914 | |
| ... | ... | @@ -2381,7 +2363,7 @@ pub fn resolveSourceLocations( |
| 2381 | 2363 | defer prog_node.end(); |
| 2382 | 2364 | |
| 2383 | 2365 | var cu_i: usize = 0; |
| 2384 | | var cu: *const CompileUnit = &d.compile_unit_list.items[0]; |
| 2366 | var cu: *CompileUnit = &d.compile_unit_list.items[0]; |
| 2385 | 2367 | var range = cu.pc_range.?; |
| 2386 | 2368 | next_pc: for (sorted_pc_addrs, output) |pc, *out| { |
| 2387 | 2369 | defer prog_node.completeOne(); |
| ... | ... | @@ -2403,7 +2385,7 @@ pub fn resolveSourceLocations( |
| 2403 | 2385 | } |
| 2404 | 2386 | // TODO: instead of calling this function, break the function up into one that parses the |
| 2405 | 2387 | // information once and prepares a context that can be reused for the entire batch. |
| 2406 | | if (getLineNumberInfo(d, gpa, cu.*, pc)) |src_loc| { |
| 2388 | if (getLineNumberInfo(d, gpa, cu, pc)) |src_loc| { |
| 2407 | 2389 | out.* = src_loc; |
| 2408 | 2390 | } else |err| switch (err) { |
| 2409 | 2391 | error.MissingDebugInfo, error.InvalidDebugInfo => out.* = std.debug.SourceLocation.invalid, |
| ... | ... | @@ -2419,7 +2401,7 @@ fn getSymbol(di: *Dwarf, allocator: Allocator, address: u64) !std.debug.Symbol { |
| 2419 | 2401 | .compile_unit_name = compile_unit.die.getAttrString(di, std.dwarf.AT.name, di.section(.debug_str), compile_unit.*) catch |err| switch (err) { |
| 2420 | 2402 | error.MissingDebugInfo, error.InvalidDebugInfo => "???", |
| 2421 | 2403 | }, |
| 2422 | | .source_location = di.getLineNumberInfo(allocator, compile_unit.*, address) catch |err| switch (err) { |
| 2404 | .source_location = di.getLineNumberInfo(allocator, compile_unit, address) catch |err| switch (err) { |
| 2423 | 2405 | error.MissingDebugInfo, error.InvalidDebugInfo => null, |
| 2424 | 2406 | else => return err, |
| 2425 | 2407 | }, |