Commit b36b93fb3e

Andrew Kelley <superjoe30@gmail.com>
2018-08-31 21:02:41
awareness of debug subsections
1 parent 99170aa
Changed files (2)
std/debug/index.zig
@@ -451,6 +451,34 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
     std.debug.warn("v {} s {} a {}\n", version, signature, age);
     // We validated the executable and pdb match.
 
+    const name_bytes_len = try pdb_stream.stream.readIntLe(u32);
+    const name_bytes = try allocator.alloc(u8, name_bytes_len);
+    try pdb_stream.stream.readNoEof(name_bytes);
+
+    //const HashTableHeader = packed struct {
+    //    Size: u32,
+    //    Capacity: u32,
+
+    //    fn maxLoad(cap: u32) u32 {
+    //        return cap * 2 / 3 + 1;
+    //    }
+    //};
+    //var hash_tbl_hdr: HashTableHeader = undefined;
+    //try pdb_stream.stream.readStruct(Header, &hash_tbl_hdr);
+    //if (hash_tbl_hdr.Capacity == 0)
+    //    return error.InvalidDebugInfo;
+
+    //if (hash_tbl_hdr.Size > HashTableHeader.maxLoad(hash_tbl_hdr.Capacity))
+    //    return error.InvalidDebugInfo;
+
+    //std.debug.warn("{}\n", hash_tbl_hdr);
+
+    //var more_buf: [100]u8 = undefined;
+    //const more_len = try pdb_stream.stream.read(more_buf[0..]);
+    //for (more_buf[0..more_len]) |x| {
+    //    std.debug.warn("{x2} {c}\n", x, x);
+    //}
+
     return di;
 }
 
std/pdb.zig
@@ -92,65 +92,6 @@ const Module = struct {
     obj_file_name: []u8,
 };
 
