authorgravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-04-11 02:27:45-07:00
committergravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-04-12 04:01:30-07:00
logcbd7f54f06e788f54573dbbe261b9defad32020b
treece68fd45ba221d90d0bdb51fb0388a763ee4e619
parent334f40576e48e7204455f264c883f9ea86588e1a

Use readers to simplify PDB parsing


1 files changed, 32 insertions(+), 35 deletions(-)

lib/std/debug/Pdb.zig+32-35
...@@ -225,14 +225,13 @@ pub fn parseInfoStream(self: *Pdb) !void {...@@ -225,14 +225,13 @@ pub fn parseInfoStream(self: *Pdb) !void {
225225
226pub fn getProcSym(self: *Pdb, module: *Module, address: u64) ?*align(1) pdb.ProcSym {226pub fn getProcSym(self: *Pdb, module: *Module, address: u64) ?*align(1) pdb.ProcSym {
227 _ = self;227 _ = self;
228
229 std.debug.assert(module.populated);228 std.debug.assert(module.populated);
230229 var reader: Io.Reader = .fixed(module.symbols);
231 var symbol_i: usize = 0;230 while (true) {
232 while (symbol_i != module.symbols.len) {231 const prefix = reader.takeStructPointer(pdb.RecordPrefix) catch return null;
233 const prefix: *align(1) pdb.RecordPrefix = @ptrCast(&module.symbols[symbol_i]);
234 if (prefix.record_len < 2)232 if (prefix.record_len < 2)
235 return null;233 return null;
234 reader.discardAll(prefix.record_len - @sizeOf(u16)) catch return null;
236 switch (prefix.record_kind) {235 switch (prefix.record_kind) {
237 .lproc32, .gproc32 => {236 .lproc32, .gproc32 => {
238 const proc_sym: *align(1) pdb.ProcSym = @ptrCast(prefix);237 const proc_sym: *align(1) pdb.ProcSym = @ptrCast(prefix);
...@@ -242,9 +241,7 @@ pub fn getProcSym(self: *Pdb, module: *Module, address: u64) ?*align(1) pdb.Proc...@@ -242,9 +241,7 @@ pub fn getProcSym(self: *Pdb, module: *Module, address: u64) ?*align(1) pdb.Proc
242 },241 },
243 else => {},242 else => {},
244 }243 }
245 symbol_i += prefix.record_len + @sizeOf(u16);
246 }244 }
247
248 return null;245 return null;
249}246}
250247
...@@ -253,12 +250,17 @@ pub const InlineSiteSymIterator = struct {...@@ -253,12 +250,17 @@ pub const InlineSiteSymIterator = struct {
253 offset: usize,250 offset: usize,
254 end: usize,251 end: usize,
255252
253 const empty: InlineSiteSymIterator = .{
254 .module_index = 0,
255 .offset = 0,
256 .end = 0,
257 };
258
256 pub fn next(iter: *InlineSiteSymIterator, module: *Module) ?*align(1) pdb.InlineSiteSym {259 pub fn next(iter: *InlineSiteSymIterator, module: *Module) ?*align(1) pdb.InlineSiteSym {
257 while (iter.offset < iter.end) {260 while (iter.offset < iter.end) {
258 const inline_prefix: *align(1) pdb.RecordPrefix = @ptrCast(&module.symbols[iter.offset]);261 const inline_prefix: *align(1) pdb.RecordPrefix = @ptrCast(&module.symbols[iter.offset]);
259 if (inline_prefix.record_len < 2)
260 return null;
261 const end = iter.offset + inline_prefix.record_len + @sizeOf(u16);262 const end = iter.offset + inline_prefix.record_len + @sizeOf(u16);
263 if (end > iter.end) return null;
262 defer iter.offset = end;264 defer iter.offset = end;
263 switch (inline_prefix.record_kind) {265 switch (inline_prefix.record_kind) {
264 // Skip nested procedures266 // Skip nested procedures
...@@ -556,7 +558,8 @@ pub fn findInlineeName(self: *const Pdb, inlinee: u32) ?[]const u8 {...@@ -556,7 +558,8 @@ pub fn findInlineeName(self: *const Pdb, inlinee: u32) ?[]const u8 {
556 const header = reader.takeStructPointer(pdb.IpiStreamHeader) catch return null;558 const header = reader.takeStructPointer(pdb.IpiStreamHeader) catch return null;
557 for (header.type_index_begin..header.type_index_end) |curr_type_index| {559 for (header.type_index_begin..header.type_index_end) |curr_type_index| {
558 const prefix = reader.takeStructPointer(pdb.LfRecordPrefix) catch return null;560 const prefix = reader.takeStructPointer(pdb.LfRecordPrefix) catch return null;
559 reader.discardAll(prefix.len - @sizeOf(@FieldType(pdb.LfRecordPrefix, "len"))) catch return null;561 if (prefix.len < 2) return null;
562 reader.discardAll(prefix.len - @sizeOf(u16)) catch return null;
560563
561 if (curr_type_index == type_index) {564 if (curr_type_index == type_index) {
562 switch (prefix.kind) {565 switch (prefix.kind) {
...@@ -580,7 +583,9 @@ pub fn getInlinees(self: *Pdb, module: *Module, proc_sym: *align(1) const pdb.Pr...@@ -580,7 +583,9 @@ pub fn getInlinees(self: *Pdb, module: *Module, proc_sym: *align(1) const pdb.Pr
580 const offset = @intFromPtr(proc_sym) -583 const offset = @intFromPtr(proc_sym) -
581 @intFromPtr(module.symbols.ptr) +584 @intFromPtr(module.symbols.ptr) +
582 proc_sym.record_len +585 proc_sym.record_len +
583 @sizeOf(@FieldType(pdb.ProcSym, "record_len"));586 @sizeOf(u16);
587 const symbols_end = @intFromPtr(module.symbols.ptr) + module.symbols.len;
588 if (offset > symbols_end or proc_sym.end > symbols_end) return .empty;
584 return .{589 return .{
585 .module_index = module_index,590 .module_index = module_index,
586 .offset = offset,591 .offset = offset,
...@@ -588,17 +593,19 @@ pub fn getInlinees(self: *Pdb, module: *Module, proc_sym: *align(1) const pdb.Pr...@@ -588,17 +593,19 @@ pub fn getInlinees(self: *Pdb, module: *Module, proc_sym: *align(1) const pdb.Pr
588 };593 };
589}594}
590595
591pub fn getBinaryAnnotations(self: *Pdb, site: *align(1) const pdb.InlineSiteSym) BinaryAnnotation.Iterator {596pub fn getBinaryAnnotations(self: *Pdb, module: *Module, site: *align(1) const pdb.InlineSiteSym) BinaryAnnotation.Iterator {
592 _ = self;597 _ = self;
593 var start: usize = @intFromPtr(site) + @sizeOf(pdb.InlineSiteSym);598 var start: usize = @intFromPtr(site) + @sizeOf(pdb.InlineSiteSym);
594 var end = start + site.record_len + @sizeOf(@FieldType(pdb.InlineSiteSym, "record_len")) - @sizeOf(pdb.InlineSiteSym);599 var end = start + site.record_len + @sizeOf(u16) - @sizeOf(pdb.InlineSiteSym);
595 switch (site.record_kind) {600 switch (site.record_kind) {
596 .inlinesite => {},601 .inlinesite => {},
597 .inlinesite2 => start += @sizeOf(pdb.InlineSiteSym2) - @sizeOf(pdb.InlineSiteSym),602 .inlinesite2 => start += @sizeOf(pdb.InlineSiteSym2) - @sizeOf(pdb.InlineSiteSym),
598 else => end = start,603 else => end = start,
599 }604 }
605 if (start < @intFromPtr(module.symbols.ptr) or end > @intFromPtr(module.symbols.ptr) + module.symbols.len) return .empty;
606 const len = end - start;
600 const ptr: [*]const u8 = @ptrFromInt(start);607 const ptr: [*]const u8 = @ptrFromInt(start);
601 const slice = ptr[0..end - start];608 const slice = ptr[0..len];
602 return .{ .reader = Io.Reader.fixed(slice) };609 return .{ .reader = Io.Reader.fixed(slice) };
603}610}
604611
...@@ -609,7 +616,7 @@ pub fn getInlineSiteSourceLocation(...@@ -609,7 +616,7 @@ pub fn getInlineSiteSourceLocation(
609 inlinee_src_line: *align(1) const pdb.InlineeSourceLine,616 inlinee_src_line: *align(1) const pdb.InlineeSourceLine,
610 offset_in_func: usize,617 offset_in_func: usize,
611) !?std.debug.SourceLocation {618) !?std.debug.SourceLocation {
612 var ranges: BinaryAnnotation.RangeIterator = .init(self.getBinaryAnnotations(site));619 var ranges: BinaryAnnotation.RangeIterator = .init(self.getBinaryAnnotations(mod, site));
613 while (try ranges.next()) |range| {620 while (try ranges.next()) |range| {
614 if (!range.contains(offset_in_func)) continue;621 if (!range.contains(offset_in_func)) continue;
615622
...@@ -658,36 +665,26 @@ pub fn getInlineeSourceLine(...@@ -658,36 +665,26 @@ pub fn getInlineeSourceLine(
658 inlinee: u32,665 inlinee: u32,
659) ?InlineeSourceLine {666) ?InlineeSourceLine {
660 _ = self;667 _ = self;
661 var sect_offset: usize = 0;668 var subsects: Io.Reader = .fixed(mod.subsect_info);
662 var skip_len: usize = undefined;669 while (subsects.takeStructPointer(pdb.DebugSubsectionHeader) catch null) |subsect_hdr| {
663 while (sect_offset < mod.subsect_info.len) : (sect_offset += skip_len) {670 var subsect: Io.Reader = .fixed(subsects.take(subsect_hdr.length) catch return null);
664 const subsect_hdr: *align(1) pdb.DebugSubsectionHeader = @ptrCast(&mod.subsect_info[sect_offset]);
665 skip_len = subsect_hdr.length;
666 sect_offset += @sizeOf(pdb.DebugSubsectionHeader);
667
668 if (subsect_hdr.kind == .inlinee_lines) {671 if (subsect_hdr.kind == .inlinee_lines) {
669 var offset = sect_offset;672 const signature = subsect.takeEnum(pdb.InlineeSourceLineSignature, .little) catch return null;
670 const signature: *const align(1) pdb.InlineeSourceLineSignature = @ptrCast(&mod.subsect_info[offset]);673 const has_extra_files = switch (signature) {
671 offset += @sizeOf(pdb.InlineeSourceLineSignature);
672
673 const has_extra_files = switch (signature.*) {
674 .normal => false,674 .normal => false,
675 .ex => true,675 .ex => true,
676 else => continue,676 else => continue,
677 };677 };
678678
679 while (offset < sect_offset + subsect_hdr.length) {679 while (subsect.takeStructPointer(pdb.InlineeSourceLine) catch null) |inlinee_src_line| {
680 const inlinee_src_line: *const align(1) pdb.InlineeSourceLine = @ptrCast(&mod.subsect_info[offset]);
681 offset += @sizeOf(pdb.InlineeSourceLine);
682
683 if (has_extra_files) {680 if (has_extra_files) {
684 const file_count: *const align(1) u32 = @ptrCast(&mod.subsect_info[offset]);681 const file_count = subsect.takeInt(u32, .little) catch return null;
685 offset += @sizeOf(u32);682 const file_bytes = std.math.mul(usize, file_count, @sizeOf(u32)) catch return null;
686 offset += file_count.* * @sizeOf(u32);683 subsect.discardAll(file_bytes) catch return null;
687 }684 }
688685
689 if (inlinee_src_line.inlinee == inlinee) return .{686 if (inlinee_src_line.inlinee == inlinee) return .{
690 .signature = signature.*,687 .signature = signature,
691 .info = inlinee_src_line,688 .info = inlinee_src_line,
692 };689 };
693 }690 }