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 {...@@ -451,6 +451,34 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
451 std.debug.warn("v {} s {} a {}\n", version, signature, age);451 std.debug.warn("v {} s {} a {}\n", version, signature, age);
452 // We validated the executable and pdb match.452 // 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
454 return di;482 return di;
455}483}
456484
std/pdb.zig+119-128
...@@ -92,65 +92,6 @@ const Module = struct {...@@ -92,65 +92,6 @@ const Module = struct {
92 obj_file_name: []u8,92 obj_file_name: []u8,
93};93};
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
154/// Duplicate copy of SymbolRecordKind, but using the official CV names. Useful95/// Duplicate copy of SymbolRecordKind, but using the official CV names. Useful
155/// for reference purposes and when dealing with unknown record types.96/// for reference purposes and when dealing with unknown record types.
156pub const SymbolKind = packed enum(u16) {97pub const SymbolKind = packed enum(u16) {
...@@ -434,6 +375,32 @@ const ColumnNumberEntry = packed struct {...@@ -434,6 +375,32 @@ const ColumnNumberEntry = packed struct {
434 EndColumn: u16,375 EndColumn: u16,
435};376};
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
438pub const Pdb = struct {405pub const Pdb = struct {
439 in_file: os.File,406 in_file: os.File,
...@@ -569,14 +536,17 @@ pub const Pdb = struct {...@@ -569,14 +536,17 @@ pub const Pdb = struct {
569 const prefix = @ptrCast(*RecordPrefix, &symbols[symbol_i]);536 const prefix = @ptrCast(*RecordPrefix, &symbols[symbol_i]);
570 if (prefix.RecordLen < 2)537 if (prefix.RecordLen < 2)
571 return error.InvalidDebugInfo;538 return error.InvalidDebugInfo;
572 if (prefix.RecordKind == SymbolKind.S_LPROC32) {539 switch (prefix.RecordKind) {
573 const proc_sym = @ptrCast(*ProcSym, &symbols[symbol_i + @sizeOf(RecordPrefix)]);540 SymbolKind.S_LPROC32 => {
574 const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;541 const proc_sym = @ptrCast(*ProcSym, &symbols[symbol_i + @sizeOf(RecordPrefix)]);
575 const vaddr_end = vaddr_start + proc_sym.CodeSize;542 const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
576 std.debug.warn(" {}\n", proc_sym);543 const vaddr_end = vaddr_start + proc_sym.CodeSize;
577 if (address >= vaddr_start and address < vaddr_end) {544 std.debug.warn(" {}\n", proc_sym);
578 break proc_sym;545 if (address >= vaddr_start and address < vaddr_end) {
579 }546 break proc_sym;
547 }
548 },
549 else => {},
580 }550 }
581 symbol_i += prefix.RecordLen + @sizeOf(u16);551 symbol_i += prefix.RecordLen + @sizeOf(u16);
582 if (symbol_i > symbols.len)552 if (symbol_i > symbols.len)
...@@ -592,73 +562,94 @@ pub const Pdb = struct {...@@ -592,73 +562,94 @@ pub const Pdb = struct {
592 return error.MissingDebugInfo;562 return error.MissingDebugInfo;
593 }563 }
594564
595 const line_info = try self.allocator.alloc(u8, mod.mod_info.C13ByteSize);565 const subsect_info = try self.allocator.alloc(u8, mod.mod_info.C13ByteSize);
596 std.debug.warn("read C13 line info {} bytes\n", line_info.len);566 std.debug.warn("read C13 line info {} bytes\n", subsect_info.len);
597 try modi.stream.readNoEof(line_info);567 const line_info_file_pos = modi.getFilePos();
598568 try modi.stream.readNoEof(subsect_info);
599 var line_index: usize = 0;569
600 while (line_index != line_info.len) {570 const DebugSubsectionHeader = packed struct {
601 std.debug.warn("unknown bytes: {x2} {x2} {x2} {x2} {x2} {x2} {x2} {x2}\n",571 Kind: DebugSubsectionKind, /// codeview::DebugSubsectionKind enum
602 line_info[line_index+0],572 Length: u32, /// number of bytes occupied by this record.
603 line_info[line_index+1],573 };
604 line_info[line_index+2],574 var sect_offset: usize = 0;
605 line_info[line_index+3],575 var skip_len: usize = undefined;
606 line_info[line_index+4],576 var have_line_info: bool = false;
607 line_info[line_index+5],577 subsections: while (sect_offset != subsect_info.len) : (sect_offset += skip_len) {
608 line_info[line_index+6],578 const subsect_hdr = @ptrCast(*DebugSubsectionHeader, &subsect_info[sect_offset]);
609 line_info[line_index+7],579 skip_len = subsect_hdr.Length;
610 );580 sect_offset += @sizeOf(DebugSubsectionHeader);
611 line_index += 8;581
612582 switch (subsect_hdr.Kind) {
613 const line_hdr = @ptrCast(*LineFragmentHeader, &line_info[line_index]);583 DebugSubsectionKind.Lines => {
614 if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;584 if (have_line_info)
615 std.debug.warn("{}\n", line_hdr);585 continue :subsections;
616 line_index += @sizeOf(LineFragmentHeader);586
617587 var line_index: usize = sect_offset;
618 const block_hdr = @ptrCast(*LineBlockFragmentHeader, &line_info[line_index]);588
619 std.debug.warn("{}\n", block_hdr);589 const line_hdr = @ptrCast(*LineFragmentHeader, &subsect_info[line_index]);
620 line_index += @sizeOf(LineBlockFragmentHeader);590 if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;
621591 std.debug.warn("{}\n", line_hdr);
622 const has_column = line_hdr.Flags.LF_HaveColumns;592 line_index += @sizeOf(LineFragmentHeader);
623 std.debug.warn("has column: {}\n", has_column);593
624594 const block_hdr = @ptrCast(*LineBlockFragmentHeader, &subsect_info[line_index]);
625 const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;595 std.debug.warn("{}\n", block_hdr);
626 const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;596 line_index += @sizeOf(LineBlockFragmentHeader);
627 if (address >= frag_vaddr_start and address < frag_vaddr_end) {597
628 std.debug.warn("found line listing\n");598 const has_column = line_hdr.Flags.LF_HaveColumns;
629 var line_i: usize = 0;599 std.debug.warn("has column: {}\n", has_column);
630 const start_line_index = line_index;600
631 while (line_i < block_hdr.NumLines) : (line_i += 1) {601 const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
632 const line_num_entry = @ptrCast(*LineNumberEntry, &line_info[line_index]);602 const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
633 line_index += @sizeOf(LineNumberEntry);603 if (address >= frag_vaddr_start and address < frag_vaddr_end) {
634 const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);604 std.debug.warn("found line listing\n");
635 std.debug.warn("{} {}\n", line_num_entry, flags);605 var line_i: usize = 0;
636 const vaddr_start = frag_vaddr_start + line_num_entry.Offset;606 const start_line_index = line_index;
637 const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End;607 while (line_i < block_hdr.NumLines) : (line_i += 1) {
638 std.debug.warn("test {x} <= {x} < {x}\n", vaddr_start, address, vaddr_end);608 const line_num_entry = @ptrCast(*LineNumberEntry, &subsect_info[line_index]);
639 if (address >= vaddr_start and address < vaddr_end) {609 line_index += @sizeOf(LineNumberEntry);
640 std.debug.warn("{} line {}\n", block_hdr.NameIndex, flags.Start);610 const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);
641 if (has_column) {611 std.debug.warn("{} {}\n", line_num_entry, flags);
642 line_index = start_line_index + @sizeOf(LineNumberEntry) * block_hdr.NumLines;612 const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
643 line_index += @sizeOf(ColumnNumberEntry) * line_i;613 const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End;
644 const col_num_entry = @ptrCast(*ColumnNumberEntry, &line_info[line_index]);614 std.debug.warn("test {x} <= {x} < {x}\n", vaddr_start, address, vaddr_end);
645 std.debug.warn("col {}\n", col_num_entry.StartColumn);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 }
646 }626 }
647 return;627 return error.MissingDebugInfo;
648 }628 }
649 }629
650 return error.MissingDebugInfo;630 },
651 } else {631 DebugSubsectionKind.FileChecksums => {
652 line_index += @sizeOf(LineNumberEntry) * block_hdr.NumLines;632 var chksum_index: usize = sect_offset;
653 if (has_column)633
654 line_index += @sizeOf(ColumnNumberEntry) * block_hdr.NumLines;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 },
655 }647 }
656648
657 if (line_index > mod.mod_info.C13ByteSize)649 if (sect_offset > subsect_info.len)
658 return error.InvalidDebugInfo;650 return error.InvalidDebugInfo;
659 }651 }
660652 std.debug.warn("end subsections\n");
661 std.debug.warn("end line info\n");
662 }653 }
663};654};
664655