minidumps: initial gather / events for process/modules/threads

This commit is contained in:
Ryan Fleury
2026-05-16 20:53:46 -07:00
parent fddf353ea0
commit 6d6cd7033d
3 changed files with 172 additions and 9 deletions
+137 -4
View File
@@ -43,7 +43,7 @@ d_exception_kind_from_dmn(DMN_ExceptionKind kind)
} }
internal D_TlsModel internal D_TlsModel
d_dynamic_linker_type_from_dmn(DMN_TlsModel type) d_tls_model_from_dmn(DMN_TlsModel type)
{ {
D_TlsModel result = D_TlsModel_Null; D_TlsModel result = D_TlsModel_Null;
switch(type) switch(type)
@@ -245,6 +245,18 @@ d_handle_from_dmn(D_MachineID machine_id, DMN_Handle handle)
return result; return result;
} }
internal D_Handle
d_dump_handle_make(D_MachineID machine_id, U64 id)
{
D_Handle result = {0};
{
result.machine_id = machine_id;
result.controller_kind = D_ControllerKind_Dump;
result.entity_id = id;
}
return result;
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Trap Type Functions //~ rjf: Trap Type Functions
@@ -4346,7 +4358,7 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D
out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->process);
out_evt->arch = event->arch; out_evt->arch = event->arch;
out_evt->entity_id = event->code; out_evt->entity_id = event->code;
out_evt->tls_model = d_dynamic_linker_type_from_dmn(event->tls_model); out_evt->tls_model = d_tls_model_from_dmn(event->tls_model);
out_evt->target_os = OperatingSystem_CURRENT; // TODO: operating system of the remote target machine out_evt->target_os = OperatingSystem_CURRENT; // TODO: operating system of the remote target machine
d_ctrl_state->process_counter += 1; d_ctrl_state->process_counter += 1;
}break; }break;
@@ -4967,15 +4979,136 @@ d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg)
void *base = file_map_view_open(map, AccessFlag_Read, r1u64(0, props.size)); void *base = file_map_view_open(map, AccessFlag_Read, r1u64(0, props.size));
String8 data = str8(base, base ? props.size : 0); String8 data = str8(base, base ? props.size : 0);
{ {
Temp scratch = scratch_begin(0, 0);
D_EventList evts = {0};
//- rjf: try minidump parse -> construct events for entity creation //- rjf: try minidump parse -> construct events for entity creation
{ {
MDMP_Header header = {0}; MDMP_Header header = {0};
str8_deserial_read_struct(data, 0, &header); str8_deserial_read_struct(data, 0, &header);
if(header.magic == MDMP_MAGIC) if(header.magic == MDMP_MAGIC)
{
// rjf: extract directories
U64 directories_count = 0;
MDMP_Directory *directories = 0;
{ {
U64 directories_foff = header.stream_directory_foff; U64 directories_foff = header.stream_directory_foff;
U64 directories_count = header.number_of_streams; if(directories_foff < data.size)
// MDMP_Directory *directories = {
U64 max_directories_count = (data.size - directories_foff) / sizeof(MDMP_Directory);
directories_count = Min(header.number_of_streams, max_directories_count);
directories = (MDMP_Directory *)(data.str + directories_foff);
}
}
// rjf: gather specific directories
MDMP_SystemInfo *system_info = 0;
MDMP_Thread *threads = 0;
U64 threads_count = 0;
MDMP_Module *modules = 0;
U64 modules_count = 0;
{
for EachIndex(idx, directories_count)
{
MDMP_Directory *dir = &directories[idx];
switch(dir->stream_kind)
{
default:{}break;
case MDMP_StreamKind_SystemInfo:
if(data.str + dir->location.foff + dir->location.data_size < data.str + data.size)
{
system_info = (MDMP_SystemInfo *)(data.str + dir->location.foff);
}break;
case MDMP_StreamKind_ThreadList:
{
U32 threads_count_32 = 0;
U64 off = dir->location.foff;
off += str8_deserial_read_struct(data, off, &threads_count_32);
U64 threads_count_max = (data.size - off) / sizeof(MDMP_Thread);
threads = (MDMP_Thread *)(data.str + off);
threads_count = Min(threads_count_32, threads_count_max);
}break;
case MDMP_StreamKind_ModuleList:
{
U32 modules_count_32 = 0;
U64 off = dir->location.foff;
off += str8_deserial_read_struct(data, off, &modules_count_32);
U64 modules_count_max = (data.size - off) / sizeof(MDMP_Module);
modules = (MDMP_Module *)(data.str + off);
modules_count = Min(modules_count_32, modules_count_max);
}break;
}
}
}
// rjf: system info -> arch
Arch arch = Arch_Null;
if(system_info != 0) switch(system_info->processor_architecture)
{
default:{}break;
case MDMP_Arch_x86:{arch = Arch_x86;}break;
case MDMP_Arch_x64:{arch = Arch_x64;}break;
}
// rjf: process creation
U64 handle_id_gen = 1;
D_Handle process = d_dump_handle_make(D_MachineID_Local, handle_id_gen);
handle_id_gen += 1;
{
D_Event *evt = d_event_list_push(scratch.arena, &evts);
evt->kind = D_EventKind_NewProc;
evt->msg_id = msg->msg_id;
evt->entity = process;
evt->arch = arch;
}
// rjf: thread creation
for EachIndex(idx, threads_count)
{
MDMP_Thread *thread = &threads[idx];
D_Event *evt = d_event_list_push(scratch.arena, &evts);
evt->kind = D_EventKind_NewThread;
evt->msg_id = msg->msg_id;
evt->entity = d_dump_handle_make(D_MachineID_Local, handle_id_gen);
evt->parent = process;
evt->arch = arch;
evt->entity_id = thread->id;
// TODO(rjf): evt->stack_base = ; (use thread->stack)
// TODO(rjf): evt->tls_root = ; (use thread->thread_context)
handle_id_gen += 1;
}
// rjf: module loads
for EachIndex(idx, modules_count)
{
MDMP_Module *module = &modules[idx];
String8 module_name = {0};
{
U64 module_name_off = module->module_name_foff;
U64 off = module_name_off;
U32 module_name_size = 0;
off += str8_deserial_read_struct(data, off, &module_name_size);
String8 module_name_raw_data = str8_prefix(str8_skip(data, off), module_name_size);
String16 module_name_16 = str16((U16 *)module_name_raw_data.str, module_name_raw_data.size / sizeof(U16));
module_name = str8_from_16(scratch.arena, module_name_16);
}
D_Event *evt = d_event_list_push(scratch.arena, &evts);
evt->kind = D_EventKind_NewModule;
evt->msg_id = msg->msg_id;
evt->entity = d_dump_handle_make(D_MachineID_Local, handle_id_gen);
evt->parent = process;
evt->arch = arch;
evt->vaddr_rng = r1u64(module->image_base_vaddr, module->image_base_vaddr + module->image_size);
evt->string = module_name;
// TODO(rjf): evt->stack_base = ; (use thread->stack)
// TODO(rjf): evt->tls_root = ; (use thread->thread_context)
handle_id_gen += 1;
}
// rjf: push events
d_c2u_push_events(&evts);
scratch_end(scratch);
} }
} }
} }
+2 -1
View File
@@ -351,7 +351,7 @@ thread_static D_EntityCtxLookupAccel *d_entity_ctx_lookup_accel = 0;
internal U64 d_hash_from_handle(D_Handle handle); internal U64 d_hash_from_handle(D_Handle handle);
internal D_EventCause d_event_cause_from_dmn_event_kind(DMN_EventKind event_kind); internal D_EventCause d_event_cause_from_dmn_event_kind(DMN_EventKind event_kind);
internal D_ExceptionKind d_exception_kind_from_dmn(DMN_ExceptionKind kind); internal D_ExceptionKind d_exception_kind_from_dmn(DMN_ExceptionKind kind);
internal D_TlsModel d_dynamic_linker_type_from_dmn(DMN_TlsModel type); internal D_TlsModel d_tls_model_from_dmn(DMN_TlsModel type);
internal String8 d_string_from_event_kind(D_EventKind kind); internal String8 d_string_from_event_kind(D_EventKind kind);
internal String8 d_string_from_msg_kind(D_MsgKind kind); internal String8 d_string_from_msg_kind(D_MsgKind kind);
internal D_EntityKind d_entity_kind_from_string(String8 string); internal D_EntityKind d_entity_kind_from_string(String8 string);
@@ -370,6 +370,7 @@ internal String8 d_string_from_handle(Arena *arena, D_Handle handle);
internal D_Handle d_handle_from_string(String8 string); internal D_Handle d_handle_from_string(String8 string);
internal DMN_Handle d_dmn_from_handle(D_Handle handle); internal DMN_Handle d_dmn_from_handle(D_Handle handle);
internal D_Handle d_handle_from_dmn(D_MachineID machine_id, DMN_Handle handle); internal D_Handle d_handle_from_dmn(D_MachineID machine_id, DMN_Handle handle);
internal D_Handle d_dump_handle_make(D_MachineID machine_id, U64 id);
//////////////////////////////// ////////////////////////////////
//~ rjf: Trap Type Functions //~ rjf: Trap Type Functions
+32 -3
View File
@@ -100,14 +100,14 @@ typedef struct MDMP_LocationDescriptor32 MDMP_LocationDescriptor32;
struct MDMP_LocationDescriptor32 struct MDMP_LocationDescriptor32
{ {
U32 data_size; U32 data_size;
U32 voff; U32 foff;
}; };
typedef struct MDMP_LocationDescriptor64 MDMP_LocationDescriptor64; typedef struct MDMP_LocationDescriptor64 MDMP_LocationDescriptor64;
struct MDMP_LocationDescriptor64 struct MDMP_LocationDescriptor64
{ {
U64 data_size; U64 data_size;
U64 voff; U64 foff;
}; };
typedef struct MDMP_Directory MDMP_Directory; typedef struct MDMP_Directory MDMP_Directory;
@@ -168,7 +168,7 @@ struct MDMP_Module
U32 image_size; U32 image_size;
U32 checksum; U32 checksum;
U32 time_date_stamp; U32 time_date_stamp;
U32 module_name_voff; U32 module_name_foff;
MDMP_FixedFileInfo version_info; MDMP_FixedFileInfo version_info;
MDMP_LocationDescriptor32 cv_record; MDMP_LocationDescriptor32 cv_record;
MDMP_LocationDescriptor32 misc_record; MDMP_LocationDescriptor32 misc_record;
@@ -197,4 +197,33 @@ struct MDMP_ExceptionStream
MDMP_LocationDescriptor32 thread_context; MDMP_LocationDescriptor32 thread_context;
}; };
typedef U16 MDMP_Arch;
typedef enum MDMP_ArchEnum
{
MDMP_Arch_x86 = 0,
MDMP_Arch_Arm = 5,
MDMP_Arch_IA64 = 6,
MDMP_Arch_x64 = 9,
MDMP_Arch_Unknown = 0xffff,
}
MDMP_ArchEnum;
typedef struct MDMP_SystemInfo MDMP_SystemInfo;
struct MDMP_SystemInfo
{
MDMP_Arch processor_architecture;
U16 processor_level;
U16 processor_revision;
U8 number_of_processors;
U8 product_type;
U32 major_version;
U32 minor_version;
U32 build_number;
U32 platform_id;
U32 csd_version_rva;
U16 suite_mask;
U16 padding;
// CPU_INFORMATION Cpu; (architecture dependent)
};
#endif // MINIDUMP_H #endif // MINIDUMP_H