| ... | @@ -365,7 +365,8 @@ const ProcSym = packed struct { | ... | @@ -365,7 +365,8 @@ const ProcSym = packed struct { |
| 365 | CodeOffset: u32, | 365 | CodeOffset: u32, |
| 366 | Segment: u16, | 366 | Segment: u16, |
| 367 | Flags: ProcSymFlags, | 367 | Flags: ProcSymFlags, |
| 368 | Name: u8, | 368 | // following is a null terminated string |
| | 369 | // Name: [*]u8, |
| 369 | }; | 370 | }; |
| 370 | | 371 | |
| 371 | const ProcSymFlags = packed struct { | 372 | const ProcSymFlags = packed struct { |
| ... | @@ -389,6 +390,51 @@ const RecordPrefix = packed struct { | ... | @@ -389,6 +390,51 @@ const RecordPrefix = packed struct { |
| 389 | RecordKind: SymbolKind, /// Record kind enum (SymRecordKind or TypeRecordKind) | 390 | RecordKind: SymbolKind, /// Record kind enum (SymRecordKind or TypeRecordKind) |
| 390 | }; | 391 | }; |
| 391 | | 392 | |
| | 393 | const LineFragmentHeader = packed struct { |
| | 394 | RelocOffset: u32, /// Code offset of line contribution. |
| | 395 | RelocSegment: u16, /// Code segment of line contribution. |
| | 396 | Flags: LineFlags, |
| | 397 | CodeSize: u32, /// Code size of this line contribution. |
| | 398 | }; |
| | 399 | |
| | 400 | const LineFlags = packed struct { |
| | 401 | LF_HaveColumns: bool, /// CV_LINES_HAVE_COLUMNS |
| | 402 | unused: u15, |
| | 403 | }; |
| | 404 | |
| | 405 | /// The following two variable length arrays appear immediately after the |
| | 406 | /// header. The structure definitions follow. |
| | 407 | /// LineNumberEntry Lines[NumLines]; |
| | 408 | /// ColumnNumberEntry Columns[NumLines]; |
| | 409 | const LineBlockFragmentHeader = packed struct { |
| | 410 | /// Offset of FileChecksum entry in File |
| | 411 | /// checksums buffer. The checksum entry then |
| | 412 | /// contains another offset into the string |
| | 413 | /// table of the actual name. |
| | 414 | NameIndex: u32, |
| | 415 | NumLines: u32, |
| | 416 | BlockSize: u32, /// code size of block, in bytes |
| | 417 | }; |
| | 418 | |
| | 419 | |
| | 420 | const LineNumberEntry = packed struct { |
| | 421 | Offset: u32, /// Offset to start of code bytes for line number |
| | 422 | Flags: u32, |
| | 423 | |
| | 424 | /// TODO runtime crash when I make the actual type of Flags this |
| | 425 | const Flags = packed struct { |
| | 426 | Start: u24, |
| | 427 | End: u7, |
| | 428 | IsStatement: bool, |
| | 429 | }; |
| | 430 | }; |
| | 431 | |
| | 432 | const ColumnNumberEntry = packed struct { |
| | 433 | StartColumn: u16, |
| | 434 | EndColumn: u16, |
| | 435 | }; |
| | 436 | |
| | 437 | |
| 392 | pub const Pdb = struct { | 438 | pub const Pdb = struct { |
| 393 | in_file: os.File, | 439 | in_file: os.File, |
| 394 | allocator: *mem.Allocator, | 440 | allocator: *mem.Allocator, |
| ... | @@ -537,16 +583,82 @@ pub const Pdb = struct { | ... | @@ -537,16 +583,82 @@ pub const Pdb = struct { |
| 537 | return error.InvalidDebugInfo; | 583 | return error.InvalidDebugInfo; |
| 538 | } else return error.MissingDebugInfo; | 584 | } else return error.MissingDebugInfo; |
| 539 | | 585 | |
| 540 | std.debug.warn("found in {s}: {}\n", ([*]u8)((*[1]u8)(&proc_sym.Name)), proc_sym); | 586 | std.debug.warn("found in {s}: {}\n", @ptrCast([*]u8, proc_sym) + @sizeOf(ProcSym), proc_sym); |
| 541 | | 587 | |
| 542 | if (mod.mod_info.C11ByteSize != 0) | 588 | if (mod.mod_info.C11ByteSize != 0) |
| 543 | return error.InvalidDebugInfo; | 589 | return error.InvalidDebugInfo; |
| 544 | | 590 | |
| 545 | if (mod.mod_info.C13ByteSize != 0) { | 591 | if (mod.mod_info.C13ByteSize == 0) { |
| 546 | std.debug.warn("read C13 line info\n"); | 592 | return error.MissingDebugInfo; |
| | 593 | } |
| | 594 | |
| | 595 | const line_info = try self.allocator.alloc(u8, mod.mod_info.C13ByteSize); |
| | 596 | std.debug.warn("read C13 line info {} bytes\n", line_info.len); |
| | 597 | try modi.stream.readNoEof(line_info); |
| | 598 | |
| | 599 | var line_index: usize = 0; |
| | 600 | while (line_index != line_info.len) { |
| | 601 | std.debug.warn("unknown bytes: {x2} {x2} {x2} {x2} {x2} {x2} {x2} {x2}\n", |
| | 602 | line_info[line_index+0], |
| | 603 | line_info[line_index+1], |
| | 604 | line_info[line_index+2], |
| | 605 | line_info[line_index+3], |
| | 606 | line_info[line_index+4], |
| | 607 | line_info[line_index+5], |
| | 608 | line_info[line_index+6], |
| | 609 | line_info[line_index+7], |
| | 610 | ); |
| | 611 | line_index += 8; |
| | 612 | |
| | 613 | const line_hdr = @ptrCast(*LineFragmentHeader, &line_info[line_index]); |
| | 614 | if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo; |
| | 615 | std.debug.warn("{}\n", line_hdr); |
| | 616 | line_index += @sizeOf(LineFragmentHeader); |
| | 617 | |
| | 618 | const block_hdr = @ptrCast(*LineBlockFragmentHeader, &line_info[line_index]); |
| | 619 | std.debug.warn("{}\n", block_hdr); |
| | 620 | line_index += @sizeOf(LineBlockFragmentHeader); |
| | 621 | |
| | 622 | const has_column = line_hdr.Flags.LF_HaveColumns; |
| | 623 | std.debug.warn("has column: {}\n", has_column); |
| | 624 | |
| | 625 | const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset; |
| | 626 | const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize; |
| | 627 | if (address >= frag_vaddr_start and address < frag_vaddr_end) { |
| | 628 | std.debug.warn("found line listing\n"); |
| | 629 | var line_i: usize = 0; |
| | 630 | const start_line_index = line_index; |
| | 631 | while (line_i < block_hdr.NumLines) : (line_i += 1) { |
| | 632 | const line_num_entry = @ptrCast(*LineNumberEntry, &line_info[line_index]); |
| | 633 | line_index += @sizeOf(LineNumberEntry); |
| | 634 | const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags); |
| | 635 | std.debug.warn("{} {}\n", line_num_entry, flags); |
| | 636 | const vaddr_start = frag_vaddr_start + line_num_entry.Offset; |
| | 637 | const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End; |
| | 638 | std.debug.warn("test {x} <= {x} < {x}\n", vaddr_start, address, vaddr_end); |
| | 639 | if (address >= vaddr_start and address < vaddr_end) { |
| | 640 | std.debug.warn("{} line {}\n", block_hdr.NameIndex, flags.Start); |
| | 641 | if (has_column) { |
| | 642 | line_index = start_line_index + @sizeOf(LineNumberEntry) * block_hdr.NumLines; |
| | 643 | line_index += @sizeOf(ColumnNumberEntry) * line_i; |
| | 644 | const col_num_entry = @ptrCast(*ColumnNumberEntry, &line_info[line_index]); |
| | 645 | std.debug.warn("col {}\n", col_num_entry.StartColumn); |
| | 646 | } |
| | 647 | return; |
| | 648 | } |
| | 649 | } |
| | 650 | return error.MissingDebugInfo; |
| | 651 | } else { |
| | 652 | line_index += @sizeOf(LineNumberEntry) * block_hdr.NumLines; |
| | 653 | if (has_column) |
| | 654 | line_index += @sizeOf(ColumnNumberEntry) * block_hdr.NumLines; |
| | 655 | } |
| | 656 | |
| | 657 | if (line_index > mod.mod_info.C13ByteSize) |
| | 658 | return error.InvalidDebugInfo; |
| 547 | } | 659 | } |
| 548 | | 660 | |
| 549 | // TODO: locate corresponding source line information | 661 | std.debug.warn("end line info\n"); |
| 550 | } | 662 | } |
| 551 | }; | 663 | }; |
| 552 | | 664 | |