| ... | ... | @@ -365,7 +365,8 @@ const ProcSym = packed struct { |
| 365 | 365 | CodeOffset: u32, |
| 366 | 366 | Segment: u16, |
| 367 | 367 | Flags: ProcSymFlags, |
| 368 | | Name: u8, |
| 368 | // following is a null terminated string |
| 369 | // Name: [*]u8, |
| 369 | 370 | }; |
| 370 | 371 | |
| 371 | 372 | const ProcSymFlags = packed struct { |
| ... | ... | @@ -389,6 +390,51 @@ const RecordPrefix = packed struct { |
| 389 | 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 | 438 | pub const Pdb = struct { |
| 393 | 439 | in_file: os.File, |
| 394 | 440 | allocator: *mem.Allocator, |
| ... | ... | @@ -537,16 +583,82 @@ pub const Pdb = struct { |
| 537 | 583 | return error.InvalidDebugInfo; |
| 538 | 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 | 588 | if (mod.mod_info.C11ByteSize != 0) |
| 543 | 589 | return error.InvalidDebugInfo; |
| 544 | 590 | |
| 545 | | if (mod.mod_info.C13ByteSize != 0) { |
| 546 | | std.debug.warn("read C13 line info\n"); |
| 591 | if (mod.mod_info.C13ByteSize == 0) { |
| 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 | |