-/// Distinguishes individual records in the Symbols subsection of a .debug$S
-/// section. Equivalent to SYM_ENUM_e in cvinfo.h.
-pub const SymbolRecordKind = enum(u16) {
-    InlineesSym = 4456,
-    ScopeEndSym = 6,
-    InlineSiteEnd = 4430,
-    ProcEnd = 4431,
-    Thunk32Sym = 4354,
-    TrampolineSym = 4396,
-    SectionSym = 4406,
-    CoffGroupSym = 4407,
-    ExportSym = 4408,
-    ProcSym = 4367,
-    GlobalProcSym = 4368,
-    ProcIdSym = 4422,
-    GlobalProcIdSym = 4423,
-    DPCProcSym = 4437,
-    DPCProcIdSym = 4438,
-    RegisterSym = 4358,
-    PublicSym32 = 4366,
-    ProcRefSym = 4389,
-    LocalProcRef = 4391,
-    EnvBlockSym = 4413,
-    InlineSiteSym = 4429,
-    LocalSym = 4414,
-    DefRangeSym = 4415,
-    DefRangeSubfieldSym = 4416,
-    DefRangeRegisterSym = 4417,
-    DefRangeFramePointerRelSym = 4418,
-    DefRangeSubfieldRegisterSym = 4419,
-    DefRangeFramePointerRelFullScopeSym = 4420,
-    DefRangeRegisterRelSym = 4421,
-    BlockSym = 4355,
-    LabelSym = 4357,
-    ObjNameSym = 4353,
-    Compile2Sym = 4374,
-    Compile3Sym = 4412,
-    FrameProcSym = 4114,
-    CallSiteInfoSym = 4409,
-    FileStaticSym = 4435,
-    HeapAllocationSiteSym = 4446,
-    FrameCookieSym = 4410,
-    CallerSym = 4442,
-    CalleeSym = 4443,
-    UDTSym = 4360,
-    CobolUDT = 4361,
-    BuildInfoSym = 4428,
-    BPRelativeSym = 4363,
-    RegRelativeSym = 4369,
-    ConstantSym = 4359,
-    ManagedConstant = 4397,
-    DataSym = 4364,
-    GlobalData = 4365,
-    ManagedLocalData = 4380,
-    ManagedGlobalData = 4381,
-    ThreadLocalDataSym = 4370,
-    GlobalTLS = 4371,
-};
-
 /// Duplicate copy of SymbolRecordKind, but using the official CV names. Useful
 /// for reference purposes and when dealing with unknown record types.
 pub const SymbolKind = packed enum(u16) {
@@ -434,6 +375,32 @@ const ColumnNumberEntry = packed struct {
     EndColumn: u16,
 };
 
+/// Checksum bytes follow.
+const FileChecksumEntryHeader = packed struct {
+    FileNameOffset: u32, /// Byte offset of filename in global string table.
+    ChecksumSize: u8, /// Number of bytes of checksum.
+    ChecksumKind: u8, /// FileChecksumKind
+};
+
+const DebugSubsectionKind = packed enum(u32) {
+  None = 0,
+  Symbols = 0xf1,
+  Lines = 0xf2,
+  StringTable = 0xf3,
+  FileChecksums = 0xf4,
+  FrameData = 0xf5,
+  InlineeLines = 0xf6,
+  CrossScopeImports = 0xf7,
+  CrossScopeExports = 0xf8,
+
+  // These appear to relate to .Net assembly info.
+  ILLines = 0xf9,
+  FuncMDTokenMap = 0xfa,
+  TypeMDTokenMap = 0xfb,
+  MergedAssemblyInput = 0xfc,
+
+  CoffSymbolRVA = 0xfd,
+};
 
 pub const Pdb = struct {
     in_file: os.File,
@@ -569,14 +536,17 @@ pub const Pdb = struct {
             const prefix = @ptrCast(*RecordPrefix, &symbols[symbol_i]);
             if (prefix.RecordLen < 2)
                 return error.InvalidDebugInfo;
-            if (prefix.RecordKind == SymbolKind.S_LPROC32) {
-                const proc_sym = @ptrCast(*ProcSym, &symbols[symbol_i + @sizeOf(RecordPrefix)]);
-                const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
-                const vaddr_end = vaddr_start + proc_sym.CodeSize;
-                std.debug.warn("  {}\n", proc_sym);
-                if (address >= vaddr_start and address < vaddr_end) {
-                    break proc_sym;
-                }
+            switch (prefix.RecordKind) {
+                SymbolKind.S_LPROC32 => {
+                    const proc_sym = @ptrCast(*ProcSym, &symbols[symbol_i + @sizeOf(RecordPrefix)]);
+                    const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
+                    const vaddr_end = vaddr_start + proc_sym.CodeSize;
+                    std.debug.warn("  {}\n", proc_sym);
+                    if (address >= vaddr_start and address < vaddr_end) {
+                        break proc_sym;
+                    }
+                },
+                else => {},
             }
             symbol_i += prefix.RecordLen + @sizeOf(u16);
             if (symbol_i > symbols.len)
@@ -592,73 +562,94 @@ pub const Pdb = struct {
             return error.MissingDebugInfo;
         }
 
-        const line_info = try self.allocator.alloc(u8, mod.mod_info.C13ByteSize);
-        std.debug.warn("read C13 line info {} bytes\n", line_info.len);
-        try modi.stream.readNoEof(line_info);
-
-        var line_index: usize = 0;
-        while (line_index != line_info.len) {
-            std.debug.warn("unknown bytes: {x2} {x2} {x2} {x2}  {x2} {x2} {x2} {x2}\n",
-                line_info[line_index+0],
-                line_info[line_index+1],
-                line_info[line_index+2],
-                line_info[line_index+3],
-                line_info[line_index+4],
-                line_info[line_index+5],
-                line_info[line_index+6],
-                line_info[line_index+7],
-            );
-            line_index += 8;
-
-            const line_hdr = @ptrCast(*LineFragmentHeader, &line_info[line_index]);
-            if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;
-            std.debug.warn("{}\n", line_hdr);
-            line_index += @sizeOf(LineFragmentHeader);
-
-            const block_hdr = @ptrCast(*LineBlockFragmentHeader, &line_info[line_index]);
-            std.debug.warn("{}\n", block_hdr);
-            line_index += @sizeOf(LineBlockFragmentHeader);
-
-            const has_column = line_hdr.Flags.LF_HaveColumns;
-            std.debug.warn("has column: {}\n", has_column);
-
-            const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
-            const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
-            if (address >= frag_vaddr_start and address < frag_vaddr_end) {
-                std.debug.warn("found line listing\n");
-                var line_i: usize = 0;
-                const start_line_index = line_index;
-                while (line_i < block_hdr.NumLines) : (line_i += 1) {
-                    const line_num_entry = @ptrCast(*LineNumberEntry, &line_info[line_index]);
-                    line_index += @sizeOf(LineNumberEntry);
-                    const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);
-                    std.debug.warn("{} {}\n", line_num_entry, flags);
-                    const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
-                    const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End;
-                    std.debug.warn("test {x} <= {x} < {x}\n", vaddr_start, address, vaddr_end);
-                    if (address >= vaddr_start and address < vaddr_end) {
-                        std.debug.warn("{} line {}\n", block_hdr.NameIndex, flags.Start);
-                        if (has_column) {
-                            line_index = start_line_index + @sizeOf(LineNumberEntry) * block_hdr.NumLines;
-                            line_index += @sizeOf(ColumnNumberEntry) * line_i;
-                            const col_num_entry = @ptrCast(*ColumnNumberEntry, &line_info[line_index]);
-                            std.debug.warn("col {}\n", col_num_entry.StartColumn);
+        const subsect_info = try self.allocator.alloc(u8, mod.mod_info.C13ByteSize);
+        std.debug.warn("read C13 line info {} bytes\n", subsect_info.len);
+        const line_info_file_pos = modi.getFilePos();
+        try modi.stream.readNoEof(subsect_info);
+
+        const DebugSubsectionHeader = packed struct {
+            Kind: DebugSubsectionKind, /// codeview::DebugSubsectionKind enum
+            Length: u32, /// number of bytes occupied by this record.
+        };
+        var sect_offset: usize = 0;
+        var skip_len: usize = undefined;
+        var have_line_info: bool = false;
+        subsections: while (sect_offset != subsect_info.len) : (sect_offset += skip_len) {
+            const subsect_hdr = @ptrCast(*DebugSubsectionHeader, &subsect_info[sect_offset]);
+            skip_len = subsect_hdr.Length;
+            sect_offset += @sizeOf(DebugSubsectionHeader);
+
+            switch (subsect_hdr.Kind) {
+                DebugSubsectionKind.Lines => {
+                    if (have_line_info)
+                        continue :subsections;
+
+                    var line_index: usize = sect_offset;
+
+                    const line_hdr = @ptrCast(*LineFragmentHeader, &subsect_info[line_index]);
+                    if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;
+                    std.debug.warn("{}\n", line_hdr);
+                    line_index += @sizeOf(LineFragmentHeader);
+
+                    const block_hdr = @ptrCast(*LineBlockFragmentHeader, &subsect_info[line_index]);
+                    std.debug.warn("{}\n", block_hdr);
+                    line_index += @sizeOf(LineBlockFragmentHeader);
+
+                    const has_column = line_hdr.Flags.LF_HaveColumns;
+                    std.debug.warn("has column: {}\n", has_column);
+
+                    const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
+                    const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
+                    if (address >= frag_vaddr_start and address < frag_vaddr_end) {
+                        std.debug.warn("found line listing\n");
+                        var line_i: usize = 0;
+                        const start_line_index = line_index;
+                        while (line_i < block_hdr.NumLines) : (line_i += 1) {
+                            const line_num_entry = @ptrCast(*LineNumberEntry, &subsect_info[line_index]);
+                            line_index += @sizeOf(LineNumberEntry);
+                            const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);
+                            std.debug.warn("{} {}\n", line_num_entry, flags);
+                            const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
+                            const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End;
+                            std.debug.warn("test {x} <= {x} < {x}\n", vaddr_start, address, vaddr_end);
+                            if (address >= vaddr_start and address < vaddr_end) {
+                                std.debug.warn("{} line {}\n", block_hdr.NameIndex, flags.Start);
+                                if (has_column) {
+                                    line_index = start_line_index + @sizeOf(LineNumberEntry) * block_hdr.NumLines;
+                                    line_index += @sizeOf(ColumnNumberEntry) * line_i;
+                                    const col_num_entry = @ptrCast(*ColumnNumberEntry, &subsect_info[line_index]);
+                                    std.debug.warn("col {}\n", col_num_entry.StartColumn);
+                                }
+                                have_line_info = true;
+                                continue :subsections;
+                            }
                         }
-                        return;
+                        return error.MissingDebugInfo;
                     }
-                }
-                return error.MissingDebugInfo;
-            } else {
-                line_index += @sizeOf(LineNumberEntry) * block_hdr.NumLines;
-                if (has_column)
-                    line_index += @sizeOf(ColumnNumberEntry) * block_hdr.NumLines;
+
+                },
+                DebugSubsectionKind.FileChecksums => {
+                    var chksum_index: usize = sect_offset;
+
+                    while (chksum_index != subsect_info.len) {
+                        const chksum_hdr = @ptrCast(*FileChecksumEntryHeader, &subsect_info[chksum_index]);
+                        std.debug.warn("{}\n", chksum_hdr);
+                        const len = @sizeOf(FileChecksumEntryHeader) + chksum_hdr.ChecksumSize;
+                        chksum_index += len + (len % 4);
+                        if (chksum_index > subsect_info.len)
+                            return error.InvalidDebugInfo;
+                    }
+
+                },
+                else => {
+                    std.debug.warn("ignore subsection {}\n", @tagName(subsect_hdr.Kind));
+                },
             }
 
-            if (line_index > mod.mod_info.C13ByteSize)
+            if (sect_offset > subsect_info.len)
                 return error.InvalidDebugInfo;
         }
-
-        std.debug.warn("end line info\n");
+        std.debug.warn("end subsections\n");
     }
 };