mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 03:03:09 +00:00
debug: fix resource (de)allocation for Elf and Coff targets
With this change, it is now possible to safely call `var di = std.debug.openSelfDebugInfo(gpa)`. Calling then `di.deinit()` on the object will correctly free all allocated resources. Ensure we store the result of `mmap` with correct alignment.
This commit is contained in:
parent
96c1314443
commit
28ca203b71
@ -4,8 +4,6 @@ const mem = std.mem;
|
|||||||
const os = std.os;
|
const os = std.os;
|
||||||
const File = std.fs.File;
|
const File = std.fs.File;
|
||||||
|
|
||||||
const ArrayList = std.ArrayList;
|
|
||||||
|
|
||||||
// CoffHeader.machine values
|
// CoffHeader.machine values
|
||||||
// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313(v=vs.85).aspx
|
// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313(v=vs.85).aspx
|
||||||
const IMAGE_FILE_MACHINE_I386 = 0x014c;
|
const IMAGE_FILE_MACHINE_I386 = 0x014c;
|
||||||
@ -117,7 +115,7 @@ pub const Coff = struct {
|
|||||||
|
|
||||||
coff_header: CoffHeader,
|
coff_header: CoffHeader,
|
||||||
pe_header: OptionalHeader,
|
pe_header: OptionalHeader,
|
||||||
sections: ArrayList(Section),
|
sections: std.ArrayListUnmanaged(Section) = .{},
|
||||||
|
|
||||||
guid: [16]u8,
|
guid: [16]u8,
|
||||||
age: u32,
|
age: u32,
|
||||||
@ -128,12 +126,15 @@ pub const Coff = struct {
|
|||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.coff_header = undefined,
|
.coff_header = undefined,
|
||||||
.pe_header = undefined,
|
.pe_header = undefined,
|
||||||
.sections = ArrayList(Section).init(allocator),
|
|
||||||
.guid = undefined,
|
.guid = undefined,
|
||||||
.age = undefined,
|
.age = undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Coff) void {
|
||||||
|
self.sections.deinit(self.allocator);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn loadHeader(self: *Coff) !void {
|
pub fn loadHeader(self: *Coff) !void {
|
||||||
const pe_pointer_offset = 0x3C;
|
const pe_pointer_offset = 0x3C;
|
||||||
|
|
||||||
@ -291,7 +292,7 @@ pub const Coff = struct {
|
|||||||
if (self.sections.items.len == self.coff_header.number_of_sections)
|
if (self.sections.items.len == self.coff_header.number_of_sections)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try self.sections.ensureTotalCapacityPrecise(self.coff_header.number_of_sections);
|
try self.sections.ensureTotalCapacityPrecise(self.allocator, self.coff_header.number_of_sections);
|
||||||
|
|
||||||
const in = self.in_file.reader();
|
const in = self.in_file.reader();
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ pub const SymbolInfo = struct {
|
|||||||
compile_unit_name: []const u8 = "???",
|
compile_unit_name: []const u8 = "???",
|
||||||
line_info: ?LineInfo = null,
|
line_info: ?LineInfo = null,
|
||||||
|
|
||||||
pub fn deinit(self: @This(), allocator: mem.Allocator) void {
|
pub fn deinit(self: SymbolInfo, allocator: mem.Allocator) void {
|
||||||
if (self.line_info) |li| {
|
if (self.line_info) |li| {
|
||||||
li.deinit(allocator);
|
li.deinit(allocator);
|
||||||
}
|
}
|
||||||
@ -50,6 +50,13 @@ pub const SymbolInfo = struct {
|
|||||||
const PdbOrDwarf = union(enum) {
|
const PdbOrDwarf = union(enum) {
|
||||||
pdb: pdb.Pdb,
|
pdb: pdb.Pdb,
|
||||||
dwarf: DW.DwarfInfo,
|
dwarf: DW.DwarfInfo,
|
||||||
|
|
||||||
|
fn deinit(self: *PdbOrDwarf, allocator: mem.Allocator) void {
|
||||||
|
switch (self.*) {
|
||||||
|
.pdb => |*inner| inner.deinit(),
|
||||||
|
.dwarf => |*inner| inner.deinit(allocator),
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var stderr_mutex = std.Thread.Mutex{};
|
var stderr_mutex = std.Thread.Mutex{};
|
||||||
@ -793,6 +800,7 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo
|
|||||||
errdefer coff_file.close();
|
errdefer coff_file.close();
|
||||||
|
|
||||||
const coff_obj = try allocator.create(coff.Coff);
|
const coff_obj = try allocator.create(coff.Coff);
|
||||||
|
errdefer allocator.destroy(coff_obj);
|
||||||
coff_obj.* = coff.Coff.init(allocator, coff_file);
|
coff_obj.* = coff.Coff.init(allocator, coff_file);
|
||||||
|
|
||||||
var di = ModuleDebugInfo{
|
var di = ModuleDebugInfo{
|
||||||
@ -1386,7 +1394,7 @@ pub const DebugInfo = struct {
|
|||||||
pub const ModuleDebugInfo = switch (native_os) {
|
pub const ModuleDebugInfo = switch (native_os) {
|
||||||
.macos, .ios, .watchos, .tvos => struct {
|
.macos, .ios, .watchos, .tvos => struct {
|
||||||
base_address: usize,
|
base_address: usize,
|
||||||
mapped_memory: []const u8,
|
mapped_memory: []align(mem.page_size) const u8,
|
||||||
symbols: []const MachoSymbol,
|
symbols: []const MachoSymbol,
|
||||||
strings: [:0]const u8,
|
strings: [:0]const u8,
|
||||||
ofiles: OFileTable,
|
ofiles: OFileTable,
|
||||||
@ -1406,6 +1414,7 @@ pub const ModuleDebugInfo = switch (native_os) {
|
|||||||
}
|
}
|
||||||
self.ofiles.deinit();
|
self.ofiles.deinit();
|
||||||
allocator.free(self.symbols);
|
allocator.free(self.symbols);
|
||||||
|
os.munmap(self.mapped_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !OFileInfo {
|
fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !OFileInfo {
|
||||||
@ -1609,18 +1618,20 @@ pub const ModuleDebugInfo = switch (native_os) {
|
|||||||
debug_data: PdbOrDwarf,
|
debug_data: PdbOrDwarf,
|
||||||
coff: *coff.Coff,
|
coff: *coff.Coff,
|
||||||
|
|
||||||
pub fn allocator(self: @This()) mem.Allocator {
|
fn deinit(self: *@This(), allocator: mem.Allocator) void {
|
||||||
return self.coff.allocator;
|
self.debug_data.deinit(allocator);
|
||||||
|
self.coff.deinit();
|
||||||
|
allocator.destroy(self.coff);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo {
|
pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo {
|
||||||
// Translate the VA into an address into this object
|
// Translate the VA into an address into this object
|
||||||
const relocated_address = address - self.base_address;
|
const relocated_address = address - self.base_address;
|
||||||
|
|
||||||
switch (self.debug_data) {
|
switch (self.debug_data) {
|
||||||
.dwarf => |*dwarf| {
|
.dwarf => |*dwarf| {
|
||||||
const dwarf_address = relocated_address + self.coff.pe_header.image_base;
|
const dwarf_address = relocated_address + self.coff.pe_header.image_base;
|
||||||
return getSymbolFromDwarf(dwarf_address, dwarf);
|
return getSymbolFromDwarf(allocator, dwarf_address, dwarf);
|
||||||
},
|
},
|
||||||
.pdb => {
|
.pdb => {
|
||||||
// fallthrough to pdb handling
|
// fallthrough to pdb handling
|
||||||
@ -1666,17 +1677,28 @@ pub const ModuleDebugInfo = switch (native_os) {
|
|||||||
.linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris => struct {
|
.linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris => struct {
|
||||||
base_address: usize,
|
base_address: usize,
|
||||||
dwarf: DW.DwarfInfo,
|
dwarf: DW.DwarfInfo,
|
||||||
mapped_memory: []const u8,
|
mapped_memory: []align(mem.page_size) const u8,
|
||||||
|
|
||||||
pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo {
|
fn deinit(self: *@This(), allocator: mem.Allocator) void {
|
||||||
|
self.dwarf.deinit(allocator);
|
||||||
|
os.munmap(self.mapped_memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo {
|
||||||
// Translate the VA into an address into this object
|
// Translate the VA into an address into this object
|
||||||
const relocated_address = address - self.base_address;
|
const relocated_address = address - self.base_address;
|
||||||
return getSymbolFromDwarf(relocated_address, &self.dwarf);
|
return getSymbolFromDwarf(allocator, relocated_address, &self.dwarf);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.wasi => struct {
|
.wasi => struct {
|
||||||
pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo {
|
fn deinit(self: *@This(), allocator: mem.Allocator) void {
|
||||||
_ = self;
|
_ = self;
|
||||||
|
_ = allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo {
|
||||||
|
_ = self;
|
||||||
|
_ = allocator;
|
||||||
_ = address;
|
_ = address;
|
||||||
return SymbolInfo{};
|
return SymbolInfo{};
|
||||||
}
|
}
|
||||||
@ -1684,14 +1706,14 @@ pub const ModuleDebugInfo = switch (native_os) {
|
|||||||
else => DW.DwarfInfo,
|
else => DW.DwarfInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getSymbolFromDwarf(address: u64, di: *DW.DwarfInfo) !SymbolInfo {
|
fn getSymbolFromDwarf(allocator: mem.Allocator, address: u64, di: *DW.DwarfInfo) !SymbolInfo {
|
||||||
if (nosuspend di.findCompileUnit(address)) |compile_unit| {
|
if (nosuspend di.findCompileUnit(address)) |compile_unit| {
|
||||||
return SymbolInfo{
|
return SymbolInfo{
|
||||||
.symbol_name = nosuspend di.getSymbolName(address) orelse "???",
|
.symbol_name = nosuspend di.getSymbolName(address) orelse "???",
|
||||||
.compile_unit_name = compile_unit.die.getAttrString(di, DW.AT.name) catch |err| switch (err) {
|
.compile_unit_name = compile_unit.die.getAttrString(di, DW.AT.name) catch |err| switch (err) {
|
||||||
error.MissingDebugInfo, error.InvalidDebugInfo => "???",
|
error.MissingDebugInfo, error.InvalidDebugInfo => "???",
|
||||||
},
|
},
|
||||||
.line_info = nosuspend di.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) {
|
.line_info = nosuspend di.getLineNumberInfo(allocator, compile_unit.*, address) catch |err| switch (err) {
|
||||||
error.MissingDebugInfo, error.InvalidDebugInfo => null,
|
error.MissingDebugInfo, error.InvalidDebugInfo => null,
|
||||||
else => return err,
|
else => return err,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -764,7 +764,6 @@ pub const Pdb = struct {
|
|||||||
const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);
|
const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);
|
||||||
|
|
||||||
return debug.LineInfo{
|
return debug.LineInfo{
|
||||||
.allocator = self.allocator,
|
|
||||||
.file_name = source_file_name,
|
.file_name = source_file_name,
|
||||||
.line = flags.Start,
|
.line = flags.Start,
|
||||||
.column = column,
|
.column = column,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user