| author | |
| committer | |
| log | 8a6de78e0787015153707361a58659834d4c39c2 |
| tree | 18fb97ac91195813754f80506807db4a22923baa |
| parent | e13a182990c638bb69cd04e253ad6e0ecd734407 |
| parent | 24b1a0027fc663cbb648c265ba19067b108d0dcb |
| signature |
Dwarf on windows4 files changed, 156 insertions(+), 51 deletions(-)
lib/std/Progress.zig+15-5| ... | @@ -22,6 +22,10 @@ const Progress = @This(); | ... | @@ -22,6 +22,10 @@ const Progress = @This(); |
| 22 | /// not print on update() | 22 | /// not print on update() |
| 23 | terminal: ?std.fs.File = undefined, | 23 | terminal: ?std.fs.File = undefined, |
| 24 | 24 | ||
| 25 | /// Is this a windows API terminal (note: this is not the same as being run on windows | ||
| 26 | /// because other terminals exist like MSYS/git-bash) | ||
| 27 | is_windows_terminal: bool = false, | ||
| 28 | |||
| 25 | /// Whether the terminal supports ANSI escape codes. | 29 | /// Whether the terminal supports ANSI escape codes. |
| 26 | supports_ansi_escape_codes: bool = false, | 30 | supports_ansi_escape_codes: bool = false, |
| 27 | 31 | ||
| ... | @@ -143,6 +147,7 @@ pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !* | ... | @@ -143,6 +147,7 @@ pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !* |
| 143 | self.terminal = stderr; | 147 | self.terminal = stderr; |
| 144 | self.supports_ansi_escape_codes = true; | 148 | self.supports_ansi_escape_codes = true; |
| 145 | } else if (std.builtin.os.tag == .windows and stderr.isTty()) { | 149 | } else if (std.builtin.os.tag == .windows and stderr.isTty()) { |
| 150 | self.is_windows_terminal = true; | ||
| 146 | self.terminal = stderr; | 151 | self.terminal = stderr; |
| 147 | } else if (std.builtin.os.tag != .windows) { | 152 | } else if (std.builtin.os.tag != .windows) { |
| 148 | // we are in a "dumb" terminal like in acme or writing to a file | 153 | // we are in a "dumb" terminal like in acme or writing to a file |
| ... | @@ -192,8 +197,9 @@ const DECRC = "\x1b8"; | ... | @@ -192,8 +197,9 @@ const DECRC = "\x1b8"; |
| 192 | // supported by some terminals (eg. Terminal.app). | 197 | // supported by some terminals (eg. Terminal.app). |
| 193 | 198 | ||
| 194 | fn refreshWithHeldLock(self: *Progress) void { | 199 | fn refreshWithHeldLock(self: *Progress) void { |
| 195 | const is_dumb = !self.supports_ansi_escape_codes and !(std.builtin.os.tag == .windows); | 200 | const is_dumb = !self.supports_ansi_escape_codes and !self.is_windows_terminal; |
| 196 | if (is_dumb and self.dont_print_on_dumb) return; | 201 | if (is_dumb and self.dont_print_on_dumb) return; |
| 202 | |||
| 197 | const file = self.terminal orelse return; | 203 | const file = self.terminal orelse return; |
| 198 | 204 | ||
| 199 | var end: usize = 0; | 205 | var end: usize = 0; |
| ... | @@ -206,6 +212,8 @@ fn refreshWithHeldLock(self: *Progress) void { | ... | @@ -206,6 +212,8 @@ fn refreshWithHeldLock(self: *Progress) void { |
| 206 | std.mem.copy(u8, self.output_buffer[end..], seq_before); | 212 | std.mem.copy(u8, self.output_buffer[end..], seq_before); |
| 207 | end += seq_before.len; | 213 | end += seq_before.len; |
| 208 | } else if (std.builtin.os.tag == .windows) winapi: { | 214 | } else if (std.builtin.os.tag == .windows) winapi: { |
| 215 | std.debug.assert(self.is_windows_terminal); | ||
| 216 | |||
| 209 | var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; | 217 | var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; |
| 210 | if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) | 218 | if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) |
| 211 | unreachable; | 219 | unreachable; |
| ... | @@ -282,7 +290,7 @@ fn refreshWithHeldLock(self: *Progress) void { | ... | @@ -282,7 +290,7 @@ fn refreshWithHeldLock(self: *Progress) void { |
| 282 | const seq_after = DECRC; | 290 | const seq_after = DECRC; |
| 283 | std.mem.copy(u8, self.output_buffer[end..], seq_after); | 291 | std.mem.copy(u8, self.output_buffer[end..], seq_after); |
| 284 | end += seq_after.len; | 292 | end += seq_after.len; |
| 285 | } else if (std.builtin.os.tag != .windows) { | 293 | } else if (!self.is_windows_terminal) { |
| 286 | self.output_buffer[end] = '\n'; | 294 | self.output_buffer[end] = '\n'; |
| 287 | end += 1; | 295 | end += 1; |
| 288 | } | 296 | } |
| ... | @@ -293,8 +301,10 @@ fn refreshWithHeldLock(self: *Progress) void { | ... | @@ -293,8 +301,10 @@ fn refreshWithHeldLock(self: *Progress) void { |
| 293 | }; | 301 | }; |
| 294 | 302 | ||
| 295 | if (std.builtin.os.tag == .windows) { | 303 | if (std.builtin.os.tag == .windows) { |
| 296 | if (windows.kernel32.SetConsoleCursorPosition(file.handle, saved_cursor_pos) != windows.TRUE) | 304 | if (self.is_windows_terminal) { |
| 297 | unreachable; | 305 | const res = windows.kernel32.SetConsoleCursorPosition(file.handle, saved_cursor_pos); |
| 306 | std.debug.assert(res == windows.TRUE); | ||
| 307 | } | ||
| 298 | } | 308 | } |
| 299 | 309 | ||
| 300 | self.prev_refresh_timestamp = self.timer.read(); | 310 | self.prev_refresh_timestamp = self.timer.read(); |
| ... | @@ -318,7 +328,7 @@ fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: any | ... | @@ -318,7 +328,7 @@ fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: any |
| 318 | end.* = self.output_buffer.len; | 328 | end.* = self.output_buffer.len; |
| 319 | }, | 329 | }, |
| 320 | } | 330 | } |
| 321 | const bytes_needed_for_esc_codes_at_end = if (std.builtin.os.tag == .windows) 0 else 11; | 331 | const bytes_needed_for_esc_codes_at_end: u8 = if (self.is_windows_terminal) 0 else 11; |
| 322 | const max_end = self.output_buffer.len - bytes_needed_for_esc_codes_at_end; | 332 | const max_end = self.output_buffer.len - bytes_needed_for_esc_codes_at_end; |
| 323 | if (end.* > max_end) { | 333 | if (end.* > max_end) { |
| 324 | const suffix = "... "; | 334 | const suffix = "... "; |
lib/std/coff.zig+67-10| ... | @@ -98,6 +98,7 @@ pub const CoffError = error{ | ... | @@ -98,6 +98,7 @@ pub const CoffError = error{ |
| 98 | InvalidPEHeader, | 98 | InvalidPEHeader, |
| 99 | InvalidMachine, | 99 | InvalidMachine, |
| 100 | MissingCoffSection, | 100 | MissingCoffSection, |
| 101 | MissingStringTable, | ||
| 101 | }; | 102 | }; |
| 102 | 103 | ||
| 103 | // Official documentation of the format: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format | 104 | // Official documentation of the format: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format |
| ... | @@ -162,20 +163,47 @@ pub const Coff = struct { | ... | @@ -162,20 +163,47 @@ pub const Coff = struct { |
| 162 | try self.loadOptionalHeader(); | 163 | try self.loadOptionalHeader(); |
| 163 | } | 164 | } |
| 164 | 165 | ||
| 166 | fn readStringFromTable(self: *Coff, offset: usize, buf: []u8) ![]const u8 { | ||
| 167 | if (self.coff_header.pointer_to_symbol_table == 0) { | ||
| 168 | // No symbol table therefore no string table | ||
| 169 | return error.MissingStringTable; | ||
| 170 | } | ||
| 171 | // The string table is at the end of the symbol table and symbols are 18 bytes long | ||
| 172 | const string_table_offset = self.coff_header.pointer_to_symbol_table + (self.coff_header.number_of_symbols * 18) + offset; | ||
| 173 | const in = self.in_file.reader(); | ||
| 174 | const old_pos = try self.in_file.getPos(); | ||
| 175 | |||
| 176 | try self.in_file.seekTo(string_table_offset); | ||
| 177 | defer { | ||
| 178 | self.in_file.seekTo(old_pos) catch unreachable; | ||
| 179 | } | ||
| 180 | |||
| 181 | const str = try in.readUntilDelimiterOrEof(buf, 0); | ||
| 182 | return str orelse ""; | ||
| 183 | } | ||
| 184 | |||
| 165 | fn loadOptionalHeader(self: *Coff) !void { | 185 | fn loadOptionalHeader(self: *Coff) !void { |
| 166 | const in = self.in_file.reader(); | 186 | const in = self.in_file.reader(); |
| 187 | const opt_header_pos = try self.in_file.getPos(); | ||
| 188 | |||
| 167 | self.pe_header.magic = try in.readIntLittle(u16); | 189 | self.pe_header.magic = try in.readIntLittle(u16); |
| 168 | // For now we're only interested in finding the reference to the .pdb, | 190 | // All we care about is the image base value and PDB info |
| 169 | // so we'll skip most of this header, which size is different in 32 | 191 | // The header structure is different for 32 or 64 bit |
| 170 | // 64 bits by the way. | 192 | var num_rva_pos: u64 = undefined; |
| 171 | var skip_size: u16 = undefined; | ||
| 172 | if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { | 193 | if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { |
| 173 | skip_size = 2 * @sizeOf(u8) + 8 * @sizeOf(u16) + 18 * @sizeOf(u32); | 194 | num_rva_pos = opt_header_pos + 92; |
| 195 | |||
| 196 | try self.in_file.seekTo(opt_header_pos + 28); | ||
| 197 | const image_base32 = try in.readIntLittle(u32); | ||
| 198 | self.pe_header.image_base = image_base32; | ||
| 174 | } else if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { | 199 | } else if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { |
| 175 | skip_size = 2 * @sizeOf(u8) + 8 * @sizeOf(u16) + 12 * @sizeOf(u32) + 5 * @sizeOf(u64); | 200 | num_rva_pos = opt_header_pos + 108; |
| 201 | |||
| 202 | try self.in_file.seekTo(opt_header_pos + 24); | ||
| 203 | self.pe_header.image_base = try in.readIntLittle(u64); | ||
| 176 | } else return error.InvalidPEMagic; | 204 | } else return error.InvalidPEMagic; |
| 177 | 205 | ||
| 178 | try self.in_file.seekBy(skip_size); | 206 | try self.in_file.seekTo(num_rva_pos); |
| 179 | 207 | ||
| 180 | const number_of_rva_and_sizes = try in.readIntLittle(u32); | 208 | const number_of_rva_and_sizes = try in.readIntLittle(u32); |
| 181 | if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES) | 209 | if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES) |
| ... | @@ -258,11 +286,23 @@ pub const Coff = struct { | ... | @@ -258,11 +286,23 @@ pub const Coff = struct { |
| 258 | 286 | ||
| 259 | const in = self.in_file.reader(); | 287 | const in = self.in_file.reader(); |
| 260 | 288 | ||
| 261 | var name: [8]u8 = undefined; | 289 | var name: [32]u8 = undefined; |
| 262 | 290 | ||
| 263 | var i: u16 = 0; | 291 | var i: u16 = 0; |
| 264 | while (i < self.coff_header.number_of_sections) : (i += 1) { | 292 | while (i < self.coff_header.number_of_sections) : (i += 1) { |
| 265 | try in.readNoEof(name[0..]); | 293 | try in.readNoEof(name[0..8]); |
| 294 | |||
| 295 | if (name[0] == '/') { | ||
| 296 | // This is a long name and stored in the string table | ||
| 297 | const offset_len = mem.indexOfScalar(u8, name[1..], 0) orelse 7; | ||
| 298 | |||
| 299 | const str_offset = try std.fmt.parseInt(u32, name[1 .. offset_len + 1], 10); | ||
| 300 | const str = try self.readStringFromTable(str_offset, &name); | ||
| 301 | std.mem.set(u8, name[str.len..], 0); | ||
| 302 | } else { | ||
| 303 | std.mem.set(u8, name[8..], 0); | ||
| 304 | } | ||
| 305 | |||
| 266 | try self.sections.append(Section{ | 306 | try self.sections.append(Section{ |
| 267 | .header = SectionHeader{ | 307 | .header = SectionHeader{ |
| 268 | .name = name, | 308 | .name = name, |
| ... | @@ -288,6 +328,22 @@ pub const Coff = struct { | ... | @@ -288,6 +328,22 @@ pub const Coff = struct { |
| 288 | } | 328 | } |
| 289 | return null; | 329 | return null; |
| 290 | } | 330 | } |
| 331 | |||
| 332 | // Return an owned slice full of the section data | ||
| 333 | pub fn getSectionData(self: *Coff, comptime name: []const u8, allocator: *mem.Allocator) ![]u8 { | ||
| 334 | const sec = for (self.sections.items) |*sec| { | ||
| 335 | if (mem.eql(u8, sec.header.name[0..name.len], name)) { | ||
| 336 | break sec; | ||
| 337 | } | ||
| 338 | } else { | ||
| 339 | return error.MissingCoffSection; | ||
| 340 | }; | ||
| 341 | const in = self.in_file.reader(); | ||
| 342 | try self.in_file.seekTo(sec.header.pointer_to_raw_data); | ||
| 343 | const out_buff = try allocator.alloc(u8, sec.header.misc.virtual_size); | ||
| 344 | try in.readNoEof(out_buff); | ||
| 345 | return out_buff; | ||
| 346 | } | ||
| 291 | }; | 347 | }; |
| 292 | 348 | ||
| 293 | const CoffHeader = struct { | 349 | const CoffHeader = struct { |
| ... | @@ -308,6 +364,7 @@ const OptionalHeader = struct { | ... | @@ -308,6 +364,7 @@ const OptionalHeader = struct { |
| 308 | 364 | ||
| 309 | magic: u16, | 365 | magic: u16, |
| 310 | data_directory: [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]DataDirectory, | 366 | data_directory: [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]DataDirectory, |
| 367 | image_base: u64, | ||
| 311 | }; | 368 | }; |
| 312 | 369 | ||
| 313 | const DebugDirectoryEntry = packed struct { | 370 | const DebugDirectoryEntry = packed struct { |
| ... | @@ -331,7 +388,7 @@ const SectionHeader = struct { | ... | @@ -331,7 +388,7 @@ const SectionHeader = struct { |
| 331 | virtual_size: u32, | 388 | virtual_size: u32, |
| 332 | }; | 389 | }; |
| 333 | 390 | ||
| 334 | name: [8]u8, | 391 | name: [32]u8, |
| 335 | misc: Misc, | 392 | misc: Misc, |
| 336 | virtual_address: u32, | 393 | virtual_address: u32, |
| 337 | size_of_raw_data: u32, | 394 | size_of_raw_data: u32, |
lib/std/debug.zig+69-31| ... | @@ -53,6 +53,10 @@ pub const SymbolInfo = struct { | ... | @@ -53,6 +53,10 @@ pub const SymbolInfo = struct { |
| 53 | } | 53 | } |
| 54 | } | 54 | } |
| 55 | }; | 55 | }; |
| 56 | const PdbOrDwarf = union(enum) { | ||
| 57 | pdb: pdb.Pdb, | ||
| 58 | dwarf: DW.DwarfInfo, | ||
| 59 | }; | ||
| 56 | 60 | ||
| 57 | var stderr_mutex = std.Thread.Mutex{}; | 61 | var stderr_mutex = std.Thread.Mutex{}; |
| 58 | 62 | ||
| ... | @@ -669,10 +673,32 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf | ... | @@ -669,10 +673,32 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf |
| 669 | var di = ModuleDebugInfo{ | 673 | var di = ModuleDebugInfo{ |
| 670 | .base_address = undefined, | 674 | .base_address = undefined, |
| 671 | .coff = coff_obj, | 675 | .coff = coff_obj, |
| 672 | .pdb = undefined, | 676 | .debug_data = undefined, |
| 673 | }; | 677 | }; |
| 674 | 678 | ||
| 675 | try di.coff.loadHeader(); | 679 | try di.coff.loadHeader(); |
| 680 | try di.coff.loadSections(); | ||
| 681 | if (di.coff.getSection(".debug_info")) |sec| { | ||
| 682 | // This coff file has embedded DWARF debug info | ||
| 683 | // TODO: free the section data slices | ||
| 684 | const debug_info_data = di.coff.getSectionData(".debug_info", allocator) catch null; | ||
| 685 | const debug_abbrev_data = di.coff.getSectionData(".debug_abbrev", allocator) catch null; | ||
| 686 | const debug_str_data = di.coff.getSectionData(".debug_str", allocator) catch null; | ||
| 687 | const debug_line_data = di.coff.getSectionData(".debug_line", allocator) catch null; | ||
| 688 | const debug_ranges_data = di.coff.getSectionData(".debug_ranges", allocator) catch null; | ||
| 689 | |||
| 690 | var dwarf = DW.DwarfInfo{ | ||
| 691 | .endian = native_endian, | ||
| 692 | .debug_info = debug_info_data orelse return error.MissingDebugInfo, | ||
| 693 | .debug_abbrev = debug_abbrev_data orelse return error.MissingDebugInfo, | ||
| 694 | .debug_str = debug_str_data orelse return error.MissingDebugInfo, | ||
| 695 | .debug_line = debug_line_data orelse return error.MissingDebugInfo, | ||
| 696 | .debug_ranges = debug_ranges_data, | ||
| 697 | }; | ||
| 698 | try DW.openDwarfDebugInfo(&dwarf, allocator); | ||
| 699 | di.debug_data = PdbOrDwarf{ .dwarf = dwarf }; | ||
| 700 | return di; | ||
| 701 | } | ||
| 676 | 702 | ||
| 677 | var path_buf: [windows.MAX_PATH]u8 = undefined; | 703 | var path_buf: [windows.MAX_PATH]u8 = undefined; |
| 678 | const len = try di.coff.getPdbPath(path_buf[0..]); | 704 | const len = try di.coff.getPdbPath(path_buf[0..]); |
| ... | @@ -681,11 +707,12 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf | ... | @@ -681,11 +707,12 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf |
| 681 | const path = try fs.path.resolve(allocator, &[_][]const u8{raw_path}); | 707 | const path = try fs.path.resolve(allocator, &[_][]const u8{raw_path}); |
| 682 | defer allocator.free(path); | 708 | defer allocator.free(path); |
| 683 | 709 | ||
| 684 | di.pdb = try pdb.Pdb.init(allocator, path); | 710 | di.debug_data = PdbOrDwarf{ .pdb = undefined }; |
| 685 | try di.pdb.parseInfoStream(); | 711 | di.debug_data.pdb = try pdb.Pdb.init(allocator, path); |
| 686 | try di.pdb.parseDbiStream(); | 712 | try di.debug_data.pdb.parseInfoStream(); |
| 713 | try di.debug_data.pdb.parseDbiStream(); | ||
| 687 | 714 | ||
| 688 | if (!mem.eql(u8, &di.coff.guid, &di.pdb.guid) or di.coff.age != di.pdb.age) | 715 | if (!mem.eql(u8, &di.coff.guid, &di.debug_data.pdb.guid) or di.coff.age != di.debug_data.pdb.age) |
| 689 | return error.InvalidDebugInfo; | 716 | return error.InvalidDebugInfo; |
| 690 | 717 | ||
| 691 | return di; | 718 | return di; |
| ... | @@ -1331,7 +1358,7 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1331,7 +1358,7 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1331 | }, | 1358 | }, |
| 1332 | .uefi, .windows => struct { | 1359 | .uefi, .windows => struct { |
| 1333 | base_address: usize, | 1360 | base_address: usize, |
| 1334 | pdb: pdb.Pdb, | 1361 | debug_data: PdbOrDwarf, |
| 1335 | coff: *coff.Coff, | 1362 | coff: *coff.Coff, |
| 1336 | 1363 | ||
| 1337 | pub fn allocator(self: @This()) *mem.Allocator { | 1364 | pub fn allocator(self: @This()) *mem.Allocator { |
| ... | @@ -1342,8 +1369,18 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1342,8 +1369,18 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1342 | // Translate the VA into an address into this object | 1369 | // Translate the VA into an address into this object |
| 1343 | const relocated_address = address - self.base_address; | 1370 | const relocated_address = address - self.base_address; |
| 1344 | 1371 | ||
| 1372 | switch (self.debug_data) { | ||
| 1373 | .dwarf => |*dwarf| { | ||
| 1374 | const dwarf_address = relocated_address + self.coff.pe_header.image_base; | ||
| 1375 | return getSymbolFromDwarf(dwarf_address, dwarf); | ||
| 1376 | }, | ||
| 1377 | .pdb => { | ||
| 1378 | // fallthrough to pdb handling | ||
| 1379 | }, | ||
| 1380 | } | ||
| 1381 | |||
| 1345 | var coff_section: *coff.Section = undefined; | 1382 | var coff_section: *coff.Section = undefined; |
| 1346 | const mod_index = for (self.pdb.sect_contribs) |sect_contrib| { | 1383 | const mod_index = for (self.debug_data.pdb.sect_contribs) |sect_contrib| { |
| 1347 | if (sect_contrib.Section > self.coff.sections.items.len) continue; | 1384 | if (sect_contrib.Section > self.coff.sections.items.len) continue; |
| 1348 | // Remember that SectionContribEntry.Section is 1-based. | 1385 | // Remember that SectionContribEntry.Section is 1-based. |
| 1349 | coff_section = &self.coff.sections.items[sect_contrib.Section - 1]; | 1386 | coff_section = &self.coff.sections.items[sect_contrib.Section - 1]; |
| ... | @@ -1358,15 +1395,15 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1358,15 +1395,15 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1358 | return SymbolInfo{}; | 1395 | return SymbolInfo{}; |
| 1359 | }; | 1396 | }; |
| 1360 | 1397 | ||
| 1361 | const module = (try self.pdb.getModule(mod_index)) orelse | 1398 | const module = (try self.debug_data.pdb.getModule(mod_index)) orelse |
| 1362 | return error.InvalidDebugInfo; | 1399 | return error.InvalidDebugInfo; |
| 1363 | const obj_basename = fs.path.basename(module.obj_file_name); | 1400 | const obj_basename = fs.path.basename(module.obj_file_name); |
| 1364 | 1401 | ||
| 1365 | const symbol_name = self.pdb.getSymbolName( | 1402 | const symbol_name = self.debug_data.pdb.getSymbolName( |
| 1366 | module, | 1403 | module, |
| 1367 | relocated_address - coff_section.header.virtual_address, | 1404 | relocated_address - coff_section.header.virtual_address, |
| 1368 | ) orelse "???"; | 1405 | ) orelse "???"; |
| 1369 | const opt_line_info = try self.pdb.getLineNumberInfo( | 1406 | const opt_line_info = try self.debug_data.pdb.getLineNumberInfo( |
| 1370 | module, | 1407 | module, |
| 1371 | relocated_address - coff_section.header.virtual_address, | 1408 | relocated_address - coff_section.header.virtual_address, |
| 1372 | ); | 1409 | ); |
| ... | @@ -1386,32 +1423,33 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1386,32 +1423,33 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1386 | pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo { | 1423 | pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo { |
| 1387 | // Translate the VA into an address into this object | 1424 | // Translate the VA into an address into this object |
| 1388 | const relocated_address = address - self.base_address; | 1425 | const relocated_address = address - self.base_address; |
| 1389 | 1426 | return getSymbolFromDwarf(relocated_address, &self.dwarf); | |
| 1390 | if (nosuspend self.dwarf.findCompileUnit(relocated_address)) |compile_unit| { | ||
| 1391 | return SymbolInfo{ | ||
| 1392 | .symbol_name = nosuspend self.dwarf.getSymbolName(relocated_address) orelse "???", | ||
| 1393 | .compile_unit_name = compile_unit.die.getAttrString(&self.dwarf, DW.AT_name) catch |err| switch (err) { | ||
| 1394 | error.MissingDebugInfo, error.InvalidDebugInfo => "???", | ||
| 1395 | else => return err, | ||
| 1396 | }, | ||
| 1397 | .line_info = nosuspend self.dwarf.getLineNumberInfo(compile_unit.*, relocated_address) catch |err| switch (err) { | ||
| 1398 | error.MissingDebugInfo, error.InvalidDebugInfo => null, | ||
| 1399 | else => return err, | ||
| 1400 | }, | ||
| 1401 | }; | ||
| 1402 | } else |err| switch (err) { | ||
| 1403 | error.MissingDebugInfo, error.InvalidDebugInfo => { | ||
| 1404 | return SymbolInfo{}; | ||
| 1405 | }, | ||
| 1406 | else => return err, | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | unreachable; | ||
| 1410 | } | 1427 | } |
| 1411 | }, | 1428 | }, |
| 1412 | else => DW.DwarfInfo, | 1429 | else => DW.DwarfInfo, |
| 1413 | }; | 1430 | }; |
| 1414 | 1431 | ||
| 1432 | fn getSymbolFromDwarf(address: u64, di: *DW.DwarfInfo) !SymbolInfo { | ||
| 1433 | if (nosuspend di.findCompileUnit(address)) |compile_unit| { | ||
| 1434 | return SymbolInfo{ | ||
| 1435 | .symbol_name = nosuspend di.getSymbolName(address) orelse "???", | ||
| 1436 | .compile_unit_name = compile_unit.die.getAttrString(di, DW.AT_name) catch |err| switch (err) { | ||
| 1437 | error.MissingDebugInfo, error.InvalidDebugInfo => "???", | ||
| 1438 | else => return err, | ||
| 1439 | }, | ||
| 1440 | .line_info = nosuspend di.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) { | ||
| 1441 | error.MissingDebugInfo, error.InvalidDebugInfo => null, | ||
| 1442 | else => return err, | ||
| 1443 | }, | ||
| 1444 | }; | ||
| 1445 | } else |err| switch (err) { | ||
| 1446 | error.MissingDebugInfo, error.InvalidDebugInfo => { | ||
| 1447 | return SymbolInfo{}; | ||
| 1448 | }, | ||
| 1449 | else => return err, | ||
| 1450 | } | ||
| 1451 | } | ||
| 1452 | |||
| 1415 | /// TODO multithreaded awareness | 1453 | /// TODO multithreaded awareness |
| 1416 | var debug_info_allocator: ?*mem.Allocator = null; | 1454 | var debug_info_allocator: ?*mem.Allocator = null; |
| 1417 | var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined; | 1455 | var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined; |
lib/std/dwarf.zig+5-5| ... | @@ -144,7 +144,7 @@ const FileEntry = struct { | ... | @@ -144,7 +144,7 @@ const FileEntry = struct { |
| 144 | }; | 144 | }; |
| 145 | 145 | ||
| 146 | const LineNumberProgram = struct { | 146 | const LineNumberProgram = struct { |
| 147 | address: usize, | 147 | address: u64, |
| 148 | file: usize, | 148 | file: usize, |
| 149 | line: i64, | 149 | line: i64, |
| 150 | column: u64, | 150 | column: u64, |
| ... | @@ -153,12 +153,12 @@ const LineNumberProgram = struct { | ... | @@ -153,12 +153,12 @@ const LineNumberProgram = struct { |
| 153 | end_sequence: bool, | 153 | end_sequence: bool, |
| 154 | 154 | ||
| 155 | default_is_stmt: bool, | 155 | default_is_stmt: bool, |
| 156 | target_address: usize, | 156 | target_address: u64, |
| 157 | include_dirs: []const []const u8, | 157 | include_dirs: []const []const u8, |
| 158 | file_entries: *ArrayList(FileEntry), | 158 | file_entries: *ArrayList(FileEntry), |
| 159 | 159 | ||
| 160 | prev_valid: bool, | 160 | prev_valid: bool, |
| 161 | prev_address: usize, | 161 | prev_address: u64, |
| 162 | prev_file: usize, | 162 | prev_file: usize, |
| 163 | prev_line: i64, | 163 | prev_line: i64, |
| 164 | prev_column: u64, | 164 | prev_column: u64, |
| ... | @@ -186,7 +186,7 @@ const LineNumberProgram = struct { | ... | @@ -186,7 +186,7 @@ const LineNumberProgram = struct { |
| 186 | self.prev_end_sequence = undefined; | 186 | self.prev_end_sequence = undefined; |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | pub fn init(is_stmt: bool, include_dirs: []const []const u8, file_entries: *ArrayList(FileEntry), target_address: usize) LineNumberProgram { | 189 | pub fn init(is_stmt: bool, include_dirs: []const []const u8, file_entries: *ArrayList(FileEntry), target_address: u64) LineNumberProgram { |
| 190 | return LineNumberProgram{ | 190 | return LineNumberProgram{ |
| 191 | .address = 0, | 191 | .address = 0, |
| 192 | .file = 1, | 192 | .file = 1, |
| ... | @@ -691,7 +691,7 @@ pub const DwarfInfo = struct { | ... | @@ -691,7 +691,7 @@ pub const DwarfInfo = struct { |
| 691 | return result; | 691 | return result; |
| 692 | } | 692 | } |
| 693 | 693 | ||
| 694 | pub fn getLineNumberInfo(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !debug.LineInfo { | 694 | pub fn getLineNumberInfo(di: *DwarfInfo, compile_unit: CompileUnit, target_address: u64) !debug.LineInfo { |
| 695 | var stream = io.fixedBufferStream(di.debug_line); | 695 | var stream = io.fixedBufferStream(di.debug_line); |
| 696 | const in = &stream.reader(); | 696 | const in = &stream.reader(); |
| 697 | const seekable = &stream.seekableStream(); | 697 | const seekable = &stream.seekableStream(); |