From 6ad5f1a52e0bb4a6d52f908445e6d95de5720396 Mon Sep 17 00:00:00 2001
From: dd86k
Date: Tue, 2 Jul 2024 16:03:15 -0400
Subject: [PATCH] object: Move mdmp to new code
---
dumper/format/mdmp.d | 53 ++++----
src/adbg/object/format/dmp.d | 4 +-
src/adbg/object/format/mdmp.d | 220 +++++++++++++++++++++++++++-------
src/adbg/object/server.d | 5 -
src/adbg/utils/bit.d | 6 +-
5 files changed, 212 insertions(+), 76 deletions(-)
diff --git a/dumper/format/mdmp.d b/dumper/format/mdmp.d
index 60c9fd7f..64ca5189 100644
--- a/dumper/format/mdmp.d
+++ b/dumper/format/mdmp.d
@@ -19,8 +19,8 @@ int dump_minidump(adbg_object_t *o) {
if (SELECTED(Select.headers))
dump_minidump_headers(o);
- //if (SELECTED(Select.debug_))
- // dump_minidump_debug(o);
+ if (SELECTED(Select.debug_))
+ dump_minidump_debug(o);
return 0;
}
@@ -29,11 +29,14 @@ private:
void dump_minidump_headers(adbg_object_t *o) {
print_header("Header");
- with (o.i.mdmp.header) {
+
+ mdmp_header_t *header = adbg_object_mdmp_header(o);
+
+ with (header) {
print_x32("Signature", Signature);
print_x16("Magic", Magic);
print_u16("Version", Version);
- print_x32("StreamCount", StreamCount);
+ print_u32("StreamCount", StreamCount);
print_x32("StreamRva", StreamRva);
print_x32("Checksum", Checksum);
print_x32("Timestamp", Timestamp, ctime32(Timestamp));
@@ -70,33 +73,25 @@ void dump_minidump_headers(adbg_object_t *o) {
void dump_minidump_debug(adbg_object_t *o) {
print_header("Debug");
- uint cnt = o.i.mdmp.header.StreamCount;
- uint off = o.i.mdmp.header.StreamRva;
- mdmp_directory_entry *dir = void;
- if (adbg_object_offsetl(o, cast(void**)&dir, off, cnt * mdmp_directory_entry.sizeof))
- panic(1, "Directory outside file bounds");
-
- for (uint i; i < cnt; ++i) {
- mdmp_directory_entry *entry = &dir[i];
-
- with (entry) {
- print_x32("StreamType", StreamType);
- print_x32("Size", Size);
- print_x32("Rva", Rva);
- }
+ reset_error();
+ size_t i;
+ for (mdmp_directory_entry_t *entry; (entry = adbg_object_mdmp_dir_entry(o, i)) != null; ++i) {
+ print_section(cast(uint)i);
+ print_u32("StreamType", entry.StreamType, adbg_object_mdmp_dir_entry_type_string(entry));
+ print_x32("Size", entry.Size);
+ print_x32("Rva", entry.Rva);
switch (entry.StreamType) {
case ThreadListStream:
print_header("Threadlist");
- mdmp_threadlist *tlist = void;
- if (adbg_object_offsetl(o, cast(void**)&tlist,
- entry.Rva, uint.sizeof + mdmp_thread.sizeof)) {
- print_warningf("Threadlist.Rva points outbound");
- continue;
- }
- for (uint ti; ti < tlist.Count; ++ti) {
- mdmp_thread *thread = &tlist.Threads.ptr[ti];
+ mdmp_threadlist_t *threads =
+ cast(mdmp_threadlist_t*)adbg_object_mdmp_dir_entry_data(o, entry);
+ if (threads == null)
+ panic_adbg();
+
+ for (uint ti; ti < threads.Count; ++ti) {
+ mdmp_thread_t *thread = &threads.Threads.ptr[ti];
print_section(ti);
print_x32("ID", thread.ID);
print_x32("SuspendCount", thread.SuspendCount);
@@ -104,6 +99,7 @@ void dump_minidump_debug(adbg_object_t *o) {
print_x32("Priority", thread.Priority);
print_x64("Teb", thread.Teb);
+ /*
X86_NT_CONTEXT *context = void;
if (adbg_object_offsetl(o, cast(void**)&context,
thread.ThreadContext.Rva, thread.ThreadContext.Size)) {
@@ -112,7 +108,10 @@ void dump_minidump_debug(adbg_object_t *o) {
}
print_x32("Eip", context.Eip);
+ */
}
+
+ adbg_object_mdmp_dir_entry_data_close(threads);
break;
case ModuleListStream:
break;
@@ -159,4 +158,6 @@ void dump_minidump_debug(adbg_object_t *o) {
default: continue;
}
}
+ if (i == 0 && errorcode())
+ panic_adbg();
}
\ No newline at end of file
diff --git a/src/adbg/object/format/dmp.d b/src/adbg/object/format/dmp.d
index a3638e50..5453356e 100644
--- a/src/adbg/object/format/dmp.d
+++ b/src/adbg/object/format/dmp.d
@@ -137,8 +137,10 @@ int adbg_object_dmp_load(adbg_object_t *o) {
o.internal = calloc(1, internal_dmp_t.sizeof);
if (o.internal == null)
return adbg_oops(AdbgError.crt);
- if (adbg_object_read_at(o, 0, o.internal, MAX!(dmp32_header_t.sizeof, dmp64_header_t.sizeof)))
+ if (adbg_object_read_at(o, 0, o.internal, MAX!(dmp32_header_t.sizeof, dmp64_header_t.sizeof))) {
+ free(o.internal);
return adbg_errno();
+ }
o.format = AdbgObject.dmp;
diff --git a/src/adbg/object/format/mdmp.d b/src/adbg/object/format/mdmp.d
index 3c281d64..d4f4a0fa 100644
--- a/src/adbg/object/format/mdmp.d
+++ b/src/adbg/object/format/mdmp.d
@@ -9,8 +9,10 @@
/// License: BSD-3-Clause-Clear
module adbg.object.format.mdmp;
-import adbg.object.server : AdbgObject, adbg_object_t;
-import adbg.utils.bit : CHAR32;
+import adbg.object.server;
+import adbg.error;
+import adbg.utils.bit;
+import core.stdc.stdlib;
/// Signature value
enum MDMP_MAGIC = CHAR32!"MDMP";
@@ -165,25 +167,7 @@ enum : MINIDUMP_TYPE {
MiniDumpValidTypeFlags = 0x01ffffff
}
-struct mdmp_location_descriptor {
- uint Size;
- uint Rva;
-}
-struct mdmp_location_descriptor64 {
- ulong Size;
- ulong Rva;
-}
-struct mdmp_memory_descriptor {
- ulong RangeStart;
- mdmp_location_descriptor Memory;
-}
-// Used for full-memory minidumps
-struct mdmp_memory_descriptor64 {
- ulong RangeStart;
- ulong Size;
-}
-
-struct mdump_header {
+struct mdmp_header_t {
/// "MDMP" string.
uint Signature;
/// Used internally. Typically 0xa793.
@@ -203,7 +187,25 @@ struct mdump_header {
ulong Flags;
}
-struct mdmp_vs_fixedfileinfo {
+struct mdmp_location_descriptor_t {
+ uint Size;
+ uint Rva;
+}
+struct mdmp_location_descriptor64_t {
+ ulong Size;
+ ulong Rva;
+}
+struct mdmp_memory_descriptor_t {
+ ulong RangeStart;
+ mdmp_location_descriptor_t Memory;
+}
+// Used for full-memory minidumps
+struct mdmp_memory_descriptor64_t {
+ ulong RangeStart;
+ ulong Size;
+}
+
+struct mdmp_vs_fixedfileinfo_t {
/// 0xFEEF04BD
uint dwSignature;
uint dwStrucVersion;
@@ -220,7 +222,7 @@ struct mdmp_vs_fixedfileinfo {
uint dwFileDateLS;
}
/* // Pseudo-structure
-struct mdmp_vs_versioninfo {
+struct mdmp_vs_versioninfo_t {
ushort wLength;
ushort wValueLength;
ushort wType;
@@ -235,70 +237,204 @@ struct mdmp_vs_versioninfo {
// Type 3 - Thread list
//
-struct mdmp_directory_entry {
+struct mdmp_directory_entry_t {
uint StreamType;
uint Size;
uint Rva;
}
-struct mdmp_thread {
+struct mdmp_thread_t {
uint ID;
uint SuspendCount;
uint PriorityClass;
uint Priority;
ulong Teb;
- mdmp_memory_descriptor Stack;
- mdmp_location_descriptor ThreadContext;
+ mdmp_memory_descriptor_t Stack;
+ mdmp_location_descriptor_t ThreadContext;
}
-struct mdmp_threadlist {
+struct mdmp_threadlist_t {
uint Count;
- mdmp_thread[0] Threads;
+ mdmp_thread_t[0] Threads;
}
-struct mdmp_thread_ex {
+struct mdmp_thread_ex_t {
uint ID;
uint SuspendCount;
uint PriorityClass;
uint Priority;
ulong Teb;
- mdmp_memory_descriptor Stack;
- mdmp_location_descriptor ThreadContext;
- mdmp_memory_descriptor BackingStore;
+ mdmp_memory_descriptor_t Stack;
+ mdmp_location_descriptor_t ThreadContext;
+ mdmp_memory_descriptor_t BackingStore;
}
-struct mdmp_threadlist_ex {
+struct mdmp_threadlist_ex_t {
uint Count;
- mdmp_thread_ex[1] Threads;
+ mdmp_thread_ex_t[1] Threads;
}
//
// Type 4 - Module list
//
-struct mdmp_module {
+// 64-bit?
+struct mdmp_module_t {
ulong Imagebase;
uint ImageSize;
uint Checksum;
uint Timestamp;
uint ModuleNameRva;
- mdmp_vs_fixedfileinfo VersionInfo;
- mdmp_location_descriptor CvRecord;
- mdmp_location_descriptor MiscRecord;
+ mdmp_vs_fixedfileinfo_t VersionInfo;
+ mdmp_location_descriptor_t CvRecord;
+ mdmp_location_descriptor_t MiscRecord;
ulong Reserved0;
ulong Reserved1;
}
-struct mdmp_module_list {
+struct mdmp_module_list_t {
uint Count;
- mdmp_module[1] Modules;
+ mdmp_module_t[1] Modules;
}
//
// Functions
//
+private
+struct internal_mdmp_t {
+ mdmp_header_t header;
+ mdmp_directory_entry_t *directories;
+}
+
int adbg_object_mdmp_load(adbg_object_t *o) {
+ o.internal = calloc(1, internal_mdmp_t.sizeof);
+ if (o.internal == null)
+ return adbg_oops(AdbgError.crt);
+ if (adbg_object_read_at(o, 0, o.internal, mdmp_header_t.sizeof)) {
+ free(o.internal);
+ return adbg_errno();
+ }
+
o.format = AdbgObject.mdmp;
- //if (o.i.mdmp.header.Version != MDMP
+ //TODO: Support swapping
return 0;
}
+
+mdmp_header_t* adbg_object_mdmp_header(adbg_object_t *o) {
+ if (o == null) {
+ adbg_oops(AdbgError.invalidArgument);
+ return null;
+ }
+ if (o.internal == null) {
+ adbg_oops(AdbgError.uninitiated);
+ return null;
+ }
+ return &(cast(internal_mdmp_t*)o.internal).header;
+}
+
+mdmp_directory_entry_t* adbg_object_mdmp_dir_entry(adbg_object_t *o, size_t index) {
+ if (o == null) {
+ adbg_oops(AdbgError.invalidArgument);
+ return null;
+ }
+ if (o.internal == null) {
+ adbg_oops(AdbgError.uninitiated);
+ return null;
+ }
+
+ internal_mdmp_t *internal = cast(internal_mdmp_t*)o.internal;
+
+ if (index >= internal.header.StreamCount) {
+ adbg_oops(AdbgError.indexBounds);
+ return null;
+ }
+
+ size_t size = internal.header.StreamCount * mdmp_directory_entry_t.sizeof;
+
+ // Directories not loaded
+ if (internal.directories == null) {
+ internal.directories = cast(mdmp_directory_entry_t*)malloc(size);
+ if (internal.directories == null) {
+ adbg_oops(AdbgError.crt);
+ return null;
+ }
+ if (adbg_object_read_at(o, internal.header.StreamRva, internal.directories, size)) {
+ free(internal.directories);
+ return null;
+ }
+ }
+
+ mdmp_directory_entry_t *entry = internal.directories + index;
+ if (adbg_bits_boundchk(entry, mdmp_directory_entry_t.sizeof, internal.directories, size)) {
+ adbg_oops(AdbgError.offsetBounds);
+ return null;
+ }
+
+ return entry;
+}
+
+const(char)* adbg_object_mdmp_dir_entry_type_string(mdmp_directory_entry_t *entry) {
+ if (entry == null) {
+ adbg_oops(AdbgError.invalidArgument);
+ return null;
+ }
+
+ switch (entry.StreamType) {
+ case ThreadListStream: return "ThreadListStream";
+ case ModuleListStream: return "ModuleListStream";
+ case MemoryListStream: return "MemoryListStream";
+ case ExceptionStream: return "ExceptionStream";
+ case SystemInfoStream: return "SystemInfoStream";
+ case ThreadExListStream: return "ThreadExListStream";
+ case Memory64ListStream: return "Memory64ListStream";
+ case CommentStreamA: return "CommentStreamA";
+ case CommentStreamW: return "CommentStreamW";
+ case HandleDataStream: return "HandleDataStream";
+ case FunctionTableStream: return "FunctionTableStream";
+ case UnloadedModuleListStream: return "UnloadedModuleListStream";
+ case MiscInfoStream: return "MiscInfoStream";
+ case MemoryInfoListStream: return "MemoryInfoListStream";
+ case ThreadInfoListStream: return "ThreadInfoListStream";
+ case HandleOperationListStream: return "HandleOperationListStream";
+ case TokenStream: return "TokenStream";
+ case JavaScriptDataStream: return "JavaScriptDataStream";
+ case SystemMemoryInfoStream: return "SystemMemoryInfoStream";
+ case ProcessVmCountersStream: return "ProcessVmCountersStream";
+ case IptTraceStream: return "IptTraceStream";
+ case ThreadNamesStream: return "ThreadNamesStream";
+ default:
+ adbg_oops(AdbgError.unimplemented);
+ return null;
+ }
+}
+
+uint adbg_object_mdmp_dir_entry_size(mdmp_directory_entry_t *entry) {
+ if (entry == null) {
+ adbg_oops(AdbgError.invalidArgument);
+ return 0;
+ }
+ return entry.Size;
+}
+void* adbg_object_mdmp_dir_entry_data(adbg_object_t *o, mdmp_directory_entry_t *entry) {
+ if (o == null || entry == null) {
+ adbg_oops(AdbgError.invalidArgument);
+ return null;
+ }
+ if (o.internal == null) {
+ adbg_oops(AdbgError.uninitiated);
+ return null;
+ }
+
+ void *data = malloc(entry.Size);
+ if (data == null) {
+ adbg_oops(AdbgError.crt);
+ return null;
+ }
+ if (adbg_object_read_at(o, entry.Rva, data, entry.Size))
+ return null;
+
+ return data;
+}
+void adbg_object_mdmp_dir_entry_data_close(void *data) {
+ if (data) free(data);
+}
diff --git a/src/adbg/object/server.d b/src/adbg/object/server.d
index af3bf4ea..a3de2618 100644
--- a/src/adbg/object/server.d
+++ b/src/adbg/object/server.d
@@ -224,11 +224,6 @@ struct adbg_object_t {
}
pdb70_t pdb70;
- struct mdmp_t {
- mdump_header *header;
- }
- mdmp_t mdmp;
-
struct omf_t {
omf_lib_header *header;
int pgsize;
diff --git a/src/adbg/utils/bit.d b/src/adbg/utils/bit.d
index e108f86e..37c0d36e 100644
--- a/src/adbg/utils/bit.d
+++ b/src/adbg/utils/bit.d
@@ -213,7 +213,7 @@ unittest {
/// bufsize = Size of the bufer memory allocation.
/// Returns: True is pointer instance breaches outside allocated memory buffer.
align(true)
-bool adbg_bits_ptrbounds(void *ptr, size_t sizeof, void *buffer, size_t bufsize) {
+bool adbg_bits_boundchk(void *ptr, size_t sizeof, void *buffer, size_t bufsize) {
// ptr + sizeof might overflow
return ptr < buffer || ptr >= buffer + bufsize || ptr + sizeof > buffer + bufsize;
}
@@ -235,4 +235,6 @@ unittest {
assert(adbg_bits_ptrbounds(P!40, 4, P!0, 20));
assert(adbg_bits_ptrbounds(P!(-1), 4, P!0, 20));
assert(adbg_bits_ptrbounds(P!0, 100, P!0, 20));
-}
\ No newline at end of file
+}
+
+alias adbg_bits_ptrbounds = adbg_bits_boundchk;
\ No newline at end of file