Skip to content

Commit 9b807f9

Browse files
authored
Merge pull request #14247 from kcbanner/windows_improve_module_lookup
Windows debug info lookup improvements
2 parents bb4cb34 + 58e5588 commit 9b807f9

File tree

4 files changed

+208
-159
lines changed

4 files changed

+208
-159
lines changed

lib/std/coff.zig

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,65 +1061,55 @@ pub const CoffError = error{
10611061

10621062
// Official documentation of the format: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
10631063
pub const Coff = struct {
1064-
allocator: mem.Allocator,
1065-
data: []const u8 = undefined,
1066-
is_image: bool = false,
1067-
coff_header_offset: usize = 0,
1064+
data: []const u8,
1065+
is_image: bool,
1066+
coff_header_offset: usize,
10681067

10691068
guid: [16]u8 = undefined,
10701069
age: u32 = undefined,
10711070

1072-
pub fn deinit(self: *Coff) void {
1073-
self.allocator.free(self.data);
1074-
}
1075-
1076-
/// Takes ownership of `data`.
1077-
pub fn parse(self: *Coff, data: []const u8) !void {
1078-
self.data = data;
1079-
1071+
// The lifetime of `data` must be longer than the lifetime of the returned Coff
1072+
pub fn init(data: []const u8) !Coff {
10801073
const pe_pointer_offset = 0x3C;
10811074
const pe_magic = "PE\x00\x00";
10821075

1083-
var stream = std.io.fixedBufferStream(self.data);
1076+
var stream = std.io.fixedBufferStream(data);
10841077
const reader = stream.reader();
10851078
try stream.seekTo(pe_pointer_offset);
1086-
const coff_header_offset = try reader.readIntLittle(u32);
1079+
var coff_header_offset = try reader.readIntLittle(u32);
10871080
try stream.seekTo(coff_header_offset);
10881081
var buf: [4]u8 = undefined;
10891082
try reader.readNoEof(&buf);
1090-
self.is_image = mem.eql(u8, pe_magic, &buf);
1083+
const is_image = mem.eql(u8, pe_magic, &buf);
1084+
1085+
var coff = @This(){
1086+
.data = data,
1087+
.is_image = is_image,
1088+
.coff_header_offset = coff_header_offset,
1089+
};
10911090

10921091
// Do some basic validation upfront
1093-
if (self.is_image) {
1094-
self.coff_header_offset = coff_header_offset + 4;
1095-
const coff_header = self.getCoffHeader();
1092+
if (is_image) {
1093+
coff.coff_header_offset = coff.coff_header_offset + 4;
1094+
const coff_header = coff.getCoffHeader();
10961095
if (coff_header.size_of_optional_header == 0) return error.MissingPEHeader;
10971096
}
10981097

10991098
// JK: we used to check for architecture here and throw an error if not x86 or derivative.
11001099
// However I am willing to take a leap of faith and let aarch64 have a shot also.
1100+
1101+
return coff;
11011102
}
11021103

11031104
pub fn getPdbPath(self: *Coff, buffer: []u8) !usize {
11041105
assert(self.is_image);
11051106

1106-
const header = blk: {
1107-
if (self.getSectionByName(".buildid")) |hdr| {
1108-
break :blk hdr;
1109-
} else if (self.getSectionByName(".rdata")) |hdr| {
1110-
break :blk hdr;
1111-
} else {
1112-
return error.MissingCoffSection;
1113-
}
1114-
};
1115-
11161107
const data_dirs = self.getDataDirectories();
11171108
const debug_dir = data_dirs[@enumToInt(DirectoryEntry.DEBUG)];
1118-
const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data;
11191109

11201110
var stream = std.io.fixedBufferStream(self.data);
11211111
const reader = stream.reader();
1122-
try stream.seekTo(file_offset);
1112+
try stream.seekTo(debug_dir.virtual_address);
11231113

11241114
// Find the correct DebugDirectoryEntry, and where its data is stored.
11251115
// It can be in any section.
@@ -1128,16 +1118,8 @@ pub const Coff = struct {
11281118
blk: while (i < debug_dir_entry_count) : (i += 1) {
11291119
const debug_dir_entry = try reader.readStruct(DebugDirectoryEntry);
11301120
if (debug_dir_entry.type == .CODEVIEW) {
1131-
for (self.getSectionHeaders()) |*section| {
1132-
const section_start = section.virtual_address;
1133-
const section_size = section.virtual_size;
1134-
const rva = debug_dir_entry.address_of_raw_data;
1135-
const offset = rva - section_start;
1136-
if (section_start <= rva and offset < section_size and debug_dir_entry.size_of_data <= section_size - offset) {
1137-
try stream.seekTo(section.pointer_to_raw_data + offset);
1138-
break :blk;
1139-
}
1140-
}
1121+
try stream.seekTo(debug_dir_entry.address_of_raw_data);
1122+
break :blk;
11411123
}
11421124
}
11431125

@@ -1238,6 +1220,16 @@ pub const Coff = struct {
12381220
return @ptrCast([*]align(1) const SectionHeader, self.data.ptr + offset)[0..coff_header.number_of_sections];
12391221
}
12401222

1223+
pub fn getSectionHeadersAlloc(self: *const Coff, allocator: mem.Allocator) ![]SectionHeader {
1224+
const section_headers = self.getSectionHeaders();
1225+
const out_buff = try allocator.alloc(SectionHeader, section_headers.len);
1226+
for (out_buff) |*section_header, i| {
1227+
section_header.* = section_headers[i];
1228+
}
1229+
1230+
return out_buff;
1231+
}
1232+
12411233
pub fn getSectionName(self: *const Coff, sect_hdr: *align(1) const SectionHeader) []const u8 {
12421234
const name = sect_hdr.getName() orelse blk: {
12431235
const strtab = self.getStrtab().?;
@@ -1256,12 +1248,15 @@ pub const Coff = struct {
12561248
return null;
12571249
}
12581250

1251+
pub fn getSectionData(self: *const Coff, comptime name: []const u8) ![]const u8 {
1252+
const sec = self.getSectionByName(name) orelse return error.MissingCoffSection;
1253+
return self.data[sec.pointer_to_raw_data..][0..sec.virtual_size];
1254+
}
1255+
12591256
// Return an owned slice full of the section data
12601257
pub fn getSectionDataAlloc(self: *const Coff, comptime name: []const u8, allocator: mem.Allocator) ![]u8 {
1261-
const sec = self.getSectionByName(name) orelse return error.MissingCoffSection;
1262-
const out_buff = try allocator.alloc(u8, sec.virtual_size);
1263-
mem.copy(u8, out_buff, self.data[sec.pointer_to_raw_data..][0..sec.virtual_size]);
1264-
return out_buff;
1258+
const section_data = try self.getSectionData(name);
1259+
return allocator.dupe(u8, section_data);
12651260
}
12661261
};
12671262

0 commit comments

Comments
 (0)