coffdump -> raddump

This commit is contained in:
Nikita Smith
2024-12-12 15:09:59 -08:00
parent b6b64be867
commit 76b742ceb8
5 changed files with 4775 additions and 2863 deletions
+3 -3
View File
@@ -106,8 +106,9 @@ if not "%no_meta%"=="1" (
:: --- Build Everything (@build_targets) --------------------------------------
pushd build
if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg.exe || exit /b 1
if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %link_natvis%"%~dp0\src\linker\linker.natvis" %out%radlink.exe || exit /b 1
if "%rdi_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_pdb\rdi_from_pdb_main.c %compile_link% %out%rdi_from_pdb.exe || exit /b 1
if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %link_natvis%"%~dp0\src\linker\linker.natvis" %out%radlink.exe || exit /b 1
if "%raddump%"=="1" set didbuild=1 && %compile% ..\src\raddump\raddump_main.c %compile_link% %out%raddump.exe || exit /b 1
if "%rdi_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_pdb\rdi_from_pdb_main.c %compile_link% %out%rdi_from_pdb.exe || exit /b 2
if "%rdi_from_dwarf%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1
if "%rdi_dump%"=="1" set didbuild=1 && %compile% ..\src\rdi_dump\rdi_dump_main.c %compile_link% %out%rdi_dump.exe || exit /b 1
if "%rdi_breakpad_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_breakpad_from_pdb\rdi_breakpad_from_pdb_main.c %compile_link% %out%rdi_breakpad_from_pdb.exe || exit /b 1
@@ -117,7 +118,6 @@ if "%textperf%"=="1" set didbuild=1 && %compile% ..\src\scratc
if "%convertperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\convertperf.c %compile_link% %out%convertperf.exe || exit /b 1
if "%debugstringperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\debugstringperf.c %compile_link% %out%debugstringperf.exe || exit /b 1
if "%parse_inline_sites%"=="1" set didbuild=1 && %compile% ..\src\scratch\parse_inline_sites.c %compile_link% %out%parse_inline_sites.exe || exit /b 1
if "%coffdump%"=="1" set didbuild=1 && %compile% ..\src\dumpers\coffdump.c %compile_link% %out%coffdump.exe || exit /b 1
if "%mule_main%"=="1" set didbuild=1 && del vc*.pdb mule*.pdb && %compile_release% %only_compile% ..\src\mule\mule_inline.cpp && %compile_release% %only_compile% ..\src\mule\mule_o2.cpp && %compile_debug% %EHsc% ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj %compile_link% %no_aslr% %out%mule_main.exe || exit /b 1
if "%mule_module%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1
if "%mule_hotload%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_hotload_main.c %compile_link% %out%mule_hotload.exe & %compile% ..\src\mule\mule_hotload_module_main.c %compile_link% %link_dll% %out%mule_hotload_module.dll || exit /b 1
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+142
View File
@@ -0,0 +1,142 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef RADDUMP_H
#define RADDUMP_H
#define RD_INDENT_WIDTH 4
#define RD_INDENT_MAX 4096
#define rd_printf(f, ...) str8_list_pushf(arena, out, "%S" f, indent, __VA_ARGS__)
#define rd_newline() str8_list_pushf(arena, out, "");
#define rd_errorf(f, ...) rd_printf("ERROR: "f, __VA_ARGS__)
#define rd_indent() do { if (indent.size + RD_INDENT_WIDTH <= RD_INDENT_MAX) { indent.size += RD_INDENT_WIDTH; } else { Assert(!"indent overflow"); } } while (0)
#define rd_unindent() do { if (indent.size >= RD_INDENT_WIDTH) { indent.size -= RD_INDENT_WIDTH; } else { Assert(!"unbalanced indent"); } } while (0)
typedef U64 RD_Option;
enum RD_OptionEnum
{
RD_Option_Help = (1 << 0),
RD_Option_Version = (1 << 1),
RD_Option_Headers = (1 << 2),
RD_Option_Sections = (1 << 3),
RD_Option_Debug = (1 << 4),
RD_Option_Imports = (1 << 5),
RD_Option_Exports = (1 << 6),
RD_Option_Disasm = (1 << 7),
RD_Option_Rawdata = (1 << 8),
RD_Option_Tls = (1 << 9),
RD_Option_Codeview = (1 << 10),
RD_Option_Symbols = (1 << 11),
RD_Option_Relocs = (1 << 12),
RD_Option_Exceptions = (1 << 13),
RD_Option_LoadConfig = (1 << 14),
RD_Option_Resources = (1 << 15),
RD_Option_LongNames = (1 << 16),
};
typedef struct RD_Marker
{
U64 off;
String8 string;
} RD_Marker;
typedef struct RD_MarkerArray
{
U64 count;
RD_Marker *v;
} RD_MarkerArray;
typedef struct MarkerNode
{
struct MarkerNode *next;
RD_Marker v;
} RD_MarkerNode;
typedef struct RD_MarkerList
{
U64 count;
RD_MarkerNode *first;
RD_MarkerNode *last;
} RD_MarkerList;
typedef struct RD_DisasmResult
{
String8 text;
U64 size;
} RD_DisasmResult;
////////////////////////////////
//- Markers
internal RD_MarkerArray * rd_section_markers_from_coff_symbol_table(Arena *arena, String8 raw_data, U64 string_table_off, U64 section_count, COFF_Symbol32Array symbols);
//- Disasm
internal RD_DisasmResult rd_disasm_next_instruction(Arena *arena, Arch arch, U64 addr, String8 raw_code);
internal void rd_format_disasm(Arena *arena, String8List *out, String8 indent, Arch arch, U64 image_base, U64 sect_off, U64 marker_count, RD_Marker *markers, String8 raw_code);
//- Raw Data
internal String8 rd_format_hex_array(Arena *arena, U8 *ptr, U64 size);
internal void rd_format_raw_data(Arena *arena, String8List *out, String8 indent, U64 bytes_per_row, U64 marker_count, RD_Marker *markers, String8 raw_data);
//- CodeView
internal void cv_format_binary_annots(Arena *arena, String8List *out, String8 indent, CV_Arch arch, String8 raw_data);
internal void cv_format_lvar_addr_range(Arena *arena, String8List *out, String8 indent, CV_LvarAddrRange range);
internal void cv_format_lvar_addr_gap(Arena *arena, String8List *out, String8 indent, String8 raw_data);
internal void cv_format_lvar_attr(Arena *arena, String8List *out, String8 indent, CV_LocalVarAttr attr);
internal void cv_format_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, U32 type, String8 raw_symbol);
internal U64 cv_format_leaf(Arena *arena, String8List *out, String8 indent, CV_LeafKind kind, String8 raw_leaf);
internal void cv_format_debug_t(Arena *arena, String8List *out, String8 indent, CV_DebugT debug_t);
internal void cv_format_symbols_c13(Arena *arena, String8List *out, String8 indent, String8 raw_data);
internal void cv_format_lines_c13(Arena *arena, String8List *out, String8 indent, String8 raw_lines);
internal void cv_format_file_checksums(Arena *arena, String8List *out, String8 indent, String8 raw_chksums);
internal void cv_format_string_table(Arena *arena, String8List *out, String8 indent, String8 raw_strtab);
internal void cv_format_inlinee_lines(Arena *arena, String8List *out, String8 indent, String8 raw_data);
internal void cv_format_symbols_section(Arena *arena, String8List *out, String8 indent, String8 raw_ss);
//- COFF
internal void coff_format_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ArchiveMemberHeader header, String8 long_names);
internal void coff_format_section_table(Arena *arena, String8List *out, String8 indent, String8 raw_data, U64 string_table_off, 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_format_relocs(Arena *arena, String8List *out, String8 indent, String8 raw_data, U64 string_table_off, COFF_MachineType machine, U64 sect_count, COFF_SectionHeader *sect_headers, COFF_Symbol32Array symbols);
internal void coff_format_symbol_table(Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_big_obj, U64 string_table_off, COFF_Symbol32Array symbols);
internal void coff_format_big_obj_header(Arena *arena, String8List *out, String8 indent, COFF_HeaderBigObj *header);
internal void coff_format_header(Arena *arena, String8List *out, String8 indent, COFF_Header *header);
internal void coff_format_import(Arena *arena, String8List *out, String8 indent, COFF_ImportHeader *header);
internal void coff_format_big_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts);
internal void coff_format_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts);
internal void coff_format_archive(Arena *arena, String8List *out, String8 indent, String8 raw_archive, RD_Option opts);
//- MSVC CRT
internal void mscrt_format_eh_handler_type32(Arena *arena, String8List *out, String8 indent, MSCRT_EhHandlerType32 *handler);
//- PE
internal void pe_format_data_directory_ranges(Arena *arena, String8List *out, String8 indent, U64 count, PE_DataDirectory *dirs);
internal void pe_format_optional_header32(Arena *arena, String8List *out, String8 indent, PE_OptionalHeader32 *opt_header, PE_DataDirectory *dirs);
internal void pe_format_optional_header32plus(Arena *arena, String8List *out, String8 indent, PE_OptionalHeader32Plus *opt_header, PE_DataDirectory *dirs);
internal void pe_format_load_config32(Arena *arena, String8List *out, String8 indent, PE_LoadConfig32 *lc);
internal void pe_format_load_config64(Arena *arena, String8List *out, String8 indent, PE_LoadConfig64 *lc);
internal void pe_format_tls(Arena *arena, String8List *out, String8 indent, PE_ParsedTLS tls);
internal void pe_format_debug_directory(Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 raw_dir);
internal void pe_format_export_table(Arena *arena, String8List *out, String8 indent, PE_ParsedExportTable exptab);
internal void pe_format_static_import_table(Arena *arena, String8List *out, String8 indent, U64 image_base, PE_ParsedStaticImportTable imptab);
internal void pe_format_delay_import_table(Arena *arena, String8List *out, String8 indent, U64 image_base, PE_ParsedDelayImportTable imptab);
internal void pe_format_resources(Arena *arena, String8List *out, String8 indent, PE_ResourceDir *root);
internal void pe_format_exceptions_x8664(Arena *arena, String8List *out, String8 indent, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 except_frange);
internal void pe_format_exceptions(Arena *arena, String8List *out, String8 indent, COFF_MachineType machine, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 except_frange);
internal void pe_format_base_relocs(Arena *arena, String8List *out, String8 indent, COFF_MachineType machine, U64 image_base, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 base_reloc_franges);
internal void pe_format(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts);
////////////////////////////////
internal void format_preamble(Arena *arena, String8List *out, String8 indent, String8 input_path, String8 raw_data);
#endif // RADDUMP_H
+182
View File
@@ -0,0 +1,182 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#define BUILD_CONSOLE_INTERFACE 1
#define BUILD_TITLE "Epic Games Tools (R) RAD Dumper"
////////////////////////////////
#include "third_party/xxHash/xxhash.c"
#include "third_party/xxHash/xxhash.h"
#include "third_party/radsort/radsort.h"
#include "third_party/zydis/zydis.h"
#include "third_party/zydis/zydis.c"
////////////////////////////////
#include "base/base_inc.h"
#include "os/os_inc.h"
#include "path/path.h"
#include "coff/coff.h"
#include "coff/coff_enum.h"
#include "pe/pe.h"
#include "msvc_crt/msvc_crt.h"
#include "msvc_crt/msvc_crt_enum.h"
#include "codeview/codeview.h"
#include "codeview/codeview_parse.h"
#include "codeview/codeview_enum.h"
#include "msf/msf.h"
#include "msf/msf_parse.h"
#include "pdb/pdb.h"
#include "base/base_inc.c"
#include "os/os_inc.c"
#include "path/path.c"
#include "coff/coff.c"
#include "coff/coff_enum.c"
#include "pe/pe.c"
#include "msvc_crt/msvc_crt.c"
#include "msvc_crt/msvc_crt_enum.c"
#include "codeview/codeview.c"
#include "codeview/codeview_parse.c"
#include "codeview/codeview_enum.c"
#include "msf/msf.c"
#include "msf/msf_parse.c"
#include "pdb/pdb.c"
#include "linker/base_ext/base_core.h"
#include "linker/base_ext/base_core.c"
#include "linker/path_ext/path.h"
#include "linker/path_ext/path.c"
#include "linker/thread_pool/thread_pool.h"
#include "linker/thread_pool/thread_pool.c"
#include "linker/codeview_ext/codeview.h"
#include "linker/codeview_ext/codeview.c"
#include "linker/hash_table.h"
#include "linker/hash_table.c"
#include "raddump/raddump.h"
#include "raddump/raddump.c"
////////////////////////////////
global read_only struct
{
RD_Option opt;
char *name;
char *help;
} g_rd_dump_option_map[] = {
{ RD_Option_Help, "help", "Print help and exit" },
{ RD_Option_Version, "v", "Print version and exit" },
{ RD_Option_Headers, "headers", "Dump DOS header, file header, optional header, and/or archive header" },
{ RD_Option_Sections, "sections", "Dump section headers as table" },
{ RD_Option_Rawdata, "rawdata", "Dump raw section data" },
{ RD_Option_Codeview, "cv", "Dump CodeView" },
{ RD_Option_Disasm, "disasm", "Disassemble code sections" },
{ RD_Option_Symbols, "symbols", "Dump COFF symbol table" },
{ RD_Option_Relocs, "relocs", "Dump relocations" },
{ RD_Option_Exceptions, "exceptions", "Dump exceptions" },
{ RD_Option_Tls, "tls", "Dump Thread Local Storage directory" },
{ RD_Option_Debug, "debug", "Dump debug directory" },
{ RD_Option_Imports, "imports", "Dump import table" },
{ RD_Option_Exports, "exports", "Dump export table" },
{ RD_Option_LoadConfig, "loadconfig", "Dump load config" },
{ RD_Option_Resources, "resources", "Dump resource directory" },
{ RD_Option_LongNames, "longnames", "Dump archive long names" },
};
internal void
entry_point(CmdLine *cmdline)
{
Temp scratch = scratch_begin(0,0);
// parse options
RD_Option opts = 0;
{
for (CmdLineOpt *cmd = cmdline->options.first; cmd != 0; cmd = cmd->next) {
RD_Option opt = 0;
for (U64 opt_idx = 0; opt_idx < ArrayCount(g_rd_dump_option_map); ++opt_idx) {
String8 opt_name = str8_cstring(g_rd_dump_option_map[opt_idx].name);
if (str8_match(cmd->string, opt_name, StringMatchFlag_CaseInsensitive)) {
opt = g_rd_dump_option_map[opt_idx].opt;
break;
} else if (str8_match(cmd->string, str8_lit("all"), StringMatchFlag_CaseInsensitive)) {
opt = ~0ull & ~(RD_Option_Help|RD_Option_Version);
break;
}
}
if (opt == 0) {
fprintf(stderr, "Unknown argument: \"%.*s\"\n", str8_varg(cmd->string));
os_abort(1);
}
opts |= opt;
}
}
// print help
if (opts & RD_Option_Help) {
for (U64 opt_idx = 0; opt_idx < ArrayCount(g_rd_dump_option_map); ++opt_idx) {
fprintf(stdout, "-%s %s\n", g_rd_dump_option_map[opt_idx].name, g_rd_dump_option_map[opt_idx].help);
}
os_abort(0);
}
// print version
if (opts & RD_Option_Version) {
fprintf(stdout, BUILD_TITLE_STRING_LITERAL "\n");
fprintf(stdout, "\traddump <options> <inputs>\n");
os_abort(0);
}
// input check
if (cmdline->inputs.node_count == 0) {
fprintf(stderr, "No input file specified\n");
os_abort(1);
} else if (cmdline->inputs.node_count > 1) {
fprintf(stderr, "Too many inputs specified, expected one\n");
os_abort(1);
}
// read input
String8 file_path = str8_list_first(&cmdline->inputs);
String8 raw_data = os_data_from_file_path(scratch.arena, file_path);
// is read ok?
if (raw_data.size == 0) {
fprintf(stderr, "Unable to read input file \"%.*s\"\n", str8_varg(file_path));
os_abort(1);
}
// make indent
String8 indent;
{
U64 indent_buffer_size = RD_INDENT_WIDTH * RD_INDENT_MAX;
U8 *indent_buffer = push_array(scratch.arena, U8, indent_buffer_size);
MemorySet(indent_buffer, ' ', indent_buffer_size);
indent = str8(indent_buffer, 0);
}
// format input
String8List out = {0};
format_preamble(scratch.arena, &out, indent, file_path, raw_data);
if (coff_is_archive(raw_data) || coff_is_thin_archive(raw_data)) {
coff_format_archive(scratch.arena, &out, indent, raw_data, opts);
} else if (coff_is_big_obj(raw_data)) {
coff_format_big_obj(scratch.arena, &out, indent, raw_data, opts);
} else if (coff_is_obj(raw_data)) {
coff_format_obj(scratch.arena, &out, indent, raw_data, opts);
} else if (is_pe(raw_data)) {
pe_format(scratch.arena, &out, indent, raw_data, opts);
} else if (pe_is_res(raw_data)) {
//tool_out_coff_res(stdout, file_data);
}
// print formatted string
String8 out_string = str8_list_join(scratch.arena, &out, &(StringJoin){ .sep = str8_lit("\n"),});
fprintf(stdout, "%.*s", str8_varg(out_string));
scratch_end(scratch);
}