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