mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
Iterates inline sites in the correct order
This commit is contained in:
@@ -253,12 +253,6 @@ pub const InlineSiteSymIterator = struct {
|
||||
offset: usize,
|
||||
end: usize,
|
||||
|
||||
pub const empty: InlineSiteSymIterator = .{
|
||||
.module_index = 0,
|
||||
.offset = 0,
|
||||
.end = 0,
|
||||
};
|
||||
|
||||
pub fn next(iter: *InlineSiteSymIterator, module: *Module) ?*align(1) pdb.InlineSiteSym {
|
||||
while (iter.offset < iter.end) {
|
||||
const inline_prefix: *align(1) pdb.RecordPrefix = @ptrCast(&module.symbols[iter.offset]);
|
||||
|
||||
@@ -33,6 +33,7 @@ pub const SymbolIterator = struct {
|
||||
|
||||
pub fn deinit(self: *SymbolIterator, io: Io) void {
|
||||
if (self.lock) |lock| lock.unlockShared(io);
|
||||
self.symbols.deinit();
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
@@ -62,11 +63,10 @@ pub const SymbolIterator = struct {
|
||||
const pdb = if (di.pdb) |*pdb| pdb else unreachable;
|
||||
|
||||
// Get the next inlinee if it exists
|
||||
while (info.inlinees.next(info.module)) |site| {
|
||||
const parent: *align(1) const std.pdb.RecordPrefix = @ptrCast(&info.module.symbols[site.parent - @sizeOf(u16) * 2]);
|
||||
if (pdb.getInlineeInfo(info.module, site.inlinee) catch null) |loc| {
|
||||
if (info.proc_sym) |proc_sym| {
|
||||
const offset_in_func = info.addr - proc_sym.code_offset;
|
||||
if (info.proc) |proc| {
|
||||
while (info.inline_sites.pop()) |site| {
|
||||
if (pdb.getInlineeInfo(info.module, site.inlinee) catch null) |loc| {
|
||||
const offset_in_func = info.addr - proc.code_offset;
|
||||
if (try pdb.calculateOffset(site, loc, offset_in_func)) |offset| {
|
||||
return .{
|
||||
.name = pdb.findInlineeName(site.inlinee),
|
||||
@@ -81,15 +81,9 @@ pub const SymbolIterator = struct {
|
||||
// Return the main symbol and end the iterator
|
||||
defer self.symbols = .none;
|
||||
return .{
|
||||
.name = if (info.proc_sym) |proc_sym|
|
||||
pdb.getSymbolName(proc_sym)
|
||||
else
|
||||
null,
|
||||
.name = if (info.proc) |proc| pdb.getSymbolName(proc) else null,
|
||||
.compile_unit_name = fs.path.basename(info.module.obj_file_name),
|
||||
.source_location = pdb.getLineNumberInfo(
|
||||
info.module,
|
||||
info.addr,
|
||||
) catch null,
|
||||
.source_location = pdb.getLineNumberInfo(info.module, info.addr) catch null,
|
||||
};
|
||||
},
|
||||
.dwarf => |info| {
|
||||
@@ -126,7 +120,9 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) SymbolIterator {
|
||||
errdefer si.lock.unlockShared(io);
|
||||
const module = si.findModule(gpa, address) catch |err| return .failing(err);
|
||||
const di = module.getDebugInfo(gpa, io) catch |err| return .failing(err);
|
||||
const symbols = di.getSymbols(address - @intFromPtr(module.entry.DllBase)) catch |err| return .failing(err);
|
||||
const symbols = Module.DebugInfo.Symbols.init(di, address - @intFromPtr(module.entry.DllBase))
|
||||
catch |err| return .failing(err);
|
||||
errdefer comptime unreachable;
|
||||
return .{
|
||||
.lock = &si.lock,
|
||||
.module = module,
|
||||
@@ -343,71 +339,94 @@ const Module = struct {
|
||||
pub const Symbols = union(enum) {
|
||||
pdb: struct {
|
||||
module: *Pdb.Module,
|
||||
proc_sym: ?*align(1) const std.pdb.ProcSym,
|
||||
addr: usize,
|
||||
inlinees: Pdb.InlineSiteSymIterator,
|
||||
},
|
||||
dwarf: struct {
|
||||
proc: ?*align(1) const std.pdb.ProcSym,
|
||||
addr: usize,
|
||||
/// Inline sites are stored in the pdb in reverse order, so we build up a list of up
|
||||
/// front so that our iterator can return them in the correct order without doing an
|
||||
/// n^2 search. We don't try to filter inline sites based on address until the user
|
||||
/// calls `next` as this requires parsing binary annotations, and this is work we
|
||||
/// may be able to elide if the caller chooses to early out before finishing
|
||||
/// iteration, e.g. because they only wanted the topmost call.
|
||||
inline_sites: std.ArrayList(*align(1) const std.pdb.InlineSiteSym),
|
||||
},
|
||||
dwarf: struct { addr: usize },
|
||||
none: void,
|
||||
};
|
||||
fn getSymbols(di: *DebugInfo, vaddr: usize) Error!Symbols {
|
||||
pdb: {
|
||||
const pdb = &(di.pdb orelse break :pdb);
|
||||
var coff_section: *align(1) const coff.SectionHeader = undefined;
|
||||
const mod_index = for (pdb.sect_contribs) |sect_contrib| {
|
||||
if (sect_contrib.section > di.coff_section_headers.len) continue;
|
||||
// Remember that SectionContribEntry.Section is 1-based.
|
||||
coff_section = &di.coff_section_headers[sect_contrib.section - 1];
|
||||
|
||||
const vaddr_start = coff_section.virtual_address + sect_contrib.offset;
|
||||
const vaddr_end = vaddr_start + sect_contrib.size;
|
||||
if (vaddr >= vaddr_start and vaddr < vaddr_end) {
|
||||
break sect_contrib.module_index;
|
||||
fn init(di: *DebugInfo, vaddr: usize) Error!Symbols {
|
||||
const gpa = std.debug.getDebugInfoAllocator();
|
||||
|
||||
pdb: {
|
||||
const pdb = &(di.pdb orelse break :pdb);
|
||||
var coff_section: *align(1) const coff.SectionHeader = undefined;
|
||||
const mod_index = for (pdb.sect_contribs) |sect_contrib| {
|
||||
if (sect_contrib.section > di.coff_section_headers.len) continue;
|
||||
// Remember that SectionContribEntry.Section is 1-based.
|
||||
coff_section = &di.coff_section_headers[sect_contrib.section - 1];
|
||||
|
||||
const vaddr_start = coff_section.virtual_address + sect_contrib.offset;
|
||||
const vaddr_end = vaddr_start + sect_contrib.size;
|
||||
if (vaddr >= vaddr_start and vaddr < vaddr_end) {
|
||||
break sect_contrib.module_index;
|
||||
}
|
||||
} else {
|
||||
// we have no information to add to the address
|
||||
break :pdb;
|
||||
};
|
||||
const module = pdb.getModule(mod_index) catch |err| switch (err) {
|
||||
error.InvalidDebugInfo,
|
||||
error.MissingDebugInfo,
|
||||
error.OutOfMemory,
|
||||
=> |e| return e,
|
||||
|
||||
error.ReadFailed,
|
||||
error.EndOfStream,
|
||||
=> return error.InvalidDebugInfo,
|
||||
} orelse {
|
||||
return error.InvalidDebugInfo; // bad module index
|
||||
};
|
||||
|
||||
const addr = vaddr - coff_section.virtual_address;
|
||||
const maybe_proc = pdb.getProcSym(module, addr);
|
||||
|
||||
var inline_sites: std.ArrayList(*align(1) const std.pdb.InlineSiteSym) = .empty;
|
||||
if (maybe_proc) |proc| {
|
||||
var iter = pdb.getInlinees(module, proc);
|
||||
while (iter.next(module)) |inline_site| {
|
||||
try inline_sites.append(gpa, inline_site);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// we have no information to add to the address
|
||||
break :pdb;
|
||||
};
|
||||
const module = pdb.getModule(mod_index) catch |err| switch (err) {
|
||||
error.InvalidDebugInfo,
|
||||
error.MissingDebugInfo,
|
||||
error.OutOfMemory,
|
||||
=> |e| return e,
|
||||
|
||||
error.ReadFailed,
|
||||
error.EndOfStream,
|
||||
=> return error.InvalidDebugInfo,
|
||||
} orelse {
|
||||
return error.InvalidDebugInfo; // bad module index
|
||||
};
|
||||
return .{ .pdb = .{
|
||||
.module = module,
|
||||
.proc = maybe_proc,
|
||||
.addr = addr,
|
||||
.inline_sites = inline_sites,
|
||||
} };
|
||||
}
|
||||
|
||||
const addr = vaddr - coff_section.virtual_address;
|
||||
const proc_sym = pdb.getProcSym(module, addr);
|
||||
const inlinees: Pdb.InlineSiteSymIterator = if (proc_sym) |sym|
|
||||
pdb.getInlinees(module, sym)
|
||||
else
|
||||
.empty;
|
||||
return .{ .pdb = .{
|
||||
.module = module,
|
||||
.proc_sym = proc_sym,
|
||||
.addr = addr,
|
||||
.inlinees = inlinees,
|
||||
} };
|
||||
// Dwarf
|
||||
dwarf: {
|
||||
if (di.dwarf == null) break :dwarf;
|
||||
const addr = vaddr + di.coff_image_base;
|
||||
return .{ .dwarf = .{
|
||||
.addr = addr,
|
||||
} };
|
||||
}
|
||||
|
||||
return error.MissingDebugInfo;
|
||||
}
|
||||
|
||||
// Dwarf
|
||||
dwarf: {
|
||||
if (di.dwarf == null) break :dwarf;
|
||||
const addr = vaddr + di.coff_image_base;
|
||||
return .{ .dwarf = .{
|
||||
.addr = addr,
|
||||
} };
|
||||
fn deinit(self: *Symbols) void {
|
||||
switch (self.*) {
|
||||
.pdb => |*info| {
|
||||
const gpa = std.debug.getDebugInfoAllocator();
|
||||
info.inline_sites.deinit(gpa);
|
||||
},
|
||||
.dwarf, .none => {},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return error.MissingDebugInfo;
|
||||
}
|
||||
};
|
||||
|
||||
fn deinit(module: *Module, gpa: Allocator, io: Io) void {
|
||||
|
||||
Reference in New Issue
Block a user