| ... | ... | @@ -28,7 +28,7 @@ const Module = struct { |
| 28 | 28 | populated: bool, |
| 29 | 29 | symbols: []u8, |
| 30 | 30 | subsect_info: []u8, |
| 31 | | checksums: []u32, |
| 31 | checksum_offset: ?usize, |
| 32 | 32 | }; |
| 33 | 33 | |
| 34 | 34 | /// Tries to write to stderr, unbuffered, and ignores any error returned. |
| ... | ... | @@ -276,6 +276,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 276 | 276 | |
| 277 | 277 | var coff_section: *coff.Section = undefined; |
| 278 | 278 | const mod_index = for (di.sect_contribs) |sect_contrib| { |
| 279 | if (sect_contrib.Section >= di.coff.sections.len) continue; |
| 279 | 280 | coff_section = &di.coff.sections.toSlice()[sect_contrib.Section]; |
| 280 | 281 | |
| 281 | 282 | const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; |
| ... | ... | @@ -326,72 +327,80 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 326 | 327 | |
| 327 | 328 | var sect_offset: usize = 0; |
| 328 | 329 | var skip_len: usize = undefined; |
| 329 | | const opt_line_info = subsections: while (sect_offset != subsect_info.len) : (sect_offset += skip_len) { |
| 330 | | const subsect_hdr = @ptrCast(*pdb.DebugSubsectionHeader, &subsect_info[sect_offset]); |
| 331 | | skip_len = subsect_hdr.Length; |
| 332 | | sect_offset += @sizeOf(pdb.DebugSubsectionHeader); |
| 333 | | |
| 334 | | switch (subsect_hdr.Kind) { |
| 335 | | pdb.DebugSubsectionKind.Lines => { |
| 336 | | var line_index: usize = sect_offset; |
| 337 | | |
| 338 | | const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]); |
| 339 | | if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo; |
| 340 | | line_index += @sizeOf(pdb.LineFragmentHeader); |
| 341 | | |
| 342 | | const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]); |
| 343 | | line_index += @sizeOf(pdb.LineBlockFragmentHeader); |
| 344 | | |
| 345 | | const has_column = line_hdr.Flags.LF_HaveColumns; |
| 346 | | |
| 347 | | const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset; |
| 348 | | const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize; |
| 349 | | if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) { |
| 350 | | var line_i: usize = 0; |
| 351 | | const start_line_index = line_index; |
| 352 | | while (line_i < block_hdr.NumLines) : (line_i += 1) { |
| 353 | | const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]); |
| 354 | | line_index += @sizeOf(pdb.LineNumberEntry); |
| 355 | | const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags); |
| 356 | | const vaddr_start = frag_vaddr_start + line_num_entry.Offset; |
| 357 | | const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End; |
| 358 | | if (relative_address >= vaddr_start and relative_address < vaddr_end) { |
| 359 | | const chksum_index = block_hdr.NameIndex; |
| 360 | | std.debug.warn("looking up checksum {}\n", chksum_index); |
| 361 | | const strtab_offset = mod.checksums[chksum_index]; |
| 362 | | try di.pdb.string_table.seekTo(@sizeOf(pdb.PDBStringTableHeader) + strtab_offset); |
| 363 | | const source_file_name = try di.pdb.string_table.readNullTermString(allocator); |
| 364 | | const line = flags.Start; |
| 365 | | const column = if (has_column) blk: { |
| 366 | | line_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines; |
| 367 | | line_index += @sizeOf(pdb.ColumnNumberEntry) * line_i; |
| 368 | | const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[line_index]); |
| 369 | | break :blk col_num_entry.StartColumn; |
| 370 | | } else 0; |
| 371 | | break :subsections LineInfo{ |
| 372 | | .allocator = allocator, |
| 373 | | .file_name = source_file_name, |
| 374 | | .line = line, |
| 375 | | .column = column, |
| 376 | | }; |
| 330 | const opt_line_info = subsections: { |
| 331 | const checksum_offset = mod.checksum_offset orelse break :subsections null; |
| 332 | while (sect_offset != subsect_info.len) : (sect_offset += skip_len) { |
| 333 | const subsect_hdr = @ptrCast(*pdb.DebugSubsectionHeader, &subsect_info[sect_offset]); |
| 334 | skip_len = subsect_hdr.Length; |
| 335 | sect_offset += @sizeOf(pdb.DebugSubsectionHeader); |
| 336 | |
| 337 | switch (subsect_hdr.Kind) { |
| 338 | pdb.DebugSubsectionKind.Lines => { |
| 339 | var line_index: usize = sect_offset; |
| 340 | |
| 341 | const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]); |
| 342 | if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo; |
| 343 | line_index += @sizeOf(pdb.LineFragmentHeader); |
| 344 | |
| 345 | const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]); |
| 346 | line_index += @sizeOf(pdb.LineBlockFragmentHeader); |
| 347 | |
| 348 | const has_column = line_hdr.Flags.LF_HaveColumns; |
| 349 | |
| 350 | const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset; |
| 351 | const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize; |
| 352 | if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) { |
| 353 | var line_i: usize = 0; |
| 354 | const start_line_index = line_index; |
| 355 | while (line_i < block_hdr.NumLines) : (line_i += 1) { |
| 356 | const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]); |
| 357 | line_index += @sizeOf(pdb.LineNumberEntry); |
| 358 | const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags); |
| 359 | const vaddr_start = frag_vaddr_start + line_num_entry.Offset; |
| 360 | const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End; |
| 361 | if (relative_address >= vaddr_start and relative_address < vaddr_end) { |
| 362 | const subsect_index = checksum_offset + block_hdr.NameIndex; |
| 363 | const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]); |
| 364 | const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset; |
| 365 | try di.pdb.string_table.seekTo(strtab_offset); |
| 366 | const source_file_name = try di.pdb.string_table.readNullTermString(allocator); |
| 367 | const line = flags.Start; |
| 368 | const column = if (has_column) blk: { |
| 369 | line_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines; |
| 370 | line_index += @sizeOf(pdb.ColumnNumberEntry) * line_i; |
| 371 | const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[line_index]); |
| 372 | break :blk col_num_entry.StartColumn; |
| 373 | } else 0; |
| 374 | break :subsections LineInfo{ |
| 375 | .allocator = allocator, |
| 376 | .file_name = source_file_name, |
| 377 | .line = line, |
| 378 | .column = column, |
| 379 | }; |
| 380 | } |
| 377 | 381 | } |
| 382 | break :subsections null; |
| 378 | 383 | } |
| 379 | | break :subsections null; |
| 380 | | } |
| 381 | | }, |
| 382 | | else => {}, |
| 383 | | } |
| 384 | }, |
| 385 | else => {}, |
| 386 | } |
| 384 | 387 | |
| 385 | | if (sect_offset > subsect_info.len) |
| 386 | | return error.InvalidDebugInfo; |
| 387 | | } else null; |
| 388 | if (sect_offset > subsect_info.len) |
| 389 | return error.InvalidDebugInfo; |
| 390 | } else { |
| 391 | break :subsections null; |
| 392 | } |
| 393 | }; |
| 388 | 394 | |
| 389 | 395 | if (tty_color) { |
| 396 | setTtyColor(TtyColor.White); |
| 390 | 397 | if (opt_line_info) |li| { |
| 391 | | try out_stream.print("{}:{}:{}: ", li.file_name, li.line, li.column); |
| 398 | try out_stream.print("{}:{}:{}", li.file_name, li.line, li.column); |
| 392 | 399 | } else { |
| 393 | | try out_stream.print("???:?:?: "); |
| 400 | try out_stream.print("???:?:?"); |
| 394 | 401 | } |
| 402 | setTtyColor(TtyColor.Reset); |
| 403 | try out_stream.print(": "); |
| 395 | 404 | setTtyColor(TtyColor.Dim); |
| 396 | 405 | try out_stream.print("0x{x} in {} ({})", relocated_address, symbol_name, obj_basename); |
| 397 | 406 | setTtyColor(TtyColor.Reset); |
| ... | ... | @@ -470,8 +479,7 @@ fn setTtyColor(tty_color: TtyColor) void { |
| 470 | 479 | windows.FOREGROUND_RED|windows.FOREGROUND_GREEN|windows.FOREGROUND_BLUE|windows.FOREGROUND_INTENSITY); |
| 471 | 480 | }, |
| 472 | 481 | TtyColor.Dim => { |
| 473 | | _ = windows.SetConsoleTextAttribute(stderr_file.handle, |
| 474 | | windows.FOREGROUND_RED|windows.FOREGROUND_GREEN|windows.FOREGROUND_BLUE); |
| 482 | _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY); |
| 475 | 483 | }, |
| 476 | 484 | TtyColor.Reset => { |
| 477 | 485 | _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs); |
| ... | ... | @@ -502,7 +510,6 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void { |
| 502 | 510 | mod.subsect_info = try allocator.alloc(u8, mod.mod_info.C13ByteSize); |
| 503 | 511 | try modi.stream.readNoEof(mod.subsect_info); |
| 504 | 512 | |
| 505 | | var checksum_list = ArrayList(u32).init(allocator); |
| 506 | 513 | var sect_offset: usize = 0; |
| 507 | 514 | var skip_len: usize = undefined; |
| 508 | 515 | while (sect_offset != mod.subsect_info.len) : (sect_offset += skip_len) { |
| ... | ... | @@ -512,18 +519,8 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void { |
| 512 | 519 | |
| 513 | 520 | switch (subsect_hdr.Kind) { |
| 514 | 521 | pdb.DebugSubsectionKind.FileChecksums => { |
| 515 | | var chksum_index: usize = sect_offset; |
| 516 | | |
| 517 | | while (chksum_index != mod.subsect_info.len) { |
| 518 | | const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[chksum_index]); |
| 519 | | std.debug.warn("{} {}\n", checksum_list.len, chksum_hdr); |
| 520 | | try checksum_list.append(chksum_hdr.FileNameOffset); |
| 521 | | const len = @sizeOf(pdb.FileChecksumEntryHeader) + chksum_hdr.ChecksumSize; |
| 522 | | chksum_index += len + (len % 4); |
| 523 | | if (chksum_index > mod.subsect_info.len) |
| 524 | | return error.InvalidDebugInfo; |
| 525 | | } |
| 526 | | |
| 522 | mod.checksum_offset = sect_offset; |
| 523 | break; |
| 527 | 524 | }, |
| 528 | 525 | else => {}, |
| 529 | 526 | } |
| ... | ... | @@ -531,13 +528,6 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void { |
| 531 | 528 | if (sect_offset > mod.subsect_info.len) |
| 532 | 529 | return error.InvalidDebugInfo; |
| 533 | 530 | } |
| 534 | | mod.checksums = checksum_list.toOwnedSlice(); |
| 535 | | |
| 536 | | for (mod.checksums) |strtab_offset| { |
| 537 | | try di.pdb.string_table.seekTo(@sizeOf(pdb.PDBStringTableHeader) + strtab_offset); |
| 538 | | const source_file_name = try di.pdb.string_table.readNullTermString(allocator); |
| 539 | | std.debug.warn("{}={}\n", strtab_offset, source_file_name); |
| 540 | | } |
| 541 | 531 | |
| 542 | 532 | mod.populated = true; |
| 543 | 533 | } |
| ... | ... | @@ -807,7 +797,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 807 | 797 | .populated = false, |
| 808 | 798 | .symbols = undefined, |
| 809 | 799 | .subsect_info = undefined, |
| 810 | | .checksums = undefined, |
| 800 | .checksum_offset = null, |
| 811 | 801 | }); |
| 812 | 802 | |
| 813 | 803 | mod_info_offset += this_record_len; |