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