| ... | @@ -53,6 +53,10 @@ pub const SymbolInfo = struct { | ... | @@ -53,6 +53,10 @@ pub const SymbolInfo = struct { |
| 53 | } | 53 | } |
| 54 | } | 54 | } |
| 55 | }; | 55 | }; |
| | 56 | const PdbOrDwarf = union(enum) { |
| | 57 | pdb: pdb.Pdb, |
| | 58 | dwarf: DW.DwarfInfo, |
| | 59 | }; |
| 56 | | 60 | |
| 57 | var stderr_mutex = std.Thread.Mutex{}; | 61 | var stderr_mutex = std.Thread.Mutex{}; |
| 58 | | 62 | |
| ... | @@ -669,10 +673,32 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf | ... | @@ -669,10 +673,32 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf |
| 669 | var di = ModuleDebugInfo{ | 673 | var di = ModuleDebugInfo{ |
| 670 | .base_address = undefined, | 674 | .base_address = undefined, |
| 671 | .coff = coff_obj, | 675 | .coff = coff_obj, |
| 672 | .pdb = undefined, | 676 | .debug_data = undefined, |
| 673 | }; | 677 | }; |
| 674 | | 678 | |
| 675 | try di.coff.loadHeader(); | 679 | try di.coff.loadHeader(); |
| | 680 | try di.coff.loadSections(); |
| | 681 | if (di.coff.getSection(".debug_info")) |sec| { |
| | 682 | // This coff file has embedded DWARF debug info |
| | 683 | // TODO: free the section data slices |
| | 684 | const debug_info_data = di.coff.getSectionData(".debug_info", allocator) catch null; |
| | 685 | const debug_abbrev_data = di.coff.getSectionData(".debug_abbrev", allocator) catch null; |
| | 686 | const debug_str_data = di.coff.getSectionData(".debug_str", allocator) catch null; |
| | 687 | const debug_line_data = di.coff.getSectionData(".debug_line", allocator) catch null; |
| | 688 | const debug_ranges_data = di.coff.getSectionData(".debug_ranges", allocator) catch null; |
| | 689 | |
| | 690 | var dwarf = DW.DwarfInfo{ |
| | 691 | .endian = native_endian, |
| | 692 | .debug_info = debug_info_data orelse return error.MissingDebugInfo, |
| | 693 | .debug_abbrev = debug_abbrev_data orelse return error.MissingDebugInfo, |
| | 694 | .debug_str = debug_str_data orelse return error.MissingDebugInfo, |
| | 695 | .debug_line = debug_line_data orelse return error.MissingDebugInfo, |
| | 696 | .debug_ranges = debug_ranges_data, |
| | 697 | }; |
| | 698 | try DW.openDwarfDebugInfo(&dwarf, allocator); |
| | 699 | di.debug_data = PdbOrDwarf{ .dwarf = dwarf }; |
| | 700 | return di; |
| | 701 | } |
| 676 | | 702 | |
| 677 | var path_buf: [windows.MAX_PATH]u8 = undefined; | 703 | var path_buf: [windows.MAX_PATH]u8 = undefined; |
| 678 | const len = try di.coff.getPdbPath(path_buf[0..]); | 704 | const len = try di.coff.getPdbPath(path_buf[0..]); |
| ... | @@ -681,11 +707,12 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf | ... | @@ -681,11 +707,12 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf |
| 681 | const path = try fs.path.resolve(allocator, &[_][]const u8{raw_path}); | 707 | const path = try fs.path.resolve(allocator, &[_][]const u8{raw_path}); |
| 682 | defer allocator.free(path); | 708 | defer allocator.free(path); |
| 683 | | 709 | |
| 684 | di.pdb = try pdb.Pdb.init(allocator, path); | 710 | di.debug_data = PdbOrDwarf{ .pdb = undefined }; |
| 685 | try di.pdb.parseInfoStream(); | 711 | di.debug_data.pdb = try pdb.Pdb.init(allocator, path); |
| 686 | try di.pdb.parseDbiStream(); | 712 | try di.debug_data.pdb.parseInfoStream(); |
| | 713 | try di.debug_data.pdb.parseDbiStream(); |
| 687 | | 714 | |
| 688 | if (!mem.eql(u8, &di.coff.guid, &di.pdb.guid) or di.coff.age != di.pdb.age) | 715 | if (!mem.eql(u8, &di.coff.guid, &di.debug_data.pdb.guid) or di.coff.age != di.debug_data.pdb.age) |
| 689 | return error.InvalidDebugInfo; | 716 | return error.InvalidDebugInfo; |
| 690 | | 717 | |
| 691 | return di; | 718 | return di; |
| ... | @@ -1331,7 +1358,7 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1331,7 +1358,7 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1331 | }, | 1358 | }, |
| 1332 | .uefi, .windows => struct { | 1359 | .uefi, .windows => struct { |
| 1333 | base_address: usize, | 1360 | base_address: usize, |
| 1334 | pdb: pdb.Pdb, | 1361 | debug_data: PdbOrDwarf, |
| 1335 | coff: *coff.Coff, | 1362 | coff: *coff.Coff, |
| 1336 | | 1363 | |
| 1337 | pub fn allocator(self: @This()) *mem.Allocator { | 1364 | pub fn allocator(self: @This()) *mem.Allocator { |
| ... | @@ -1342,8 +1369,18 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1342,8 +1369,18 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1342 | // Translate the VA into an address into this object | 1369 | // Translate the VA into an address into this object |
| 1343 | const relocated_address = address - self.base_address; | 1370 | const relocated_address = address - self.base_address; |
| 1344 | | 1371 | |
| | 1372 | switch (self.debug_data) { |
| | 1373 | .dwarf => |*dwarf| { |
| | 1374 | const dwarf_address = relocated_address + self.coff.pe_header.image_base; |
| | 1375 | return getSymbolFromDwarf(dwarf_address, dwarf); |
| | 1376 | }, |
| | 1377 | .pdb => { |
| | 1378 | // fallthrough to pdb handling |
| | 1379 | }, |
| | 1380 | } |
| | 1381 | |
| 1345 | var coff_section: *coff.Section = undefined; | 1382 | var coff_section: *coff.Section = undefined; |
| 1346 | const mod_index = for (self.pdb.sect_contribs) |sect_contrib| { | 1383 | const mod_index = for (self.debug_data.pdb.sect_contribs) |sect_contrib| { |
| 1347 | if (sect_contrib.Section > self.coff.sections.items.len) continue; | 1384 | if (sect_contrib.Section > self.coff.sections.items.len) continue; |
| 1348 | // Remember that SectionContribEntry.Section is 1-based. | 1385 | // Remember that SectionContribEntry.Section is 1-based. |
| 1349 | coff_section = &self.coff.sections.items[sect_contrib.Section - 1]; | 1386 | coff_section = &self.coff.sections.items[sect_contrib.Section - 1]; |
| ... | @@ -1358,15 +1395,15 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1358,15 +1395,15 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1358 | return SymbolInfo{}; | 1395 | return SymbolInfo{}; |
| 1359 | }; | 1396 | }; |
| 1360 | | 1397 | |
| 1361 | const module = (try self.pdb.getModule(mod_index)) orelse | 1398 | const module = (try self.debug_data.pdb.getModule(mod_index)) orelse |
| 1362 | return error.InvalidDebugInfo; | 1399 | return error.InvalidDebugInfo; |
| 1363 | const obj_basename = fs.path.basename(module.obj_file_name); | 1400 | const obj_basename = fs.path.basename(module.obj_file_name); |
| 1364 | | 1401 | |
| 1365 | const symbol_name = self.pdb.getSymbolName( | 1402 | const symbol_name = self.debug_data.pdb.getSymbolName( |
| 1366 | module, | 1403 | module, |
| 1367 | relocated_address - coff_section.header.virtual_address, | 1404 | relocated_address - coff_section.header.virtual_address, |
| 1368 | ) orelse "???"; | 1405 | ) orelse "???"; |
| 1369 | const opt_line_info = try self.pdb.getLineNumberInfo( | 1406 | const opt_line_info = try self.debug_data.pdb.getLineNumberInfo( |
| 1370 | module, | 1407 | module, |
| 1371 | relocated_address - coff_section.header.virtual_address, | 1408 | relocated_address - coff_section.header.virtual_address, |
| 1372 | ); | 1409 | ); |
| ... | @@ -1386,32 +1423,33 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1386,32 +1423,33 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1386 | pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo { | 1423 | pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo { |
| 1387 | // Translate the VA into an address into this object | 1424 | // Translate the VA into an address into this object |
| 1388 | const relocated_address = address - self.base_address; | 1425 | const relocated_address = address - self.base_address; |
| 1389 | | 1426 | return getSymbolFromDwarf(relocated_address, &self.dwarf); |
| 1390 | if (nosuspend self.dwarf.findCompileUnit(relocated_address)) |compile_unit| { | | |
| 1391 | return SymbolInfo{ | | |
| 1392 | .symbol_name = nosuspend self.dwarf.getSymbolName(relocated_address) orelse "???", | | |
| 1393 | .compile_unit_name = compile_unit.die.getAttrString(&self.dwarf, DW.AT_name) catch |err| switch (err) { | | |
| 1394 | error.MissingDebugInfo, error.InvalidDebugInfo => "???", | | |
| 1395 | else => return err, | | |
| 1396 | }, | | |
| 1397 | .line_info = nosuspend self.dwarf.getLineNumberInfo(compile_unit.*, relocated_address) catch |err| switch (err) { | | |
| 1398 | error.MissingDebugInfo, error.InvalidDebugInfo => null, | | |
| 1399 | else => return err, | | |
| 1400 | }, | | |
| 1401 | }; | | |
| 1402 | } else |err| switch (err) { | | |
| 1403 | error.MissingDebugInfo, error.InvalidDebugInfo => { | | |
| 1404 | return SymbolInfo{}; | | |
| 1405 | }, | | |
| 1406 | else => return err, | | |
| 1407 | } | | |
| 1408 | | | |
| 1409 | unreachable; | | |
| 1410 | } | 1427 | } |
| 1411 | }, | 1428 | }, |
| 1412 | else => DW.DwarfInfo, | 1429 | else => DW.DwarfInfo, |
| 1413 | }; | 1430 | }; |
| 1414 | | 1431 | |
| | 1432 | fn getSymbolFromDwarf(address: u64, di: *DW.DwarfInfo) !SymbolInfo { |
| | 1433 | if (nosuspend di.findCompileUnit(address)) |compile_unit| { |
| | 1434 | return SymbolInfo{ |
| | 1435 | .symbol_name = nosuspend di.getSymbolName(address) orelse "???", |
| | 1436 | .compile_unit_name = compile_unit.die.getAttrString(di, DW.AT_name) catch |err| switch (err) { |
| | 1437 | error.MissingDebugInfo, error.InvalidDebugInfo => "???", |
| | 1438 | else => return err, |
| | 1439 | }, |
| | 1440 | .line_info = nosuspend di.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) { |
| | 1441 | error.MissingDebugInfo, error.InvalidDebugInfo => null, |
| | 1442 | else => return err, |
| | 1443 | }, |
| | 1444 | }; |
| | 1445 | } else |err| switch (err) { |
| | 1446 | error.MissingDebugInfo, error.InvalidDebugInfo => { |
| | 1447 | return SymbolInfo{}; |
| | 1448 | }, |
| | 1449 | else => return err, |
| | 1450 | } |
| | 1451 | } |
| | 1452 | |
| 1415 | /// TODO multithreaded awareness | 1453 | /// TODO multithreaded awareness |
| 1416 | var debug_info_allocator: ?*mem.Allocator = null; | 1454 | var debug_info_allocator: ?*mem.Allocator = null; |
| 1417 | var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined; | 1455 | var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined; |