From 834f38f73b352d2f77bf577f0dea3df603674f7d Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 10 Jun 2025 14:14:39 -0700 Subject: [PATCH] pass over rdi dumping code; relocate to rdi_format_local; eliminate redundant helpers; plug into radbin --- src/codeview/codeview.mdesk | 2 +- src/lib_rdi_format/rdi_format_parse.h | 4 +- src/lib_rdi_make/rdi_make.c | 2 +- src/lib_rdi_make/rdi_make.h | 5 +- src/linker/rdi/rdi.c | 13 - src/linker/rdi/rdi.h | 1 - src/os/core/os_core.c | 35 +- src/radbin/radbin.c | 40 +- src/raddump/raddump.c | 1219 ----------------------- src/raddump/raddump.h | 30 - src/rdi_format/rdi_format_local.c | 1310 +++++++++++++++++++++++++ src/rdi_format/rdi_format_local.h | 91 ++ 12 files changed, 1467 insertions(+), 1285 deletions(-) diff --git a/src/codeview/codeview.mdesk b/src/codeview/codeview.mdesk index ac511efd..10a9dd61 100644 --- a/src/codeview/codeview.mdesk +++ b/src/codeview/codeview.mdesk @@ -588,7 +588,7 @@ CV_LeafKindTable: {MATRIX - 0x151c} {VFTABLE - 0x151d} {FUNC_ID FuncId 0x1601} - {MFUNC_ID MFuncId 0x1602} + {MFUNC_ID MFuncId 0x1602} {BUILDINFO BuildInfo 0x1603} {SUBSTR_LIST SubstrList 0x1604} {STRING_ID StringId 0x1605} diff --git a/src/lib_rdi_format/rdi_format_parse.h b/src/lib_rdi_format/rdi_format_parse.h index bf768d9e..f8b7e096 100644 --- a/src/lib_rdi_format/rdi_format_parse.h +++ b/src/lib_rdi_format/rdi_format_parse.h @@ -146,8 +146,8 @@ RDI_PROC RDI_ParseStatus rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out); RDI_PROC void *rdi_section_raw_data_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_SectionEncoding *encoding_out, RDI_U64 *size_out); RDI_PROC void *rdi_section_raw_table_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 *count_out); RDI_PROC void *rdi_section_raw_element_from_kind_idx(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 idx); -#define rdi_table_from_name(rdi, name, count_out) (RDI_SectionElementType_##name *)rdi_section_raw_table_from_kind((rdi), RDI_SectionKind_##name, (count_out)) -#define rdi_element_from_name_idx(rdi, name, idx) (RDI_SectionElementType_##name *)rdi_section_raw_element_from_kind_idx((rdi), RDI_SectionKind_##name, (idx)) +#define rdi_table_from_name(rdi, name, count_out) ((RDI_SectionElementType_##name *)rdi_section_raw_table_from_kind((rdi), RDI_SectionKind_##name, (count_out))) +#define rdi_element_from_name_idx(rdi, name, idx) ((RDI_SectionElementType_##name *)rdi_section_raw_element_from_kind_idx((rdi), RDI_SectionKind_##name, (idx))) //- info about whole parse RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi); diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 1f0f9295..4af2d48c 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -1313,7 +1313,7 @@ rdim_location_set_push_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM scopes->location_count +=1; } -//- location block chunk list +//- rjf:location block chunk list RDI_PROC RDI_LocationBlock * rdim_location_block_chunk_list_push_array(RDIM_Arena *arena, RDIM_String8List *list, RDI_U32 count) diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 743aaff7..a798af08 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1519,9 +1519,8 @@ RDI_PROC RDIM_Location *rdim_push_location_val_reg(RDIM_Arena *arena, RDI_U8 reg //- rjf: location sets RDI_PROC void rdim_location_set_push_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_LocationSet *locset, RDIM_Rng1U64 voff_range, RDIM_Location *location); -//- location block chunk list - -RDI_PROC RDI_LocationBlock * rdim_location_block_chunk_list_push_array(RDIM_Arena *arena, RDIM_String8List *list, RDI_U32 count); +//- rjf:location block chunk list +RDI_PROC RDI_LocationBlock *rdim_location_block_chunk_list_push_array(RDIM_Arena *arena, RDIM_String8List *list, RDI_U32 count); RDI_PROC RDI_U32 rdim_count_from_location_block_chunk_list(RDIM_String8List *list); //////////////////////////////// diff --git a/src/linker/rdi/rdi.c b/src/linker/rdi/rdi.c index 2491ac7b..8b137891 100644 --- a/src/linker/rdi/rdi.c +++ b/src/linker/rdi/rdi.c @@ -1,14 +1 @@ -internal String8 -rdi_string_from_name_map_kind(RDI_NameMapKind kind) -{ - String8 result = {0}; - switch(kind) - { - default:{}break; -#define X(name) case RDI_NameMapKind_##name:{result = str8_lit(#name);}break; - RDI_NameMapKind_XList -#undef X - } - return result; -} diff --git a/src/linker/rdi/rdi.h b/src/linker/rdi/rdi.h index b5d7e894..531a62b0 100644 --- a/src/linker/rdi/rdi.h +++ b/src/linker/rdi/rdi.h @@ -1,5 +1,4 @@ #pragma once -internal String8 rdi_string_from_name_map_kind(RDI_NameMapKind kind); diff --git a/src/os/core/os_core.c b/src/os/core/os_core.c index c305b370..048072e0 100644 --- a/src/os/core/os_core.c +++ b/src/os/core/os_core.c @@ -90,13 +90,40 @@ os_write_data_list_to_file_path(String8 path, String8List list) if(!os_handle_match(file, os_handle_zero())) { good = 1; - U64 off = 0; - for(String8Node *n = list.first; n != 0; n = n->next) + Temp scratch = scratch_begin(0, 0); + U64 write_buffer_size = KB(64); + U8 *write_buffer = push_array_no_zero(scratch.arena, U8, write_buffer_size); + U64 write_buffer_write_pos = 0; + U64 write_buffer_read_pos = 0; + U64 file_off = 0; { - os_file_write(file, r1u64(off, off+n->string.size), n->string.str); - off += n->string.size; + for(String8Node *n = list.first; n != 0; n = n->next) + { + for(U64 n_off = 0; n_off < n->string.size;) + { + U64 write_buffer_unconsumed_size = (write_buffer_write_pos - write_buffer_read_pos); + U64 write_buffer_available_size = (write_buffer_size - write_buffer_unconsumed_size); + if(write_buffer_available_size == 0) + { + os_file_write(file, r1u64(file_off, file_off+write_buffer_size), write_buffer); + file_off += write_buffer_size; + write_buffer_read_pos += write_buffer_size; + } + else + { + U64 bytes_to_copy = Min(write_buffer_available_size, n->string.size - n_off); + write_buffer_write_pos += ring_write(write_buffer, write_buffer_size, write_buffer_write_pos, n->string.str + n_off, bytes_to_copy); + n_off += bytes_to_copy; + } + } + } + if(write_buffer_write_pos > write_buffer_read_pos) + { + os_file_write(file, r1u64(file_off, file_off + (write_buffer_write_pos-write_buffer_read_pos)), write_buffer); + } } os_file_close(file); + scratch_end(scratch); } return good; } diff --git a/src/radbin/radbin.c b/src/radbin/radbin.c index c55fc11c..0ba02424 100644 --- a/src/radbin/radbin.c +++ b/src/radbin/radbin.c @@ -406,10 +406,9 @@ rb_entry_point(CmdLine *cmdline) fprintf(stderr, "%.*s Help\n", str8_varg(output_kind_info[output_kind].title)); fprintf(stderr, "To see top-level options for radbin, run the binary with no arguments.\n\n"); } + fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); } - fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); - ////////////////////////////// //- rjf: perform operation based on output kind // @@ -820,6 +819,8 @@ rb_entry_point(CmdLine *cmdline) // case OutputKind_Dump: { + B32 deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic")); + //- rjf: no inputs => help if(cmdline->inputs.node_count == 0) { @@ -832,7 +833,31 @@ rb_entry_point(CmdLine *cmdline) for(RB_FileNode *n = input_files.first; n != 0; n = n->next) { RB_File *f = n->v; - // TODO(rjf) + str8_list_pushf(arena, &output_blobs, "# %S (%S)\n\n", deterministic ? str8_skip_last_slash(f->path) : f->path, rb_file_format_display_name_table[f->format]); + switch(f->format) + { + default:{}break; + + //- rjf: RDI file + case RB_FileFormat_RDI: + { + RDI_Parsed rdi = {0}; + RDI_ParseStatus rdi_status = rdi_parse(f->data.str, f->data.size, &rdi); + switch(rdi_status) + { + default:{}break; + case RDI_ParseStatus_HeaderDoesNotMatch: {str8_list_pushf(arena, &output_blobs, "");}break; + case RDI_ParseStatus_UnsupportedVersionNumber:{str8_list_pushf(arena, &output_blobs, "");}break; + case RDI_ParseStatus_InvalidDataSecionLayout: {}break; + case RDI_ParseStatus_MissingRequiredSection: {}break; + case RDI_ParseStatus_Good: + { + String8List dump = rdi_dump_list_from_parsed(arena, &rdi, RDI_DumpSubsetFlag_All); + str8_list_concat_in_place(&output_blobs, &dump); + }break; + } + }break; + } } //- rjf: join with output @@ -845,14 +870,7 @@ rb_entry_point(CmdLine *cmdline) // if(output_path.size != 0) ProfScope("write outputs [file]") { - OS_Handle output_file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Write, output_path); - U64 off = 0; - for(String8Node *n = output_blobs.first; n != 0; n = n->next) - { - os_file_write(output_file, r1u64(off, off+n->string.size), n->string.str); - off += n->string.size; - } - os_file_close(output_file); + os_write_data_list_to_file_path(output_path, output_blobs); log_infof("Results written to %S", output_path); } else ProfScope("write outputs [stdout]") diff --git a/src/raddump/raddump.c b/src/raddump/raddump.c index f8114ff5..2e626226 100644 --- a/src/raddump/raddump.c +++ b/src/raddump/raddump.c @@ -249,19 +249,6 @@ rd_string_from_array_hex_u64(Arena *arena, U64 *v, U64 count) return result; } -internal String8 -rd_string_from_range_array_u64_hex(Arena *arena, U64 *v, U64 count) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; - for (U64 i = 0; i+2 <= count; i += 2) { - str8_list_pushf(scratch.arena, &list, "[%#llx, %#llx)", v[i+0], v[i+1]); - } - String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); - scratch_end(scratch); - return result; -} - internal void rd_format_preamble(Arena *arena, String8List *out, String8 indent, String8 input_path, String8 raw_data) { @@ -604,1212 +591,6 @@ rd_print_raw_data(Arena *arena, } } -internal String8 -str8_from_rdi_string_idx(RDI_Parsed *rdi, U32 idx) -{ - String8 result = str8_zero(); - result.str = rdi_string_from_idx(rdi, idx, &result.size); - return result; -} - -internal String8 -rdi_string_from_data_section_kind(Arena *arena, RDI_SectionKind v) -{ - String8 result; - switch (v) { - default: result = push_str8f(arena, "", v); break; -#define X(name, lower, type) case RDI_SectionKind_##name:{result = str8_lit(#name);} break; - RDI_SectionKind_XList -#undef X - } - return result; -} - -internal String8 -rdi_string_from_arch(Arena *arena, RDI_Arch v) -{ - String8 result; - switch (v) { - default:{ result = push_str8f(arena, "", v); } break; -#define X(name) case RDI_LocalKind_##name:{ result = str8_lit(#name); } break; - RDI_LocalKind_XList -#undef X - } - return result; -} - -internal String8 -rdi_string_from_member_kind(Arena *arena, RDI_MemberKind v) -{ - String8 result; - switch (v) { - default: { result = push_str8f(arena, "", v); } break; -#define X(name) case RDI_MemberKind_##name: { result = str8_lit(#name); } break; - RDI_MemberKind_XList -#undef X - } - return result; -} - -internal String8 -rdi_string_from_reg_code_x86(U64 reg_code) -{ -#define X(name, value) case RDI_RegCodeX86_##name: return str8_lit(#name); - switch (reg_code) { - RDI_RegCodeX86_XList - } -#undef X - return str8_lit(""); -} - -internal String8 -rdi_string_from_reg_code_x64(U64 reg_code) -{ -#define X(name, value) case RDI_RegCodeX64_##name: return str8_lit(#name); - switch (reg_code) { - RDI_RegCodeX64_XList - } -#undef X - return str8_lit(""); -} - -internal String8 -rdi_string_from_reg_code(Arena *arena, RDI_Arch arch, U64 reg_code) -{ - switch (arch) { - case RDI_Arch_NULL: break; - case RDI_Arch_X86: return rdi_string_from_reg_code_x86(reg_code); - case RDI_Arch_X64: return rdi_string_from_reg_code_x64(reg_code); - default: InvalidPath; - } - return push_str8f(arena, "??? (%llu)", reg_code); -} - -internal String8 -rdi_string_from_eval_op(Arena *arena, RDI_EvalOp op) -{ - switch (op) { - case RDI_EvalOp_Stop: return str8_lit("Stop"); - case RDI_EvalOp_Noop: return str8_lit("Noop"); - case RDI_EvalOp_Cond: return str8_lit("Cond"); - case RDI_EvalOp_Skip: return str8_lit("Skip"); - case RDI_EvalOp_MemRead: return str8_lit("MemRead"); - case RDI_EvalOp_RegRead: return str8_lit("RegRead"); - case RDI_EvalOp_RegReadDyn: return str8_lit("RegReadDyn"); - case RDI_EvalOp_FrameOff: return str8_lit("FrameOff"); - case RDI_EvalOp_ModuleOff: return str8_lit("ModuleOff"); - case RDI_EvalOp_TLSOff: return str8_lit("TLSOff"); - case RDI_EvalOp_ObjectOff: return str8_lit("ObjectOff"); - case RDI_EvalOp_CFA: return str8_lit("CFA"); - case RDI_EvalOp_ConstU8: return str8_lit("ConstU8"); - case RDI_EvalOp_ConstU16: return str8_lit("ConstU16"); - case RDI_EvalOp_ConstU32: return str8_lit("ConstU32"); - case RDI_EvalOp_ConstU64: return str8_lit("ConstU64"); - case RDI_EvalOp_ConstU128: return str8_lit("ConstU128"); - case RDI_EvalOp_ConstString: return str8_lit("ConstString"); - case RDI_EvalOp_Abs: return str8_lit("Abs"); - case RDI_EvalOp_Neg: return str8_lit("Neg"); - case RDI_EvalOp_Add: return str8_lit("Add"); - case RDI_EvalOp_Sub: return str8_lit("Sub"); - case RDI_EvalOp_Mul: return str8_lit("Mul"); - case RDI_EvalOp_Div: return str8_lit("Div"); - case RDI_EvalOp_Mod: return str8_lit("Mod"); - case RDI_EvalOp_LShift: return str8_lit("LShift"); - case RDI_EvalOp_RShift: return str8_lit("RShift"); - case RDI_EvalOp_BitAnd: return str8_lit("BitAnd"); - case RDI_EvalOp_BitOr: return str8_lit("BitOr"); - case RDI_EvalOp_BitXor: return str8_lit("BitXor"); - case RDI_EvalOp_BitNot: return str8_lit("BitNot"); - case RDI_EvalOp_LogAnd: return str8_lit("LogAnd"); - case RDI_EvalOp_LogOr: return str8_lit("LogOr"); - case RDI_EvalOp_LogNot: return str8_lit("LogNot"); - case RDI_EvalOp_EqEq: return str8_lit("EqEq"); - case RDI_EvalOp_NtEq: return str8_lit("NtEq"); - case RDI_EvalOp_LsEq: return str8_lit("LsEq"); - case RDI_EvalOp_GrEq: return str8_lit("GrEq"); - case RDI_EvalOp_Less: return str8_lit("Less"); - case RDI_EvalOp_Grtr: return str8_lit("Grtr"); - case RDI_EvalOp_Trunc: return str8_lit("Trunc"); - case RDI_EvalOp_TruncSigned: return str8_lit("TruncSigned"); - case RDI_EvalOp_Convert: return str8_lit("Convert"); - case RDI_EvalOp_Pick: return str8_lit("Pick"); - case RDI_EvalOp_Pop: return str8_lit("Pop"); - case RDI_EvalOp_Insert: return str8_lit("Insert"); - case RDI_EvalOp_ValueRead: return str8_lit("ValueRead"); - case RDI_EvalOp_ByteSwap: return str8_lit("ByteSwap"); - case RDI_EvalOp_CallSiteValue: return str8_lit("CallSiteValue"); - case RDI_EvalOp_PartialValue: return str8_lit("PartialValue"); - case RDI_EvalOp_PartialValueBit: return str8_lit("PartialValueBit"); - } - return push_str8f(arena, "%#x", op); -} - -internal String8 -rdi_string_from_eval_type_group(Arena *arena, RDI_EvalTypeGroup x) -{ - switch (x) { - case RDI_EvalTypeGroup_Other: return str8_lit("Other"); - case RDI_EvalTypeGroup_U: return str8_lit("U"); - case RDI_EvalTypeGroup_S: return str8_lit("S"); - case RDI_EvalTypeGroup_F32: return str8_lit("F32"); - case RDI_EvalTypeGroup_F64: return str8_lit("F64"); - } - return push_str8f(arena, "%#x", x); -} - -internal String8 -rdi_string_from_binary_section_flags(Arena *arena, RDI_BinarySectionFlags flags) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; -#define X(name) if (flags & RDI_BinarySectionFlag_##name) { flags &= ~RDI_BinarySectionFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } - RDI_BinarySectionFlags_XList; -#undef X - String8 result = rd_string_from_flags(arena, list, flags); - scratch_end(scratch); - return result; -} - -internal String8 -rdi_string_from_type_modifier_flags(Arena *arena, RDI_TypeModifierFlags flags) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; -#define X(name) if(flags & RDI_TypeModifierFlag_##name) { flags &= ~RDI_TypeModifierFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } - RDI_TypeModifierFlags_XList; -#undef X - String8 result = rd_string_from_flags(arena, list, flags); - scratch_end(scratch); - return result; -} - -internal String8 -rdi_string_from_udt_flags(Arena *arena, RDI_UDTFlags flags) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; -#define X(name) if (flags & RDI_UDTFlag_##name) { flags &= ~RDI_UDTFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } - RDI_UDTFlags_XList; -#undef X - String8 result = rd_string_from_flags(arena, list, flags); - scratch_end(scratch); - return result; -} - -internal String8 -rdi_string_from_link_flags(Arena *arena, RDI_LinkFlags flags) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; -#define X(name) if (flags & RDI_LinkFlag_##name) { flags &= ~RDI_LinkFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } - RDI_LinkFlags_XList; -#undef X - String8 result = rd_string_from_flags(arena, list, flags); - scratch_end(scratch); - return result; -} - -internal void -rdi_print_data_sections(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi) -{ - Temp scratch = scratch_begin(&arena, 1); - for(U64 idx = 0; idx < rdi->sections_count; idx += 1) { - RDI_SectionKind kind = (RDI_SectionKind)idx; - RDI_Section *section = &rdi->sections[idx]; - String8 kind_str = rdi_string_from_data_section_kind(scratch.arena, kind); - rd_printf("data_section[%5llu] = {%#08llx, %7u, %7u}, %S", idx, section->off, section->encoded_size, section->unpacked_size, kind_str); - } - scratch_end(scratch); -} - -internal void -rdi_print_top_level_info(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_TopLevelInfo *tli) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("arch =%S", rdi_string_from_arch(scratch.arena, tli->arch)); - rd_printf("exe_name ='%S'", str8_from_rdi_string_idx(rdi, tli->exe_name_string_idx)); - rd_printf("voff_max =%#08llx", tli->voff_max); - rd_printf("producer_name='%S'", str8_from_rdi_string_idx(rdi, tli->producer_name_string_idx)); - scratch_end(scratch); -} - -internal void -rdi_print_binary_section(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_BinarySection *bin_section) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, bin_section->name_string_idx)); - rd_printf("flags =%S", rdi_string_from_binary_section_flags(scratch.arena, bin_section->flags)); - rd_printf("voff_first=%#08x", bin_section->voff_first); - rd_printf("voff_opl =%#08x", bin_section->voff_opl); - rd_printf("foff_first=%#08x", bin_section->foff_first); - rd_printf("foff_opl =%#08x", bin_section->foff_opl); - scratch_end(scratch); -} - -internal void -rdi_print_file_path(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_FilePathNode *file_path) -{ - U64 file_path_count = 0; - RDI_FilePathNode *file_path_array = rdi_table_from_name(rdi, FilePathNodes, &file_path_count); - - String8 name = str8_from_rdi_string_idx(rdi, file_path->name_string_idx); - U64 this_idx = (U64)(file_path - file_path_array); - - if (file_path->source_file_idx == 0) { - rd_printf("[%llu] '%S'", this_idx, name); - } else { - rd_printf("[%llu] '%S'; source_file=%u", this_idx, name, file_path->source_file_idx); - } - - for (U32 child = file_path->first_child; child != 0; ) { - // get node for child - RDI_FilePathNode *child_node = 0; - if (child < file_path_count) { - child_node = file_path_array + child; - } - if (child_node == 0) { - break; - } - - // stringize child - rd_indent(); - rdi_print_file_path(arena, out, indent, rdi, child_node); - rd_unindent(); - - // increment iterator - child = child_node->next_sibling; - } -} - -internal void -rdi_print_source_file(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_SourceFile *source_file) -{ - rd_printf("{ file_path_node_idx= "); - rd_printf("file_path_node_idx= %u", source_file->file_path_node_idx); - rd_printf("path= '%S'", str8_from_rdi_string_idx(rdi, source_file->normal_full_path_string_idx)); - rd_printf("source_line_map= %u", source_file->source_line_map_idx); -} - -internal void -rdi_print_line_table(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_LineTable *line_table) -{ - RDI_ParsedLineTable parsed_line_table = {0}; - rdi_parsed_from_line_table(rdi, line_table, &parsed_line_table); - - rd_printf("lines:"); - for (U32 i = 0; i < parsed_line_table.count; i += 1) { - U64 first = parsed_line_table.voffs[i]; - U64 opl = parsed_line_table.voffs[i + 1]; - RDI_Line *line = parsed_line_table.lines + i; - RDI_Column *col = 0; - if (i < parsed_line_table.col_count) { - col = parsed_line_table.cols + i; - } - if (col == 0) { - rd_printf("[0x%08llx,0x%08llx) file=%u; line=%u", first, opl, line->file_idx, line->line_num); - } else { - rd_printf("[0x%08llx,0x%08llx) file=%u; line=%u; columns=[%u,%u)", first, opl, line->file_idx, line->line_num, col->col_first, col->col_opl); - } - } -} - -internal void -rdi_print_source_line_map(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_SourceLineMap *map) -{ - Temp scratch = scratch_begin(&arena, 1); - - RDI_ParsedSourceLineMap line_map = {0}; - rdi_parsed_from_source_line_map(rdi, map, &line_map); - - rd_printf("source lines:"); - for (U32 line_num_idx = 0; line_num_idx < line_map.count; ++line_num_idx) { - Temp temp = temp_begin(scratch.arena); - - String8List list = {0}; - U32 voff_lo = line_map.ranges[line_num_idx]; - U32 voff_hi = ClampTop(line_map.ranges[line_num_idx + 1], line_map.voff_count); - for (U64 voff_idx = voff_lo; voff_idx < voff_hi; ++voff_idx) { - str8_list_pushf(temp.arena, &list, "%#llx", line_map.voffs[voff_idx]); - } - - String8 voffs = str8_list_join(temp.arena, &list, &(StringJoin){.sep=str8_lit(", ")}); - rd_printf("%u: %S", line_map.nums[line_num_idx], voffs); - - temp_end(temp); - } - - scratch_end(scratch); -} - -internal void -rdi_print_unit(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Unit *unit) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("unit_name ='%S'", str8_from_rdi_string_idx(rdi, unit->unit_name_string_idx)); - rd_printf("compiler_name ='%S'", str8_from_rdi_string_idx(rdi, unit->compiler_name_string_idx)); - rd_printf("source_file_path =%u", unit->source_file_path_node); - rd_printf("object_file_path =%u", unit->object_file_path_node); - rd_printf("archive_file_path=%u", unit->archive_file_path_node); - rd_printf("build_path =%u", unit->build_path_node); - rd_printf("language =%S", rdi_string_from_language(scratch.arena, unit->language)); - rd_printf("line_table_idx =%u", unit->line_table_idx); - scratch_end(scratch); -} - -internal void -rdi_print_type_node(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_TypeNode *type) -{ - Temp scratch = scratch_begin(&arena, 1); - - String8 type_kind_str = {0}; - type_kind_str.str = rdi_string_from_type_kind(type->kind, &type_kind_str.size); - - rd_printf("kind =%S", type_kind_str); - if (type->kind == RDI_TypeKind_Modifier) { - rd_printf("flags =%S", rdi_string_from_type_modifier_flags(scratch.arena, type->flags)); - } else { - if (type->flags != 0) { - rd_printf("flags=%#x (missing stringizer path)", type->flags); - } - } - rd_printf("byte_size =%u", type->byte_size); - if (RDI_TypeKind_FirstBuiltIn <= type->kind && type->kind <= RDI_TypeKind_LastBuiltIn) { - rd_printf("built_in.name ='%S'", str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx)); - } else if (type->kind == RDI_TypeKind_Array) { - rd_printf("constructed.direct_type =%u", type->constructed.direct_type_idx); - rd_printf("constructed.array_count =%u", type->constructed.count); - } else if (type->kind == RDI_TypeKind_Function) { - U32 param_idx_count = 0; - U32 *param_idx_array = rdi_idx_run_from_first_count(rdi, type->constructed.param_idx_run_first, type->constructed.count, ¶m_idx_count); - String8 param_idx_str = rd_string_from_array_u32(scratch.arena, param_idx_array, param_idx_count); - rd_printf("constructed.params =%S", param_idx_str); - rd_printf("return type =%u", type->constructed.direct_type_idx); - } else if (type->kind == RDI_TypeKind_Method) { - U32 param_idx_count = 0; - U32 *param_idx_array = rdi_idx_run_from_first_count(rdi, type->constructed.param_idx_run_first, type->constructed.count, ¶m_idx_count); - String8 this_type_str = str8_lit("\?\?\?"); - if (param_idx_count > 0) { - this_type_str = push_str8f(scratch.arena, "%u", param_idx_array[0]); - param_idx_count -= 1; - param_idx_array += 1; - } - String8 param_idx_str = rd_string_from_array_u32(scratch.arena, param_idx_array, param_idx_count); - rd_printf("constructed.this_type =%S", this_type_str); - rd_printf("constructed.params =%S", param_idx_str); - rd_printf("return type =%u", type->constructed.direct_type_idx); - } else if (RDI_TypeKind_FirstConstructed <= type->kind && type->kind <= RDI_TypeKind_LastConstructed) { - - rd_printf("constructed.direct_type =%u", type->constructed.direct_type_idx); - } else if (RDI_TypeKind_FirstUserDefined <= type->kind && type->kind <= RDI_TypeKind_LastUserDefined){ - rd_printf("user_defined.name ='%S'", str8_from_rdi_string_idx(rdi, type->user_defined.name_string_idx)); - rd_printf("user_defined.direct_type=%u", type->user_defined.direct_type_idx); - rd_printf("user_defined.udt =%u", type->user_defined.udt_idx); - } else if (type->kind == RDI_TypeKind_Bitfield) { - rd_printf("bitfield.off =%u", type->bitfield.off); - rd_printf("bitfield.size =%u", type->bitfield.size); - } - - scratch_end(scratch); -} - -internal void -rdi_print_udt(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_UDT *udt) -{ - Temp scratch = scratch_begin(&arena, 1); - - U64 member_count = 0; - U64 enum_member_count = 0; - RDI_Member *member_array = rdi_table_from_name(rdi, Members, &member_count); - RDI_EnumMember *enum_member_array = rdi_table_from_name(rdi, EnumMembers, &enum_member_count); - - String8 flags_str = rdi_string_from_udt_flags(scratch.arena, udt->flags); - - rd_printf("self_type=%u", udt->self_type_idx); - rd_printf("flags =%S", flags_str); - if (udt->file_idx != 0) { - rd_printf("loc ={file=%u; line=%u; col=%u}", udt->file_idx, udt->line, udt->col); - } - - // enum members - if (udt->flags & RDI_UDTFlag_EnumMembers) { - U32 member_hi = ClampTop(udt->member_first + udt->member_count, enum_member_count); - U32 member_lo = ClampTop(udt->member_first, member_hi); - if (member_lo < member_hi) { - rd_printf("members={"); - rd_indent(); - RDI_EnumMember *enum_member = enum_member_array + member_lo; - for (U32 i = member_lo; i < member_hi; ++i, ++enum_member) { - rd_printf("{ %llu, '%S' }", enum_member->val, str8_from_rdi_string_idx(rdi, enum_member->name_string_idx)); - } - rd_unindent(); - rd_printf("}"); - } - } - // field members - else { - U32 member_hi = ClampTop(udt->member_first + udt->member_count, member_count); - U32 member_lo = ClampTop(udt->member_first, member_hi); - if (member_lo < member_hi) { - rd_printf("members={"); - rd_indent(); - RDI_Member *member = member_array + member_lo; - for (U32 i = member_lo; i < member_hi; ++i, ++member) { - String8 kind_str = rdi_string_from_member_kind(scratch.arena, member->kind); - String8 name_str = str8_from_rdi_string_idx(rdi, member->name_string_idx); - rd_printf("{ kind=%S, type=%u, off=%u, name='%S' }", kind_str, member->type_idx, member->off, name_str); - } - rd_unindent(); - rd_printf("}"); - } - } - scratch_end(scratch); -} - -internal String8 -rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc) -{ - Temp scratch = scratch_begin(&arena, 1); - - String8List fmt = {0}; - for (U64 cursor = 0; cursor < bc.size; ) { - RDI_EvalOp op = RDI_EvalOp_Stop; - cursor += str8_deserial_read_struct(bc, cursor, &op); - - U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; - U32 imm_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); - - String8 imm = {0}; - cursor += str8_deserial_read_block(bc, cursor, imm_size, &imm); - if (imm.size != imm_size) { - str8_list_pushf(scratch.arena, &fmt, "(ERROR: not enough bytes to read immediate)"); - break; - } - - String8 imm_fmt = {0}; - switch (op) { - case RDI_EvalOp_Stop: goto exit; - case RDI_EvalOp_Noop: break; - case RDI_EvalOp_Cond: break; - case RDI_EvalOp_Skip: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U16 *)imm.str); - } break; - case RDI_EvalOp_MemRead: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U8 *)imm.str); - } break; - case RDI_EvalOp_RegRead: { - U32 regread = *(U32 *)imm.str; - RDI_RegCode reg_code = Extract8(regread, 0); - U8 byte_size = Extract8(regread, 1); - U8 byte_off = Extract8(regread, 2); - String8 reg_str = rdi_string_from_reg_code(scratch.arena, arch, reg_code); - imm_fmt = push_str8f(scratch.arena, "%S, Size: %u", rd_string_from_reg_off(scratch.arena, reg_str, byte_off), byte_size); - } break; - case RDI_EvalOp_RegReadDyn: break; - case RDI_EvalOp_FrameOff: { - imm_fmt = push_str8f(scratch.arena, "%+lld", *(S64 *)imm.str); - } break; - case RDI_EvalOp_ModuleOff: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); - } break; - case RDI_EvalOp_TLSOff: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); - } break; - case RDI_EvalOp_ConstU8: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U8 *)imm.str); - } break; - case RDI_EvalOp_ConstU16: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U16 *)imm.str); - } break; - case RDI_EvalOp_ConstU32: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); - } break; - case RDI_EvalOp_ConstU64: { - imm_fmt = push_str8f(scratch.arena, "%llu", *(U64 *)imm.str); - } break; - case RDI_EvalOp_ConstU128: { - imm_fmt = push_str8f(scratch.arena, "Lo: %llu, Hi: %llu", *(U64 *)imm.str, *((U64 *)imm.str + 1)); - } break; - case RDI_EvalOp_ConstString: { - U8 size = *(U8 *)imm.str; - String8 string = {0}; - cursor += str8_deserial_read_block(bc, cursor, size, &string); - - imm_fmt = push_str8f(scratch.arena, "(%u) \"%S\"", size, string); - } break; - case RDI_EvalOp_Abs: - case RDI_EvalOp_Neg: - case RDI_EvalOp_Add: - case RDI_EvalOp_Sub: - case RDI_EvalOp_Mul: - case RDI_EvalOp_Div: - case RDI_EvalOp_Mod: - case RDI_EvalOp_LShift: - case RDI_EvalOp_RShift: - case RDI_EvalOp_BitAnd: - case RDI_EvalOp_BitOr: - case RDI_EvalOp_BitXor: - case RDI_EvalOp_BitNot: - case RDI_EvalOp_LogAnd: - case RDI_EvalOp_LogOr: - case RDI_EvalOp_LogNot: - case RDI_EvalOp_EqEq: - case RDI_EvalOp_NtEq: - case RDI_EvalOp_LsEq: - case RDI_EvalOp_GrEq: - case RDI_EvalOp_Less: - case RDI_EvalOp_Grtr: { - U8 eval_type_group = *(U8 *)imm.str; - imm_fmt = rdi_string_from_eval_type_group(scratch.arena, eval_type_group); - } break; - case RDI_EvalOp_Trunc: - case RDI_EvalOp_TruncSigned: { - U8 trunc = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", trunc); - } break; - case RDI_EvalOp_Convert: { - U16 convert = *(U16 *)imm.str; - U8 in = Extract8(convert, 0); - U8 out = Extract8(convert, 1); - String8 in_str = rdi_string_from_eval_type_group(scratch.arena, in); - String8 out_str = rdi_string_from_eval_type_group(scratch.arena, out); - imm_fmt = push_str8f(scratch.arena, "in: %S out: %S", in_str, out_str); - } break; - case RDI_EvalOp_Pick: { - U8 pick = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", pick); - } break; - case RDI_EvalOp_Pop: break; - case RDI_EvalOp_Insert: { - U8 insert = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", insert); - } break; - case RDI_EvalOp_ValueRead: { - U8 bytes_to_read = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", bytes_to_read); - } break; - case RDI_EvalOp_ByteSwap: { - U8 byte_size = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", byte_size); - } break; - case RDI_EvalOp_CallSiteValue: { - U32 call_site_bc_size = *(U32 *)imm.str; - String8 call_site_bc = {0}; - cursor += str8_deserial_read_block(bc, cursor, call_site_bc_size, &call_site_bc); - - String8 call_site_str = rdi_string_from_bytecode(scratch.arena, arch, call_site_bc); - imm_fmt = push_str8f(scratch.arena, "%S", call_site_str); - } break; - case RDI_EvalOp_PartialValue: { - U32 partial_value_size = *(U32 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", partial_value_size); - } break; - case RDI_EvalOp_PartialValueBit: { - U64 partial_value = *(U64 *)imm.str; - U32 bit_size = Extract32(partial_value, 0); - U32 bit_off = Extract32(partial_value, 1); - imm_fmt = push_str8f(scratch.arena, "Off: %u, Size: %u", bit_size, bit_off); - } break; - } - - String8 op_str = rdi_string_from_eval_op(scratch.arena, op); - if (imm_fmt.size) { - str8_list_pushf(scratch.arena, &fmt, "RDI_EvalOp_%S(%S)", op_str, imm_fmt); - } else { - str8_list_pushf(scratch.arena, &fmt, "RDI_EvalOp_%S", op_str); - } - } - exit:; - - String8 result = str8_list_join(arena, &fmt, &(StringJoin){.sep = str8_lit(", ")}); - - scratch_end(scratch); - return result; -} - -internal void -rdi_print_locations(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Arch arch, U64 block_lo, U64 block_hi) -{ - Temp scratch = scratch_begin(&arena, 1); - - U64 location_block_count = 0; - U64 location_data_size = 0; - RDI_LocationBlock *location_block_array = rdi_table_from_name(rdi, LocationBlocks, &location_block_count); - RDI_U8 *location_data = rdi_table_from_name(rdi, LocationData, &location_data_size); - - block_lo = ClampTop(block_lo, location_block_count); - block_hi = ClampTop(block_hi, location_block_count); - - for (U32 block_idx = block_lo; block_idx < block_hi; ++block_idx) { - RDI_LocationBlock *block_ptr = &location_block_array[block_idx]; - - String8List fmt = {0}; - - if (block_ptr->scope_off_first == 0 && block_ptr->scope_off_opl == max_U32) { - str8_list_pushf(scratch.arena, &fmt, "*always*:"); - } else { - str8_list_pushf(scratch.arena, &fmt, "[%#08x, %#08x):", block_ptr->scope_off_first, block_ptr->scope_off_opl); - } - - if (block_ptr->location_data_off >= location_data_size) { - str8_list_pushf(scratch.arena, &fmt, "", block_ptr->location_data_off); - } else { - U8 *loc_data_opl = location_data + location_data_size; - U8 *loc_base_ptr = location_data + block_ptr->location_data_off; - RDI_LocationKind kind = *(RDI_LocationKind*)loc_base_ptr; - switch (kind) { - default: { - str8_list_pushf(scratch.arena, &fmt, "\?\?\?: %u", kind); - } break; - - case RDI_LocationKind_AddrBytecodeStream: { - String8 bc = str8_range(loc_base_ptr + 1, loc_data_opl); - String8 bc_str = rdi_string_from_bytecode(scratch.arena, arch, bc); - str8_list_pushf(scratch.arena, &fmt, "AddrBytecodeStream(%S)", bc_str); - } break; - - case RDI_LocationKind_ValBytecodeStream: { - String8 bc = str8_range(loc_base_ptr + 1, loc_data_opl); - String8 bc_str = rdi_string_from_bytecode(scratch.arena, arch, bc); - str8_list_pushf(scratch.arena, &fmt, "ValBytecodeStream(%S)", bc_str); - } break; - - case RDI_LocationKind_AddrRegPlusU16: { - if (loc_base_ptr + sizeof(RDI_LocationRegPlusU16) > loc_data_opl) { - str8_list_pushf(scratch.arena, &fmt, "AddrRegPlusU16(\?\?\?)"); - } else { - RDI_LocationRegPlusU16 *loc = (RDI_LocationRegPlusU16*)loc_base_ptr; - str8_list_pushf(scratch.arena, &fmt, "AddrRegPlusU16(reg: %S, off: %u)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code), loc->offset); - } - } break; - - case RDI_LocationKind_AddrAddrRegPlusU16: { - if (loc_base_ptr + sizeof(RDI_LocationRegPlusU16) > loc_data_opl){ - str8_list_pushf(scratch.arena, &fmt, "AddrAddrRegPlusU16(\?\?\?)"); - } else { - RDI_LocationRegPlusU16 *loc = (RDI_LocationRegPlusU16 *)loc_base_ptr; - str8_list_pushf(scratch.arena, &fmt, "AddrAddrRegisterPlusU16(reg: %S, off: %u)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code), loc->offset); - } - } break; - - case RDI_LocationKind_ValReg: { - if (loc_base_ptr + sizeof(RDI_LocationReg) > loc_data_opl) { - str8_list_pushf(scratch.arena, &fmt, "ValReg(\?\?\?)"); - } else { - RDI_LocationReg *loc = (RDI_LocationReg*)loc_base_ptr; - str8_list_pushf(scratch.arena, &fmt, "ValReg(reg: %S)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code)); - } - } break; - } - } - - String8 print_string = str8_list_join(scratch.arena, &fmt, &(StringJoin){.sep=str8_lit(" ")}); - rd_printf("%S", print_string); - } - - scratch_end(scratch); -} - -internal void -rdi_print_global_variable(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_GlobalVariable *gvar) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, gvar->name_string_idx)); - rd_printf("link_flags =%S", rdi_string_from_link_flags(scratch.arena, gvar->link_flags)); - rd_printf("voff =%#08x", gvar->voff); - rd_printf("type_idx =%u", gvar->type_idx); - rd_printf("container_idx=%u", gvar->container_idx); - scratch_end(scratch); -} - -internal void -rdi_print_thread_variable(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_ThreadVariable *tvar) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, tvar->name_string_idx)); - rd_printf("link_flags =%S", rdi_string_from_link_flags(scratch.arena, tvar->link_flags)); - rd_printf("tls_off =%#08x", tvar->tls_off); - rd_printf("type_idx =%u", tvar->type_idx); - rd_printf("container_idx=%u", tvar->container_idx); - scratch_end(scratch); -} - -internal void -rdi_print_constant(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Constant *constant) -{ - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, constant->name_string_idx)); - rd_printf("type_idx ='%u'", constant->type_idx); -} - -internal void -rdi_print_procedure(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Procedure *proc, RDI_Arch arch) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, proc->name_string_idx)); - rd_printf("link_name ='%S'", str8_from_rdi_string_idx(rdi, proc->link_name_string_idx)); - rd_printf("link_flags =%S", rdi_string_from_link_flags(scratch.arena, proc->link_flags)); - rd_printf("type_idx =%u", proc->type_idx); - rd_printf("root_scope_idx =%u", proc->root_scope_idx); - rd_printf("container_idx =%u", proc->container_idx); - rd_printf("frame_base (first=%u, opl=%u)", proc->frame_base_location_first, proc->frame_base_location_opl); - rd_indent(); - rdi_print_locations(arena, out, indent, rdi, arch, proc->frame_base_location_first, proc->frame_base_location_opl); - rd_unindent(); - - scratch_end(scratch); -} - -internal void -rdi_print_scope(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Scope *scope, RDI_Arch arch) -{ - Temp scratch = scratch_begin(&arena, 1); - - U64 scope_count = 0; - U64 scope_voff_count = 0; - U64 local_count = 0; - U64 proc_count = 0; - U64 inline_site_count = 0; - RDI_Scope *scope_array = rdi_table_from_name(rdi, Scopes, &scope_count); - U64 *scope_voff_array = rdi_table_from_name(rdi, ScopeVOffData, &scope_voff_count); - RDI_Local *local_array = rdi_table_from_name(rdi, Locals, &local_count); - RDI_Procedure *proc_array = rdi_table_from_name(rdi, Procedures, &proc_count); - RDI_InlineSite *inline_site_array = rdi_table_from_name(rdi, InlineSites, &inline_site_count); - - U32 voff_range_lo = ClampTop(scope->voff_range_first, scope_voff_count); - U32 voff_range_hi = ClampTop(scope->voff_range_opl, scope_voff_count); - U32 voff_range_count = (voff_range_hi - voff_range_lo); - U64 *voff_ptr = scope_voff_array + voff_range_lo; - String8 voff_str = rd_string_from_range_array_u64_hex(scratch.arena, voff_ptr, voff_range_count); - - U64 scope_idx = (U64)(scope - scope_array); - rd_printf("scope[%llu]", scope_idx); - rd_indent(); - - String8 proc_name = str8_lit("???"); - if (scope->proc_idx < proc_count) { - RDI_Procedure *proc = &proc_array[scope->proc_idx]; - proc_name = str8_from_rdi_string_idx(rdi, proc->name_string_idx); - } - - String8 inline_site_name = str8_lit(""); - if (scope->inline_site_idx != 0) { - if (scope->inline_site_idx < inline_site_count) { - RDI_InlineSite *inline_site = &inline_site_array[scope->inline_site_idx]; - inline_site_name = str8_from_rdi_string_idx(rdi, inline_site->name_string_idx); - } else { - inline_site_name = str8_lit("???"); - } - inline_site_name = push_str8f(scratch.arena, " '%S'", inline_site_name); - } - - rd_printf("proc_idx =%u '%S'", scope->proc_idx, proc_name); - rd_printf("first_child_scope_idx =%u", scope->first_child_scope_idx); - rd_printf("next_sibling_scope_idx=%u", scope->next_sibling_scope_idx); - rd_printf("inline_site_idx =%u%S", scope->inline_site_idx, inline_site_name); - rd_printf("voff_ranges =%S", voff_str); - - // local_array - { - U32 local_lo = ClampTop(scope->local_first, local_count); - U32 local_hi = ClampTop(local_lo + scope->local_count, local_count); - if (local_lo < local_hi) { - for (U32 local_idx = local_lo; local_idx < local_hi; ++local_idx) { - RDI_Local *local_ptr = &local_array[local_idx]; - - rd_printf("local[%u]", local_idx); - rd_indent(); - rd_printf("kind =%S", rdi_string_from_local_kind(scratch.arena, local_ptr->kind)); - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, local_ptr->name_string_idx)); - rd_printf("type_idx=%u", local_ptr->type_idx); - - if (local_ptr->location_first < local_ptr->location_opl) { - rd_printf("locations:"); - rd_indent(); - rdi_print_locations(arena, out, indent, rdi, arch, local_ptr->location_first, local_ptr->location_opl); - rd_unindent(); - } - rd_unindent(); - } - } - } - - for (U32 child_scope_idx = scope->first_child_scope_idx; child_scope_idx != 0; ) { - if (child_scope_idx >= scope_count) { - rd_errorf("child scope index (%u) is out of bounds", child_scope_idx); - break; - } - - rd_indent(); - RDI_Scope *child_scope = scope_array + child_scope_idx; - rdi_print_scope(arena, out, indent, rdi, child_scope, arch); - rd_unindent(); - - // advance to next child - child_scope_idx = child_scope->next_sibling_scope_idx; - } - - rd_unindent(); - rd_printf("[/%llu]", scope_idx); - - scratch_end(scratch); -} - -internal void -rdi_print_inline_site(Arena *arena, - String8List *out, - String8 indent, - RDI_Parsed *rdi, - U64 idx, - RDI_InlineSite *inline_site) -{ - Temp scratch = scratch_begin(&arena, 1); - String8 inline_site_idx = push_str8f(scratch.arena, "inline_site[%u]", idx); - String8 type_idx = push_str8f(scratch.arena, "type_idx = %u,", inline_site->type_idx); - String8 owner_type_idx = push_str8f(scratch.arena, "owner_type_idx = %u,", inline_site->owner_type_idx); - String8 line_table_idx = push_str8f(scratch.arena, "line_table_idx = %u,", inline_site->line_table_idx); - rd_printf("%-20S = { %-25S %-25S %-25S name = '%-20S' }", - inline_site_idx, - type_idx, - owner_type_idx, - line_table_idx, - str8_from_rdi_string_idx(rdi, inline_site->name_string_idx)); - scratch_end(scratch); -} - -internal void -rdi_print_vmap_entry(Arena *arena, String8List *out, String8 indent, RDI_VMapEntry *v) -{ - rd_printf("%#llx: %llu", v->voff, v->idx); -} - -internal void -rdi_print(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RD_Option opts) -{ - RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); - - if (opts & RD_Option_RdiDataSections) { - rd_printf("# DATA SECTIONS"); - rd_indent(); - rdi_print_data_sections(arena, out, indent, rdi); - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiTopLevelInfo) { - rd_printf("# TOP LEVEL INFO"); - rd_indent(); - rdi_print_top_level_info(arena, out, indent, rdi, tli); - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiBinarySections) { - U64 count; - RDI_BinarySection *v = rdi_table_from_name(rdi, BinarySections, &count); - rd_printf("# BINARY SECTIONS"); - rd_indent(); - for (U64 idx = 0; idx < count; ++idx) { - rd_printf("section[%llu]:", idx); - rd_indent(); - rdi_print_binary_section(arena, out, indent, rdi, &v[idx]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiFilePaths) { - U64 file_path_count = 0; - RDI_FilePathNode *file_path_array = rdi_table_from_name(rdi, FilePathNodes, &file_path_count); - rd_printf("# FILE PATHS"); - rd_indent(); - for (U64 i = 0; i < file_path_count; ++i) { - if (file_path_array[i].parent_path_node == 0) { - rdi_print_file_path(arena, out, indent, rdi, &file_path_array[i]); - } - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiSourceFiles) { - U64 source_file_count = 0; - RDI_SourceFile *source_file_array = rdi_table_from_name(rdi, SourceFiles, &source_file_count); - rd_printf("# SOURCE FILES"); - rd_indent(); - for (U64 i = 0; i < source_file_count; ++i) { - RDI_SourceFile *source_file = &source_file_array[i]; - rd_printf("source_file[%4llu] = { file_path_node_idx = %4u, source_line_map = %4u, path = '%S' }", - i, - source_file->file_path_node_idx, - source_file->source_line_map_idx, - str8_from_rdi_string_idx(rdi, source_file->normal_full_path_string_idx)); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiUnits) { - U64 unit_count = 0; - RDI_Unit *unit_array = rdi_table_from_name(rdi, Units, &unit_count); - rd_printf("# UNITS"); - rd_indent(); - for (U64 i = 0; i < unit_count; ++i) { - rd_printf("unit[%llu]:", i); - rd_indent(); - rdi_print_unit(arena, out, indent, rdi, &unit_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiUnitVMap) { - U64 vmap_count = 0; - RDI_VMapEntry *vmap_array = rdi_table_from_name(rdi, UnitVMap, &vmap_count); - rd_printf("# UNIT VMAP"); - rd_indent(); - for (U64 i = 0; i < vmap_count; ++i) { - rdi_print_vmap_entry(arena, out, indent, &vmap_array[i]); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiLineTables) { - U64 line_table_count = 0; - RDI_LineTable *line_table_array = rdi_table_from_name(rdi, LineTables, &line_table_count); - rd_printf("# LINE TABLES"); - rd_indent(); - for (U64 i = 0; i < line_table_count; ++i) { - rd_printf("line_table[%llu]", i); - rd_indent(); - rdi_print_line_table(arena, out, indent, rdi, &line_table_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiSourceLineMaps) { - U64 source_line_map_count = 0; - RDI_SourceLineMap *source_line_map_array = rdi_table_from_name(rdi, SourceLineMaps, &source_line_map_count); - rd_printf("# SOURCE LINE MAPS"); - rd_indent(); - for (U64 i = 0; i < source_line_map_count; ++i) { - rd_printf("source_line_map[%llu]:", i); - rd_indent(); - rdi_print_source_line_map(arena, out, indent, rdi, &source_line_map_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiTypeNodes) { - U64 type_node_count = 0; - RDI_TypeNode *type_node_array = rdi_table_from_name(rdi, TypeNodes, &type_node_count); - rd_printf("# TYPE NODES"); - rd_indent(); - for (U64 i = 0; i < type_node_count; ++i) { - rd_printf("type[%llu]", i); - rd_indent(); - rdi_print_type_node(arena, out, indent, rdi, &type_node_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiUserDefinedTypes) { - U64 udt_count = 0; - RDI_UDT *udt_array = rdi_table_from_name(rdi, UDTs, &udt_count); - rd_printf("# UDTS"); - rd_indent(); - for (U64 i = 0; i < udt_count; ++i) { - rd_printf("udt[%u]:", i); - rd_indent(); - rdi_print_udt(arena, out, indent, rdi, &udt_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiGlobalVars) { - U64 gvar_count = 0; - RDI_GlobalVariable *gvar_array = rdi_table_from_name(rdi, GlobalVariables, &gvar_count); - rd_printf("# GLOBAL VARIABLES"); - rd_indent(); - for (U64 i = 0; i < gvar_count; ++i) { - rd_printf("global_variable[%llu]:", i); - rd_indent(); - rdi_print_global_variable(arena, out, indent, rdi, &gvar_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiGlobalVarsVMap) { - U64 vmap_count = 0; - RDI_VMapEntry *vmap_array = rdi_table_from_name(rdi, GlobalVMap, &vmap_count); - rd_printf("# GLOBAL VMAP"); - rd_indent(); - for (U64 i = 0; i < vmap_count; ++i) { - rdi_print_vmap_entry(arena, out, indent, &vmap_array[i]); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiThreadVars) { - U64 tvar_count = 0; - RDI_ThreadVariable *tvar_array = rdi_table_from_name(rdi, ThreadVariables, &tvar_count); - rd_printf("# THREAD VARIABLES"); - rd_indent(); - for (U64 i = 0; i < tvar_count; ++i) { - rd_printf("thread_variable[%llu]:", i); - rd_indent(); - rdi_print_thread_variable(arena, out, indent, rdi, &tvar_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiConstants) { - U64 constants_count = 0; - RDI_Constant *constants_array = rdi_table_from_name(rdi, Constants, &constants_count); - rd_printf("# CONSTANTS"); - rd_indent(); - for (U64 i = 0; i < constants_count; ++i) { - rd_printf("constant[%llu]:", i); - rd_indent(); - rdi_print_constant(arena, out, indent, rdi, &constants_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiProcedures) { - U64 proc_count = 0; - RDI_Procedure *proc_array = rdi_table_from_name(rdi, Procedures, &proc_count); - rd_printf("# PROCEDURES"); - rd_indent(); - for (U64 i = 0; i < proc_count; ++i) { - rd_printf("procedure[%llu]:", i); - rd_indent(); - rdi_print_procedure(arena, out, indent, rdi, &proc_array[i], tli->arch); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiScopes) { - U64 scope_count = 0; - RDI_Scope *scope_array = rdi_table_from_name(rdi, Scopes, &scope_count); - rd_printf("# SCOPES"); - rd_indent(); - for (U64 i = 0; i < scope_count; ++i) { - if (scope_array[i].parent_scope_idx == 0) { - rdi_print_scope(arena, out, indent, rdi, &scope_array[i], tli->arch); - } - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiScopeVMap) { - U64 vmap_count = 0; - RDI_VMapEntry *vmap_array = rdi_table_from_name(rdi, ScopeVMap, &vmap_count); - rd_printf("# SCOPE VMAP"); - rd_indent(); - for (U64 i = 0; i < vmap_count; ++i) { - rdi_print_vmap_entry(arena, out, indent, &vmap_array[i]); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiInlineSites) { - U64 inline_site_count = 0; - RDI_InlineSite *inline_site_array = rdi_table_from_name(rdi, InlineSites, &inline_site_count); - rd_printf("# INLINE SITES"); - rd_indent(); - for (U64 i = 0; i < inline_site_count; ++i) { - rdi_print_inline_site(arena, out, indent, rdi, i, &inline_site_array[i]); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiNameMaps) { - Temp scratch = scratch_begin(&arena, 1); - U64 name_map_count = 0; - RDI_NameMap *name_map_array = rdi_table_from_name(rdi, NameMaps, &name_map_count); - rd_printf("# NAME MAPS"); - rd_indent(); - for (U64 i = 0; i < name_map_count; ++i) { - if (i > 0) { - rd_newline(); - } - RDI_ParsedNameMap name_map = {0}; - rdi_parsed_from_name_map(rdi, &name_map_array[i], &name_map); - rd_printf("name_map[%S]",rdi_string_from_name_map_kind(i)); - rd_indent(); - for (U64 bucket_idx = 0; bucket_idx < name_map.bucket_count; ++bucket_idx) { - if (name_map.buckets[bucket_idx].node_count == 0) { - continue; - } - rd_printf("bucket[%llu]:", bucket_idx); - rd_indent(); - RDI_NameMapNode *node_ptr = name_map.nodes + name_map.buckets[bucket_idx].first_node; - RDI_NameMapNode *node_opl = node_ptr + name_map.buckets[bucket_idx].node_count; - for (; node_ptr < node_opl; ++node_ptr) { - Temp temp = temp_begin(scratch.arena); - String8 str = str8_from_rdi_string_idx(rdi, node_ptr->string_idx); - String8 indices; - if (node_ptr->match_count == 1) { - indices = push_str8f(temp.arena, "%u", node_ptr->match_idx_or_idx_run_first); - } else { - U32 idx_count = 0; - U32 *idx_array = rdi_idx_run_from_first_count(rdi, node_ptr->match_idx_or_idx_run_first, node_ptr->match_count, &idx_count); - indices = rd_string_from_array_u32(temp.arena, idx_array, idx_count); - } - rd_printf("match \"%S\": %S", str, indices); - temp_end(temp); - } - rd_unindent(); - } - rd_unindent(); - } - rd_unindent(); - rd_newline(); - scratch_end(scratch); - } - if (opts & RD_Option_RdiStrings) { - U64 stridx_count = 0; - U32 *stridx_array = rdi_table_from_name(rdi, StringTable, &stridx_count); - rd_printf("# STRINGS"); - rd_indent(); - for (U64 i = 0; i < stridx_count; ++i) { - rd_printf("string[%llu]: \"%S\"", i, str8_from_rdi_string_idx(rdi, i)); - } - rd_unindent(); - rd_newline(); - } -} - internal String8 dw_string_from_reg_off(Arena *arena, Arch arch, U64 reg_idx, S64 reg_off) { diff --git a/src/raddump/raddump.h b/src/raddump/raddump.h index 5638e0ed..634e442a 100644 --- a/src/raddump/raddump.h +++ b/src/raddump/raddump.h @@ -189,36 +189,6 @@ internal void rd_print_raw_data (Arena *arena, String8List *out, String8 ind // RDI -internal String8 rdi_string_from_data_section_kind(Arena *arena, RDI_SectionKind v); -internal String8 rdi_string_from_arch (Arena *arena, RDI_Arch v); -internal String8 rdi_string_from_language (Arena *arena, RDI_Language v); -internal String8 rdi_string_from_local_kind (Arena *arena, RDI_LocalKind v); -//internal String8 rdi_string_from_type_kind (Arena *arena, RDI_TypeKind v); -internal String8 rdi_string_from_member_kind (Arena *arena, RDI_MemberKind v); - -internal String8 rdi_string_from_binary_section_flags(Arena *arena, RDI_BinarySectionFlags flags); -internal String8 rdi_string_from_type_modifier (Arena *arena, RDI_TypeModifierFlags flags); -internal String8 rdi_string_from_udt_flags (Arena *arena, RDI_UDTFlags flags); -internal String8 rdi_string_from_link_flags (Arena *arena, RDI_LinkFlags flags); - -internal void rdi_print_data_sections (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi); -internal void rdi_print_top_level_info (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_TopLevelInfo *tli); -internal void rdi_print_binary_section (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_BinarySection *bin_section); -internal void rdi_print_file_path (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_FilePathNode *file_path); -internal void rdi_print_source_file (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_SourceFile *source_file); -internal void rdi_print_line_table (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_LineTable *line_table); -internal void rdi_print_source_line_map(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_SourceLineMap *map); -internal void rdi_print_unit (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Unit *unit); -internal void rdi_print_type_node (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_TypeNode *type); -internal void rdi_print_udt (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_UDT *udt); -internal void rdi_print_global_variable(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_GlobalVariable *gvar); -internal void rdi_print_thread_variable(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_ThreadVariable *tvar); -internal void rdi_print_constant (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Constant *constant); -internal void rdi_print_procedure (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Procedure *proc, RDI_Arch arch); -internal void rdi_print_scope (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Scope *scope, RDI_Arch arch); -internal void rdi_print_inline_site (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, U64 idx, RDI_InlineSite *inline_site); -internal void rdi_print_vmap_entry (Arena *arena, String8List *out, String8 indent, RDI_VMapEntry *v); - // DWARF internal String8List dw_string_list_from_expression (Arena *arena, String8 raw_data, U64 cu_base, U64 address_size, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format); diff --git a/src/rdi_format/rdi_format_local.c b/src/rdi_format/rdi_format_local.c index 0cf4656f..2000246a 100644 --- a/src/rdi_format/rdi_format_local.c +++ b/src/rdi_format/rdi_format_local.c @@ -4,6 +4,9 @@ #include "lib_rdi_format/rdi_format.c" #include "lib_rdi_format/rdi_format_parse.c" +//////////////////////////////// +//~ rjf: RDI Decompression + internal void rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed *og_rdi) { @@ -50,3 +53,1310 @@ rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed * } } +//////////////////////////////// +//~ rjf: Lookup Helpers + +internal String8 +str8_from_rdi_string_idx(RDI_Parsed *rdi, U32 idx) +{ + String8 result = {0}; + result.str = rdi_string_from_idx(rdi, idx, &result.size); + return result; +} + +//////////////////////////////// +//~ rjf: String <=> Enum + +internal String8 +rdi_string_from_data_section_kind(Arena *arena, RDI_SectionKind v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);}break; +#define X(name, lower, type) case RDI_SectionKind_##name:{result = str8_lit(#name);}break; + RDI_SectionKind_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_arch(Arena *arena, RDI_Arch v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);} break; +#define X(name) case RDI_Arch_##name:{result = str8_lit(#name);} break; + RDI_Arch_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_language(Arena *arena, RDI_Language v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);}break; +#define X(name) case RDI_Language_##name:{result = str8_lit(#name);}break; + RDI_Language_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_local_kind(Arena *arena, RDI_LocalKind v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);}break; +#define X(name) case RDI_LocalKind_##name:{result = str8_lit(#name);}break; + RDI_LocalKind_XList +#undef X + } + return result; +} + +#if 0 +internal String8 +rdi_string_from_type_kind(Arena *arena, RDI_TypeKind v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);}break; +#define X(name) case RDI_TypeKind_##name:{result = str8_lit(#name);}break; + RDI_TypeKind_XList +#undef X + } + return result; +} +#endif + +internal String8 +rdi_string_from_member_kind(Arena *arena, RDI_MemberKind v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);}break; +#define X(name) case RDI_MemberKind_##name:{result = str8_lit(#name);}break; + RDI_MemberKind_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_name_map_kind(RDI_NameMapKind kind) +{ + String8 result = {0}; + switch(kind) + { + default:{}break; +#define X(name) case RDI_NameMapKind_##name:{result = str8_lit(#name);}break; + RDI_NameMapKind_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_reg_code_x86(U64 reg_code) +{ + String8 result = {0}; + switch(reg_code) + { + default:{}break; +#define X(name, value) case RDI_RegCodeX86_##name:{result = str8_lit(#name);}break; + RDI_RegCodeX86_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_reg_code_x64(U64 reg_code) +{ + String8 result = {0}; + switch(reg_code) + { + default:{}break; +#define X(name, value) case RDI_RegCodeX64_##name:{result = str8_lit(#name);}break; + RDI_RegCodeX64_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_reg_code(Arena *arena, RDI_Arch arch, U64 reg_code) +{ + String8 result = {0}; + switch(arch) + { + default: + case RDI_Arch_NULL: {result = push_str8f(arena, "??? (%llu)", reg_code);}break; + case RDI_Arch_X86: {result = rdi_string_from_reg_code_x86(reg_code);}break; + case RDI_Arch_X64: {result = rdi_string_from_reg_code_x64(reg_code);}break; + } + return result; +} + +internal String8 +rdi_string_from_eval_op(Arena *arena, RDI_EvalOp op) +{ + String8 result = {0}; + switch(op) + { + default:{result = push_str8f(arena, "%#x", op);}break; +#define X(name) case RDI_EvalOp_##name:{result = str8_lit("#name");}break; + RDI_EvalOp_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_eval_type_group(Arena *arena, RDI_EvalTypeGroup eval_type_group) +{ + String8 result = {0}; + switch(eval_type_group) + { + default:{result = push_str8f(arena, "%#x", eval_type_group);}break; +#define X(name) case RDI_EvalTypeGroup_##name:{result = str8_lit("#name");}break; + RDI_EvalTypeGroup_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_binary_section_flags(Arena *arena, RDI_BinarySectionFlags flags) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; +#define X(name) if (flags & RDI_BinarySectionFlag_##name) { flags &= ~RDI_BinarySectionFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } + RDI_BinarySectionFlags_XList; +#undef X + StringJoin join = {.sep = str8_lit("|")}; + String8 result = str8_list_join(arena, &list, &join); + if(result.size == 0) { result = str8_lit("None"); } + scratch_end(scratch); + return result; +} + +internal String8 +rdi_string_from_type_modifier_flags(Arena *arena, RDI_TypeModifierFlags flags) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; +#define X(name) if(flags & RDI_TypeModifierFlag_##name) { flags &= ~RDI_TypeModifierFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } + RDI_TypeModifierFlags_XList; +#undef X + StringJoin join = {.sep = str8_lit("|")}; + String8 result = str8_list_join(arena, &list, &join); + if(result.size == 0) { result = str8_lit("None"); } + scratch_end(scratch); + return result; +} + +internal String8 +rdi_string_from_udt_flags(Arena *arena, RDI_UDTFlags flags) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; +#define X(name) if (flags & RDI_UDTFlag_##name) { flags &= ~RDI_UDTFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } + RDI_UDTFlags_XList; +#undef X + StringJoin join = {.sep = str8_lit("|")}; + String8 result = str8_list_join(arena, &list, &join); + if(result.size == 0) { result = str8_lit("None"); } + scratch_end(scratch); + return result; +} + +internal String8 +rdi_string_from_link_flags(Arena *arena, RDI_LinkFlags flags) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; +#define X(name) if (flags & RDI_LinkFlag_##name) { flags &= ~RDI_LinkFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } + RDI_LinkFlags_XList; +#undef X + StringJoin join = {.sep = str8_lit("|")}; + String8 result = str8_list_join(arena, &list, &join); + if(result.size == 0) { result = str8_lit("None"); } + scratch_end(scratch); + return result; +} + +internal String8 +rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List fmt = {0}; + for(U64 cursor = 0; cursor < bc.size; ) + { + RDI_EvalOp op = RDI_EvalOp_Stop; + cursor += str8_deserial_read_struct(bc, cursor, &op); + + U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; + U32 imm_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); + + String8 imm = {0}; + cursor += str8_deserial_read_block(bc, cursor, imm_size, &imm); + if (imm.size != imm_size) { + str8_list_pushf(scratch.arena, &fmt, "(ERROR: not enough bytes to read immediate)"); + break; + } + + String8 imm_fmt = {0}; + switch (op) { + case RDI_EvalOp_Stop: goto exit; + case RDI_EvalOp_Noop: break; + case RDI_EvalOp_Cond: break; + case RDI_EvalOp_Skip: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U16 *)imm.str); + } break; + case RDI_EvalOp_MemRead: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U8 *)imm.str); + } break; + case RDI_EvalOp_RegRead: { + U32 regread = *(U32 *)imm.str; + RDI_RegCode reg_code = Extract8(regread, 0); + U8 byte_size = Extract8(regread, 1); + U8 byte_off = Extract8(regread, 2); + String8 reg_str = rdi_string_from_reg_code(scratch.arena, arch, reg_code); + imm_fmt = push_str8f(scratch.arena, "%S+%I64u, Size: %u", reg_str, byte_off, byte_size); + } break; + case RDI_EvalOp_RegReadDyn: break; + case RDI_EvalOp_FrameOff: { + imm_fmt = push_str8f(scratch.arena, "%+lld", *(S64 *)imm.str); + } break; + case RDI_EvalOp_ModuleOff: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); + } break; + case RDI_EvalOp_TLSOff: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); + } break; + case RDI_EvalOp_ConstU8: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U8 *)imm.str); + } break; + case RDI_EvalOp_ConstU16: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U16 *)imm.str); + } break; + case RDI_EvalOp_ConstU32: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); + } break; + case RDI_EvalOp_ConstU64: { + imm_fmt = push_str8f(scratch.arena, "%llu", *(U64 *)imm.str); + } break; + case RDI_EvalOp_ConstU128: { + imm_fmt = push_str8f(scratch.arena, "Lo: %llu, Hi: %llu", *(U64 *)imm.str, *((U64 *)imm.str + 1)); + } break; + case RDI_EvalOp_ConstString: { + U8 size = *(U8 *)imm.str; + String8 string = {0}; + cursor += str8_deserial_read_block(bc, cursor, size, &string); + + imm_fmt = push_str8f(scratch.arena, "(%u) \"%S\"", size, string); + } break; + case RDI_EvalOp_Abs: + case RDI_EvalOp_Neg: + case RDI_EvalOp_Add: + case RDI_EvalOp_Sub: + case RDI_EvalOp_Mul: + case RDI_EvalOp_Div: + case RDI_EvalOp_Mod: + case RDI_EvalOp_LShift: + case RDI_EvalOp_RShift: + case RDI_EvalOp_BitAnd: + case RDI_EvalOp_BitOr: + case RDI_EvalOp_BitXor: + case RDI_EvalOp_BitNot: + case RDI_EvalOp_LogAnd: + case RDI_EvalOp_LogOr: + case RDI_EvalOp_LogNot: + case RDI_EvalOp_EqEq: + case RDI_EvalOp_NtEq: + case RDI_EvalOp_LsEq: + case RDI_EvalOp_GrEq: + case RDI_EvalOp_Less: + case RDI_EvalOp_Grtr: { + U8 eval_type_group = *(U8 *)imm.str; + imm_fmt = rdi_string_from_eval_type_group(scratch.arena, eval_type_group); + } break; + case RDI_EvalOp_Trunc: + case RDI_EvalOp_TruncSigned: { + U8 trunc = *(U8 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", trunc); + } break; + case RDI_EvalOp_Convert: { + U16 convert = *(U16 *)imm.str; + U8 in = Extract8(convert, 0); + U8 out = Extract8(convert, 1); + String8 in_str = rdi_string_from_eval_type_group(scratch.arena, in); + String8 out_str = rdi_string_from_eval_type_group(scratch.arena, out); + imm_fmt = push_str8f(scratch.arena, "in: %S out: %S", in_str, out_str); + } break; + case RDI_EvalOp_Pick: { + U8 pick = *(U8 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", pick); + } break; + case RDI_EvalOp_Pop: break; + case RDI_EvalOp_Insert: { + U8 insert = *(U8 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", insert); + } break; + case RDI_EvalOp_ValueRead: { + U8 bytes_to_read = *(U8 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", bytes_to_read); + } break; + case RDI_EvalOp_ByteSwap: { + U8 byte_size = *(U8 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", byte_size); + } break; + case RDI_EvalOp_CallSiteValue: { + U32 call_site_bc_size = *(U32 *)imm.str; + String8 call_site_bc = {0}; + cursor += str8_deserial_read_block(bc, cursor, call_site_bc_size, &call_site_bc); + + String8 call_site_str = rdi_string_from_bytecode(scratch.arena, arch, call_site_bc); + imm_fmt = push_str8f(scratch.arena, "%S", call_site_str); + } break; + case RDI_EvalOp_PartialValue: { + U32 partial_value_size = *(U32 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", partial_value_size); + } break; + case RDI_EvalOp_PartialValueBit: { + U64 partial_value = *(U64 *)imm.str; + U32 bit_size = Extract32(partial_value, 0); + U32 bit_off = Extract32(partial_value, 1); + imm_fmt = push_str8f(scratch.arena, "Off: %u, Size: %u", bit_size, bit_off); + } break; + } + + String8 op_str = rdi_string_from_eval_op(scratch.arena, op); + if (imm_fmt.size) { + str8_list_pushf(scratch.arena, &fmt, "RDI_EvalOp_%S(%S)", op_str, imm_fmt); + } else { + str8_list_pushf(scratch.arena, &fmt, "RDI_EvalOp_%S", op_str); + } + } + exit:; + + String8 result = str8_list_join(arena, &fmt, &(StringJoin){.sep = str8_lit(", ")}); + + scratch_end(scratch); + return result; +} + +internal String8List +rdi_strings_from_locations(Arena *arena, RDI_Parsed *rdi, RDI_Arch arch, Rng1U64 location_block_range) +{ + String8List strings = {0}; + Temp scratch = scratch_begin(&arena, 1); + U64 location_block_count = 0; + U64 location_data_size = 0; + RDI_LocationBlock *location_block_array = rdi_table_from_name(rdi, LocationBlocks, &location_block_count); + RDI_U8 *location_data = rdi_table_from_name(rdi, LocationData, &location_data_size); + Rng1U64 location_block_range_clamped = r1u64(ClampTop(location_block_range.min, location_block_count), + ClampTop(location_block_range.max, location_block_count)); + for(U64 block_idx = location_block_range_clamped.min; + block_idx < location_block_range_clamped.max; + block_idx +=1) + { + String8 qualifier = {0}; + String8 location_info = {0}; + RDI_LocationBlock *block_ptr = &location_block_array[block_idx]; + if(block_ptr->scope_off_first == 0 && block_ptr->scope_off_opl == max_U32) + { + qualifier = str8_lit("*always*"); + } + else + { + qualifier = push_str8f(scratch.arena, "[%#08x, %#08x): ", block_ptr->scope_off_first, block_ptr->scope_off_opl); + } + if(block_ptr->location_data_off >= location_data_size) + { + location_info = push_str8f(scratch.arena, "", block_ptr->location_data_off); + } + else + { + U8 *loc_data_opl = location_data + location_data_size; + U8 *loc_base_ptr = location_data + block_ptr->location_data_off; + RDI_LocationKind kind = *(RDI_LocationKind *)loc_base_ptr; + switch(kind) + { + default: + { + location_info = push_str8f(scratch.arena, "\?\?\? (%u)", kind); + }break; + case RDI_LocationKind_AddrBytecodeStream: + { + String8 bc = str8_range(loc_base_ptr + 1, loc_data_opl); + String8 bc_str = rdi_string_from_bytecode(scratch.arena, arch, bc); + location_info = push_str8f(scratch.arena, "AddrBytecodeStream(%S)", bc_str); + }break; + case RDI_LocationKind_ValBytecodeStream: + { + String8 bc = str8_range(loc_base_ptr + 1, loc_data_opl); + String8 bc_str = rdi_string_from_bytecode(scratch.arena, arch, bc); + location_info = push_str8f(scratch.arena, "ValBytecodeStream(%S)", bc_str); + }break; + case RDI_LocationKind_AddrRegPlusU16: + { + if(loc_base_ptr + sizeof(RDI_LocationRegPlusU16) > loc_data_opl) + { + location_info = push_str8f(scratch.arena, "AddrRegPlusU16(\?\?\?)"); + } + else + { + RDI_LocationRegPlusU16 *loc = (RDI_LocationRegPlusU16*)loc_base_ptr; + location_info = push_str8f(scratch.arena, "AddrRegPlusU16(reg: %S, off: %u)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code), loc->offset); + } + }break; + case RDI_LocationKind_AddrAddrRegPlusU16: + { + if(loc_base_ptr + sizeof(RDI_LocationRegPlusU16) > loc_data_opl) + { + location_info = push_str8f(scratch.arena, "AddrAddrRegPlusU16(\?\?\?)"); + } + else + { + RDI_LocationRegPlusU16 *loc = (RDI_LocationRegPlusU16 *)loc_base_ptr; + location_info = push_str8f(scratch.arena, "AddrAddrRegisterPlusU16(reg: %S, off: %u)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code), loc->offset); + } + }break; + case RDI_LocationKind_ValReg: + { + if(loc_base_ptr + sizeof(RDI_LocationReg) > loc_data_opl) + { + location_info = push_str8f(scratch.arena, "ValReg(\?\?\?)"); + } + else + { + RDI_LocationReg *loc = (RDI_LocationReg*)loc_base_ptr; + location_info = push_str8f(scratch.arena, "ValReg(reg: %S)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code)); + } + } break; + } + } + str8_list_pushf(arena, &strings, "%S: %S", qualifier, location_info); + } + scratch_end(scratch); + return strings; +} + +//////////////////////////////// +//~ rjf: RDI Dumping + +internal void +rdi_dump_scope(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Scope *scope, RDI_Arch arch) +{ + Temp scratch = scratch_begin(&arena, 1); + + U64 scope_count = 0; + U64 scope_voff_count = 0; + U64 local_count = 0; + U64 proc_count = 0; + U64 inline_site_count = 0; + RDI_Scope *scope_array = rdi_table_from_name(rdi, Scopes, &scope_count); + U64 *scope_voff_array = rdi_table_from_name(rdi, ScopeVOffData, &scope_voff_count); + RDI_Local *local_array = rdi_table_from_name(rdi, Locals, &local_count); + RDI_Procedure *proc_array = rdi_table_from_name(rdi, Procedures, &proc_count); + RDI_InlineSite *inline_site_array = rdi_table_from_name(rdi, InlineSites, &inline_site_count); + + U32 voff_range_lo = ClampTop(scope->voff_range_first, scope_voff_count); + U32 voff_range_hi = ClampTop(scope->voff_range_opl, scope_voff_count); + U32 voff_range_count = (voff_range_hi - voff_range_lo); + U64 *voff_ptr = scope_voff_array + voff_range_lo; + String8 voff_str = {0}; + { + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; + for(U64 i = 0; i+2 <= voff_range_count; i += 2) + { + str8_list_pushf(scratch.arena, &list, "[%#llx, %#llx)", voff_ptr[i+0], voff_ptr[i+1]); + } + voff_str = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); + scratch_end(scratch); + } + + U64 scope_idx = (U64)(scope - scope_array); + dumpf("scope[%llu]", scope_idx); + rd_indent(); + + String8 proc_name = str8_lit("???"); + if (scope->proc_idx < proc_count) { + RDI_Procedure *proc = &proc_array[scope->proc_idx]; + proc_name = str8_from_rdi_string_idx(rdi, proc->name_string_idx); + } + + String8 inline_site_name = str8_lit(""); + if (scope->inline_site_idx != 0) { + if (scope->inline_site_idx < inline_site_count) { + RDI_InlineSite *inline_site = &inline_site_array[scope->inline_site_idx]; + inline_site_name = str8_from_rdi_string_idx(rdi, inline_site->name_string_idx); + } else { + inline_site_name = str8_lit("???"); + } + inline_site_name = push_str8f(scratch.arena, " '%S'", inline_site_name); + } + + dumpf("proc_idx =%u '%S'", scope->proc_idx, proc_name); + dumpf("first_child_scope_idx =%u", scope->first_child_scope_idx); + dumpf("next_sibling_scope_idx=%u", scope->next_sibling_scope_idx); + dumpf("inline_site_idx =%u%S", scope->inline_site_idx, inline_site_name); + dumpf("voff_ranges =%S", voff_str); + + // local_array + { + U32 local_lo = ClampTop(scope->local_first, local_count); + U32 local_hi = ClampTop(local_lo + scope->local_count, local_count); + if (local_lo < local_hi) { + for (U32 local_idx = local_lo; local_idx < local_hi; ++local_idx) { + RDI_Local *local_ptr = &local_array[local_idx]; + + dumpf("local[%u]", local_idx); + rd_indent(); + dumpf("kind =%S", rdi_string_from_local_kind(scratch.arena, local_ptr->kind)); + dumpf("name ='%S'", str8_from_rdi_string_idx(rdi, local_ptr->name_string_idx)); + dumpf("type_idx=%u", local_ptr->type_idx); + + if (local_ptr->location_first < local_ptr->location_opl) { + dumpf("locations:"); + rd_indent(); + rdi_dump_locations(arena, out, indent, rdi, arch, local_ptr->location_first, local_ptr->location_opl); + rd_unindent(); + } + rd_unindent(); + } + } + } + + for (U32 child_scope_idx = scope->first_child_scope_idx; child_scope_idx != 0; ) { + if (child_scope_idx >= scope_count) { + rd_errorf("child scope index (%u) is out of bounds", child_scope_idx); + break; + } + + rd_indent(); + RDI_Scope *child_scope = scope_array + child_scope_idx; + rdi_dump_scope(arena, out, indent, rdi, child_scope, arch); + rd_unindent(); + + // advance to next child + child_scope_idx = child_scope->next_sibling_scope_idx; + } + + rd_unindent(); + dumpf("[/%llu]", scope_idx); + + scratch_end(scratch); +} + +internal String8List +rdi_dump_list_from_parsed(Arena *arena, RDI_Parsed *rdi, RDI_DumpSubsetFlags flags) +{ + String8List strings = {0}; + String8 indent = str8_lit(" "); +#define dump(str) str8_list_push(arena, &strings, (str)) +#define dumpf(...) str8_list_pushf(arena, &strings, __VA_ARGS__) +#define DumpSubset(name) if(flags & RDI_DumpSubsetFlag_##name) DeferLoop(dumpf("# %S\n\n", rdi_name_title_from_dump_subset_table[RDI_DumpSubset_##name]), dump(str8_lit("\n"))) + + ////////////////////////////// + //- rjf: dump data sections + // + DumpSubset(DataSections) + { + for EachIndex(idx, rdi->sections_count) + { + Temp scratch = scratch_begin(&arena, 1); + RDI_SectionKind kind = (RDI_SectionKind)idx; + RDI_Section *section = &rdi->sections[idx]; + String8 kind_str = rdi_string_from_data_section_kind(scratch.arena, kind); + dumpf("data_section[%5llu] = {%#08llx, %7u, %7u}, %S\n", idx, section->off, section->encoded_size, section->unpacked_size, kind_str); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump top-level-info + // + DumpSubset(TopLevelInfo) + { + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + Temp scratch = scratch_begin(&arena, 1); + dumpf("arch =%S\n", rdi_string_from_arch(scratch.arena, tli->arch)); + dumpf("exe_name ='%S'\n", str8_from_rdi_string_idx(rdi, tli->exe_name_string_idx)); + dumpf("voff_max =%#08llx\n", tli->voff_max); + dumpf("producer_name='%S'\n", str8_from_rdi_string_idx(rdi, tli->producer_name_string_idx)); + scratch_end(scratch); + } + + ////////////////////////////// + //- rjf: dump binary sections + // + DumpSubset(BinarySections) + { + U64 count = 0; + RDI_BinarySection *v = rdi_table_from_name(rdi, BinarySections, &count); + for EachIndex(idx, count) + { + Temp scratch = scratch_begin(&arena, 1); + RDI_BinarySection *bin_section = &v[idx]; + dumpf("binary_section[%I64u]:\n", idx); + dumpf(" name ='%S'\n", str8_from_rdi_string_idx(rdi, bin_section->name_string_idx)); + dumpf(" flags =%S\n", rdi_string_from_binary_section_flags(scratch.arena, bin_section->flags)); + dumpf(" voff_first=%#08x\n", bin_section->voff_first); + dumpf(" voff_opl =%#08x\n", bin_section->voff_opl); + dumpf(" foff_first=%#08x\n", bin_section->foff_first); + dumpf(" foff_opl =%#08x\n", bin_section->foff_opl); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump file paths + // + DumpSubset(FilePaths) + { + U64 count = 0; + RDI_FilePathNode *v = rdi_table_from_name(rdi, FilePathNodes, &count); + RDI_FilePathNode *nil = &v[0]; + for EachIndex(idx, count) + { + RDI_FilePathNode *root = &v[idx]; + if(root->parent_path_node != 0) { continue; } + S64 depth = 0; + for(RDI_FilePathNode *n = root, *rec_next = nil; n != nil; n = rec_next) + { + // rjf: dump + if(n->source_file_idx == 0) + { + dumpf("%.*s[%I64u] '%S'\n", depth*2, indent.str, (U64)(n - v), str8_from_rdi_string_idx(rdi, n->name_string_idx)); + } + else + { + dumpf("%.*s[%I64u] '%S': source_file=%u\n", depth*2, indent.str, (U64)(n - v), str8_from_rdi_string_idx(rdi, n->name_string_idx), n->source_file_idx); + } + + // rjf: find next node + rec_next = nil; + if(n->first_child) + { + rec_next = rdi_element_from_name_idx(rdi, FilePathNodes, n->first_child); + depth += 1; + } + else for(RDI_FilePathNode *p = n; + p != nil && p != root; + p = rdi_element_from_name_idx(rdi, FilePathNodes, p->parent_path_node), depth -= 1) + { + if(p->next_sibling) + { + rec_next = rdi_element_from_name_idx(rdi, FilePathNodes, p->next_sibling); + break; + } + } + } + } + } + + ////////////////////////////// + //- rjf: dump source files + // + DumpSubset(SourceFiles) + { + U64 source_file_count = 0; + RDI_SourceFile *source_file_array = rdi_table_from_name(rdi, SourceFiles, &source_file_count); + for(U64 i = 0; i < source_file_count; ++i) + { + RDI_SourceFile *source_file = &source_file_array[i]; + dumpf("source_file[%4llu] = { file_path_node_idx = %4u, source_line_map = %4u, path = '%S' }\n", + i, + source_file->file_path_node_idx, + source_file->source_line_map_idx, + str8_from_rdi_string_idx(rdi, source_file->normal_full_path_string_idx)); + } + } + + ////////////////////////////// + //- rjf: dump units + // + DumpSubset(Units) + { + U64 count = 0; + RDI_Unit *v = rdi_table_from_name(rdi, Units, &count); + for EachIndex(idx, count) + { + RDI_Unit *unit = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + dumpf("unit[%I64u]:\n", idx); + dumpf(" unit_name ='%S'\n", str8_from_rdi_string_idx(rdi, unit->unit_name_string_idx)); + dumpf(" compiler_name ='%S'\n", str8_from_rdi_string_idx(rdi, unit->compiler_name_string_idx)); + dumpf(" source_file_path =%u\n", unit->source_file_path_node); + dumpf(" object_file_path =%u\n", unit->object_file_path_node); + dumpf(" archive_file_path=%u\n", unit->archive_file_path_node); + dumpf(" build_path =%u\n", unit->build_path_node); + dumpf(" language =%S\n", rdi_string_from_language(scratch.arena, unit->language)); + dumpf(" line_table_idx =%u\n", unit->line_table_idx); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump unit vmap + // + DumpSubset(UnitVMap) + { + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, UnitVMap, &count); + for EachIndex(idx, count) + { + dumpf("%I64x -> #%I64u\n", v[idx].voff, v[idx].idx); + } + } + + ////////////////////////////// + //- rjf: dump line tables + // + DumpSubset(LineTables) + { + U64 count = 0; + RDI_LineTable *v = rdi_table_from_name(rdi, LineTables, &count); + for EachIndex(idx, count) + { + RDI_LineTable *line_table = &v[idx]; + RDI_ParsedLineTable parsed_line_table = {0}; + rdi_parsed_from_line_table(rdi, line_table, &parsed_line_table); + dumpf("line_table[%I64u]:\n", idx); + for EachIndex(line_idx, parsed_line_table.count) + { + U64 first = parsed_line_table.voffs[line_idx]; + U64 opl = parsed_line_table.voffs[line_idx + 1]; + RDI_Line *line = parsed_line_table.lines + line_idx; + RDI_Column *col = 0; + if(line_idx < parsed_line_table.col_count) + { + col = parsed_line_table.cols + line_idx; + } + if(col == 0) + { + dumpf(" [0x%08I64x,0x%08I64x) file=%u; line=%u\n", first, opl, line->file_idx, line->line_num); + } + else + { + dumpf(" [0x%08I64x,0x%08I64x) file=%u; line=%u; columns=[%u,%u)\n", first, opl, line->file_idx, line->line_num, col->col_first, col->col_opl); + } + } + } + } + + ////////////////////////////// + //- rjf: dump source line maps + // + DumpSubset(SourceLineMaps) + { + U64 count = 0; + RDI_SourceLineMap *v = rdi_table_from_name(rdi, SourceLineMaps, &count); + for EachIndex(idx, count) + { + Temp scratch = scratch_begin(&arena, 1); + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, &v[idx], &line_map); + dumpf("source_line_map[%I64u]:\n", idx); + for EachIndex(line_num_idx, line_map.count) + { + Temp temp = temp_begin(scratch.arena); + String8List list = {0}; + U32 voff_lo = line_map.ranges[line_num_idx]; + U32 voff_hi = ClampTop(line_map.ranges[line_num_idx + 1], line_map.voff_count); + for(U64 voff_idx = voff_lo; voff_idx < voff_hi; voff_idx += 1) + { + str8_list_pushf(temp.arena, &list, "%#llx", line_map.voffs[voff_idx]); + } + String8 voffs_string = str8_list_join(temp.arena, &list, &(StringJoin){.sep = str8_lit(", ")}); + dumpf(" %u: %S\n", line_map.nums[line_num_idx], voffs_string); + temp_end(temp); + } + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump type nodes + // + DumpSubset(TypeNodes) + { + U64 count = 0; + RDI_TypeNode *v = rdi_table_from_name(rdi, TypeNodes, &count); + for EachIndex(idx, count) + { + Temp scratch = scratch_begin(&arena, 1); + RDI_TypeNode *type = &v[idx]; + String8 type_kind_str = {0}; + type_kind_str.str = rdi_string_from_type_kind(type->kind, &type_kind_str.size); + dumpf("type[%I64u]:\n", idx); + dumpf(" kind =%S\n", type_kind_str); + if(type->kind == RDI_TypeKind_Modifier) + { + dumpf(" flags =%S\n", rdi_string_from_type_modifier_flags(scratch.arena, type->flags)); + } + else if(type->flags != 0) + { + dumpf(" flags=%#x (missing stringizer path)\n", type->flags); + } + dumpf(" byte_size =%u\n", type->byte_size); + if(RDI_TypeKind_FirstBuiltIn <= type->kind && type->kind <= RDI_TypeKind_LastBuiltIn) + { + dumpf(" built_in.name ='%S'\n", str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx)); + } + else if(type->kind == RDI_TypeKind_Array) + { + dumpf(" constructed.direct_type =%u\n", type->constructed.direct_type_idx); + dumpf(" constructed.array_count =%u\n", type->constructed.count); + } + else if(type->kind == RDI_TypeKind_Function) + { + U32 param_idx_count = 0; + U32 *param_idx_array = rdi_idx_run_from_first_count(rdi, type->constructed.param_idx_run_first, type->constructed.count, ¶m_idx_count); + String8List param_idx_strings = {0}; + for(U32 param_idx = 0; param_idx < param_idx_count; param_idx += 1) + { + str8_list_pushf(scratch.arena, ¶m_idx_strings, "%u", param_idx_array[param_idx]); + } + String8 param_idx_str = str8_list_join(scratch.arena, ¶m_idx_strings, &(StringJoin){.pre = str8_lit("["), .sep = str8_lit(", "), .post = str8_lit("]")}); + dumpf(" constructed.params =%S\n", param_idx_str); + dumpf(" return_type =%u\n", type->constructed.direct_type_idx); + } + else if(type->kind == RDI_TypeKind_Method) + { + U32 param_idx_count = 0; + U32 *param_idx_array = rdi_idx_run_from_first_count(rdi, type->constructed.param_idx_run_first, type->constructed.count, ¶m_idx_count); + String8 this_type_str = str8_lit("\?\?\?"); + if(param_idx_count > 0) + { + this_type_str = push_str8f(scratch.arena, "%u", param_idx_array[0]); + param_idx_count -= 1; + param_idx_array += 1; + } + String8List param_idx_strings = {0}; + for(U32 param_idx = 0; param_idx < param_idx_count; param_idx += 1) + { + str8_list_pushf(scratch.arena, ¶m_idx_strings, "%u", param_idx_array[param_idx]); + } + String8 param_idx_str = str8_list_join(scratch.arena, ¶m_idx_strings, &(StringJoin){.pre = str8_lit("["), .sep = str8_lit(", "), .post = str8_lit("]")}); + dumpf(" constructed.this_type =%S\n", this_type_str); + dumpf(" constructed.params =%S\n", param_idx_str); + dumpf(" return_type =%u\n", type->constructed.direct_type_idx); + } + else if(RDI_TypeKind_FirstConstructed <= type->kind && type->kind <= RDI_TypeKind_LastConstructed) + { + dumpf(" constructed.direct_type =%u\n", type->constructed.direct_type_idx); + } + else if(RDI_TypeKind_FirstUserDefined <= type->kind && type->kind <= RDI_TypeKind_LastUserDefined) + { + dumpf(" user_defined.name ='%S'\n", str8_from_rdi_string_idx(rdi, type->user_defined.name_string_idx)); + dumpf(" user_defined.direct_type=%u\n", type->user_defined.direct_type_idx); + dumpf(" user_defined.udt =%u\n", type->user_defined.udt_idx); + } + else if(type->kind == RDI_TypeKind_Bitfield) + { + dumpf(" bitfield.off =%u\n", type->bitfield.off); + dumpf(" bitfield.size =%u\n", type->bitfield.size); + } + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump user defined types + // + DumpSubset(UserDefinedTypes) + { + U64 count = 0; + RDI_UDT *v = rdi_table_from_name(rdi, UDTs, &count); + U64 all_members_count = 0; + RDI_Member *all_members = rdi_table_from_name(rdi, Members, &all_members_count); + U64 all_enum_members_count = 0; + RDI_EnumMember *all_enum_members = rdi_table_from_name(rdi, EnumMembers, &all_enum_members_count); + for EachIndex(idx, count) + { + RDI_UDT *udt = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + dumpf("udt[%I64u]:\n", idx); + dumpf(" self_type=%u\n", udt->self_type_idx); + dumpf(" flags =%S\n", rdi_string_from_udt_flags(scratch.arena, udt->flags)); + if(udt->file_idx != 0) + { + dumpf(" loc ={file=%u; line=%u; col=%u}\n", udt->file_idx, udt->line, udt->col); + } + if(udt->flags & RDI_UDTFlag_EnumMembers) + { + U32 member_hi = ClampTop(udt->member_first + udt->member_count, all_enum_members_count); + U32 member_lo = ClampTop(udt->member_first, member_hi); + if(member_lo < member_hi) + { + dumpf(" enum_members=\n"); + dumpf(" {\n"); + for(U32 enum_member_idx = member_lo; enum_member_idx < member_hi; enum_member_idx += 1) + { + RDI_EnumMember *enum_member = &all_enum_members[enum_member_idx]; + dumpf(" { %llu, '%S' }\n", enum_member->val, str8_from_rdi_string_idx(rdi, enum_member->name_string_idx)); + } + dumpf(" }\n"); + } + } + else + { + U32 member_hi = ClampTop(udt->member_first + udt->member_count, all_members_count); + U32 member_lo = ClampTop(udt->member_first, member_hi); + if(member_lo < member_hi) + { + dumpf(" members=\n"); + dumpf(" {\n"); + for(U32 member_idx = member_lo; member_idx < member_hi; member_idx += 1) + { + RDI_Member *member = &all_members[member_idx]; + String8 kind_str = rdi_string_from_member_kind(scratch.arena, member->kind); + String8 name_str = str8_from_rdi_string_idx(rdi, member->name_string_idx); + dumpf(" { kind=%S, type=%u, off=%u, name='%S' }\n", kind_str, member->type_idx, member->off, name_str); + } + dumpf(" }\n"); + } + } + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump global variables + // + DumpSubset(GlobalVariables) + { + U64 count = 0; + RDI_GlobalVariable *v = rdi_table_from_name(rdi, GlobalVariables, &count); + for EachIndex(idx, count) + { + RDI_GlobalVariable *gvar = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + dumpf("global_variable[%I64u]:\n", idx); + dumpf(" name ='%S'\n", str8_from_rdi_string_idx(rdi, gvar->name_string_idx)); + dumpf(" link_flags =%S\n", rdi_string_from_link_flags(scratch.arena, gvar->link_flags)); + dumpf(" voff =%#08x\n", gvar->voff); + dumpf(" type_idx =%u\n", gvar->type_idx); + dumpf(" container_idx=%u\n", gvar->container_idx); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump global variables vmap + // + DumpSubset(GlobalVariablesVMap) + { + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, GlobalVMap, &count); + for EachIndex(idx, count) + { + dumpf("%I64x -> #%I64u\n", v[idx].voff, v[idx].idx); + } + } + + ////////////////////////////// + //- rjf: dump thread variables + // + DumpSubset(ThreadVariables) + { + U64 count = 0; + RDI_ThreadVariable *v = rdi_table_from_name(rdi, ThreadVariables, &count); + for EachIndex(idx, count) + { + RDI_ThreadVariable *tvar = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + dumpf("thread_variable[%I64u]:\n", idx); + dumpf(" name ='%S'\n", str8_from_rdi_string_idx(rdi, tvar->name_string_idx)); + dumpf(" link_flags =%S\n", rdi_string_from_link_flags(scratch.arena, tvar->link_flags)); + dumpf(" tls_off =%#08x\n", tvar->tls_off); + dumpf(" type_idx =%u\n", tvar->type_idx); + dumpf(" container_idx=%u\n", tvar->container_idx); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump constants + // + DumpSubset(Constants) + { + U64 count = 0; + RDI_Constant *v = rdi_table_from_name(rdi, Constants, &count); + for EachIndex(idx, count) + { + RDI_Constant *cnst = &v[idx]; + dumpf("constant[%I64u]:\n", idx); + dumpf(" name ='%S'\n", str8_from_rdi_string_idx(rdi, cnst->name_string_idx)); + dumpf(" type_idx ='%u'\n", cnst->type_idx); + } + } + + ////////////////////////////// + //- rjf: dump procedures + // + DumpSubset(Procedures) + { + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + U64 count = 0; + RDI_Procedure *v = rdi_table_from_name(rdi, Procedures, &count); + for EachIndex(idx, count) + { + RDI_Procedure *proc = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + String8List frame_base_location_strings = rdi_strings_from_locations(scratch.arena, rdi, tli->arch, r1u64(proc->frame_base_location_first, proc->frame_base_location_opl)); + dumpf("procedure[%I64u]:\n", idx); + dumpf(" name ='%S'\n", str8_from_rdi_string_idx(rdi, proc->name_string_idx)); + dumpf(" link_name ='%S'\n", str8_from_rdi_string_idx(rdi, proc->link_name_string_idx)); + dumpf(" link_flags =%S\n", rdi_string_from_link_flags(scratch.arena, proc->link_flags)); + dumpf(" type_idx =%u\n", proc->type_idx); + dumpf(" root_scope_idx =%u\n", proc->root_scope_idx); + dumpf(" container_idx =%u\n", proc->container_idx); + dumpf(" frame_base (first=%u, opl=%u)=\n", proc->frame_base_location_first, proc->frame_base_location_opl); + dumpf(" {\n"); + for(String8Node *n = frame_base_location_strings.first; n != 0; n = n->next) + { + dumpf(" %S\n", n->string); + } + dumpf(" }\n"); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump scopes + // + DumpSubset(Scopes) + { + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + U64 scope_voffs_count = 0; + U64 *scope_voffs = rdi_table_from_name(rdi, ScopeVOffData, &scope_voffs_count); + U64 locals_count = 0; + RDI_Local *locals = rdi_table_from_name(rdi, Locals, &locals_count); + U64 count = 0; + RDI_Scope *v = rdi_table_from_name(rdi, Scopes, &count); + RDI_Scope *nil = &v[0]; + for EachIndex(idx, count) + { + if(v[idx].parent_scope_idx != 0) { continue; } + RDI_Scope *root = &v[idx]; + S64 depth = 0; + for(RDI_Scope *scope = root, *rec_next = nil; scope != nil; scope = rec_next) + { + // rjf: scope list(voff_range) => string + String8 voff_range_list_string = {0}; + { + U32 voff_range_lo = ClampTop(scope->voff_range_first, scope_voffs_count); + U32 voff_range_hi = ClampTop(scope->voff_range_opl, scope_voffs_count); + U32 voff_range_count = (voff_range_hi - voff_range_lo); + U64 *voff_ptr = scope_voffs + voff_range_lo; + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; + for(U64 i = 0; i+2 <= voff_range_count; i += 2) + { + str8_list_pushf(scratch.arena, &list, "[%#llx, %#llx)", voff_ptr[i+0], voff_ptr[i+1]); + } + voff_range_list_string = str8_list_join(arena, &list, &(StringJoin){.sep = str8_lit(", ")}); + scratch_end(scratch); + } + + // rjf: scope procedure -> name + String8 procedure_name = str8_from_rdi_string_idx(rdi, rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx)->name_string_idx); + if(procedure_name.size == 0) + { + procedure_name = str8_lit("???"); + } + + // rjf: scope inline site -> name + String8 inline_site_name = str8_from_rdi_string_idx(rdi, rdi_element_from_name_idx(rdi, InlineSites, scope->inline_site_idx)->name_string_idx); + if(inline_site_name.size == 0) + { + inline_site_name = str8_lit("???"); + } + + // rjf: dump + dumpf("%.*sscope[%I64u]:\n", depth*2, indent.str, (U64)(scope - v)); + dumpf("%.*s{\n", depth*2, indent.str); + dumpf("%.*s proc_idx =%u ('%S')\n", depth*2, indent.str, scope->proc_idx, procedure_name); + dumpf("%.*s first_child_scope_idx =%u\n", depth*2, indent.str, scope->first_child_scope_idx); + dumpf("%.*s next_sibling_scope_idx=%u\n", depth*2, indent.str, scope->next_sibling_scope_idx); + if(scope->inline_site_idx != 0) + { + dumpf("%.*s inline_site_idx =%u ('%S')\n", depth*2, indent.str, scope->inline_site_idx, inline_site_name); + } + dumpf("%.*s voff_ranges =%S\n", depth*2, indent.str, voff_range_list_string); + dumpf("%.*s locals=\n", depth*2, indent.str); + dumpf("%.*s {\n", depth*2, indent.str); + { + U32 local_lo = ClampTop(scope->local_first, locals_count); + U32 local_hi = ClampTop(local_lo + scope->local_count, locals_count); + if(local_lo < local_hi) + { + for(U32 local_idx = local_lo; local_idx < local_hi; local_idx += 1) + { + Temp scratch = scratch_begin(&arena, 1); + RDI_Local *local_ptr = &locals[local_idx]; + dumpf("%.*s local[%u]:\n", depth*2, indent.str, local_idx); + dumpf("%.*s kind =%S\n", depth*2, indent.str, rdi_string_from_local_kind(scratch.arena, local_ptr->kind)); + dumpf("%.*s name ='%S'\n", depth*2, indent.str, str8_from_rdi_string_idx(rdi, local_ptr->name_string_idx)); + dumpf("%.*s type_idx=%u\n", depth*2, indent.str, local_ptr->type_idx); + dumpf("%.*s locations=\n", depth*2, indent.str); + dumpf("%.*s {\n", depth*2, indent.str); + if(local_ptr->location_first < local_ptr->location_opl) + { + String8List locations_strings = rdi_strings_from_locations(arena, rdi, tli->arch, r1u64(local_ptr->location_first, local_ptr->location_opl)); + for(String8Node *n = locations_strings.first; n != 0; n = n->next) + { + dumpf("%.*s %S\n", depth*2, indent.str, n->string); + } + } + dumpf("%.*s }\n", depth*2, indent.str); + scratch_end(scratch); + } + } + } + dumpf("%.*s }\n", depth*2, indent.str); + + // rjf: get next recursion + rec_next = nil; + if(scope->first_child_scope_idx) + { + rec_next = rdi_element_from_name_idx(rdi, Scopes, scope->first_child_scope_idx); + depth += 1; + } + else for(RDI_Scope *p = scope; + p != nil; + p = rdi_element_from_name_idx(rdi, Scopes, p->parent_scope_idx), depth -= 1) + { + dumpf("%.*s} [/%I64u] \n", depth*2, indent.str, (U64)(p-v)); + if(p->next_sibling_scope_idx != 0) + { + rec_next = rdi_element_from_name_idx(rdi, Scopes, p->next_sibling_scope_idx); + break; + } + } + } + } + } + + ////////////////////////////// + //- rjf: dump scope vmap + // + DumpSubset(ScopeVMap) + { + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, ScopeVMap, &count); + for EachIndex(idx, count) + { + dumpf("%I64x -> #%I64u\n", v[idx].voff, v[idx].idx); + } + } + + ////////////////////////////// + //- rjf: dump inline sites + // + DumpSubset(InlineSites) + { + U64 count = 0; + RDI_InlineSite *v = rdi_table_from_name(rdi, InlineSites, &count); + for EachIndex(idx, count) + { + RDI_InlineSite *inline_site = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + String8 inline_site_idx = push_str8f(scratch.arena, "inline_site[%u]", idx); + String8 type_idx = push_str8f(scratch.arena, "type_idx = %u,", inline_site->type_idx); + String8 owner_type_idx = push_str8f(scratch.arena, "owner_type_idx = %u,", inline_site->owner_type_idx); + String8 line_table_idx = push_str8f(scratch.arena, "line_table_idx = %u,", inline_site->line_table_idx); + dumpf("%-20S = { %-25S %-25S %-25S name = '%-20S' }\n", + inline_site_idx, + type_idx, + owner_type_idx, + line_table_idx, + str8_from_rdi_string_idx(rdi, inline_site->name_string_idx)); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump name maps + // + DumpSubset(NameMaps) + { + Temp scratch = scratch_begin(&arena, 1); + U64 count = 0; + RDI_NameMap *v = rdi_table_from_name(rdi, NameMaps, &count); + for EachIndex(idx, count) + { + if(idx > 0) { dumpf("\n"); } + RDI_ParsedNameMap name_map = {0}; + rdi_parsed_from_name_map(rdi, &v[idx], &name_map); + dumpf("name_map[%S]:\n", rdi_string_from_name_map_kind(idx)); + for EachIndex(bucket_idx, name_map.bucket_count) + { + if(name_map.buckets[bucket_idx].node_count == 0) { continue; } + dumpf(" bucket[%I64u]:\n", bucket_idx); + RDI_NameMapNode *node_ptr = name_map.nodes + name_map.buckets[bucket_idx].first_node; + RDI_NameMapNode *node_opl = node_ptr + name_map.buckets[bucket_idx].node_count; + for(;node_ptr < node_opl; node_ptr += 1) + { + Temp temp = temp_begin(scratch.arena); + String8 str = str8_from_rdi_string_idx(rdi, node_ptr->string_idx); + String8 indices = {0}; + if(node_ptr->match_count == 1) + { + indices = push_str8f(temp.arena, "%u", node_ptr->match_idx_or_idx_run_first); + } + else + { + U32 idx_count = 0; + U32 *idx_array = rdi_idx_run_from_first_count(rdi, node_ptr->match_idx_or_idx_run_first, node_ptr->match_count, &idx_count); + String8List idx_strings = {0}; + for(U32 idx_i = 0; idx_i < idx_count; idx_i += 1) + { + U32 idx = idx_array[idx_i]; + str8_list_pushf(temp.arena, &idx_strings, "%u"); + } + indices = str8_list_join(scratch.arena, &idx_strings, &(StringJoin){.sep = str8_lit(", ")}); + } + dumpf(" match \"%S\": %S\n", str, indices); + temp_end(temp); + } + } + } + scratch_end(scratch); + } + + ////////////////////////////// + //- rjf: dump strings + // + DumpSubset(Strings) + { + U64 count = 0; + U32 *v = rdi_table_from_name(rdi, StringTable, &count); + for EachIndex(idx, count) + { + dumpf("string[%I64u]: \"%S\"\n", idx, str8_from_rdi_string_idx(rdi, idx)); + } + } + +#undef DumpSubset +#undef dumpf +#undef dump + return strings; +} diff --git a/src/rdi_format/rdi_format_local.h b/src/rdi_format/rdi_format_local.h index 3eca0967..c3b29b90 100644 --- a/src/rdi_format/rdi_format_local.h +++ b/src/rdi_format/rdi_format_local.h @@ -7,6 +7,97 @@ #include "lib_rdi_format/rdi_format.h" #include "lib_rdi_format/rdi_format_parse.h" +//////////////////////////////// +//~ rjf: RDI Dumping Flags + +#define RDI_DumpSubset_XList \ +X(DataSections, data_sections, "DATA SECTIONS")\ +X(TopLevelInfo, top_level_info, "TOP LEVEL INFO")\ +X(BinarySections, binary_sections, "BINARY SECTIONS")\ +X(FilePaths, file_paths, "FILE PATHS")\ +X(SourceFiles, source_files, "SOURCE FILES")\ +X(LineTables, line_tables, "LINE TABLES")\ +X(SourceLineMaps, source_line_maps, "SOURCE LINE MAPS")\ +X(Units, units, "UNITS")\ +X(UnitVMap, unit_vmap, "UNIT VMAP")\ +X(TypeNodes, type_nodes, "TYPE NODES")\ +X(UserDefinedTypes, user_defined_types, "USER DEFINED TYPES")\ +X(GlobalVariables, global_variables, "GLOBAL VARIABLES")\ +X(GlobalVariablesVMap, global_variables_vmap, "GLOBAL VARIABLE VMAP")\ +X(ThreadVariables, thread_variables, "THREAD VARIABLES")\ +X(Constants, constants, "CONSTANTS")\ +X(Procedures, procedures, "PROCEDURES")\ +X(Scopes, scopes, "SCOPES")\ +X(ScopeVMap, scope_vmap, "SCOPE VMAP")\ +X(InlineSites, inline_sites, "INLINE SITES")\ +X(NameMaps, name_maps, "NAME MAPS")\ +X(Strings, strings, "STRINGS")\ + +typedef enum RDI_DumpSubset +{ +#define X(name, name_lower, title) RDI_DumpSubset_##name, + RDI_DumpSubset_XList +#undef X +} +RDI_DumpSubset; + +typedef U32 RDI_DumpSubsetFlags; +enum +{ +#define X(name, name_lower, title) RDI_DumpSubsetFlag_##name = (1< Enum + +internal String8 rdi_string_from_data_section_kind(Arena *arena, RDI_SectionKind v); +internal String8 rdi_string_from_arch (Arena *arena, RDI_Arch v); +internal String8 rdi_string_from_language (Arena *arena, RDI_Language v); +internal String8 rdi_string_from_local_kind (Arena *arena, RDI_LocalKind v); +#if 0 // TODO(rjf): conflicts with RDI... +internal String8 rdi_string_from_type_kind (Arena *arena, RDI_TypeKind v); +#endif +internal String8 rdi_string_from_member_kind (Arena *arena, RDI_MemberKind v); +internal String8 rdi_string_from_name_map_kind(RDI_NameMapKind kind); + +internal String8 rdi_string_from_binary_section_flags(Arena *arena, RDI_BinarySectionFlags flags); +internal String8 rdi_string_from_type_modifier (Arena *arena, RDI_TypeModifierFlags flags); +internal String8 rdi_string_from_udt_flags (Arena *arena, RDI_UDTFlags flags); +internal String8 rdi_string_from_link_flags (Arena *arena, RDI_LinkFlags flags); +internal String8 rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc); +internal String8List rdi_strings_from_locations(Arena *arena, RDI_Parsed *rdi, RDI_Arch arch, Rng1U64 location_block_range); + +//////////////////////////////// +//~ rjf: RDI Dumping + +internal void rdi_dump_scope (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Scope *scope, RDI_Arch arch); +internal String8List rdi_dump_list_from_parsed(Arena *arena, RDI_Parsed *rdi, RDI_DumpSubsetFlags flags); + #endif // RDI_FORMAT_LOCAL_H