authorgravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-04-07 13:39:35-07:00
committergravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-04-12 04:01:29-07:00
log781bab193b3ea026d2bd6adf8150bb6510205766
tree4e590e8cec6a082d69c006828581d14bd639324e
parent5c6885be53b0e7d791f13dee32cb945b3f8f0d7d

Iterates inline sites in the correct order


2 files changed, 88 insertions(+), 75 deletions(-)

lib/std/debug/Pdb.zig-6
......@@ -253,12 +253,6 @@ pub const InlineSiteSymIterator = struct {
253253 offset: usize,
254254 end: usize,
255255
256 pub const empty: InlineSiteSymIterator = .{
257 .module_index = 0,
258 .offset = 0,
259 .end = 0,
260 };
261
262256 pub fn next(iter: *InlineSiteSymIterator, module: *Module) ?*align(1) pdb.InlineSiteSym {
263257 while (iter.offset < iter.end) {
264258 const inline_prefix: *align(1) pdb.RecordPrefix = @ptrCast(&module.symbols[iter.offset]);
lib/std/debug/SelfInfo/Windows.zig+88-69
......@@ -33,6 +33,7 @@ pub const SymbolIterator = struct {
3333
3434 pub fn deinit(self: *SymbolIterator, io: Io) void {
3535 if (self.lock) |lock| lock.unlockShared(io);
36 self.symbols.deinit();
3637 self.* = undefined;
3738 }
3839
......@@ -62,11 +63,10 @@ pub const SymbolIterator = struct {
6263 const pdb = if (di.pdb) |*pdb| pdb else unreachable;
6364
6465 // Get the next inlinee if it exists
65 while (info.inlinees.next(info.module)) |site| {
66 const parent: *align(1) const std.pdb.RecordPrefix = @ptrCast(&info.module.symbols[site.parent - @sizeOf(u16) * 2]);
67 if (pdb.getInlineeInfo(info.module, site.inlinee) catch null) |loc| {
68 if (info.proc_sym) |proc_sym| {
69 const offset_in_func = info.addr - proc_sym.code_offset;
66 if (info.proc) |proc| {
67 while (info.inline_sites.pop()) |site| {
68 if (pdb.getInlineeInfo(info.module, site.inlinee) catch null) |loc| {
69 const offset_in_func = info.addr - proc.code_offset;
7070 if (try pdb.calculateOffset(site, loc, offset_in_func)) |offset| {
7171 return .{
7272 .name = pdb.findInlineeName(site.inlinee),
......@@ -81,15 +81,9 @@ pub const SymbolIterator = struct {
8181 // Return the main symbol and end the iterator
8282 defer self.symbols = .none;
8383 return .{
84 .name = if (info.proc_sym) |proc_sym|
85 pdb.getSymbolName(proc_sym)
86 else
87 null,
84 .name = if (info.proc) |proc| pdb.getSymbolName(proc) else null,
8885 .compile_unit_name = fs.path.basename(info.module.obj_file_name),
89 .source_location = pdb.getLineNumberInfo(
90 info.module,
91 info.addr,
92 ) catch null,
86 .source_location = pdb.getLineNumberInfo(info.module, info.addr) catch null,
9387 };
9488 },
9589 .dwarf => |info| {
......@@ -126,7 +120,9 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) SymbolIterator {
126120 errdefer si.lock.unlockShared(io);
127121 const module = si.findModule(gpa, address) catch |err| return .failing(err);
128122 const di = module.getDebugInfo(gpa, io) catch |err| return .failing(err);
129 const symbols = di.getSymbols(address - @intFromPtr(module.entry.DllBase)) catch |err| return .failing(err);
123 const symbols = Module.DebugInfo.Symbols.init(di, address - @intFromPtr(module.entry.DllBase))
124 catch |err| return .failing(err);
125 errdefer comptime unreachable;
130126 return .{
131127 .lock = &si.lock,
132128 .module = module,
......@@ -343,71 +339,94 @@ const Module = struct {
343339 pub const Symbols = union(enum) {
344340 pdb: struct {
345341 module: *Pdb.Module,
346 proc_sym: ?*align(1) const std.pdb.ProcSym,
347 addr: usize,
348 inlinees: Pdb.InlineSiteSymIterator,
349 },
350 dwarf: struct {
342 proc: ?*align(1) const std.pdb.ProcSym,
351343 addr: usize,
344 /// Inline sites are stored in the pdb in reverse order, so we build up a list of up
345 /// front so that our iterator can return them in the correct order without doing an
346 /// n^2 search. We don't try to filter inline sites based on address until the user
347 /// calls `next` as this requires parsing binary annotations, and this is work we
348 /// may be able to elide if the caller chooses to early out before finishing
349 /// iteration, e.g. because they only wanted the topmost call.
350 inline_sites: std.ArrayList(*align(1) const std.pdb.InlineSiteSym),
352351 },
352 dwarf: struct { addr: usize },
353353 none: void,
354 };
355 fn getSymbols(di: *DebugInfo, vaddr: usize) Error!Symbols {
356 pdb: {
357 const pdb = &(di.pdb orelse break :pdb);
358 var coff_section: *align(1) const coff.SectionHeader = undefined;
359 const mod_index = for (pdb.sect_contribs) |sect_contrib| {
360 if (sect_contrib.section > di.coff_section_headers.len) continue;
361 // Remember that SectionContribEntry.Section is 1-based.
362 coff_section = &di.coff_section_headers[sect_contrib.section - 1];
363
364 const vaddr_start = coff_section.virtual_address + sect_contrib.offset;
365 const vaddr_end = vaddr_start + sect_contrib.size;
366 if (vaddr >= vaddr_start and vaddr < vaddr_end) {
367 break sect_contrib.module_index;
354
355 fn init(di: *DebugInfo, vaddr: usize) Error!Symbols {
356 const gpa = std.debug.getDebugInfoAllocator();
357
358 pdb: {
359 const pdb = &(di.pdb orelse break :pdb);
360 var coff_section: *align(1) const coff.SectionHeader = undefined;
361 const mod_index = for (pdb.sect_contribs) |sect_contrib| {
362 if (sect_contrib.section > di.coff_section_headers.len) continue;
363 // Remember that SectionContribEntry.Section is 1-based.
364 coff_section = &di.coff_section_headers[sect_contrib.section - 1];
365
366 const vaddr_start = coff_section.virtual_address + sect_contrib.offset;
367 const vaddr_end = vaddr_start + sect_contrib.size;
368 if (vaddr >= vaddr_start and vaddr < vaddr_end) {
369 break sect_contrib.module_index;
370 }
371 } else {
372 // we have no information to add to the address
373 break :pdb;
374 };
375 const module = pdb.getModule(mod_index) catch |err| switch (err) {
376 error.InvalidDebugInfo,
377 error.MissingDebugInfo,
378 error.OutOfMemory,
379 => |e| return e,
380
381 error.ReadFailed,
382 error.EndOfStream,
383 => return error.InvalidDebugInfo,
384 } orelse {
385 return error.InvalidDebugInfo; // bad module index
386 };
387
388 const addr = vaddr - coff_section.virtual_address;
389 const maybe_proc = pdb.getProcSym(module, addr);
390
391 var inline_sites: std.ArrayList(*align(1) const std.pdb.InlineSiteSym) = .empty;
392 if (maybe_proc) |proc| {
393 var iter = pdb.getInlinees(module, proc);
394 while (iter.next(module)) |inline_site| {
395 try inline_sites.append(gpa, inline_site);
396 }
368397 }
369 } else {
370 // we have no information to add to the address
371 break :pdb;
372 };
373 const module = pdb.getModule(mod_index) catch |err| switch (err) {
374 error.InvalidDebugInfo,
375 error.MissingDebugInfo,
376 error.OutOfMemory,
377 => |e| return e,
378398
379 error.ReadFailed,
380 error.EndOfStream,
381 => return error.InvalidDebugInfo,
382 } orelse {
383 return error.InvalidDebugInfo; // bad module index
384 };
399 return .{ .pdb = .{
400 .module = module,
401 .proc = maybe_proc,
402 .addr = addr,
403 .inline_sites = inline_sites,
404 } };
405 }
385406
386 const addr = vaddr - coff_section.virtual_address;
387 const proc_sym = pdb.getProcSym(module, addr);
388 const inlinees: Pdb.InlineSiteSymIterator = if (proc_sym) |sym|
389 pdb.getInlinees(module, sym)
390 else
391 .empty;
392 return .{ .pdb = .{
393 .module = module,
394 .proc_sym = proc_sym,
395 .addr = addr,
396 .inlinees = inlinees,
397 } };
407 // Dwarf
408 dwarf: {
409 if (di.dwarf == null) break :dwarf;
410 const addr = vaddr + di.coff_image_base;
411 return .{ .dwarf = .{
412 .addr = addr,
413 } };
414 }
415
416 return error.MissingDebugInfo;
398417 }
399418
400 // Dwarf
401 dwarf: {
402 if (di.dwarf == null) break :dwarf;
403 const addr = vaddr + di.coff_image_base;
404 return .{ .dwarf = .{
405 .addr = addr,
406 } };
419 fn deinit(self: *Symbols) void {
420 switch (self.*) {
421 .pdb => |*info| {
422 const gpa = std.debug.getDebugInfoAllocator();
423 info.inline_sites.deinit(gpa);
424 },
425 .dwarf, .none => {},
426 }
407427 }
428 };
408429
409 return error.MissingDebugInfo;
410 }
411430 };
412431
413432 fn deinit(module: *Module, gpa: Allocator, io: Io) void {