authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-31 01:01:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-31 01:01:37-04:00
log99170aa13db236b47aa8fda4a3d94b49e6b7f93c
treeccf0a580b30163336f43590c8dc60ce7b2fa3030
parent72185e7dd36d9b87c57a3ed3719b9824ca11edf9

finding source file, line, and column info


2 files changed, 118 insertions(+), 6 deletions(-)

std/io.zig+1-1
...@@ -210,7 +210,7 @@ pub fn InStream(comptime ReadError: type) type {...@@ -210,7 +210,7 @@ pub fn InStream(comptime ReadError: type) type {
210210
211 pub fn readStruct(self: *Self, comptime T: type, ptr: *T) !void {211 pub fn readStruct(self: *Self, comptime T: type, ptr: *T) !void {
212 // Only extern and packed structs have defined in-memory layout.212 // Only extern and packed structs have defined in-memory layout.
213 assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto);213 comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto);
214 return self.readNoEof(@sliceToBytes((*[1]T)(ptr)[0..]));214 return self.readNoEof(@sliceToBytes((*[1]T)(ptr)[0..]));
215 }215 }
216 };216 };
std/pdb.zig+117-5
...@@ -365,7 +365,8 @@ const ProcSym = packed struct {...@@ -365,7 +365,8 @@ const ProcSym = packed struct {
365 CodeOffset: u32,365 CodeOffset: u32,
366 Segment: u16,366 Segment: u16,
367 Flags: ProcSymFlags,367 Flags: ProcSymFlags,
368 Name: u8,368 // following is a null terminated string
369 // Name: [*]u8,
369};370};
370371
371const ProcSymFlags = packed struct {372const ProcSymFlags = packed struct {
...@@ -389,6 +390,51 @@ const RecordPrefix = packed struct {...@@ -389,6 +390,51 @@ const RecordPrefix = packed struct {
389 RecordKind: SymbolKind, /// Record kind enum (SymRecordKind or TypeRecordKind)390 RecordKind: SymbolKind, /// Record kind enum (SymRecordKind or TypeRecordKind)
390};391};
391392
393const LineFragmentHeader = packed struct {
394 RelocOffset: u32, /// Code offset of line contribution.
395 RelocSegment: u16, /// Code segment of line contribution.
396 Flags: LineFlags,
397 CodeSize: u32, /// Code size of this line contribution.
398};
399
400const LineFlags = packed struct {
401 LF_HaveColumns: bool, /// CV_LINES_HAVE_COLUMNS
402 unused: u15,
403};
404
405/// The following two variable length arrays appear immediately after the
406/// header. The structure definitions follow.
407/// LineNumberEntry Lines[NumLines];
408/// ColumnNumberEntry Columns[NumLines];
409const LineBlockFragmentHeader = packed struct {
410 /// Offset of FileChecksum entry in File
411 /// checksums buffer. The checksum entry then
412 /// contains another offset into the string
413 /// table of the actual name.
414 NameIndex: u32,
415 NumLines: u32,
416 BlockSize: u32, /// code size of block, in bytes
417};
418
419
420const LineNumberEntry = packed struct {
421 Offset: u32, /// Offset to start of code bytes for line number
422 Flags: u32,
423
424 /// TODO runtime crash when I make the actual type of Flags this
425 const Flags = packed struct {
426 Start: u24,
427 End: u7,
428 IsStatement: bool,
429 };
430};
431
432const ColumnNumberEntry = packed struct {
433 StartColumn: u16,
434 EndColumn: u16,
435};
436
437
392pub const Pdb = struct {438pub const Pdb = struct {
393 in_file: os.File,439 in_file: os.File,
394 allocator: *mem.Allocator,440 allocator: *mem.Allocator,
...@@ -537,16 +583,82 @@ pub const Pdb = struct {...@@ -537,16 +583,82 @@ pub const Pdb = struct {
537 return error.InvalidDebugInfo;583 return error.InvalidDebugInfo;
538 } else return error.MissingDebugInfo;584 } else return error.MissingDebugInfo;
539585
540 std.debug.warn("found in {s}: {}\n", ([*]u8)((*[1]u8)(&proc_sym.Name)), proc_sym);586 std.debug.warn("found in {s}: {}\n", @ptrCast([*]u8, proc_sym) + @sizeOf(ProcSym), proc_sym);
541587
542 if (mod.mod_info.C11ByteSize != 0)588 if (mod.mod_info.C11ByteSize != 0)
543 return error.InvalidDebugInfo;589 return error.InvalidDebugInfo;
544590
545 if (mod.mod_info.C13ByteSize != 0) {591 if (mod.mod_info.C13ByteSize == 0) {
546 std.debug.warn("read C13 line info\n");592 return error.MissingDebugInfo;
593 }
594
595 const line_info = try self.allocator.alloc(u8, mod.mod_info.C13ByteSize);
596 std.debug.warn("read C13 line info {} bytes\n", line_info.len);
597 try modi.stream.readNoEof(line_info);
598
599 var line_index: usize = 0;
600 while (line_index != line_info.len) {
601 std.debug.warn("unknown bytes: {x2} {x2} {x2} {x2} {x2} {x2} {x2} {x2}\n",
602 line_info[line_index+0],
603 line_info[line_index+1],
604 line_info[line_index+2],
605 line_info[line_index+3],
606 line_info[line_index+4],
607 line_info[line_index+5],
608 line_info[line_index+6],
609 line_info[line_index+7],
610 );
611 line_index += 8;
612
613 const line_hdr = @ptrCast(*LineFragmentHeader, &line_info[line_index]);
614 if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;
615 std.debug.warn("{}\n", line_hdr);
616 line_index += @sizeOf(LineFragmentHeader);
617
618 const block_hdr = @ptrCast(*LineBlockFragmentHeader, &line_info[line_index]);
619 std.debug.warn("{}\n", block_hdr);
620 line_index += @sizeOf(LineBlockFragmentHeader);
621
622 const has_column = line_hdr.Flags.LF_HaveColumns;
623 std.debug.warn("has column: {}\n", has_column);
624
625 const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
626 const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
627 if (address >= frag_vaddr_start and address < frag_vaddr_end) {
628 std.debug.warn("found line listing\n");
629 var line_i: usize = 0;
630 const start_line_index = line_index;
631 while (line_i < block_hdr.NumLines) : (line_i += 1) {
632 const line_num_entry = @ptrCast(*LineNumberEntry, &line_info[line_index]);
633 line_index += @sizeOf(LineNumberEntry);
634 const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);
635 std.debug.warn("{} {}\n", line_num_entry, flags);
636 const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
637 const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End;
638 std.debug.warn("test {x} <= {x} < {x}\n", vaddr_start, address, vaddr_end);
639 if (address >= vaddr_start and address < vaddr_end) {
640 std.debug.warn("{} line {}\n", block_hdr.NameIndex, flags.Start);
641 if (has_column) {
642 line_index = start_line_index + @sizeOf(LineNumberEntry) * block_hdr.NumLines;
643 line_index += @sizeOf(ColumnNumberEntry) * line_i;
644 const col_num_entry = @ptrCast(*ColumnNumberEntry, &line_info[line_index]);
645 std.debug.warn("col {}\n", col_num_entry.StartColumn);
646 }
647 return;
648 }
649 }
650 return error.MissingDebugInfo;
651 } else {
652 line_index += @sizeOf(LineNumberEntry) * block_hdr.NumLines;
653 if (has_column)
654 line_index += @sizeOf(ColumnNumberEntry) * block_hdr.NumLines;
655 }
656
657 if (line_index > mod.mod_info.C13ByteSize)
658 return error.InvalidDebugInfo;
547 }659 }
548660
549 // TODO: locate corresponding source line information661 std.debug.warn("end line info\n");
550 }662 }
551};663};
552664