aboutsummaryrefslogtreecommitdiff
path: root/lib/std/coff.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-08-16 12:31:22 +0200
committerGitHub <noreply@github.com>2023-08-16 12:31:22 +0200
commit3e228bdf457d8be0fcbb8e44a8fa7a0b09677972 (patch)
tree197f5daa9b9cafadc5b4a047a29f23fea8e1fc6a /lib/std/coff.zig
parent340a45683ca8e0b23e95f5fb86bd9c827970e6e8 (diff)
parent8a5f331ec832201c6e4bdf211cdd37ca5eb4347b (diff)
downloadzig-3e228bdf457d8be0fcbb8e44a8fa7a0b09677972.tar.gz
zig-3e228bdf457d8be0fcbb8e44a8fa7a0b09677972.zip
Merge pull request #16832 from kcbanner/coff_dwarf_and_pdb
Windows: Support loading debug symbols from both the PDB file and embedded DWARF information
Diffstat (limited to 'lib/std/coff.zig')
-rw-r--r--lib/std/coff.zig35
1 files changed, 26 insertions, 9 deletions
diff --git a/lib/std/coff.zig b/lib/std/coff.zig
index c937baa18d..9db9f4d988 100644
--- a/lib/std/coff.zig
+++ b/lib/std/coff.zig
@@ -1059,6 +1059,8 @@ pub const CoffError = error{
// Official documentation of the format: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
pub const Coff = struct {
data: []const u8,
+ // Set if `data` is backed by the image as loaded by the loader
+ is_loaded: bool,
is_image: bool,
coff_header_offset: usize,
@@ -1066,7 +1068,7 @@ pub const Coff = struct {
age: u32 = undefined,
// The lifetime of `data` must be longer than the lifetime of the returned Coff
- pub fn init(data: []const u8) !Coff {
+ pub fn init(data: []const u8, is_loaded: bool) !Coff {
const pe_pointer_offset = 0x3C;
const pe_magic = "PE\x00\x00";
@@ -1082,6 +1084,7 @@ pub const Coff = struct {
var coff = @This(){
.data = data,
.is_image = is_image,
+ .is_loaded = is_loaded,
.coff_header_offset = coff_header_offset,
};
@@ -1098,27 +1101,40 @@ pub const Coff = struct {
return coff;
}
- pub fn getPdbPath(self: *Coff, buffer: []u8) !usize {
+ pub fn getPdbPath(self: *Coff, buffer: []u8) !?usize {
assert(self.is_image);
const data_dirs = self.getDataDirectories();
- const debug_dir = data_dirs[@intFromEnum(DirectoryEntry.DEBUG)];
+ if (@intFromEnum(DirectoryEntry.DEBUG) >= data_dirs.len) return null;
+ const debug_dir = data_dirs[@intFromEnum(DirectoryEntry.DEBUG)];
var stream = std.io.fixedBufferStream(self.data);
const reader = stream.reader();
- try stream.seekTo(debug_dir.virtual_address);
+
+ if (self.is_loaded) {
+ try stream.seekTo(debug_dir.virtual_address);
+ } else {
+ // Find what section the debug_dir is in, in order to convert the RVA to a file offset
+ for (self.getSectionHeaders()) |*sect| {
+ if (debug_dir.virtual_address >= sect.virtual_address and debug_dir.virtual_address < sect.virtual_address + sect.virtual_size) {
+ try stream.seekTo(sect.pointer_to_raw_data + (debug_dir.virtual_address - sect.virtual_address));
+ break;
+ }
+ } else return error.InvalidDebugDirectory;
+ }
// Find the correct DebugDirectoryEntry, and where its data is stored.
// It can be in any section.
const debug_dir_entry_count = debug_dir.size / @sizeOf(DebugDirectoryEntry);
var i: u32 = 0;
- blk: while (i < debug_dir_entry_count) : (i += 1) {
+ while (i < debug_dir_entry_count) : (i += 1) {
const debug_dir_entry = try reader.readStruct(DebugDirectoryEntry);
if (debug_dir_entry.type == .CODEVIEW) {
- try stream.seekTo(debug_dir_entry.address_of_raw_data);
- break :blk;
+ const dir_offset = if (self.is_loaded) debug_dir_entry.address_of_raw_data else debug_dir_entry.pointer_to_raw_data;
+ try stream.seekTo(dir_offset);
+ break;
}
- }
+ } else return null;
var cv_signature: [4]u8 = undefined; // CodeView signature
try reader.readNoEof(cv_signature[0..]);
@@ -1256,7 +1272,8 @@ pub const Coff = struct {
}
pub fn getSectionData(self: *const Coff, sec: *align(1) const SectionHeader) []const u8 {
- return self.data[sec.pointer_to_raw_data..][0..sec.virtual_size];
+ const offset = if (self.is_loaded) sec.virtual_address else sec.pointer_to_raw_data;
+ return self.data[offset..][0..sec.virtual_size];
}
pub fn getSectionDataAlloc(self: *const Coff, sec: *align(1) const SectionHeader, allocator: mem.Allocator) ![]u8 {