From 5b1d729748f10f1793401a0d8a68f877ceef4bcd Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 8 Sep 2024 15:26:21 -0700 Subject: [PATCH] crash/minidump: handle padding in the ThreadList stream --- src/crash/minidump.zig | 3 +- src/crash/minidump/external.zig | 3 +- src/crash/minidump/reader.zig | 4 + src/crash/minidump/stream.zig | 57 +----------- src/crash/minidump/stream_threadlist.zig | 111 +++++++++++++++++++++++ src/crash/testdata/macos.dmp | Bin 447456 -> 447584 bytes 6 files changed, 122 insertions(+), 56 deletions(-) create mode 100644 src/crash/minidump/stream_threadlist.zig diff --git a/src/crash/minidump.zig b/src/crash/minidump.zig index 1e103283f..0abd67eae 100644 --- a/src/crash/minidump.zig +++ b/src/crash/minidump.zig @@ -1,5 +1,4 @@ -const reader = @import("minidump/reader.zig"); - +pub const reader = @import("minidump/reader.zig"); pub const stream = @import("minidump/stream.zig"); pub const Reader = reader.Reader; diff --git a/src/crash/minidump/external.zig b/src/crash/minidump/external.zig index a6f89d3e9..451810883 100644 --- a/src/crash/minidump/external.zig +++ b/src/crash/minidump/external.zig @@ -44,8 +44,7 @@ pub const MemoryDescriptor = extern struct { /// https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_thread_list pub const ThreadList = extern struct { number_of_threads: u32, - - // This struct has a trailing array of `Thread` structs. + threads: [1]Thread, }; /// https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_thread diff --git a/src/crash/minidump/reader.zig b/src/crash/minidump/reader.zig index 582044879..f316e63b0 100644 --- a/src/crash/minidump/reader.zig +++ b/src/crash/minidump/reader.zig @@ -13,6 +13,7 @@ const log = std.log.scoped(.minidump_reader); pub const ReadError = error{ InvalidHeader, InvalidVersion, + StreamSizeMismatch, }; /// Reader creates a new minidump reader for the given source type. The @@ -56,6 +57,9 @@ pub fn Reader(comptime S: type) type { /// The source type for the reader. pub const Source = S; + /// The stream types for reading + pub const ThreadList = stream.thread_list.ThreadListReader(Self); + /// The reader type for stream reading. This has some other methods so /// you must still call reader() on the result to get the actual /// reader to read the data. diff --git a/src/crash/minidump/stream.zig b/src/crash/minidump/stream.zig index bb383cce0..00ec6b042 100644 --- a/src/crash/minidump/stream.zig +++ b/src/crash/minidump/stream.zig @@ -1,10 +1,12 @@ const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; -const Reader = @import("reader.zig").Reader; const log = std.log.scoped(.minidump_stream); +/// The known stream types. +pub const thread_list = @import("stream_threadlist.zig"); + /// A stream within the minidump file. A stream can be either in an encoded /// form or decoded form. The encoded form are raw bytes and aren't validated /// until they're decoded. The decoded form is a structured form of the stream. @@ -23,55 +25,6 @@ pub const EncodedStream = struct { data: []const u8, }; -/// This is the list of threads from the process. -/// -/// ThreadList is stream type 0x3. -/// StreamReader is the Reader(T).StreamReader type. -pub fn ThreadList(comptime R: type) type { - return struct { - const Self = @This(); - - /// The number of threads in the list. - count: u32, - - /// The rva to the first thread in the list. - rva: u32, - - /// The source data and endianness so we can continue reading. - source: R.Source, - endian: std.builtin.Endian, - - pub fn init(r: *R.StreamReader) !Self { - assert(r.directory.stream_type == 0x3); - try r.seekToPayload(); - - const reader = r.source.reader(); - const count = try reader.readInt(u32, r.endian); - const rva = r.directory.location.rva + @as(u32, @intCast(@sizeOf(u32))); - - return .{ - .count = count, - .rva = rva, - .source = r.source, - .endian = r.endian, - }; - } - }; -} - -test "minidump: threadlist" { - const testing = std.testing; - - var fbs = std.io.fixedBufferStream(@embedFile("../testdata/macos.dmp")); - const R = Reader(*@TypeOf(fbs)); - const r = try R.init(&fbs); - - // Get our thread list stream - const dir = try r.directory(0); - try testing.expectEqual(3, dir.stream_type); - var sr = try r.streamReader(dir); - - // Get our rich structure - const v = try ThreadList(R).init(&sr); - log.warn("threadlist count={} rva={}", .{ v.count, v.rva }); +test { + @import("std").testing.refAllDecls(@This()); } diff --git a/src/crash/minidump/stream_threadlist.zig b/src/crash/minidump/stream_threadlist.zig new file mode 100644 index 000000000..e74d11e3e --- /dev/null +++ b/src/crash/minidump/stream_threadlist.zig @@ -0,0 +1,111 @@ +const std = @import("std"); +const assert = std.debug.assert; +const external = @import("external.zig"); +const readerpkg = @import("reader.zig"); +const Reader = readerpkg.Reader; +const ReadError = readerpkg.ReadError; + +const log = std.log.scoped(.minidump_stream); + +/// This is the list of threads from the process. +/// +/// This is the Reader implementation. You usually do not use this directly. +/// Instead, use Reader(T).ThreadList which will get you the same thing. +/// +/// ThreadList is stream type 0x3. +/// StreamReader is the Reader(T).StreamReader type. +pub fn ThreadListReader(comptime R: type) type { + return struct { + const Self = @This(); + + /// The number of threads in the list. + count: u32, + + /// The rva to the first thread in the list. + rva: u32, + + /// Source data and endianness so we can read. + source: R.Source, + endian: std.builtin.Endian, + + pub fn init(r: *R.StreamReader) !Self { + assert(r.directory.stream_type == 0x3); + try r.seekToPayload(); + const reader = r.source.reader(); + + // Our count is always a u32 in the header. + const count = try reader.readInt(u32, r.endian); + + // Determine if we have padding in our header. It is possible + // for there to be padding if the list header was written by + // a 32-bit process but is being read on a 64-bit process. + const padding = padding: { + const maybe_size = @sizeOf(u32) + (@sizeOf(external.Thread) * count); + switch (std.math.order(maybe_size, r.directory.location.data_size)) { + // It should never be larger than what the directory says. + .gt => return ReadError.StreamSizeMismatch, + + // If the sizes match exactly we're good. + .eq => break :padding 0, + + .lt => { + const padding = r.directory.location.data_size - maybe_size; + if (padding != 4) return ReadError.StreamSizeMismatch; + break :padding padding; + }, + } + }; + + // Rva is the location of the first thread in the list. + const rva = r.directory.location.rva + @as(u32, @sizeOf(u32)) + padding; + + return .{ + .count = count, + .rva = rva, + .source = r.source, + .endian = r.endian, + }; + } + + /// Get the thread entry for the given index. + /// + /// Index is asserted to be less than count. + pub fn thread(self: *const Self, i: usize) !external.Thread { + assert(i < self.count); + + // Seek to the thread + const offset: u32 = @intCast(@sizeOf(external.Thread) * i); + const rva: u32 = self.rva + offset; + try self.source.seekableStream().seekTo(rva); + + // Read the thread + return try self.source.reader().readStructEndian( + external.Thread, + self.endian, + ); + } + }; +} + +test "minidump: threadlist" { + const testing = std.testing; + + var fbs = std.io.fixedBufferStream(@embedFile("../testdata/macos.dmp")); + const R = Reader(*@TypeOf(fbs)); + const r = try R.init(&fbs); + + // Get our thread list stream + const dir = try r.directory(0); + try testing.expectEqual(3, dir.stream_type); + var sr = try r.streamReader(dir); + + // Get our rich structure + const v = try R.ThreadList.init(&sr); + log.warn("threadlist count={} rva={}", .{ v.count, v.rva }); + + try testing.expectEqual(12, v.count); + for (0..v.count) |i| { + const t = try v.thread(i); + log.warn("thread i={} thread={}", .{ i, t }); + } +} diff --git a/src/crash/testdata/macos.dmp b/src/crash/testdata/macos.dmp index 5931c13a06284043c286fcda9a94aa93f2762909..212cc7e624a1a670687dc20eca7f81e4db53ba5f 100644 GIT binary patch delta 31642 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 delta 31643 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