| ... | ... | @@ -5,7 +5,7 @@ const math = std.math; |
| 5 | 5 | const mem = std.mem; |
| 6 | 6 | const os = std.os; |
| 7 | 7 | const warn = std.debug.warn; |
| 8 | | const Coff = std.coff.Coff; |
| 8 | const coff = std.coff; |
| 9 | 9 | |
| 10 | 10 | const ArrayList = std.ArrayList; |
| 11 | 11 | |
| ... | ... | @@ -153,7 +153,7 @@ pub const SymbolRecordKind = enum(u16) { |
| 153 | 153 | |
| 154 | 154 | /// Duplicate copy of SymbolRecordKind, but using the official CV names. Useful |
| 155 | 155 | /// for reference purposes and when dealing with unknown record types. |
| 156 | | pub const SymbolKind = enum(u16) { |
| 156 | pub const SymbolKind = packed enum(u16) { |
| 157 | 157 | S_COMPILE = 1, |
| 158 | 158 | S_REGISTER_16t = 2, |
| 159 | 159 | S_CONSTANT_16t = 3, |
| ... | ... | @@ -352,6 +352,33 @@ pub const SymbolKind = enum(u16) { |
| 352 | 352 | S_GTHREAD32 = 4371, |
| 353 | 353 | }; |
| 354 | 354 | |
| 355 | const TypeIndex = u32; |
| 356 | |
| 357 | const ProcSym = packed struct { |
| 358 | Parent: u32 , |
| 359 | End: u32 , |
| 360 | Next: u32 , |
| 361 | CodeSize: u32 , |
| 362 | DbgStart: u32 , |
| 363 | DbgEnd: u32 , |
| 364 | FunctionType: TypeIndex , |
| 365 | CodeOffset: u32, |
| 366 | Segment: u16, |
| 367 | Flags: ProcSymFlags, |
| 368 | Name: u8, |
| 369 | }; |
| 370 | |
| 371 | const ProcSymFlags = packed struct { |
| 372 | HasFP: bool, |
| 373 | HasIRET: bool, |
| 374 | HasFRET: bool, |
| 375 | IsNoReturn: bool, |
| 376 | IsUnreachable: bool, |
| 377 | HasCustomCallingConv: bool, |
| 378 | IsNoInline: bool, |
| 379 | HasOptimizedDebugInfo: bool, |
| 380 | }; |
| 381 | |
| 355 | 382 | const SectionContrSubstreamVersion = enum(u32) { |
| 356 | 383 | Ver60 = 0xeffe0000 + 19970605, |
| 357 | 384 | V2 = 0xeffe0000 + 20140516 |
| ... | ... | @@ -359,20 +386,20 @@ const SectionContrSubstreamVersion = enum(u32) { |
| 359 | 386 | |
| 360 | 387 | const RecordPrefix = packed struct { |
| 361 | 388 | RecordLen: u16, /// Record length, starting from &RecordKind. |
| 362 | | RecordKind: u16, /// Record kind enum (SymRecordKind or TypeRecordKind) |
| 389 | RecordKind: SymbolKind, /// Record kind enum (SymRecordKind or TypeRecordKind) |
| 363 | 390 | }; |
| 364 | 391 | |
| 365 | 392 | pub const Pdb = struct { |
| 366 | 393 | in_file: os.File, |
| 367 | 394 | allocator: *mem.Allocator, |
| 368 | | coff: *Coff, |
| 395 | coff: *coff.Coff, |
| 369 | 396 | |
| 370 | 397 | msf: Msf, |
| 371 | 398 | |
| 372 | | pub fn openFile(self: *Pdb, coff: *Coff, file_name: []u8) !void { |
| 399 | pub fn openFile(self: *Pdb, coff_ptr: *coff.Coff, file_name: []u8) !void { |
| 373 | 400 | self.in_file = try os.File.openRead(file_name); |
| 374 | | self.allocator = coff.allocator; |
| 375 | | self.coff = coff; |
| 401 | self.allocator = coff_ptr.allocator; |
| 402 | self.coff = coff_ptr; |
| 376 | 403 | |
| 377 | 404 | try self.msf.openFile(self.allocator, self.in_file); |
| 378 | 405 | } |
| ... | ... | @@ -468,8 +495,9 @@ pub const Pdb = struct { |
| 468 | 495 | // std.debug.warn("{}\n", sect_entry); |
| 469 | 496 | //} |
| 470 | 497 | |
| 498 | var coff_section: *coff.Section = undefined; |
| 471 | 499 | const mod_index = for (sect_contribs.toSlice()) |sect_contrib| { |
| 472 | | const coff_section = self.coff.sections.toSlice()[sect_contrib.Section]; |
| 500 | coff_section = &self.coff.sections.toSlice()[sect_contrib.Section]; |
| 473 | 501 | std.debug.warn("looking in coff name: {}\n", mem.toSliceConst(u8, &coff_section.header.name)); |
| 474 | 502 | |
| 475 | 503 | const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; |
| ... | ... | @@ -490,6 +518,26 @@ pub const Pdb = struct { |
| 490 | 518 | const symbols = try self.allocator.alloc(u8, mod.mod_info.SymByteSize - 4); |
| 491 | 519 | std.debug.warn("read {} bytes of symbol info\n", symbols.len); |
| 492 | 520 | try modi.stream.readNoEof(symbols); |
| 521 | var symbol_i: usize = 0; |
| 522 | const proc_sym = while (symbol_i != symbols.len) { |
| 523 | const prefix = @ptrCast(*RecordPrefix, &symbols[symbol_i]); |
| 524 | if (prefix.RecordLen < 2) |
| 525 | return error.InvalidDebugInfo; |
| 526 | if (prefix.RecordKind == SymbolKind.S_LPROC32) { |
| 527 | const proc_sym = @ptrCast(*ProcSym, &symbols[symbol_i + @sizeOf(RecordPrefix)]); |
| 528 | const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset; |
| 529 | const vaddr_end = vaddr_start + proc_sym.CodeSize; |
| 530 | std.debug.warn(" {}\n", proc_sym); |
| 531 | if (address >= vaddr_start and address < vaddr_end) { |
| 532 | break proc_sym; |
| 533 | } |
| 534 | } |
| 535 | symbol_i += prefix.RecordLen + @sizeOf(u16); |
| 536 | if (symbol_i > symbols.len) |
| 537 | return error.InvalidDebugInfo; |
| 538 | } else return error.MissingDebugInfo; |
| 539 | |
| 540 | std.debug.warn("found in {s}: {}\n", ([*]u8)((*[1]u8)(&proc_sym.Name)), proc_sym); |
| 493 | 541 | |
| 494 | 542 | if (mod.mod_info.C11ByteSize != 0) |
| 495 | 543 | return error.InvalidDebugInfo; |