authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-29 19:00:24-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-29 19:00:24-04:00
log686663239af6afd8dea814a9fe6a8885f06d6cb3
treec272fddf103f5466f3a900b996ecdbfaf7393cd6
parentf1b71053de6c5e71e2e1f73daeaff29280b69350

printing info from the ModuleInfo substream of DebugInfo


5 files changed, 120 insertions(+), 57 deletions(-)

std/coff.zig+4-4
...@@ -41,7 +41,7 @@ pub const Coff = struct {...@@ -41,7 +41,7 @@ pub const Coff = struct {
41 pub fn loadHeader(self: *Coff) !void {41 pub fn loadHeader(self: *Coff) !void {
42 const pe_pointer_offset = 0x3C;42 const pe_pointer_offset = 0x3C;
4343
44 var file_stream = io.FileInStream.init(&self.in_file);44 var file_stream = io.FileInStream.init(self.in_file);
45 const in = &file_stream.stream;45 const in = &file_stream.stream;
4646
47 var magic: [2]u8 = undefined;47 var magic: [2]u8 = undefined;
...@@ -126,7 +126,7 @@ pub const Coff = struct {...@@ -126,7 +126,7 @@ pub const Coff = struct {
126 std.debug.warn("file offset {x}\n", file_offset);126 std.debug.warn("file offset {x}\n", file_offset);
127 try self.in_file.seekTo(file_offset + debug_dir.size);127 try self.in_file.seekTo(file_offset + debug_dir.size);
128128
129 var file_stream = io.FileInStream.init(&self.in_file);129 var file_stream = io.FileInStream.init(self.in_file);
130 const in = &file_stream.stream;130 const in = &file_stream.stream;
131131
132 var cv_signature: [4]u8 = undefined; // CodeView signature132 var cv_signature: [4]u8 = undefined; // CodeView signature
...@@ -158,7 +158,7 @@ pub const Coff = struct {...@@ -158,7 +158,7 @@ pub const Coff = struct {
158158
159 self.sections = ArrayList(Section).init(self.allocator);159 self.sections = ArrayList(Section).init(self.allocator);
160160
161 var file_stream = io.FileInStream.init(&self.in_file);161 var file_stream = io.FileInStream.init(self.in_file);
162 const in = &file_stream.stream;162 const in = &file_stream.stream;
163163
164 var name: [8]u8 = undefined;164 var name: [8]u8 = undefined;
...@@ -235,4 +235,4 @@ const SectionHeader = struct {...@@ -235,4 +235,4 @@ const SectionHeader = struct {
235 number_of_relocations: u16,235 number_of_relocations: u16,
236 number_of_line_numbers: u16,236 number_of_line_numbers: u16,
237 characteristics: u32,237 characteristics: u32,
238};
\ No newline at end of file
238};
std/debug/index.zig+5-5
...@@ -40,7 +40,7 @@ pub fn getStderrStream() !*io.OutStream(io.FileOutStream.Error) {...@@ -40,7 +40,7 @@ pub fn getStderrStream() !*io.OutStream(io.FileOutStream.Error) {
40 return st;40 return st;
41 } else {41 } else {
42 stderr_file = try io.getStdErr();42 stderr_file = try io.getStdErr();
43 stderr_file_out_stream = io.FileOutStream.init(&stderr_file);43 stderr_file_out_stream = io.FileOutStream.init(stderr_file);
44 const st = &stderr_file_out_stream.stream;44 const st = &stderr_file_out_stream.stream;
45 stderr_stream = st;45 stderr_stream = st;
46 return st;46 return st;
...@@ -73,7 +73,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {...@@ -73,7 +73,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
73 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return;73 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return;
74 return;74 return;
75 };75 };
76 writeCurrentStackTrace(stderr, getDebugInfoAllocator(), debug_info, wantTtyColor(), start_addr) catch |err| {76 writeCurrentStackTrace(stderr, debug_info, wantTtyColor(), start_addr) catch |err| {
77 stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return;77 stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return;
78 return;78 return;
79 };79 };
...@@ -194,9 +194,9 @@ pub inline fn getReturnAddress(frame_count: usize) usize {...@@ -194,9 +194,9 @@ pub inline fn getReturnAddress(frame_count: usize) usize {
194 return @intToPtr(*const usize, fp + @sizeOf(usize)).*;194 return @intToPtr(*const usize, fp + @sizeOf(usize)).*;
195}195}
196196
197pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void {197pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void {
198 switch (builtin.os) {198 switch (builtin.os) {
199 builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, allocator, debug_info, tty_color, start_addr),199 builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr),
200 else => {},200 else => {},
201 }201 }
202 const AddressState = union(enum) {202 const AddressState = union(enum) {
...@@ -231,7 +231,7 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_...@@ -231,7 +231,7 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_
231 }231 }
232}232}
233233
234pub fn writeCurrentStackTraceWindows(out_stream: var, allocator: *mem.Allocator, debug_info: *DebugInfo,234pub fn writeCurrentStackTraceWindows(out_stream: var, debug_info: *DebugInfo,
235 tty_color: bool, start_addr: ?usize) !void235 tty_color: bool, start_addr: ?usize) !void
236{236{
237 var addr_buf: [1024]usize = undefined;237 var addr_buf: [1024]usize = undefined;
std/io.zig+4-4
...@@ -34,13 +34,13 @@ pub fn getStdIn() GetStdIoErrs!File {...@@ -34,13 +34,13 @@ pub fn getStdIn() GetStdIoErrs!File {
3434
35/// Implementation of InStream trait for File35/// Implementation of InStream trait for File
36pub const FileInStream = struct {36pub const FileInStream = struct {
37 file: *File,37 file: File,
38 stream: Stream,38 stream: Stream,
3939
40 pub const Error = @typeOf(File.read).ReturnType.ErrorSet;40 pub const Error = @typeOf(File.read).ReturnType.ErrorSet;
41 pub const Stream = InStream(Error);41 pub const Stream = InStream(Error);
4242
43 pub fn init(file: *File) FileInStream {43 pub fn init(file: File) FileInStream {
44 return FileInStream{44 return FileInStream{
45 .file = file,45 .file = file,
46 .stream = Stream{ .readFn = readFn },46 .stream = Stream{ .readFn = readFn },
...@@ -55,13 +55,13 @@ pub const FileInStream = struct {...@@ -55,13 +55,13 @@ pub const FileInStream = struct {
5555
56/// Implementation of OutStream trait for File56/// Implementation of OutStream trait for File
57pub const FileOutStream = struct {57pub const FileOutStream = struct {
58 file: *File,58 file: File,
59 stream: Stream,59 stream: Stream,
6060
61 pub const Error = File.WriteError;61 pub const Error = File.WriteError;
62 pub const Stream = OutStream(Error);62 pub const Stream = OutStream(Error);
6363
64 pub fn init(file: *File) FileOutStream {64 pub fn init(file: File) FileOutStream {
65 return FileOutStream{65 return FileOutStream{
66 .file = file,66 .file = file,
67 .stream = Stream{ .writeFn = writeFn },67 .stream = Stream{ .writeFn = writeFn },
std/os/file.zig+9-10
...@@ -205,17 +205,16 @@ pub const File = struct {...@@ -205,17 +205,16 @@ pub const File = struct {
205205
206 /// Upon success, the stream is in an uninitialized state. To continue using it,206 /// Upon success, the stream is in an uninitialized state. To continue using it,
207 /// you must use the open() function.207 /// you must use the open() function.
208 pub fn close(self: *File) void {208 pub fn close(self: File) void {
209 os.close(self.handle);209 os.close(self.handle);
210 self.handle = undefined;
211 }210 }
212211
213 /// Calls `os.isTty` on `self.handle`.212 /// Calls `os.isTty` on `self.handle`.
214 pub fn isTty(self: *File) bool {213 pub fn isTty(self: File) bool {
215 return os.isTty(self.handle);214 return os.isTty(self.handle);
216 }215 }
217216
218 pub fn seekForward(self: *File, amount: isize) !void {217 pub fn seekForward(self: File, amount: isize) !void {
219 switch (builtin.os) {218 switch (builtin.os) {
220 Os.linux, Os.macosx, Os.ios => {219 Os.linux, Os.macosx, Os.ios => {
221 const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);220 const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);
...@@ -246,7 +245,7 @@ pub const File = struct {...@@ -246,7 +245,7 @@ pub const File = struct {
246 }245 }
247 }246 }
248247
249 pub fn seekTo(self: *File, pos: usize) !void {248 pub fn seekTo(self: File, pos: usize) !void {
250 switch (builtin.os) {249 switch (builtin.os) {
251 Os.linux, Os.macosx, Os.ios => {250 Os.linux, Os.macosx, Os.ios => {
252 const ipos = try math.cast(isize, pos);251 const ipos = try math.cast(isize, pos);
...@@ -280,7 +279,7 @@ pub const File = struct {...@@ -280,7 +279,7 @@ pub const File = struct {
280 }279 }
281 }280 }
282281
283 pub fn getPos(self: *File) !usize {282 pub fn getPos(self: File) !usize {
284 switch (builtin.os) {283 switch (builtin.os) {
285 Os.linux, Os.macosx, Os.ios => {284 Os.linux, Os.macosx, Os.ios => {
286 const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);285 const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);
...@@ -316,7 +315,7 @@ pub const File = struct {...@@ -316,7 +315,7 @@ pub const File = struct {
316 }315 }
317 }316 }
318317
319 pub fn getEndPos(self: *File) !usize {318 pub fn getEndPos(self: File) !usize {
320 if (is_posix) {319 if (is_posix) {
321 const stat = try os.posixFStat(self.handle);320 const stat = try os.posixFStat(self.handle);
322 return @intCast(usize, stat.size);321 return @intCast(usize, stat.size);
...@@ -341,7 +340,7 @@ pub const File = struct {...@@ -341,7 +340,7 @@ pub const File = struct {
341 Unexpected,340 Unexpected,
342 };341 };
343342
344 pub fn mode(self: *File) ModeError!Mode {343 pub fn mode(self: File) ModeError!Mode {
345 if (is_posix) {344 if (is_posix) {
346 var stat: posix.Stat = undefined;345 var stat: posix.Stat = undefined;
347 const err = posix.getErrno(posix.fstat(self.handle, &stat));346 const err = posix.getErrno(posix.fstat(self.handle, &stat));
...@@ -375,7 +374,7 @@ pub const File = struct {...@@ -375,7 +374,7 @@ pub const File = struct {
375 Unexpected,374 Unexpected,
376 };375 };
377376
378 pub fn read(self: *File, buffer: []u8) ReadError!usize {377 pub fn read(self: File, buffer: []u8) ReadError!usize {
379 if (is_posix) {378 if (is_posix) {
380 var index: usize = 0;379 var index: usize = 0;
381 while (index < buffer.len) {380 while (index < buffer.len) {
...@@ -423,7 +422,7 @@ pub const File = struct {...@@ -423,7 +422,7 @@ pub const File = struct {
423422
424 pub const WriteError = os.WindowsWriteError || os.PosixWriteError;423 pub const WriteError = os.WindowsWriteError || os.PosixWriteError;
425424
426 pub fn write(self: *File, bytes: []const u8) WriteError!void {425 pub fn write(self: File, bytes: []const u8) WriteError!void {
427 if (is_posix) {426 if (is_posix) {
428 try os.posixWrite(self.handle, bytes);427 try os.posixWrite(self.handle, bytes);
429 } else if (is_windows) {428 } else if (is_windows) {
std/pdb.zig+98-34
...@@ -8,9 +8,58 @@ const warn = std.debug.warn;...@@ -8,9 +8,58 @@ const warn = std.debug.warn;
88
9const ArrayList = std.ArrayList;9const ArrayList = std.ArrayList;
1010
11pub const PdbError = error {11// https://llvm.org/docs/PDB/DbiStream.html#stream-header
12 InvalidPdbMagic,12const DbiStreamHeader = packed struct {
13 CorruptedFile,13 VersionSignature: i32,
14 VersionHeader: u32,
15 Age: u32,
16 GlobalStreamIndex: u16,
17 BuildNumber: u16,
18 PublicStreamIndex: u16,
19 PdbDllVersion: u16,
20 SymRecordStream: u16,
21 PdbDllRbld: u16,
22 ModInfoSize: u32,
23 SectionContributionSize: i32,
24 SectionMapSize: i32,
25 SourceInfoSize: i32,
26 TypeServerSize: i32,
27 MFCTypeServerIndex: u32,
28 OptionalDbgHeaderSize: i32,
29 ECSubstreamSize: i32,
30 Flags: u16,
31 Machine: u16,
32 Padding: u32,
33};
34
35const SectionContribEntry = packed struct {
36 Section: u16,
37 Padding1: [2]u8,
38 Offset: i32,
39 Size: i32,
40 Characteristics: u32,
41 ModuleIndex: u16,
42 Padding2: [2]u8,
43 DataCrc: u32,
44 RelocCrc: u32,
45};
46
47const ModInfo = packed struct {
48 Unused1: u32,
49 SectionContr: SectionContribEntry,
50 Flags: u16,
51 ModuleSymStream: u16,
52 SymByteSize: u32,
53 C11ByteSize: u32,
54 C13ByteSize: u32,
55 SourceFileCount: u16,
56 Padding: [2]u8,
57 Unused2: u32,
58 SourceFileNameIndex: u32,
59 PdbFilePathNameIndex: u32,
60 // These fields are variable length
61 //ModuleName: char[],
62 //ObjFileName: char[],
14};63};
1564
16pub const StreamType = enum(u16) {65pub const StreamType = enum(u16) {
...@@ -30,7 +79,7 @@ pub const Pdb = struct {...@@ -30,7 +79,7 @@ pub const Pdb = struct {
30 self.in_file = try os.File.openRead(file_name[0..]);79 self.in_file = try os.File.openRead(file_name[0..]);
31 self.allocator = allocator;80 self.allocator = allocator;
3281
33 try self.msf.openFile(allocator, &self.in_file);82 try self.msf.openFile(allocator, self.in_file);
34 }83 }
3584
36 pub fn getStream(self: *Pdb, stream: StreamType) ?*MsfStream {85 pub fn getStream(self: *Pdb, stream: StreamType) ?*MsfStream {
...@@ -41,29 +90,32 @@ pub const Pdb = struct {...@@ -41,29 +90,32 @@ pub const Pdb = struct {
41 }90 }
4291
43 pub fn getSourceLine(self: *Pdb, address: usize) !void {92 pub fn getSourceLine(self: *Pdb, address: usize) !void {
44 const dbi = self.getStream(StreamType.Dbi) orelse return error.CorruptedFile;93 const dbi = self.getStream(StreamType.Dbi) orelse return error.InvalidDebugInfo;
4594
46 // Dbi Header95 // Dbi Header
47 try dbi.seekForward(@sizeOf(u32) * 3 + @sizeOf(u16) * 6);96 var header: DbiStreamHeader = undefined;
48 warn("dbi stream at {} (file offset)\n", dbi.getFilePos());97 try dbi.stream.readStruct(DbiStreamHeader, &header);
49 const module_info_size = try dbi.stream.readIntLe(u32);98 std.debug.warn("{}\n", header);
50 const section_contribution_size = try dbi.stream.readIntLe(u32);
51 const section_map_size = try dbi.stream.readIntLe(u32);
52 const source_info_size = try dbi.stream.readIntLe(u32);
53 warn("module_info_size: {}\n", module_info_size);
54 warn("section_contribution_size: {}\n", section_contribution_size);
55 warn("section_map_size: {}\n", section_map_size);
56 warn("source_info_size: {}\n", source_info_size);
57 try dbi.seekForward(@sizeOf(u32) * 5 + @sizeOf(u16) * 2);
58 warn("after header dbi stream at {} (file offset)\n", dbi.getFilePos());99 warn("after header dbi stream at {} (file offset)\n", dbi.getFilePos());
59100
60 // Module Info Substream101 // Module Info Substream
61 try dbi.seekForward(@sizeOf(u32) + @sizeOf(u16) + @sizeOf(u8) * 2);102 var mod_info_offset: usize = 0;
62 const offset = try dbi.stream.readIntLe(u32);103 while (mod_info_offset < header.ModInfoSize) {
63 const size = try dbi.stream.readIntLe(u32);104 var mod_info: ModInfo = undefined;
64 try dbi.seekForward(@sizeOf(u32));105 try dbi.stream.readStruct(ModInfo, &mod_info);
65 const module_index = try dbi.stream.readIntLe(u16);106 std.debug.warn("{}\n", mod_info);
66 warn("module {} of size {} at {}\n", module_index, size, offset);107 mod_info_offset += @sizeOf(ModInfo);
108
109 const module_name = try dbi.readNullTermString(self.allocator);
110 std.debug.warn("module_name {}\n", module_name);
111 mod_info_offset += module_name.len + 1;
112
113 const obj_file_name = try dbi.readNullTermString(self.allocator);
114 std.debug.warn("obj_file_name {}\n", obj_file_name);
115 mod_info_offset += obj_file_name.len + 1;
116 }
117 std.debug.warn("end modules\n");
118
67119
68 // TODO: locate corresponding source line information120 // TODO: locate corresponding source line information
69 }121 }
...@@ -75,7 +127,7 @@ const Msf = struct {...@@ -75,7 +127,7 @@ const Msf = struct {
75 directory: MsfStream,127 directory: MsfStream,
76 streams: ArrayList(MsfStream),128 streams: ArrayList(MsfStream),
77129
78 fn openFile(self: *Msf, allocator: *mem.Allocator, file: *os.File) !void {130 fn openFile(self: *Msf, allocator: *mem.Allocator, file: os.File) !void {
79 var file_stream = io.FileInStream.init(file);131 var file_stream = io.FileInStream.init(file);
80 const in = &file_stream.stream;132 const in = &file_stream.stream;
81133
...@@ -84,7 +136,7 @@ const Msf = struct {...@@ -84,7 +136,7 @@ const Msf = struct {
84 warn("magic: '{}'\n", magic);136 warn("magic: '{}'\n", magic);
85 137
86 if (!mem.eql(u8, magic, SuperBlock.FileMagic))138 if (!mem.eql(u8, magic, SuperBlock.FileMagic))
87 return error.InvalidPdbMagic;139 return error.InvalidDebugInfo;
88140
89 self.superblock = SuperBlock {141 self.superblock = SuperBlock {
90 .block_size = try in.readIntLe(u32),142 .block_size = try in.readIntLe(u32),
...@@ -97,11 +149,11 @@ const Msf = struct {...@@ -97,11 +149,11 @@ const Msf = struct {
97149
98 switch (self.superblock.block_size) {150 switch (self.superblock.block_size) {
99 512, 1024, 2048, 4096 => {}, // llvm only uses 4096151 512, 1024, 2048, 4096 => {}, // llvm only uses 4096
100 else => return error.InvalidPdbMagic152 else => return error.InvalidDebugInfo
101 }153 }
102154
103 if (self.superblock.fileSize() != try file.getEndPos())155 if (self.superblock.fileSize() != try file.getEndPos())
104 return error.CorruptedFile; // Should always stand.156 return error.InvalidDebugInfo; // Should always stand.
105157
106 self.directory = try MsfStream.init(158 self.directory = try MsfStream.init(
107 self.superblock.block_size,159 self.superblock.block_size,
...@@ -165,12 +217,18 @@ const SuperBlock = struct {...@@ -165,12 +217,18 @@ const SuperBlock = struct {
165};217};
166218
167const MsfStream = struct {219const MsfStream = struct {
168 in_file: *os.File,220 in_file: os.File,
169 pos: usize,221 pos: usize,
170 blocks: ArrayList(u32),222 blocks: ArrayList(u32),
171 block_size: u32,223 block_size: u32,
172224
173 fn init(block_size: u32, block_count: u32, pos: usize, file: *os.File, allocator: *mem.Allocator) !MsfStream {225 /// Implementation of InStream trait for Pdb.MsfStream
226 stream: Stream,
227
228 pub const Error = @typeOf(read).ReturnType.ErrorSet;
229 pub const Stream = io.InStream(Error);
230
231 fn init(block_size: u32, block_count: u32, pos: usize, file: os.File, allocator: *mem.Allocator) !MsfStream {
174 var stream = MsfStream {232 var stream = MsfStream {
175 .in_file = file,233 .in_file = file,
176 .pos = 0,234 .pos = 0,
...@@ -198,6 +256,18 @@ const MsfStream = struct {...@@ -198,6 +256,18 @@ const MsfStream = struct {
198 return stream;256 return stream;
199 }257 }
200258
259 fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 {
260 var list = ArrayList(u8).init(allocator);
261 defer list.deinit();
262 while (true) {
263 const byte = try self.stream.readByte();
264 if (byte == 0) {
265 return list.toSlice();
266 }
267 try list.append(byte);
268 }
269 }
270
201 fn read(self: *MsfStream, buffer: []u8) !usize {271 fn read(self: *MsfStream, buffer: []u8) !usize {
202 var block_id = self.pos / self.block_size;272 var block_id = self.pos / self.block_size;
203 var block = self.blocks.items[block_id];273 var block = self.blocks.items[block_id];
...@@ -252,12 +322,6 @@ const MsfStream = struct {...@@ -252,12 +322,6 @@ const MsfStream = struct {
252 return block * self.block_size + offset;322 return block * self.block_size + offset;
253 }323 }
254324
255 /// Implementation of InStream trait for Pdb.MsfStream
256 pub const Error = @typeOf(read).ReturnType.ErrorSet;
257 pub const Stream = io.InStream(Error);
258
259 stream: Stream,
260
261 fn readFn(in_stream: *Stream, buffer: []u8) Error!usize {325 fn readFn(in_stream: *Stream, buffer: []u8) Error!usize {
262 const self = @fieldParentPtr(MsfStream, "stream", in_stream);326 const self = @fieldParentPtr(MsfStream, "stream", in_stream);
263 return self.read(buffer);327 return self.read(buffer);