authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-31 15:02:41-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-31 15:02:41-04:00
logb36b93fb3ef3ce96ecc457d0e379740b39d37f80
tree664fababca60a127048bcfa1511af49b33126e24
parent99170aa13db236b47aa8fda4a3d94b49e6b7f93c

awareness of debug subsections


2 files changed, 147 insertions(+), 128 deletions(-)

std/debug/index.zig+28
......@@ -451,6 +451,34 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
451451 std.debug.warn("v {} s {} a {}\n", version, signature, age);
452452 // We validated the executable and pdb match.
453453
454 const name_bytes_len = try pdb_stream.stream.readIntLe(u32);
455 const name_bytes = try allocator.alloc(u8, name_bytes_len);
456 try pdb_stream.stream.readNoEof(name_bytes);
457
458 //const HashTableHeader = packed struct {
459 // Size: u32,
460 // Capacity: u32,
461
462 // fn maxLoad(cap: u32) u32 {
463 // return cap * 2 / 3 + 1;
464 // }
465 //};
466 //var hash_tbl_hdr: HashTableHeader = undefined;
467 //try pdb_stream.stream.readStruct(Header, &hash_tbl_hdr);
468 //if (hash_tbl_hdr.Capacity == 0)
469 // return error.InvalidDebugInfo;
470
471 //if (hash_tbl_hdr.Size > HashTableHeader.maxLoad(hash_tbl_hdr.Capacity))
472 // return error.InvalidDebugInfo;
473
474 //std.debug.warn("{}\n", hash_tbl_hdr);
475
476 //var more_buf: [100]u8 = undefined;
477 //const more_len = try pdb_stream.stream.read(more_buf[0..]);
478 //for (more_buf[0..more_len]) |x| {
479 // std.debug.warn("{x2} {c}\n", x, x);
480 //}
481
454482 return di;
455483}
456484
std/pdb.zig+119-128
......@@ -92,65 +92,6 @@ const Module = struct {
9292 obj_file_name: []u8,
9393};
9494
95/// Distinguishes individual records in the Symbols subsection of a .debug$S
96/// section. Equivalent to SYM_ENUM_e in cvinfo.h.
97pub const SymbolRecordKind = enum(u16) {
98 InlineesSym = 4456,
99 ScopeEndSym = 6,
100 InlineSiteEnd = 4430,
101 ProcEnd = 4431,
102 Thunk32Sym = 4354,
103 TrampolineSym = 4396,
104 SectionSym = 4406,
105 CoffGroupSym = 4407,
106 ExportSym = 4408,
107 ProcSym = 4367,
108 GlobalProcSym = 4368,
109 ProcIdSym = 4422,
110 GlobalProcIdSym = 4423,
111 DPCProcSym = 4437,
112 DPCProcIdSym = 4438,
113 RegisterSym = 4358,
114 PublicSym32 = 4366,
115 ProcRefSym = 4389,
116 LocalProcRef = 4391,
117 EnvBlockSym = 4413,
118 InlineSiteSym = 4429,
119 LocalSym = 4414,
120 DefRangeSym = 4415,
121 DefRangeSubfieldSym = 4416,
122 DefRangeRegisterSym = 4417,
123 DefRangeFramePointerRelSym = 4418,
124 DefRangeSubfieldRegisterSym = 4419,
125 DefRangeFramePointerRelFullScopeSym = 4420,
126 DefRangeRegisterRelSym = 4421,
127 BlockSym = 4355,
128 LabelSym = 4357,
129 ObjNameSym = 4353,
130 Compile2Sym = 4374,
131 Compile3Sym = 4412,
132 FrameProcSym = 4114,
133 CallSiteInfoSym = 4409,
134 FileStaticSym = 4435,
135 HeapAllocationSiteSym = 4446,
136 FrameCookieSym = 4410,
137 CallerSym = 4442,
138 CalleeSym = 4443,
139 UDTSym = 4360,
140 CobolUDT = 4361,
141 BuildInfoSym = 4428,
142 BPRelativeSym = 4363,
143 RegRelativeSym = 4369,
144 ConstantSym = 4359,
145 ManagedConstant = 4397,
146 DataSym = 4364,
147 GlobalData = 4365,
148 ManagedLocalData = 4380,
149 ManagedGlobalData = 4381,
150 ThreadLocalDataSym = 4370,
151 GlobalTLS = 4371,
152};
153
15495/// Duplicate copy of SymbolRecordKind, but using the official CV names. Useful
15596/// for reference purposes and when dealing with unknown record types.
15697pub const SymbolKind = packed enum(u16) {
......@@ -434,6 +375,32 @@ const ColumnNumberEntry = packed struct {
434375 EndColumn: u16,
435376};
436377
378/// Checksum bytes follow.
379const FileChecksumEntryHeader = packed struct {
380 FileNameOffset: u32, /// Byte offset of filename in global string table.
381 ChecksumSize: u8, /// Number of bytes of checksum.
382 ChecksumKind: u8, /// FileChecksumKind
383};
384
385const DebugSubsectionKind = packed enum(u32) {
386 None = 0,
387 Symbols = 0xf1,
388 Lines = 0xf2,
389 StringTable = 0xf3,
390 FileChecksums = 0xf4,
391 FrameData = 0xf5,
392 InlineeLines = 0xf6,
393 CrossScopeImports = 0xf7,
394 CrossScopeExports = 0xf8,
395
396 // These appear to relate to .Net assembly info.
397 ILLines = 0xf9,
398 FuncMDTokenMap = 0xfa,
399 TypeMDTokenMap = 0xfb,
400 MergedAssemblyInput = 0xfc,
401
402 CoffSymbolRVA = 0xfd,
403};
437404
438405pub const Pdb = struct {
439406 in_file: os.File,
......@@ -569,14 +536,17 @@ pub const Pdb = struct {
569536 const prefix = @ptrCast(*RecordPrefix, &symbols[symbol_i]);
570537 if (prefix.RecordLen < 2)
571538 return error.InvalidDebugInfo;
572 if (prefix.RecordKind == SymbolKind.S_LPROC32) {
573 const proc_sym = @ptrCast(*ProcSym, &symbols[symbol_i + @sizeOf(RecordPrefix)]);
574 const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
575 const vaddr_end = vaddr_start + proc_sym.CodeSize;
576 std.debug.warn(" {}\n", proc_sym);
577 if (address >= vaddr_start and address < vaddr_end) {
578 break proc_sym;
579 }
539 switch (prefix.RecordKind) {
540 SymbolKind.S_LPROC32 => {
541 const proc_sym = @ptrCast(*ProcSym, &symbols[symbol_i + @sizeOf(RecordPrefix)]);
542 const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
543 const vaddr_end = vaddr_start + proc_sym.CodeSize;
544 std.debug.warn(" {}\n", proc_sym);
545 if (address >= vaddr_start and address < vaddr_end) {
546 break proc_sym;
547 }
548 },
549 else => {},
580550 }
581551 symbol_i += prefix.RecordLen + @sizeOf(u16);
582552 if (symbol_i > symbols.len)
......@@ -592,73 +562,94 @@ pub const Pdb = struct {
592562 return error.MissingDebugInfo;
593563 }
594564
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);
565 const subsect_info = try self.allocator.alloc(u8, mod.mod_info.C13ByteSize);
566 std.debug.warn("read C13 line info {} bytes\n", subsect_info.len);
567 const line_info_file_pos = modi.getFilePos();
568 try modi.stream.readNoEof(subsect_info);
569
570 const DebugSubsectionHeader = packed struct {
571 Kind: DebugSubsectionKind, /// codeview::DebugSubsectionKind enum
572 Length: u32, /// number of bytes occupied by this record.
573 };
574 var sect_offset: usize = 0;
575 var skip_len: usize = undefined;
576 var have_line_info: bool = false;
577 subsections: while (sect_offset != subsect_info.len) : (sect_offset += skip_len) {
578 const subsect_hdr = @ptrCast(*DebugSubsectionHeader, &subsect_info[sect_offset]);
579 skip_len = subsect_hdr.Length;
580 sect_offset += @sizeOf(DebugSubsectionHeader);
581
582 switch (subsect_hdr.Kind) {
583 DebugSubsectionKind.Lines => {
584 if (have_line_info)
585 continue :subsections;
586
587 var line_index: usize = sect_offset;
588
589 const line_hdr = @ptrCast(*LineFragmentHeader, &subsect_info[line_index]);
590 if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;
591 std.debug.warn("{}\n", line_hdr);
592 line_index += @sizeOf(LineFragmentHeader);
593
594 const block_hdr = @ptrCast(*LineBlockFragmentHeader, &subsect_info[line_index]);
595 std.debug.warn("{}\n", block_hdr);
596 line_index += @sizeOf(LineBlockFragmentHeader);
597
598 const has_column = line_hdr.Flags.LF_HaveColumns;
599 std.debug.warn("has column: {}\n", has_column);
600
601 const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
602 const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
603 if (address >= frag_vaddr_start and address < frag_vaddr_end) {
604 std.debug.warn("found line listing\n");
605 var line_i: usize = 0;
606 const start_line_index = line_index;
607 while (line_i < block_hdr.NumLines) : (line_i += 1) {
608 const line_num_entry = @ptrCast(*LineNumberEntry, &subsect_info[line_index]);
609 line_index += @sizeOf(LineNumberEntry);
610 const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);
611 std.debug.warn("{} {}\n", line_num_entry, flags);
612 const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
613 const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End;
614 std.debug.warn("test {x} <= {x} < {x}\n", vaddr_start, address, vaddr_end);
615 if (address >= vaddr_start and address < vaddr_end) {
616 std.debug.warn("{} line {}\n", block_hdr.NameIndex, flags.Start);
617 if (has_column) {
618 line_index = start_line_index + @sizeOf(LineNumberEntry) * block_hdr.NumLines;
619 line_index += @sizeOf(ColumnNumberEntry) * line_i;
620 const col_num_entry = @ptrCast(*ColumnNumberEntry, &subsect_info[line_index]);
621 std.debug.warn("col {}\n", col_num_entry.StartColumn);
622 }
623 have_line_info = true;
624 continue :subsections;
625 }
646626 }
647 return;
627 return error.MissingDebugInfo;
648628 }
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;
629
630 },
631 DebugSubsectionKind.FileChecksums => {
632 var chksum_index: usize = sect_offset;
633
634 while (chksum_index != subsect_info.len) {
635 const chksum_hdr = @ptrCast(*FileChecksumEntryHeader, &subsect_info[chksum_index]);
636 std.debug.warn("{}\n", chksum_hdr);
637 const len = @sizeOf(FileChecksumEntryHeader) + chksum_hdr.ChecksumSize;
638 chksum_index += len + (len % 4);
639 if (chksum_index > subsect_info.len)
640 return error.InvalidDebugInfo;
641 }
642
643 },
644 else => {
645 std.debug.warn("ignore subsection {}\n", @tagName(subsect_hdr.Kind));
646 },
655647 }
656648
657 if (line_index > mod.mod_info.C13ByteSize)
649 if (sect_offset > subsect_info.len)
658650 return error.InvalidDebugInfo;
659651 }
660
661 std.debug.warn("end line info\n");
652 std.debug.warn("end subsections\n");
662653 }
663654};
664655