@@ -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
10631063pub 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