From 248a155579f762fc6d432e3bf2a160ee7d22584c Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 19 Jun 2025 16:48:07 -0700 Subject: [PATCH] checkpoint on dump parseability pass --- project.4coder | 2 +- src/coff/coff_dump.c | 819 +++++++++++++++++++++++++++++++++++++++ src/coff/coff_dump.h | 22 ++ src/coff/coff_inc.c | 6 + src/coff/coff_inc.h | 11 + src/radbin/radbin_main.c | 6 +- src/raddump/raddump.c | 817 -------------------------------------- src/raddump/raddump.h | 15 - src/rdi/rdi_local.c | 36 +- 9 files changed, 881 insertions(+), 853 deletions(-) create mode 100644 src/coff/coff_dump.c create mode 100644 src/coff/coff_dump.h create mode 100644 src/coff/coff_inc.c create mode 100644 src/coff/coff_inc.h diff --git a/project.4coder b/project.4coder index 9da7220b..2d3c8b01 100644 --- a/project.4coder +++ b/project.4coder @@ -49,7 +49,7 @@ commands = .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [scratch] - .f2 = { .win = "raddbg_stable --ipc kill_all && build radbin release telemetry && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + .f2 = { .win = "raddbg_stable --ipc kill_all && build radbin && pushd build && radbin.exe mule_main.rdi --out:a.dump && popd", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [textperf] // .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta telemetry textperf && raddbg_stable --ipc bring_to_front && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, diff --git a/src/coff/coff_dump.c b/src/coff/coff_dump.c new file mode 100644 index 00000000..2d74d087 --- /dev/null +++ b/src/coff/coff_dump.c @@ -0,0 +1,819 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#if 0 +internal void +coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveMemberHeader header, String8 long_names) +{ + Temp scratch = scratch_begin(&arena, 1); + String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header.time_stamp); + + rd_printf("Name : %S" , header.name ); + rd_printf("Time Stamp: (%#x) %S" , header.time_stamp, time_stamp ); + rd_printf("User ID : %u" , header.user_id ); + rd_printf("Group ID : %u" , header.group_id); + rd_printf("Mode : %S" , header.mode ); + rd_printf("Data : [%#llx-%#llx)", header.data_range.min, header.data_range.max); + + scratch_end(scratch); +} + +internal void +coff_print_section_table(Arena *arena, + String8List *out, + String8 indent, + String8 string_table, + COFF_Symbol32Array symbol_table, + U64 section_count, + COFF_SectionHeader *section_table) +{ + Temp scratch = scratch_begin(&arena, 1); + + String8 *symlinks = push_array(scratch.arena, String8, section_count); + for (U64 i = 0; i < symbol_table.count; ++i) { + COFF_Symbol32 *symbol = symbol_table.v+i; + COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol->section_number, symbol->value, symbol->storage_class); + if (interp == COFF_SymbolValueInterp_Regular && + symbol->aux_symbol_count == 0 && + (symbol->storage_class == COFF_SymStorageClass_External || symbol->storage_class == COFF_SymStorageClass_Static)) { + if (symbol->section_number > 0 && symbol->section_number <= symbol_table.count) { + COFF_SectionHeader *header = section_table+(symbol->section_number-1); + if (header->flags & COFF_SectionFlag_LnkCOMDAT) { + symlinks[symbol->section_number-1] = coff_read_symbol_name(string_table, &symbol->name); + } + } + } + i += symbol->aux_symbol_count; + } + + if (section_count) { + rd_printf("# Section Table"); + rd_indent(); + + rd_printf("%-4s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-5s %-10s %s", + "No.", + "Name", + "VirtSize", + "VirtOff", + "FileSize", + "FileOff", + "RelocOff", + "LinesOff", + "RelocCnt", + "LineCnt", + "Align", + "Flags", + "Symlink"); + + for (U64 i = 0; i < section_count; ++i) { + COFF_SectionHeader *header = section_table+i; + + String8 name = str8_cstring_capped(header->name, header->name+sizeof(header->name)); + String8 full_name = coff_name_from_section_header(string_table, header); + + String8 align; + { + U64 align_size = coff_align_size_from_section_flags(header->flags); + align = push_str8f(scratch.arena, "%u", align_size); + } + + String8 flags; + { + String8List mem_flags = {0}; + if (header->flags & COFF_SectionFlag_MemRead) { + str8_list_pushf(scratch.arena, &mem_flags, "r"); + } + if (header->flags & COFF_SectionFlag_MemWrite) { + str8_list_pushf(scratch.arena, &mem_flags, "w"); + } + if (header->flags & COFF_SectionFlag_MemExecute) { + str8_list_pushf(scratch.arena, &mem_flags, "x"); + } + + String8List cnt_flags = {0}; + if (header->flags & COFF_SectionFlag_CntCode) { + str8_list_pushf(scratch.arena, &cnt_flags, "c"); + } + if (header->flags & COFF_SectionFlag_CntInitializedData) { + str8_list_pushf(scratch.arena, &cnt_flags, "d"); + } + if (header->flags & COFF_SectionFlag_CntUninitializedData) { + str8_list_pushf(scratch.arena, &cnt_flags, "u"); + } + + String8List mem_extra_flags = {0}; + if (header->flags & COFF_SectionFlag_MemShared) { + str8_list_pushf(scratch.arena, &mem_flags, "s"); + } + if (header->flags & COFF_SectionFlag_Mem16Bit) { + str8_list_pushf(scratch.arena, &mem_extra_flags, "h"); + } + if (header->flags & COFF_SectionFlag_MemLocked) { + str8_list_pushf(scratch.arena, &mem_extra_flags, "l"); + } + if (header->flags & COFF_SectionFlag_MemDiscardable) { + str8_list_pushf(scratch.arena, &mem_extra_flags, "d"); + } + if (header->flags & COFF_SectionFlag_MemNotCached) { + str8_list_pushf(scratch.arena, &mem_extra_flags, "c"); + } + if (header->flags & COFF_SectionFlag_MemNotPaged) { + str8_list_pushf(scratch.arena, &mem_extra_flags, "p"); + } + + String8List lnk_flags = {0}; + if (header->flags & COFF_SectionFlag_LnkRemove) { + str8_list_pushf(scratch.arena, &lnk_flags, "r"); + } + if (header->flags & COFF_SectionFlag_LnkCOMDAT) { + str8_list_pushf(scratch.arena, &lnk_flags, "c"); + } + if (header->flags & COFF_SectionFlag_LnkOther) { + str8_list_pushf(scratch.arena, &lnk_flags, "o"); + } + if (header->flags & COFF_SectionFlag_LnkInfo) { + str8_list_pushf(scratch.arena, &lnk_flags, "i"); + } + if (header->flags & COFF_SectionFlag_LnkNRelocOvfl) { + str8_list_pushf(scratch.arena, &lnk_flags, "f"); + } + + String8List other_flags = {0}; + if (header->flags & COFF_SectionFlag_TypeNoPad) { + str8_list_pushf(scratch.arena, &other_flags, "n"); + } + if (header->flags & COFF_SectionFlag_GpRel) { + str8_list_pushf(scratch.arena, &other_flags, "g"); + } + + String8 mem = str8_list_join(scratch.arena, &mem_flags, 0); + String8 cnt = str8_list_join(scratch.arena, &cnt_flags, 0); + String8 lnk = str8_list_join(scratch.arena, &lnk_flags, 0); + String8 ext = str8_list_join(scratch.arena, &mem_extra_flags, 0); + String8 oth = str8_list_join(scratch.arena, &other_flags, 0); + + String8List f = {0}; + str8_list_push(scratch.arena, &f, mem); + str8_list_push(scratch.arena, &f, cnt); + str8_list_push(scratch.arena, &f, ext); + str8_list_push(scratch.arena, &f, lnk); + str8_list_push(scratch.arena, &f, oth); + + flags = str8_list_join(scratch.arena, &f, &(StringJoin){ .sep = str8_lit("-") }); + + if (!flags.size) { + flags = str8_lit("none"); + } + } + + String8List l = {0}; + str8_list_pushf(scratch.arena, &l, "%-4x", i+1 ); + str8_list_pushf(scratch.arena, &l, "%-8S", name ); + str8_list_pushf(scratch.arena, &l, "%08x", header->vsize ); + str8_list_pushf(scratch.arena, &l, "%08x", header->voff ); + str8_list_pushf(scratch.arena, &l, "%08x", header->fsize ); + str8_list_pushf(scratch.arena, &l, "%08x", header->foff ); + str8_list_pushf(scratch.arena, &l, "%08x", header->relocs_foff); + str8_list_pushf(scratch.arena, &l, "%08x", header->lines_foff ); + str8_list_pushf(scratch.arena, &l, "%08x", header->reloc_count); + str8_list_pushf(scratch.arena, &l, "%08x", header->line_count ); + str8_list_pushf(scratch.arena, &l, "%-5S", align ); + str8_list_pushf(scratch.arena, &l, "%-10S", flags ); + if (symlinks[i].size > 0) { + str8_list_pushf(scratch.arena, &l, "%S", symlinks[i]); + } else { + str8_list_pushf(scratch.arena, &l, "[no symlink]"); + } + + String8 line = str8_list_join(scratch.arena, &l, &(StringJoin){ .sep = str8_lit(" "), }); + rd_printf("%S", line); + + if (full_name.size != name.size) { + rd_indent(); + rd_printf("Full Name: %S", full_name); + rd_unindent(); + } + } + + rd_newline(); + rd_printf("Flags:"); + rd_indent(); + rd_printf("r = MemRead w = MemWrite x = MemExecute"); + rd_printf("c = CntCode d = InitializedData u = UninitializedData"); + rd_printf("s = MemShared h = Mem16bit l = MemLocked d = MemDiscardable c = MemNotCached p = MemNotPaged"); + rd_printf("r = LnkRemove c = LnkComdat o = LnkOther i = LnkInfo f = LnkNRelocOvfl"); + rd_printf("g = GpRel n = TypeNoPad"); + rd_unindent(); + + rd_unindent(); + rd_newline(); + } + + scratch_end(scratch); +} + +internal void +coff_disasm_sections(Arena *arena, + String8List *out, + String8 indent, + String8 raw_data, + COFF_MachineType machine, + U64 image_base, + B32 is_obj, + RD_MarkerArray *section_markers, + U64 section_count, + COFF_SectionHeader *sections) +{ + if (section_count) { + for (U64 sect_idx = 0; sect_idx < section_count; ++sect_idx) { + COFF_SectionHeader *sect = sections+sect_idx; + if (sect->flags & COFF_SectionFlag_CntCode) { + U64 sect_off = is_obj ? sect->foff : sect->voff; + U64 sect_size = is_obj ? sect->fsize : sect->vsize; + String8 raw_code = str8_substr(raw_data, rng_1u64(sect->foff, sect->foff+sect_size)); + U64 sect_number = sect_idx+1; + RD_MarkerArray markers = section_markers[sect_number]; + + rd_printf("# Disassembly [Section No. %#llx]", sect_number); + rd_indent(); + rd_print_disasm(arena, out, indent, arch_from_coff_machine(machine), image_base, sect_off, markers.count, markers.v, raw_code); + rd_unindent(); + } + } + } +} + +internal void +coff_raw_data_sections(Arena *arena, + String8List *out, + String8 indent, + String8 raw_data, + B32 is_obj, + RD_MarkerArray *section_markers, + U64 section_count, + COFF_SectionHeader *section_table) +{ + if (section_count) { + for (U64 sect_idx = 0; sect_idx < section_count; ++sect_idx) { + COFF_SectionHeader *sect = section_table+sect_idx; + if (sect->fsize > 0) { + U64 sect_size = is_obj ? sect->fsize : sect->vsize; + String8 raw_sect = str8_substr(raw_data, rng_1u64(sect->foff, sect->foff+sect_size)); + RD_MarkerArray markers = section_markers[sect_idx]; + + rd_printf("# Raw Data [Section No. %#llx]", (sect_idx+1)); + rd_indent(); + rd_print_raw_data(arena, out, indent, 32, markers.count, markers.v, raw_sect); + rd_unindent(); + rd_newline(); + } + } + } +} + +internal void +coff_print_relocs(Arena *arena, + String8List *out, + String8 indent, + String8 raw_data, + String8 string_table, + COFF_MachineType machine, + U64 sect_count, + COFF_SectionHeader *sect_headers, + COFF_Symbol32Array symbols) +{ + Temp scratch = scratch_begin(&arena, 1); + + B32 print_header = 1; + + for (U64 sect_idx = 0; sect_idx < sect_count; ++sect_idx) { + COFF_SectionHeader *sect_header = sect_headers+sect_idx; + COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(raw_data, sect_header); + + if (reloc_info.count) { + if (print_header) { + print_header = 0; + rd_printf("# Relocations"); + rd_indent(); + } + + rd_printf("## Section %llx", sect_idx); + rd_indent(); + + rd_printf("%-4s %-8s %-16s %-16s %-8s %-7s", "No.", "Offset", "Type", "ApplyTo", "SymIdx", "SymName"); + + for (U64 reloc_idx = 0; reloc_idx < reloc_info.count; ++reloc_idx) { + COFF_Reloc *reloc = (COFF_Reloc*)(raw_data.str + reloc_info.array_off) + reloc_idx; + String8 type = coff_string_from_reloc(machine, reloc->type); + U64 apply_size = coff_apply_size_from_reloc(machine, reloc->type); + + U64 apply_foff = sect_header->foff + reloc->apply_off; + if (apply_foff + apply_size > raw_data.size) { + rd_errorf("out of bounds apply file offset %#llx in relocation %#llx", apply_foff, reloc_idx); + break; + } + + U64 raw_apply; + AssertAlways(apply_size <= sizeof(raw_apply)); + MemoryCopy(&raw_apply, raw_data.str + apply_foff, apply_size); + S64 apply = extend_sign64(raw_apply, apply_size); + + if (reloc->isymbol > symbols.count) { + rd_errorf("out of bounds symbol index %u in relocation %#llx", reloc->isymbol, reloc_idx); + break; + } + + COFF_Symbol32 *symbol = symbols.v+reloc->isymbol; + String8 symbol_name = coff_read_symbol_name(string_table, &symbol->name); + + String8List line = {0}; + str8_list_pushf(scratch.arena, &line, "%-4x", reloc_idx ); + str8_list_pushf(scratch.arena, &line, "%08x", reloc->apply_off); + str8_list_pushf(scratch.arena, &line, "%-16S", type ); + str8_list_pushf(scratch.arena, &line, "%016x", apply ); + str8_list_pushf(scratch.arena, &line, "%S", symbol_name ); + + String8 l = str8_list_join(scratch.arena, &line, &(StringJoin){.sep=str8_lit(" ")}); + rd_printf("%S", l); + } + + rd_unindent(); + } + } + + if (!print_header) { + rd_unindent(); + } + rd_newline(); + + scratch_end(scratch); +} + +internal void +coff_print_symbol_table(Arena *arena, + String8List *out, + String8 indent, + String8 raw_data, + B32 is_big_obj, + String8 string_table, + COFF_Symbol32Array symbols) +{ + Temp scratch = scratch_begin(&arena, 1); + + if (symbols.count) { + rd_printf("# Symbol Table"); + rd_indent(); + + rd_printf("%-4s %-8s %-10s %-4s %-4s %-4s %-16s %-20s", + "No.", "Value", "SectNum", "Aux", "Msb", "Lsb", "Storage", "Name"); + + for (U64 i = 0; i < symbols.count; ++i) { + COFF_Symbol32 *symbol = &symbols.v[i]; + String8 name = coff_read_symbol_name(string_table, &symbol->name); + String8 msb = coff_string_from_sym_dtype(symbol->type.u.msb); + String8 lsb = coff_string_from_sym_type(symbol->type.u.lsb); + String8 storage_class = coff_string_from_sym_storage_class(symbol->storage_class); + String8 section_number; + switch (symbol->section_number) { + case COFF_Symbol_UndefinedSection: section_number = str8_lit("Undef"); break; + case COFF_Symbol_AbsSection32: section_number = str8_lit("Abs"); break; + case COFF_Symbol_DebugSection32: section_number = str8_lit("Debug"); break; + default: section_number = push_str8f(scratch.arena, "%010x", symbol->section_number); break; + } + + String8List line = {0}; + str8_list_pushf(scratch.arena, &line, "%-4x", i ); + str8_list_pushf(scratch.arena, &line, "%08x", symbol->value ); + str8_list_pushf(scratch.arena, &line, "%-10S", section_number ); + str8_list_pushf(scratch.arena, &line, "%-4u", symbol->aux_symbol_count); + str8_list_pushf(scratch.arena, &line, "%-4S", msb ); + str8_list_pushf(scratch.arena, &line, "%-4S", lsb ); + str8_list_pushf(scratch.arena, &line, "%-16S", storage_class ); + str8_list_pushf(scratch.arena, &line, "%S", name ); + + String8 l = str8_list_join(scratch.arena, &line, &(StringJoin){.sep = str8_lit(" ")}); + rd_printf("%S", l); + + rd_indent(); + for (U64 k=i+1, c = i+symbol->aux_symbol_count; k <= c; ++k) { + void *raw_aux = &symbols.v[k]; + switch (symbol->storage_class) { + case COFF_SymStorageClass_External: { + COFF_SymbolFuncDef *func_def = (COFF_SymbolFuncDef*)&symbols.v[k]; + rd_printf("Tag Index %#x, Total Size %#x, Line Numbers %#x, Next Function %#x", + func_def->tag_index, func_def->total_size, func_def->ptr_to_ln, func_def->ptr_to_next_func); + } break; + case COFF_SymStorageClass_Function: { + COFF_SymbolFunc *func = raw_aux; + rd_printf("Ordinal Line Number %#x, Next Function %#x", func->ln, func->ptr_to_next_func); + } break; + case COFF_SymStorageClass_WeakExternal: { + COFF_SymbolWeakExt *weak = raw_aux; + String8 type = coff_string_from_weak_ext_type(weak->characteristics); + rd_printf("Tag Index %#x, Characteristics %S", weak->tag_index, type); + } break; + case COFF_SymStorageClass_File: { + COFF_SymbolFile *file = raw_aux; + String8 name = str8_cstring_capped(file->name, file->name+sizeof(file->name)); + rd_printf("Name %S", name); + } break; + case COFF_SymStorageClass_Static: { + COFF_SymbolSecDef *sd = raw_aux; + String8 selection = coff_string_from_comdat_select_type(sd->selection); + U32 number = sd->number_lo; + if (is_big_obj) { + number |= (U32)sd->number_hi << 16; + } + if (number) { + rd_printf("Length %x, Reloc Count %u, Line Count %u, Checksum %x, Section %x, Selection %S", + sd->length, sd->number_of_relocations, sd->number_of_ln, sd->check_sum, number, selection); + } else { + rd_printf("Length %x, Reloc Count %u, Line Count %u, Checksum %x", + sd->length, sd->number_of_relocations, sd->number_of_ln, sd->check_sum); + } + } break; + default: { + rd_printf("???"); + } break; + } + } + + i += symbol->aux_symbol_count; + rd_unindent(); + } + + rd_unindent(); + rd_newline(); + } + + scratch_end(scratch); +} + +internal void +coff_print_big_obj_header(Arena *arena, String8List *out, String8 indent, COFF_BigObjHeader *header) +{ + Temp scratch = scratch_begin(&arena, 1); + + String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp); + String8 machine = coff_string_from_machine_type(header->machine); + + rd_printf("# Big Obj"); + rd_indent(); + rd_printf("Time Stamp : %#x (%S)", header->time_stamp, time_stamp); + rd_printf("Machine : %#x (%S)", header->machine, machine ); + rd_printf("Section Count: %u", header->section_count ); + rd_printf("Symbol Table : %#x", header->symbol_table_foff); + rd_printf("Symbol Count : %u", header->symbol_count ); + rd_unindent(); + + scratch_end(scratch); +} + +internal void +coff_print_file_header(Arena *arena, String8List *out, String8 indent, COFF_FileHeader *header) +{ + Temp scratch = scratch_begin(&arena, 1); + + String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp); + String8 machine = coff_string_from_machine_type(header->machine); + String8 flags = coff_string_from_flags(scratch.arena, header->flags); + + rd_printf("# COFF File Header"); + rd_indent(); + rd_printf("Time Stamp : %#x (%S)", header->time_stamp, time_stamp ); + rd_printf("Machine : %#x %S", header->machine, machine ); + rd_printf("Section Count : %u", header->section_count ); + rd_printf("Symbol Table : %#x", header->symbol_table_foff ); + rd_printf("Symbol Count : %u", header->symbol_count ); + rd_printf("Optional Header Size: %#x (%m)", header->optional_header_size, header->optional_header_size); + rd_printf("Flags : %#x (%S)", header->flags, flags ); + rd_unindent(); + + scratch_end(scratch); +} + +internal void +coff_print_import(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveImportHeader *header) +{ + Temp scratch = scratch_begin(&arena, 1); + + String8 machine = coff_string_from_machine_type(header->machine); + String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp); + + rd_printf("# Import"); + rd_indent(); + rd_printf("Version : %u", header->version ); + rd_printf("Machine : %S", machine ); + rd_printf("Time Stamp: %#x (%S)", header->time_stamp, time_stamp ); + rd_printf("Data Size : %#x (%m)", header->data_size, header->data_size); + rd_printf("Hint : %u", header->hint_or_ordinal); + rd_printf("Type : %u", header->type ); + rd_printf("Import By : %u", header->import_by ); + rd_printf("Function : %S", header->func_name ); + rd_printf("DLL : %S", header->dll_name ); + rd_unindent(); + + scratch_end(scratch); +} + +internal void +coff_print_big_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts) +{ + Temp scratch = scratch_begin(&arena, 1); + + COFF_FileHeaderInfo header_info = coff_file_header_info_from_data(raw_data); + + String8 raw_header = str8_substr(raw_data, header_info.header_range); + String8 raw_section_table = str8_substr(raw_data, header_info.section_table_range); + String8 raw_string_table = str8_substr(raw_data, header_info.string_table_range); + + COFF_BigObjHeader *big_obj = (COFF_BigObjHeader *)raw_header.str; + COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str; + COFF_Symbol32Array symbol_table = coff_symbol_array_from_data_32(scratch.arena, raw_data, header_info.symbol_table_range.min, big_obj->symbol_count); + + if (opts & RD_Option_Headers) { + coff_print_big_obj_header(arena, out, indent, big_obj); + rd_newline(); + } + + if (opts & RD_Option_Sections) { + Rng1U64 sect_headers_range = rng_1u64(sizeof(*big_obj), sizeof(*big_obj) + sizeof(COFF_SectionHeader)*big_obj->section_count); + Rng1U64 symbols_range = rng_1u64(big_obj->symbol_table_foff, big_obj->symbol_table_foff + sizeof(COFF_Symbol32)*big_obj->symbol_count); + + if (sect_headers_range.max > raw_data.size) { + rd_errorf("not enough bytes to read big obj section headers"); + goto exit; + } + if (big_obj->symbol_count) { + if (symbols_range.max > raw_data.size) { + rd_errorf("not enough bytes to read big obj symbol table"); + goto exit; + } + if (contains_1u64(symbols_range, sect_headers_range.min) || + contains_1u64(symbols_range, sect_headers_range.max)) { + rd_errorf("section headers and symbol table ranges overlap"); + goto exit; + } + } + + coff_print_section_table(arena, out, indent, raw_string_table, symbol_table, big_obj->section_count, section_table); + rd_newline(); + } + + if (opts & RD_Option_Relocs) { + coff_print_relocs(arena, out, indent, raw_data, raw_string_table, big_obj->machine, big_obj->section_count, section_table, symbol_table); + rd_newline(); + } + + if (opts & RD_Option_Symbols) { + coff_print_symbol_table(arena, out, indent, raw_data, 1, raw_string_table, symbol_table); + rd_newline(); + } + + exit:; + scratch_end(scratch); +} + +internal void +coff_print_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts) +{ + Temp scratch = scratch_begin(&arena, 1); + + COFF_FileHeaderInfo header_info = coff_file_header_info_from_data(raw_data); + + String8 raw_header = str8_substr(raw_data, header_info.header_range); + String8 raw_section_table = str8_substr(raw_data, header_info.section_table_range); + String8 raw_string_table = str8_substr(raw_data, header_info.string_table_range); + + COFF_FileHeader *header = (COFF_FileHeader *)raw_header.str; + COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str; + COFF_Symbol32Array symbol_table = coff_symbol_array_from_data_16(scratch.arena, raw_data, header_info.symbol_table_range.min, header->symbol_count); + Arch arch = arch_from_coff_machine(header->machine); + + if (opts & RD_Option_Headers) { + coff_print_file_header(arena, out, indent, header); + rd_newline(); + } + + if (opts & RD_Option_Sections) { + Rng1U64 sect_headers_range = rng_1u64(sizeof(*header), sizeof(*header) + sizeof(COFF_SectionHeader)*header->section_count); + Rng1U64 symbols_range = rng_1u64(header->symbol_table_foff, header->symbol_table_foff + sizeof(COFF_Symbol16)*header->symbol_count); + + if (sect_headers_range.max > raw_data.size) { + rd_errorf("not enough bytes to read obj section headers"); + goto exit; + } + if (header->symbol_count) { + if (symbols_range.max > raw_data.size) { + rd_errorf("not enough bytes to read obj symbol table"); + goto exit; + } + if (contains_1u64(symbols_range, sect_headers_range.min) || + contains_1u64(symbols_range, sect_headers_range.max)) { + rd_errorf("section headers and symbol table ranges overlap"); + goto exit; + } + } + + coff_print_section_table(arena, out, indent, raw_string_table, symbol_table, header->section_count, section_table); + rd_newline(); + } + + if (opts & RD_Option_Relocs) { + coff_print_relocs(arena, out, indent, raw_data, raw_string_table, header->machine, header->section_count, section_table, symbol_table); + rd_newline(); + } + + if (opts & RD_Option_Symbols) { + coff_print_symbol_table(arena, out, indent, raw_data, 0, raw_string_table, symbol_table); + rd_newline(); + } + + RD_MarkerArray *section_markers = 0; + if (opts & (RD_Option_Disasm|RD_Option_Rawdata)) { + section_markers = rd_section_markers_from_coff_symbol_table(scratch.arena, raw_string_table, header->section_count, symbol_table); + } + + if (opts & RD_Option_Rawdata) { + coff_raw_data_sections(arena, out, indent, raw_data, 1, section_markers, header->section_count, section_table); + } + + if (opts & RD_Option_Disasm) { + coff_disasm_sections(arena, out, indent, raw_data, header->machine, 0, 1, section_markers, header->section_count, section_table); + rd_newline(); + } + + if (opts & RD_Option_Codeview) { + cv_format_debug_sections(arena, out, indent, raw_data, raw_string_table, header->section_count, section_table); + } + + if (opts & RD_Option_Dwarf) { + DW_Input dwarf_input = dw_input_from_coff_section_table(scratch.arena, raw_data, raw_string_table, header->section_count, section_table); + dw_format(arena, out, indent, opts, &dwarf_input, arch, ExecutableImageKind_CoffPe); + } + + exit:; + scratch_end(scratch); +} + +internal void +coff_print_archive(Arena *arena, String8List *out, String8 indent, String8 raw_archive, RD_Option opts) +{ + Temp scratch = scratch_begin(&arena, 1); + + COFF_ArchiveParse archive_parse = coff_archive_parse_from_data(raw_archive); + + if (archive_parse.error.size) { + rd_errorf("%S", archive_parse.error); + return; + } + + COFF_ArchiveFirstMember first_member = archive_parse.first_member; + { + rd_printf("# First Header"); + rd_indent(); + + rd_printf("Symbol Count : %u", first_member.symbol_count); + rd_printf("String Table Size: %#llx (%M)", first_member.string_table.size, first_member.string_table.size); + + rd_printf("Members:"); + rd_indent(); + + String8List string_table = str8_split_by_string_chars(scratch.arena, first_member.string_table, str8_lit("\0"), 0); + + if (string_table.node_count == first_member.member_offset_count) { + String8Node *string_n = string_table.first; + + for (U64 i = 0; i < string_table.node_count; ++i, string_n = string_n->next) { + U32 offset = from_be_u32(first_member.member_offsets[i]); + rd_printf("[%4u] %#08x %S", i, offset, string_n->string); + } + } else { + rd_errorf("Member offset count (%llu) doesn't match string table count (%llu)", first_member.member_offset_count); + } + + rd_unindent(); + rd_unindent(); + rd_newline(); + } + + if (archive_parse.has_second_header) { + COFF_ArchiveSecondMember second_member = archive_parse.second_member; + + rd_printf("# Second Header"); + rd_indent(); + + rd_printf("Member Count : %u", second_member.member_count); + rd_printf("Symbol Count : %u", second_member.symbol_count); + rd_printf("String Table Size: %#llx (%M)", second_member.string_table.size, second_member.string_table.size); + + String8List string_table = str8_split_by_string_chars(scratch.arena, second_member.string_table, str8_lit("\0"), 0); + + rd_printf("Members:"); + rd_indent(); + if (second_member.symbol_index_count == second_member.symbol_count) { + String8Node *string_n = string_table.first; + for (U64 i = 0; i < second_member.symbol_count; ++i, string_n = string_n->next) { + U16 symbol_number = second_member.symbol_indices[i]; + if (symbol_number > 0 && symbol_number <= second_member.member_offset_count) { + U16 symbol_idx = symbol_number - 1; + U32 member_offset = second_member.member_offsets[i]; + rd_printf("[%4u] %#08x %S", i, member_offset, string_n->string); + } else { + rd_errorf("[%4u] Out of bounds symbol number %u", i, symbol_number); + break; + } + } + } else { + rd_errorf("Symbol index count %u doesn't match symbol count %u", + second_member.symbol_index_count, second_member.symbol_count); + } + rd_unindent(); + + rd_unindent(); + rd_newline(); + } + + if (archive_parse.has_long_names && opts & RD_Option_LongNames) { + rd_printf("# Long Names"); + rd_indent(); + + String8List long_names = str8_split_by_string_chars(scratch.arena, archive_parse.long_names, str8_lit("\0"), 0); + U64 name_idx = 0; + for (String8Node *name_n = long_names.first; name_n != 0; name_n = name_n->next, ++name_idx) { + U64 offset = (U64)(name_n->string.str - archive_parse.long_names.str); + rd_printf("[%-4u] %#08x %S", name_idx, offset, name_n->string); + } + + rd_unindent(); + rd_newline(); + } + + U64 member_offset_count = 0; + U32 *member_offsets = 0; + if (archive_parse.has_second_header) { + member_offset_count = archive_parse.second_member.member_offset_count; + member_offsets = archive_parse.second_member.member_offsets; + } else { + HashTable *ht = hash_table_init(scratch.arena, 0x1000); + for (U64 i = 0; i < archive_parse.first_member.member_offset_count; ++i) { + U32 member_offset = from_be_u32(archive_parse.first_member.member_offsets[i]); + if (!hash_table_search_u32(ht, member_offset)) { + hash_table_push_u32_raw(scratch.arena, ht, member_offset, 0); + } + } + member_offset_count = ht->count; + member_offsets = keys_from_hash_table_u32(scratch.arena, ht); + radsort(member_offsets, member_offset_count, u32_is_before); + } + + rd_printf("# Members"); + rd_indent(); + + for (U64 i = 0; i < member_offset_count; ++i) { + U64 next_member_offset = i+1 < member_offset_count ? member_offsets[i+1] : raw_archive.size; + U64 member_offset = member_offsets[i]; + String8 raw_member = str8_substr(raw_archive, rng_1u64(member_offset, next_member_offset)); + COFF_ArchiveMember member = coff_archive_member_from_data(raw_member); + COFF_DataType member_type = coff_data_type_from_data(member.data); + + rd_printf("Member @ %#llx", member_offset); + rd_indent(); + + if (opts & RD_Option_Headers) { + coff_print_archive_member_header(arena, out, indent, member.header, archive_parse.long_names); + rd_newline(); + } + + switch (member_type) { + case COFF_DataType_Obj: { + coff_print_obj(arena, out, indent, member.data, opts); + } break; + case COFF_DataType_BigObj: { + coff_print_big_obj(arena, out, indent, member.data, opts); + } break; + case COFF_DataType_Import: { + if (opts & RD_Option_Headers) { + COFF_ParsedArchiveImportHeader header = {0}; + U64 parse_size = coff_parse_import(member.data, 0, &header); + if (parse_size) { + coff_print_import(arena, out, indent, &header); + } else { + rd_errorf("not enough bytes to parse import header"); + } + } + } break; + case COFF_DataType_Null: { + rd_errorf("unknown member format", member_offset); + } break; + } + + rd_unindent(); + rd_newline(); + } + + rd_unindent(); + + scratch_end(scratch); +} +#endif diff --git a/src/coff/coff_dump.h b/src/coff/coff_dump.h new file mode 100644 index 00000000..89afcecb --- /dev/null +++ b/src/coff/coff_dump.h @@ -0,0 +1,22 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef COFF_DUMP_H +#define COFF_DUMP_H + +#if 0 +internal void coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveMemberHeader header, String8 long_names); +internal void coff_print_section_table (Arena *arena, String8List *out, String8 indent, String8 string_table, COFF_Symbol32Array symbols, U64 sect_count, COFF_SectionHeader *sect_headers); +internal void coff_disasm_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, COFF_MachineType machine, U64 image_base, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections); +internal void coff_raw_data_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections); +internal void coff_print_relocs (Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 string_table, COFF_MachineType machine, U64 sect_count, COFF_SectionHeader *sect_headers, COFF_Symbol32Array symbols); +internal void coff_print_symbol_table (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_big_obj, String8 string_table, COFF_Symbol32Array symbols); +internal void coff_print_big_obj_header (Arena *arena, String8List *out, String8 indent, COFF_BigObjHeader *header); +internal void coff_print_file_header (Arena *arena, String8List *out, String8 indent, COFF_FileHeader *header); +internal void coff_print_import (Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveImportHeader *header); +internal void coff_print_big_obj (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts); +internal void coff_print_obj (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts); +internal void coff_print_archive (Arena *arena, String8List *out, String8 indent, String8 raw_archive, RD_Option opts); +#endif + +#endif // COFF_DUMP_H diff --git a/src/coff/coff_inc.c b/src/coff/coff_inc.c new file mode 100644 index 00000000..d31310d4 --- /dev/null +++ b/src/coff/coff_inc.c @@ -0,0 +1,6 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#include "coff/coff.c" +#include "coff/coff_parse.c" +#include "coff/coff_dump.c" diff --git a/src/coff/coff_inc.h b/src/coff/coff_inc.h new file mode 100644 index 00000000..7688ac63 --- /dev/null +++ b/src/coff/coff_inc.h @@ -0,0 +1,11 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef COFF_INC_H +#define COFF_INC_H + +#include "coff/coff.h" +#include "coff/coff_parse.h" +#include "coff/coff_dump.h" + +#endif // COFF_INC_H diff --git a/src/radbin/radbin_main.c b/src/radbin/radbin_main.c index a4ffadb7..f0f6f8b4 100644 --- a/src/radbin/radbin_main.c +++ b/src/radbin/radbin_main.c @@ -17,8 +17,7 @@ #include "async/async.h" #include "rdi/rdi_local.h" #include "rdi_make/rdi_make_local.h" -#include "coff/coff.h" -#include "coff/coff_parse.h" +#include "coff/coff_inc.h" #include "pe/pe.h" #include "elf/elf.h" #include "elf/elf_parse.h" @@ -44,8 +43,7 @@ #include "async/async.c" #include "rdi/rdi_local.c" #include "rdi_make/rdi_make_local.c" -#include "coff/coff.c" -#include "coff/coff_parse.c" +#include "coff/coff_inc.c" #include "pe/pe.c" #include "elf/elf.c" #include "elf/elf_parse.c" diff --git a/src/raddump/raddump.c b/src/raddump/raddump.c index defb847c..17785cb9 100644 --- a/src/raddump/raddump.c +++ b/src/raddump/raddump.c @@ -2541,823 +2541,6 @@ cv_format_debug_sections(Arena *arena, String8List *out, String8 indent, String8 } } -// COFF - -internal void -coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveMemberHeader header, String8 long_names) -{ - Temp scratch = scratch_begin(&arena, 1); - String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header.time_stamp); - - rd_printf("Name : %S" , header.name ); - rd_printf("Time Stamp: (%#x) %S" , header.time_stamp, time_stamp ); - rd_printf("User ID : %u" , header.user_id ); - rd_printf("Group ID : %u" , header.group_id); - rd_printf("Mode : %S" , header.mode ); - rd_printf("Data : [%#llx-%#llx)", header.data_range.min, header.data_range.max); - - scratch_end(scratch); -} - -internal void -coff_print_section_table(Arena *arena, - String8List *out, - String8 indent, - String8 string_table, - COFF_Symbol32Array symbol_table, - U64 section_count, - COFF_SectionHeader *section_table) -{ - Temp scratch = scratch_begin(&arena, 1); - - String8 *symlinks = push_array(scratch.arena, String8, section_count); - for (U64 i = 0; i < symbol_table.count; ++i) { - COFF_Symbol32 *symbol = symbol_table.v+i; - COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol->section_number, symbol->value, symbol->storage_class); - if (interp == COFF_SymbolValueInterp_Regular && - symbol->aux_symbol_count == 0 && - (symbol->storage_class == COFF_SymStorageClass_External || symbol->storage_class == COFF_SymStorageClass_Static)) { - if (symbol->section_number > 0 && symbol->section_number <= symbol_table.count) { - COFF_SectionHeader *header = section_table+(symbol->section_number-1); - if (header->flags & COFF_SectionFlag_LnkCOMDAT) { - symlinks[symbol->section_number-1] = coff_read_symbol_name(string_table, &symbol->name); - } - } - } - i += symbol->aux_symbol_count; - } - - if (section_count) { - rd_printf("# Section Table"); - rd_indent(); - - rd_printf("%-4s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-5s %-10s %s", - "No.", - "Name", - "VirtSize", - "VirtOff", - "FileSize", - "FileOff", - "RelocOff", - "LinesOff", - "RelocCnt", - "LineCnt", - "Align", - "Flags", - "Symlink"); - - for (U64 i = 0; i < section_count; ++i) { - COFF_SectionHeader *header = section_table+i; - - String8 name = str8_cstring_capped(header->name, header->name+sizeof(header->name)); - String8 full_name = coff_name_from_section_header(string_table, header); - - String8 align; - { - U64 align_size = coff_align_size_from_section_flags(header->flags); - align = push_str8f(scratch.arena, "%u", align_size); - } - - String8 flags; - { - String8List mem_flags = {0}; - if (header->flags & COFF_SectionFlag_MemRead) { - str8_list_pushf(scratch.arena, &mem_flags, "r"); - } - if (header->flags & COFF_SectionFlag_MemWrite) { - str8_list_pushf(scratch.arena, &mem_flags, "w"); - } - if (header->flags & COFF_SectionFlag_MemExecute) { - str8_list_pushf(scratch.arena, &mem_flags, "x"); - } - - String8List cnt_flags = {0}; - if (header->flags & COFF_SectionFlag_CntCode) { - str8_list_pushf(scratch.arena, &cnt_flags, "c"); - } - if (header->flags & COFF_SectionFlag_CntInitializedData) { - str8_list_pushf(scratch.arena, &cnt_flags, "d"); - } - if (header->flags & COFF_SectionFlag_CntUninitializedData) { - str8_list_pushf(scratch.arena, &cnt_flags, "u"); - } - - String8List mem_extra_flags = {0}; - if (header->flags & COFF_SectionFlag_MemShared) { - str8_list_pushf(scratch.arena, &mem_flags, "s"); - } - if (header->flags & COFF_SectionFlag_Mem16Bit) { - str8_list_pushf(scratch.arena, &mem_extra_flags, "h"); - } - if (header->flags & COFF_SectionFlag_MemLocked) { - str8_list_pushf(scratch.arena, &mem_extra_flags, "l"); - } - if (header->flags & COFF_SectionFlag_MemDiscardable) { - str8_list_pushf(scratch.arena, &mem_extra_flags, "d"); - } - if (header->flags & COFF_SectionFlag_MemNotCached) { - str8_list_pushf(scratch.arena, &mem_extra_flags, "c"); - } - if (header->flags & COFF_SectionFlag_MemNotPaged) { - str8_list_pushf(scratch.arena, &mem_extra_flags, "p"); - } - - String8List lnk_flags = {0}; - if (header->flags & COFF_SectionFlag_LnkRemove) { - str8_list_pushf(scratch.arena, &lnk_flags, "r"); - } - if (header->flags & COFF_SectionFlag_LnkCOMDAT) { - str8_list_pushf(scratch.arena, &lnk_flags, "c"); - } - if (header->flags & COFF_SectionFlag_LnkOther) { - str8_list_pushf(scratch.arena, &lnk_flags, "o"); - } - if (header->flags & COFF_SectionFlag_LnkInfo) { - str8_list_pushf(scratch.arena, &lnk_flags, "i"); - } - if (header->flags & COFF_SectionFlag_LnkNRelocOvfl) { - str8_list_pushf(scratch.arena, &lnk_flags, "f"); - } - - String8List other_flags = {0}; - if (header->flags & COFF_SectionFlag_TypeNoPad) { - str8_list_pushf(scratch.arena, &other_flags, "n"); - } - if (header->flags & COFF_SectionFlag_GpRel) { - str8_list_pushf(scratch.arena, &other_flags, "g"); - } - - String8 mem = str8_list_join(scratch.arena, &mem_flags, 0); - String8 cnt = str8_list_join(scratch.arena, &cnt_flags, 0); - String8 lnk = str8_list_join(scratch.arena, &lnk_flags, 0); - String8 ext = str8_list_join(scratch.arena, &mem_extra_flags, 0); - String8 oth = str8_list_join(scratch.arena, &other_flags, 0); - - String8List f = {0}; - str8_list_push(scratch.arena, &f, mem); - str8_list_push(scratch.arena, &f, cnt); - str8_list_push(scratch.arena, &f, ext); - str8_list_push(scratch.arena, &f, lnk); - str8_list_push(scratch.arena, &f, oth); - - flags = str8_list_join(scratch.arena, &f, &(StringJoin){ .sep = str8_lit("-") }); - - if (!flags.size) { - flags = str8_lit("none"); - } - } - - String8List l = {0}; - str8_list_pushf(scratch.arena, &l, "%-4x", i+1 ); - str8_list_pushf(scratch.arena, &l, "%-8S", name ); - str8_list_pushf(scratch.arena, &l, "%08x", header->vsize ); - str8_list_pushf(scratch.arena, &l, "%08x", header->voff ); - str8_list_pushf(scratch.arena, &l, "%08x", header->fsize ); - str8_list_pushf(scratch.arena, &l, "%08x", header->foff ); - str8_list_pushf(scratch.arena, &l, "%08x", header->relocs_foff); - str8_list_pushf(scratch.arena, &l, "%08x", header->lines_foff ); - str8_list_pushf(scratch.arena, &l, "%08x", header->reloc_count); - str8_list_pushf(scratch.arena, &l, "%08x", header->line_count ); - str8_list_pushf(scratch.arena, &l, "%-5S", align ); - str8_list_pushf(scratch.arena, &l, "%-10S", flags ); - if (symlinks[i].size > 0) { - str8_list_pushf(scratch.arena, &l, "%S", symlinks[i]); - } else { - str8_list_pushf(scratch.arena, &l, "[no symlink]"); - } - - String8 line = str8_list_join(scratch.arena, &l, &(StringJoin){ .sep = str8_lit(" "), }); - rd_printf("%S", line); - - if (full_name.size != name.size) { - rd_indent(); - rd_printf("Full Name: %S", full_name); - rd_unindent(); - } - } - - rd_newline(); - rd_printf("Flags:"); - rd_indent(); - rd_printf("r = MemRead w = MemWrite x = MemExecute"); - rd_printf("c = CntCode d = InitializedData u = UninitializedData"); - rd_printf("s = MemShared h = Mem16bit l = MemLocked d = MemDiscardable c = MemNotCached p = MemNotPaged"); - rd_printf("r = LnkRemove c = LnkComdat o = LnkOther i = LnkInfo f = LnkNRelocOvfl"); - rd_printf("g = GpRel n = TypeNoPad"); - rd_unindent(); - - rd_unindent(); - rd_newline(); - } - - scratch_end(scratch); -} - -internal void -coff_disasm_sections(Arena *arena, - String8List *out, - String8 indent, - String8 raw_data, - COFF_MachineType machine, - U64 image_base, - B32 is_obj, - RD_MarkerArray *section_markers, - U64 section_count, - COFF_SectionHeader *sections) -{ - if (section_count) { - for (U64 sect_idx = 0; sect_idx < section_count; ++sect_idx) { - COFF_SectionHeader *sect = sections+sect_idx; - if (sect->flags & COFF_SectionFlag_CntCode) { - U64 sect_off = is_obj ? sect->foff : sect->voff; - U64 sect_size = is_obj ? sect->fsize : sect->vsize; - String8 raw_code = str8_substr(raw_data, rng_1u64(sect->foff, sect->foff+sect_size)); - U64 sect_number = sect_idx+1; - RD_MarkerArray markers = section_markers[sect_number]; - - rd_printf("# Disassembly [Section No. %#llx]", sect_number); - rd_indent(); - rd_print_disasm(arena, out, indent, arch_from_coff_machine(machine), image_base, sect_off, markers.count, markers.v, raw_code); - rd_unindent(); - } - } - } -} - -internal void -coff_raw_data_sections(Arena *arena, - String8List *out, - String8 indent, - String8 raw_data, - B32 is_obj, - RD_MarkerArray *section_markers, - U64 section_count, - COFF_SectionHeader *section_table) -{ - if (section_count) { - for (U64 sect_idx = 0; sect_idx < section_count; ++sect_idx) { - COFF_SectionHeader *sect = section_table+sect_idx; - if (sect->fsize > 0) { - U64 sect_size = is_obj ? sect->fsize : sect->vsize; - String8 raw_sect = str8_substr(raw_data, rng_1u64(sect->foff, sect->foff+sect_size)); - RD_MarkerArray markers = section_markers[sect_idx]; - - rd_printf("# Raw Data [Section No. %#llx]", (sect_idx+1)); - rd_indent(); - rd_print_raw_data(arena, out, indent, 32, markers.count, markers.v, raw_sect); - rd_unindent(); - rd_newline(); - } - } - } -} - -internal void -coff_print_relocs(Arena *arena, - String8List *out, - String8 indent, - String8 raw_data, - String8 string_table, - COFF_MachineType machine, - U64 sect_count, - COFF_SectionHeader *sect_headers, - COFF_Symbol32Array symbols) -{ - Temp scratch = scratch_begin(&arena, 1); - - B32 print_header = 1; - - for (U64 sect_idx = 0; sect_idx < sect_count; ++sect_idx) { - COFF_SectionHeader *sect_header = sect_headers+sect_idx; - COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(raw_data, sect_header); - - if (reloc_info.count) { - if (print_header) { - print_header = 0; - rd_printf("# Relocations"); - rd_indent(); - } - - rd_printf("## Section %llx", sect_idx); - rd_indent(); - - rd_printf("%-4s %-8s %-16s %-16s %-8s %-7s", "No.", "Offset", "Type", "ApplyTo", "SymIdx", "SymName"); - - for (U64 reloc_idx = 0; reloc_idx < reloc_info.count; ++reloc_idx) { - COFF_Reloc *reloc = (COFF_Reloc*)(raw_data.str + reloc_info.array_off) + reloc_idx; - String8 type = coff_string_from_reloc(machine, reloc->type); - U64 apply_size = coff_apply_size_from_reloc(machine, reloc->type); - - U64 apply_foff = sect_header->foff + reloc->apply_off; - if (apply_foff + apply_size > raw_data.size) { - rd_errorf("out of bounds apply file offset %#llx in relocation %#llx", apply_foff, reloc_idx); - break; - } - - U64 raw_apply; - AssertAlways(apply_size <= sizeof(raw_apply)); - MemoryCopy(&raw_apply, raw_data.str + apply_foff, apply_size); - S64 apply = extend_sign64(raw_apply, apply_size); - - if (reloc->isymbol > symbols.count) { - rd_errorf("out of bounds symbol index %u in relocation %#llx", reloc->isymbol, reloc_idx); - break; - } - - COFF_Symbol32 *symbol = symbols.v+reloc->isymbol; - String8 symbol_name = coff_read_symbol_name(string_table, &symbol->name); - - String8List line = {0}; - str8_list_pushf(scratch.arena, &line, "%-4x", reloc_idx ); - str8_list_pushf(scratch.arena, &line, "%08x", reloc->apply_off); - str8_list_pushf(scratch.arena, &line, "%-16S", type ); - str8_list_pushf(scratch.arena, &line, "%016x", apply ); - str8_list_pushf(scratch.arena, &line, "%S", symbol_name ); - - String8 l = str8_list_join(scratch.arena, &line, &(StringJoin){.sep=str8_lit(" ")}); - rd_printf("%S", l); - } - - rd_unindent(); - } - } - - if (!print_header) { - rd_unindent(); - } - rd_newline(); - - scratch_end(scratch); -} - -internal void -coff_print_symbol_table(Arena *arena, - String8List *out, - String8 indent, - String8 raw_data, - B32 is_big_obj, - String8 string_table, - COFF_Symbol32Array symbols) -{ - Temp scratch = scratch_begin(&arena, 1); - - if (symbols.count) { - rd_printf("# Symbol Table"); - rd_indent(); - - rd_printf("%-4s %-8s %-10s %-4s %-4s %-4s %-16s %-20s", - "No.", "Value", "SectNum", "Aux", "Msb", "Lsb", "Storage", "Name"); - - for (U64 i = 0; i < symbols.count; ++i) { - COFF_Symbol32 *symbol = &symbols.v[i]; - String8 name = coff_read_symbol_name(string_table, &symbol->name); - String8 msb = coff_string_from_sym_dtype(symbol->type.u.msb); - String8 lsb = coff_string_from_sym_type(symbol->type.u.lsb); - String8 storage_class = coff_string_from_sym_storage_class(symbol->storage_class); - String8 section_number; - switch (symbol->section_number) { - case COFF_Symbol_UndefinedSection: section_number = str8_lit("Undef"); break; - case COFF_Symbol_AbsSection32: section_number = str8_lit("Abs"); break; - case COFF_Symbol_DebugSection32: section_number = str8_lit("Debug"); break; - default: section_number = push_str8f(scratch.arena, "%010x", symbol->section_number); break; - } - - String8List line = {0}; - str8_list_pushf(scratch.arena, &line, "%-4x", i ); - str8_list_pushf(scratch.arena, &line, "%08x", symbol->value ); - str8_list_pushf(scratch.arena, &line, "%-10S", section_number ); - str8_list_pushf(scratch.arena, &line, "%-4u", symbol->aux_symbol_count); - str8_list_pushf(scratch.arena, &line, "%-4S", msb ); - str8_list_pushf(scratch.arena, &line, "%-4S", lsb ); - str8_list_pushf(scratch.arena, &line, "%-16S", storage_class ); - str8_list_pushf(scratch.arena, &line, "%S", name ); - - String8 l = str8_list_join(scratch.arena, &line, &(StringJoin){.sep = str8_lit(" ")}); - rd_printf("%S", l); - - rd_indent(); - for (U64 k=i+1, c = i+symbol->aux_symbol_count; k <= c; ++k) { - void *raw_aux = &symbols.v[k]; - switch (symbol->storage_class) { - case COFF_SymStorageClass_External: { - COFF_SymbolFuncDef *func_def = (COFF_SymbolFuncDef*)&symbols.v[k]; - rd_printf("Tag Index %#x, Total Size %#x, Line Numbers %#x, Next Function %#x", - func_def->tag_index, func_def->total_size, func_def->ptr_to_ln, func_def->ptr_to_next_func); - } break; - case COFF_SymStorageClass_Function: { - COFF_SymbolFunc *func = raw_aux; - rd_printf("Ordinal Line Number %#x, Next Function %#x", func->ln, func->ptr_to_next_func); - } break; - case COFF_SymStorageClass_WeakExternal: { - COFF_SymbolWeakExt *weak = raw_aux; - String8 type = coff_string_from_weak_ext_type(weak->characteristics); - rd_printf("Tag Index %#x, Characteristics %S", weak->tag_index, type); - } break; - case COFF_SymStorageClass_File: { - COFF_SymbolFile *file = raw_aux; - String8 name = str8_cstring_capped(file->name, file->name+sizeof(file->name)); - rd_printf("Name %S", name); - } break; - case COFF_SymStorageClass_Static: { - COFF_SymbolSecDef *sd = raw_aux; - String8 selection = coff_string_from_comdat_select_type(sd->selection); - U32 number = sd->number_lo; - if (is_big_obj) { - number |= (U32)sd->number_hi << 16; - } - if (number) { - rd_printf("Length %x, Reloc Count %u, Line Count %u, Checksum %x, Section %x, Selection %S", - sd->length, sd->number_of_relocations, sd->number_of_ln, sd->check_sum, number, selection); - } else { - rd_printf("Length %x, Reloc Count %u, Line Count %u, Checksum %x", - sd->length, sd->number_of_relocations, sd->number_of_ln, sd->check_sum); - } - } break; - default: { - rd_printf("???"); - } break; - } - } - - i += symbol->aux_symbol_count; - rd_unindent(); - } - - rd_unindent(); - rd_newline(); - } - - scratch_end(scratch); -} - -internal void -coff_print_big_obj_header(Arena *arena, String8List *out, String8 indent, COFF_BigObjHeader *header) -{ - Temp scratch = scratch_begin(&arena, 1); - - String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp); - String8 machine = coff_string_from_machine_type(header->machine); - - rd_printf("# Big Obj"); - rd_indent(); - rd_printf("Time Stamp : %#x (%S)", header->time_stamp, time_stamp); - rd_printf("Machine : %#x (%S)", header->machine, machine ); - rd_printf("Section Count: %u", header->section_count ); - rd_printf("Symbol Table : %#x", header->symbol_table_foff); - rd_printf("Symbol Count : %u", header->symbol_count ); - rd_unindent(); - - scratch_end(scratch); -} - -internal void -coff_print_file_header(Arena *arena, String8List *out, String8 indent, COFF_FileHeader *header) -{ - Temp scratch = scratch_begin(&arena, 1); - - String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp); - String8 machine = coff_string_from_machine_type(header->machine); - String8 flags = coff_string_from_flags(scratch.arena, header->flags); - - rd_printf("# COFF File Header"); - rd_indent(); - rd_printf("Time Stamp : %#x (%S)", header->time_stamp, time_stamp ); - rd_printf("Machine : %#x %S", header->machine, machine ); - rd_printf("Section Count : %u", header->section_count ); - rd_printf("Symbol Table : %#x", header->symbol_table_foff ); - rd_printf("Symbol Count : %u", header->symbol_count ); - rd_printf("Optional Header Size: %#x (%m)", header->optional_header_size, header->optional_header_size); - rd_printf("Flags : %#x (%S)", header->flags, flags ); - rd_unindent(); - - scratch_end(scratch); -} - -internal void -coff_print_import(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveImportHeader *header) -{ - Temp scratch = scratch_begin(&arena, 1); - - String8 machine = coff_string_from_machine_type(header->machine); - String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp); - - rd_printf("# Import"); - rd_indent(); - rd_printf("Version : %u", header->version ); - rd_printf("Machine : %S", machine ); - rd_printf("Time Stamp: %#x (%S)", header->time_stamp, time_stamp ); - rd_printf("Data Size : %#x (%m)", header->data_size, header->data_size); - rd_printf("Hint : %u", header->hint_or_ordinal); - rd_printf("Type : %u", header->type ); - rd_printf("Import By : %u", header->import_by ); - rd_printf("Function : %S", header->func_name ); - rd_printf("DLL : %S", header->dll_name ); - rd_unindent(); - - scratch_end(scratch); -} - -internal void -coff_print_big_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts) -{ - Temp scratch = scratch_begin(&arena, 1); - - COFF_FileHeaderInfo header_info = coff_file_header_info_from_data(raw_data); - - String8 raw_header = str8_substr(raw_data, header_info.header_range); - String8 raw_section_table = str8_substr(raw_data, header_info.section_table_range); - String8 raw_string_table = str8_substr(raw_data, header_info.string_table_range); - - COFF_BigObjHeader *big_obj = (COFF_BigObjHeader *)raw_header.str; - COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str; - COFF_Symbol32Array symbol_table = coff_symbol_array_from_data_32(scratch.arena, raw_data, header_info.symbol_table_range.min, big_obj->symbol_count); - - if (opts & RD_Option_Headers) { - coff_print_big_obj_header(arena, out, indent, big_obj); - rd_newline(); - } - - if (opts & RD_Option_Sections) { - Rng1U64 sect_headers_range = rng_1u64(sizeof(*big_obj), sizeof(*big_obj) + sizeof(COFF_SectionHeader)*big_obj->section_count); - Rng1U64 symbols_range = rng_1u64(big_obj->symbol_table_foff, big_obj->symbol_table_foff + sizeof(COFF_Symbol32)*big_obj->symbol_count); - - if (sect_headers_range.max > raw_data.size) { - rd_errorf("not enough bytes to read big obj section headers"); - goto exit; - } - if (big_obj->symbol_count) { - if (symbols_range.max > raw_data.size) { - rd_errorf("not enough bytes to read big obj symbol table"); - goto exit; - } - if (contains_1u64(symbols_range, sect_headers_range.min) || - contains_1u64(symbols_range, sect_headers_range.max)) { - rd_errorf("section headers and symbol table ranges overlap"); - goto exit; - } - } - - coff_print_section_table(arena, out, indent, raw_string_table, symbol_table, big_obj->section_count, section_table); - rd_newline(); - } - - if (opts & RD_Option_Relocs) { - coff_print_relocs(arena, out, indent, raw_data, raw_string_table, big_obj->machine, big_obj->section_count, section_table, symbol_table); - rd_newline(); - } - - if (opts & RD_Option_Symbols) { - coff_print_symbol_table(arena, out, indent, raw_data, 1, raw_string_table, symbol_table); - rd_newline(); - } - - exit:; - scratch_end(scratch); -} - -internal void -coff_print_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts) -{ - Temp scratch = scratch_begin(&arena, 1); - - COFF_FileHeaderInfo header_info = coff_file_header_info_from_data(raw_data); - - String8 raw_header = str8_substr(raw_data, header_info.header_range); - String8 raw_section_table = str8_substr(raw_data, header_info.section_table_range); - String8 raw_string_table = str8_substr(raw_data, header_info.string_table_range); - - COFF_FileHeader *header = (COFF_FileHeader *)raw_header.str; - COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str; - COFF_Symbol32Array symbol_table = coff_symbol_array_from_data_16(scratch.arena, raw_data, header_info.symbol_table_range.min, header->symbol_count); - Arch arch = arch_from_coff_machine(header->machine); - - if (opts & RD_Option_Headers) { - coff_print_file_header(arena, out, indent, header); - rd_newline(); - } - - if (opts & RD_Option_Sections) { - Rng1U64 sect_headers_range = rng_1u64(sizeof(*header), sizeof(*header) + sizeof(COFF_SectionHeader)*header->section_count); - Rng1U64 symbols_range = rng_1u64(header->symbol_table_foff, header->symbol_table_foff + sizeof(COFF_Symbol16)*header->symbol_count); - - if (sect_headers_range.max > raw_data.size) { - rd_errorf("not enough bytes to read obj section headers"); - goto exit; - } - if (header->symbol_count) { - if (symbols_range.max > raw_data.size) { - rd_errorf("not enough bytes to read obj symbol table"); - goto exit; - } - if (contains_1u64(symbols_range, sect_headers_range.min) || - contains_1u64(symbols_range, sect_headers_range.max)) { - rd_errorf("section headers and symbol table ranges overlap"); - goto exit; - } - } - - coff_print_section_table(arena, out, indent, raw_string_table, symbol_table, header->section_count, section_table); - rd_newline(); - } - - if (opts & RD_Option_Relocs) { - coff_print_relocs(arena, out, indent, raw_data, raw_string_table, header->machine, header->section_count, section_table, symbol_table); - rd_newline(); - } - - if (opts & RD_Option_Symbols) { - coff_print_symbol_table(arena, out, indent, raw_data, 0, raw_string_table, symbol_table); - rd_newline(); - } - - RD_MarkerArray *section_markers = 0; - if (opts & (RD_Option_Disasm|RD_Option_Rawdata)) { - section_markers = rd_section_markers_from_coff_symbol_table(scratch.arena, raw_string_table, header->section_count, symbol_table); - } - - if (opts & RD_Option_Rawdata) { - coff_raw_data_sections(arena, out, indent, raw_data, 1, section_markers, header->section_count, section_table); - } - - if (opts & RD_Option_Disasm) { - coff_disasm_sections(arena, out, indent, raw_data, header->machine, 0, 1, section_markers, header->section_count, section_table); - rd_newline(); - } - - if (opts & RD_Option_Codeview) { - cv_format_debug_sections(arena, out, indent, raw_data, raw_string_table, header->section_count, section_table); - } - - if (opts & RD_Option_Dwarf) { - DW_Input dwarf_input = dw_input_from_coff_section_table(scratch.arena, raw_data, raw_string_table, header->section_count, section_table); - dw_format(arena, out, indent, opts, &dwarf_input, arch, ExecutableImageKind_CoffPe); - } - - exit:; - scratch_end(scratch); -} - -internal void -coff_print_archive(Arena *arena, String8List *out, String8 indent, String8 raw_archive, RD_Option opts) -{ - Temp scratch = scratch_begin(&arena, 1); - - COFF_ArchiveParse archive_parse = coff_archive_parse_from_data(raw_archive); - - if (archive_parse.error.size) { - rd_errorf("%S", archive_parse.error); - return; - } - - COFF_ArchiveFirstMember first_member = archive_parse.first_member; - { - rd_printf("# First Header"); - rd_indent(); - - rd_printf("Symbol Count : %u", first_member.symbol_count); - rd_printf("String Table Size: %#llx (%M)", first_member.string_table.size, first_member.string_table.size); - - rd_printf("Members:"); - rd_indent(); - - String8List string_table = str8_split_by_string_chars(scratch.arena, first_member.string_table, str8_lit("\0"), 0); - - if (string_table.node_count == first_member.member_offset_count) { - String8Node *string_n = string_table.first; - - for (U64 i = 0; i < string_table.node_count; ++i, string_n = string_n->next) { - U32 offset = from_be_u32(first_member.member_offsets[i]); - rd_printf("[%4u] %#08x %S", i, offset, string_n->string); - } - } else { - rd_errorf("Member offset count (%llu) doesn't match string table count (%llu)", first_member.member_offset_count); - } - - rd_unindent(); - rd_unindent(); - rd_newline(); - } - - if (archive_parse.has_second_header) { - COFF_ArchiveSecondMember second_member = archive_parse.second_member; - - rd_printf("# Second Header"); - rd_indent(); - - rd_printf("Member Count : %u", second_member.member_count); - rd_printf("Symbol Count : %u", second_member.symbol_count); - rd_printf("String Table Size: %#llx (%M)", second_member.string_table.size, second_member.string_table.size); - - String8List string_table = str8_split_by_string_chars(scratch.arena, second_member.string_table, str8_lit("\0"), 0); - - rd_printf("Members:"); - rd_indent(); - if (second_member.symbol_index_count == second_member.symbol_count) { - String8Node *string_n = string_table.first; - for (U64 i = 0; i < second_member.symbol_count; ++i, string_n = string_n->next) { - U16 symbol_number = second_member.symbol_indices[i]; - if (symbol_number > 0 && symbol_number <= second_member.member_offset_count) { - U16 symbol_idx = symbol_number - 1; - U32 member_offset = second_member.member_offsets[i]; - rd_printf("[%4u] %#08x %S", i, member_offset, string_n->string); - } else { - rd_errorf("[%4u] Out of bounds symbol number %u", i, symbol_number); - break; - } - } - } else { - rd_errorf("Symbol index count %u doesn't match symbol count %u", - second_member.symbol_index_count, second_member.symbol_count); - } - rd_unindent(); - - rd_unindent(); - rd_newline(); - } - - if (archive_parse.has_long_names && opts & RD_Option_LongNames) { - rd_printf("# Long Names"); - rd_indent(); - - String8List long_names = str8_split_by_string_chars(scratch.arena, archive_parse.long_names, str8_lit("\0"), 0); - U64 name_idx = 0; - for (String8Node *name_n = long_names.first; name_n != 0; name_n = name_n->next, ++name_idx) { - U64 offset = (U64)(name_n->string.str - archive_parse.long_names.str); - rd_printf("[%-4u] %#08x %S", name_idx, offset, name_n->string); - } - - rd_unindent(); - rd_newline(); - } - - U64 member_offset_count = 0; - U32 *member_offsets = 0; - if (archive_parse.has_second_header) { - member_offset_count = archive_parse.second_member.member_offset_count; - member_offsets = archive_parse.second_member.member_offsets; - } else { - HashTable *ht = hash_table_init(scratch.arena, 0x1000); - for (U64 i = 0; i < archive_parse.first_member.member_offset_count; ++i) { - U32 member_offset = from_be_u32(archive_parse.first_member.member_offsets[i]); - if (!hash_table_search_u32(ht, member_offset)) { - hash_table_push_u32_raw(scratch.arena, ht, member_offset, 0); - } - } - member_offset_count = ht->count; - member_offsets = keys_from_hash_table_u32(scratch.arena, ht); - radsort(member_offsets, member_offset_count, u32_is_before); - } - - rd_printf("# Members"); - rd_indent(); - - for (U64 i = 0; i < member_offset_count; ++i) { - U64 next_member_offset = i+1 < member_offset_count ? member_offsets[i+1] : raw_archive.size; - U64 member_offset = member_offsets[i]; - String8 raw_member = str8_substr(raw_archive, rng_1u64(member_offset, next_member_offset)); - COFF_ArchiveMember member = coff_archive_member_from_data(raw_member); - COFF_DataType member_type = coff_data_type_from_data(member.data); - - rd_printf("Member @ %#llx", member_offset); - rd_indent(); - - if (opts & RD_Option_Headers) { - coff_print_archive_member_header(arena, out, indent, member.header, archive_parse.long_names); - rd_newline(); - } - - switch (member_type) { - case COFF_DataType_Obj: { - coff_print_obj(arena, out, indent, member.data, opts); - } break; - case COFF_DataType_BigObj: { - coff_print_big_obj(arena, out, indent, member.data, opts); - } break; - case COFF_DataType_Import: { - if (opts & RD_Option_Headers) { - COFF_ParsedArchiveImportHeader header = {0}; - U64 parse_size = coff_parse_import(member.data, 0, &header); - if (parse_size) { - coff_print_import(arena, out, indent, &header); - } else { - rd_errorf("not enough bytes to parse import header"); - } - } - } break; - case COFF_DataType_Null: { - rd_errorf("unknown member format", member_offset); - } break; - } - - rd_unindent(); - rd_newline(); - } - - rd_unindent(); - - scratch_end(scratch); -} - // MSVC CRT internal void diff --git a/src/raddump/raddump.h b/src/raddump/raddump.h index 813e751c..2a11230c 100644 --- a/src/raddump/raddump.h +++ b/src/raddump/raddump.h @@ -203,21 +203,6 @@ internal void cv_print_string_table (Arena *arena, String8List *out, String8 i internal void cv_print_inlinee_lines (Arena *arena, String8List *out, String8 indent, String8 raw_data); internal void cv_print_symbols_section(Arena *arena, String8List *out, String8 indent, CV_Arch arch, String8 raw_ss); -// COFF - -internal void coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveMemberHeader header, String8 long_names); -internal void coff_print_section_table (Arena *arena, String8List *out, String8 indent, String8 string_table, COFF_Symbol32Array symbols, U64 sect_count, COFF_SectionHeader *sect_headers); -internal void coff_disasm_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, COFF_MachineType machine, U64 image_base, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections); -internal void coff_raw_data_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections); -internal void coff_print_relocs (Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 string_table, COFF_MachineType machine, U64 sect_count, COFF_SectionHeader *sect_headers, COFF_Symbol32Array symbols); -internal void coff_print_symbol_table (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_big_obj, String8 string_table, COFF_Symbol32Array symbols); -internal void coff_print_big_obj_header (Arena *arena, String8List *out, String8 indent, COFF_BigObjHeader *header); -internal void coff_print_file_header (Arena *arena, String8List *out, String8 indent, COFF_FileHeader *header); -internal void coff_print_import (Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveImportHeader *header); -internal void coff_print_big_obj (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts); -internal void coff_print_obj (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts); -internal void coff_print_archive (Arena *arena, String8List *out, String8 indent, String8 raw_archive, RD_Option opts); - // MSVC CRT internal void mscrt_print_eh_handler_type32(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, MSCRT_EhHandlerType32 *handler); diff --git a/src/rdi/rdi_local.c b/src/rdi/rdi_local.c index d0a973e3..da99890e 100644 --- a/src/rdi/rdi_local.c +++ b/src/rdi/rdi_local.c @@ -516,12 +516,12 @@ rdi_dump_list_from_parsed(Arena *arena, RDI_Parsed *rdi, RDI_DumpSubsetFlags fla 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"))) +#define DumpSubset(name) if(flags & RDI_DumpSubsetFlag_##name) DeferLoop(dumpf("////////////////////////////////\n//~ %S\n\n", rdi_name_title_from_dump_subset_table[RDI_DumpSubset_##name]), dump(str8_lit("\n"))) ////////////////////////////// //- rjf: dump data sections // - DumpSubset(DataSections) + DumpSubset(DataSections) DeferLoop(dumpf("data_sections:\n{\n"), dumpf("}\n")) { for EachIndex(idx, rdi->sections_count) { @@ -529,7 +529,7 @@ rdi_dump_list_from_parsed(Arena *arena, RDI_Parsed *rdi, RDI_DumpSubsetFlags fla 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); + dumpf(" {%#08llx %7u %7u %*s} // data_section[%I64u]\n", section->off, section->encoded_size, section->unpacked_size, 24, kind_str.str, idx); scratch_end(scratch); } } @@ -537,35 +537,39 @@ rdi_dump_list_from_parsed(Arena *arena, RDI_Parsed *rdi, RDI_DumpSubsetFlags fla ////////////////////////////// //- rjf: dump top-level-info // - DumpSubset(TopLevelInfo) + DumpSubset(TopLevelInfo) DeferLoop(dumpf("top_level_info:\n{\n"), dumpf("}\n")) { 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)); + 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) + DumpSubset(BinarySections) DeferLoop(dumpf("binary_sections:\n{\n"), dumpf("}\n")) { U64 count = 0; RDI_BinarySection *v = rdi_table_from_name(rdi, BinarySections, &count); + dumpf(" // %-16s %-16s %-12s %-12s %-12s %-12s\n", "name", "flags", "voff_first", "voff_opl", "foff_first", "foff_opl"); 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); + String8 name = str8_from_rdi_string_idx(rdi, bin_section->name_string_idx); + String8 flags = rdi_string_from_binary_section_flags(scratch.arena, bin_section->flags); + dumpf(" { %-16.*s %-16.*s 0x%-10I64x 0x%-10I64x 0x%-10I64x 0x%-10I64x } // binary_section[%I64u]\n", + str8_varg(name), + str8_varg(flags), + bin_section->voff_first, + bin_section->voff_opl, + bin_section->foff_first, + bin_section->foff_opl, + idx); scratch_end(scratch); } }