mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-18 10:02:23 -07:00
eliminate radcon, eliminate unused string helpers
This commit is contained in:
+364
-322
File diff suppressed because it is too large
Load Diff
+16
-33
@@ -38,13 +38,6 @@ struct String8Node
|
||||
String8 string;
|
||||
};
|
||||
|
||||
typedef struct String8MetaNode String8MetaNode;
|
||||
struct String8MetaNode
|
||||
{
|
||||
String8MetaNode *next;
|
||||
String8Node *node;
|
||||
};
|
||||
|
||||
typedef struct String8List String8List;
|
||||
struct String8List
|
||||
{
|
||||
@@ -59,6 +52,7 @@ struct String8Array
|
||||
{
|
||||
String8 *v;
|
||||
U64 count;
|
||||
U64 total_size;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -152,9 +146,9 @@ internal B32 char_is_lower(U8 c);
|
||||
internal B32 char_is_alpha(U8 c);
|
||||
internal B32 char_is_slash(U8 c);
|
||||
internal B32 char_is_digit(U8 c, U32 base);
|
||||
internal U8 char_to_lower(U8 c);
|
||||
internal U8 char_to_upper(U8 c);
|
||||
internal U8 char_to_correct_slash(U8 c);
|
||||
internal U8 lower_from_char(U8 c);
|
||||
internal U8 upper_from_char(U8 c);
|
||||
internal U8 correct_slash_from_char(U8 c);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: C-String Measurement
|
||||
@@ -262,12 +256,12 @@ internal F64 f64_from_str8(String8 string);
|
||||
////////////////////////////////
|
||||
//~ rjf: String List Construction Functions
|
||||
|
||||
internal String8Node* str8_list_push_node(String8List *list, String8Node *node);
|
||||
internal String8Node* str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string);
|
||||
internal String8Node* str8_list_push_node_front(String8List *list, String8Node *node);
|
||||
internal String8Node* str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string);
|
||||
internal String8Node* str8_list_push(Arena *arena, String8List *list, String8 string);
|
||||
internal String8Node* str8_list_push_front(Arena *arena, String8List *list, String8 string);
|
||||
internal String8Node *str8_list_push_node(String8List *list, String8Node *node);
|
||||
internal String8Node *str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string);
|
||||
internal String8Node *str8_list_push_node_front(String8List *list, String8Node *node);
|
||||
internal String8Node *str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string);
|
||||
internal String8Node *str8_list_push(Arena *arena, String8List *list, String8 string);
|
||||
internal String8Node *str8_list_push_front(Arena *arena, String8List *list, String8 string);
|
||||
internal void str8_list_concat_in_place(String8List *list, String8List *to_push);
|
||||
internal String8Node* str8_list_push_aligner(Arena *arena, String8List *list, U64 min, U64 align);
|
||||
internal String8Node* str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...);
|
||||
@@ -280,9 +274,7 @@ internal String8List str8_list_copy(Arena *arena, String8List *list);
|
||||
|
||||
internal String8List str8_split(Arena *arena, String8 string, U8 *split_chars, U64 split_char_count, StringSplitFlags flags);
|
||||
internal String8List str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags);
|
||||
internal String8List str8_list_split_by_string_chars(Arena *arena, String8List list, String8 split_chars, StringSplitFlags flags);
|
||||
internal String8 str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params);
|
||||
internal void str8_list_from_flags(Arena *arena, String8List *list, U32 flags, String8 *flag_string_table, U32 flag_string_count);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Data Stringification Helpers
|
||||
@@ -298,7 +290,7 @@ internal String8Array str8_array_reserve(Arena *arena, U64 count);
|
||||
internal String8Array str8_array_copy(Arena *arena, String8Array array);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Version Helpers
|
||||
//~ rjf: String <-> Version Helpers
|
||||
|
||||
internal U64 version_from_str8(String8 string);
|
||||
internal String8 str8_from_version(Arena *arena, U64 version);
|
||||
@@ -362,7 +354,6 @@ internal UnicodeDecode utf8_decode(U8 *str, U64 max);
|
||||
internal UnicodeDecode utf16_decode(U16 *str, U64 max);
|
||||
internal U32 utf8_encode(U8 *str, U32 codepoint);
|
||||
internal U32 utf16_encode(U16 *str, U32 codepoint);
|
||||
internal U32 utf8_from_utf32_single(U8 *buffer, U32 character);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Unicode String Conversions
|
||||
@@ -373,29 +364,21 @@ internal String8 str8_from_32(Arena *arena, String32 in);
|
||||
internal String32 str32_from_8(Arena *arena, String8 in);
|
||||
|
||||
////////////////////////////////
|
||||
//~ String -> Enum Conversions
|
||||
//~ rjf: Basic Types & Space Enum <-> String Conversions
|
||||
|
||||
internal OperatingSystem operating_system_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Types & Space Enum -> String Conversions
|
||||
|
||||
internal String8 string_from_dimension(Dimension dimension);
|
||||
internal String8 string_from_side(Side side);
|
||||
internal String8 string_from_operating_system(OperatingSystem os);
|
||||
internal String8 string_from_arch(Arch arch);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Time Types -> String
|
||||
|
||||
internal String8 string_from_week_day(WeekDay week_day);
|
||||
internal String8 string_from_month(Month month);
|
||||
internal String8 push_date_time_string(Arena *arena, DateTime *date_time);
|
||||
internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time);
|
||||
internal String8 string_from_date_time(Arena *arena, DateTime *date_time);
|
||||
internal String8 string_from_date_time__file_name(Arena *arena, DateTime *date_time);
|
||||
internal String8 string_from_elapsed_time(Arena *arena, DateTime dt);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Globally Unique Ids
|
||||
//~ rjf: String <-> Globally Unique IDs
|
||||
|
||||
internal String8 string_from_guid(Arena *arena, Guid guid);
|
||||
internal B32 try_guid_from_string(String8 string, Guid *guid_out);
|
||||
@@ -467,4 +450,4 @@ internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, Stri
|
||||
internal U64 u64_hash_from_seed_str8(U64 seed, String8 string);
|
||||
internal U64 u64_hash_from_str8(String8 string);
|
||||
|
||||
#endif //BASE_STRINGS_H
|
||||
#endif // BASE_STRINGS_H
|
||||
|
||||
+97
-97
@@ -31,21 +31,21 @@ coff_section_flag_from_align_size(U64 align)
|
||||
{
|
||||
COFF_SectionFlags flags = 0;
|
||||
switch (align) {
|
||||
case 0: flags = COFF_SectionAlign_None; break;
|
||||
case 1: flags = COFF_SectionAlign_1Bytes; break;
|
||||
case 2: flags = COFF_SectionAlign_2Bytes; break;
|
||||
case 4: flags = COFF_SectionAlign_4Bytes; break;
|
||||
case 8: flags = COFF_SectionAlign_8Bytes; break;
|
||||
case 16: flags = COFF_SectionAlign_16Bytes; break;
|
||||
case 32: flags = COFF_SectionAlign_32Bytes; break;
|
||||
case 64: flags = COFF_SectionAlign_64Bytes; break;
|
||||
case 128: flags = COFF_SectionAlign_128Bytes; break;
|
||||
case 256: flags = COFF_SectionAlign_256Bytes; break;
|
||||
case 512: flags = COFF_SectionAlign_512Bytes; break;
|
||||
case 1024: flags = COFF_SectionAlign_1024Bytes; break;
|
||||
case 2048: flags = COFF_SectionAlign_2048Bytes; break;
|
||||
case 4096: flags = COFF_SectionAlign_4096Bytes; break;
|
||||
case 8192: flags = COFF_SectionAlign_8192Bytes; break;
|
||||
case 0: flags = COFF_SectionAlign_None; break;
|
||||
case 1: flags = COFF_SectionAlign_1Bytes; break;
|
||||
case 2: flags = COFF_SectionAlign_2Bytes; break;
|
||||
case 4: flags = COFF_SectionAlign_4Bytes; break;
|
||||
case 8: flags = COFF_SectionAlign_8Bytes; break;
|
||||
case 16: flags = COFF_SectionAlign_16Bytes; break;
|
||||
case 32: flags = COFF_SectionAlign_32Bytes; break;
|
||||
case 64: flags = COFF_SectionAlign_64Bytes; break;
|
||||
case 128: flags = COFF_SectionAlign_128Bytes; break;
|
||||
case 256: flags = COFF_SectionAlign_256Bytes; break;
|
||||
case 512: flags = COFF_SectionAlign_512Bytes; break;
|
||||
case 1024: flags = COFF_SectionAlign_1024Bytes; break;
|
||||
case 2048: flags = COFF_SectionAlign_2048Bytes; break;
|
||||
case 4096: flags = COFF_SectionAlign_4096Bytes; break;
|
||||
case 8192: flags = COFF_SectionAlign_8192Bytes; break;
|
||||
}
|
||||
flags <<= COFF_SectionFlag_AlignShift;
|
||||
return flags;
|
||||
@@ -182,67 +182,67 @@ coff_pick_reloc_value_x64(COFF_Reloc_X64 type,
|
||||
{
|
||||
U64 reloc_value_size = 0;
|
||||
S64 reloc_value = 0;
|
||||
|
||||
|
||||
switch (type) {
|
||||
case COFF_Reloc_X64_Abs: {} break;
|
||||
case COFF_Reloc_X64_Addr64: {
|
||||
reloc_value_size = 8;
|
||||
reloc_value = symbol_virtual_offset + (S64)image_base;
|
||||
} break;
|
||||
case COFF_Reloc_X64_Addr32: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset + (S64)image_base);
|
||||
} break;
|
||||
case COFF_Reloc_X64_Addr32Nb: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = symbol_virtual_offset;
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 0));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32_1: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 1));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32_2: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 2));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32_3: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 3));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32_4: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 4));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32_5: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 5));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Section: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = symbol_section_number;
|
||||
} break;
|
||||
case COFF_Reloc_X64_SecRel: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = symbol_section_offset;
|
||||
} break;
|
||||
case COFF_Reloc_X64_SecRel7:
|
||||
case COFF_Reloc_X64_Token:
|
||||
case COFF_Reloc_X64_SRel32:
|
||||
case COFF_Reloc_X64_Pair:
|
||||
case COFF_Reloc_X64_SSpan32:
|
||||
case COFF_Reloc_X64_Unknown_11: {
|
||||
NotImplemented;
|
||||
} break;
|
||||
case COFF_Reloc_X64_Abs: {} break;
|
||||
case COFF_Reloc_X64_Addr64: {
|
||||
reloc_value_size = 8;
|
||||
reloc_value = symbol_virtual_offset + (S64)image_base;
|
||||
} break;
|
||||
case COFF_Reloc_X64_Addr32: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset + (S64)image_base);
|
||||
} break;
|
||||
case COFF_Reloc_X64_Addr32Nb: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = symbol_virtual_offset;
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 0));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32_1: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 1));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32_2: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 2));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32_3: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 3));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32_4: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 4));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Rel32_5: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 5));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Section: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = symbol_section_number;
|
||||
} break;
|
||||
case COFF_Reloc_X64_SecRel: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value = symbol_section_offset;
|
||||
} break;
|
||||
case COFF_Reloc_X64_SecRel7:
|
||||
case COFF_Reloc_X64_Token:
|
||||
case COFF_Reloc_X64_SRel32:
|
||||
case COFF_Reloc_X64_Pair:
|
||||
case COFF_Reloc_X64_SSpan32:
|
||||
case COFF_Reloc_X64_Unknown_11: {
|
||||
NotImplemented;
|
||||
} break;
|
||||
}
|
||||
|
||||
|
||||
COFF_RelocValue result = {0};
|
||||
result.size = reloc_value_size;
|
||||
result.value = reloc_value;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ coff_make_lib_member_header(Arena *arena, String8 name, COFF_TimeStamp time_stam
|
||||
str8_list_pushf(scratch.arena, &list, "%-10u", size);
|
||||
str8_list_pushf(scratch.arena, &list, "`\n");
|
||||
String8 result = str8_list_join(arena, &list, 0);
|
||||
|
||||
|
||||
Assert(result.size == sizeof(COFF_ArchiveMemberHeader));
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
@@ -302,18 +302,18 @@ coff_ordinal_data_from_hint(Arena *arena, COFF_MachineType machine, U16 hint)
|
||||
{
|
||||
String8 ordinal_data = {0};
|
||||
switch (machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: {
|
||||
U64 *ordinal = push_array(arena, U64, 1);
|
||||
*ordinal = coff_make_ordinal64(hint);
|
||||
ordinal_data = str8_struct(ordinal);
|
||||
} break;
|
||||
case COFF_MachineType_X86: {
|
||||
U32 *ordinal = push_array(arena, U32, 1);
|
||||
*ordinal = coff_make_ordinal32(hint);
|
||||
ordinal_data = str8_struct(ordinal);
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: {
|
||||
U64 *ordinal = push_array(arena, U64, 1);
|
||||
*ordinal = coff_make_ordinal64(hint);
|
||||
ordinal_data = str8_struct(ordinal);
|
||||
} break;
|
||||
case COFF_MachineType_X86: {
|
||||
U32 *ordinal = push_array(arena, U32, 1);
|
||||
*ordinal = coff_make_ordinal32(hint);
|
||||
ordinal_data = str8_struct(ordinal);
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return ordinal_data;
|
||||
}
|
||||
@@ -331,7 +331,7 @@ coff_make_import_header(Arena *arena,
|
||||
COFF_ImportHeaderFlags flags = 0;
|
||||
flags |= (type & COFF_ImportHeader_TypeMask) << COFF_ImportHeader_TypeShift;
|
||||
flags |= import_by << COFF_ImportHeader_ImportByShift;
|
||||
|
||||
|
||||
COFF_ImportHeader header = {0};
|
||||
header.sig1 = COFF_MachineType_Unknown;
|
||||
header.sig2 = max_U16;
|
||||
@@ -368,12 +368,12 @@ coff_code_align_byte_from_machine(COFF_MachineType machine)
|
||||
{
|
||||
U8 align_byte = 0;
|
||||
switch (machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64:
|
||||
case COFF_MachineType_X86: {
|
||||
align_byte = 0xCC;
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64:
|
||||
case COFF_MachineType_X86: {
|
||||
align_byte = 0xCC;
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return align_byte;
|
||||
}
|
||||
@@ -383,11 +383,11 @@ coff_default_align_from_machine(COFF_MachineType machine)
|
||||
{
|
||||
U16 align = 0;
|
||||
switch (machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: {
|
||||
align = 16;
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: {
|
||||
align = 16;
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return align;
|
||||
}
|
||||
@@ -472,7 +472,7 @@ coff_string_from_time_stamp(Arena *arena, COFF_TimeStamp time_stamp)
|
||||
result = str8_lit("-1");
|
||||
} else {
|
||||
DateTime dt = date_time_from_unix_time(time_stamp);
|
||||
result = push_date_time_string(arena, &dt);
|
||||
result = string_from_date_time(arena, &dt);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+62
-61
@@ -20,14 +20,14 @@ internal String8
|
||||
coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
|
||||
String8List srl = {0};
|
||||
|
||||
|
||||
String8List string_table = {0};
|
||||
U32 *string_table_size = push_array(scratch.arena, U32, 1);
|
||||
*string_table_size = sizeof(*string_table_size);
|
||||
str8_list_push(scratch.arena, &string_table, str8_struct(string_table_size));
|
||||
|
||||
|
||||
//
|
||||
// assing section numbers
|
||||
//
|
||||
@@ -41,11 +41,11 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
COFF_ObjSection *sect = §_n->v;
|
||||
sect->section_number = sect_idx+1;
|
||||
obj_sections[sect_idx] = sect;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
AssertAlways(obj_sections_count <= max_U16);
|
||||
|
||||
|
||||
//
|
||||
// serialize symbol table
|
||||
//
|
||||
@@ -55,26 +55,27 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
U64 symbol_idx = 0;
|
||||
for (COFF_ObjSymbolNode *symbol_n = obj_writer->symbol_first; symbol_n != 0; symbol_n = symbol_n->next) {
|
||||
COFF_ObjSymbol *s = &symbol_n->v;
|
||||
|
||||
|
||||
// assign symbol index
|
||||
s->idx = symbol_idx++;
|
||||
symbol_idx += s->aux_symbols.node_count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
U64 symbol_idx = 0;
|
||||
for (COFF_ObjSymbolNode *symbol_n = obj_writer->symbol_first; symbol_n != 0; symbol_n = symbol_n->next) {
|
||||
COFF_ObjSymbol *s = &symbol_n->v;
|
||||
|
||||
|
||||
COFF_Symbol16 *d = push_array(scratch.arena, COFF_Symbol16, 1);
|
||||
str8_list_push(scratch.arena, &symbol_table, str8_struct(d));
|
||||
|
||||
|
||||
COFF_SymbolName name = {0};
|
||||
// long name
|
||||
if (s->name.size > sizeof(name.short_name)) {
|
||||
U64 string_table_offset = string_table.total_size;
|
||||
str8_list_push_cstr(scratch.arena, &string_table, s->name);
|
||||
|
||||
str8_list_push(scratch.arena, &string.table, s->name);
|
||||
str8_list_push(scratch.arena, &string.table, str8_lit("\0"));
|
||||
|
||||
name.long_name.zeroes = 0;
|
||||
name.long_name.string_table_offset = safe_cast_u32(string_table_offset);
|
||||
}
|
||||
@@ -83,22 +84,22 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
MemoryCopyStr8(name.short_name, s->name);
|
||||
MemoryZeroTyped(name.short_name + s->name.size, sizeof(name.short_name) - s->name.size);
|
||||
}
|
||||
|
||||
|
||||
// symbol header
|
||||
AssertAlways(s->aux_symbols.node_count <= max_U8);
|
||||
d->name = name;
|
||||
d->value = s->value;
|
||||
switch (s->loc.type) {
|
||||
case COFF_SymbolLocation_Null: break;
|
||||
case COFF_SymbolLocation_Section: d->section_number = safe_cast_u16(s->loc.u.section->section_number); break;
|
||||
case COFF_SymbolLocation_Abs: d->section_number = COFF_Symbol_AbsSection16; break;
|
||||
case COFF_SymbolLocation_Undef: d->section_number = COFF_Symbol_UndefinedSection; break;
|
||||
case COFF_SymbolLocation_Common: d->section_number = COFF_Symbol_UndefinedSection; break;
|
||||
case COFF_SymbolLocation_Null: break;
|
||||
case COFF_SymbolLocation_Section: d->section_number = safe_cast_u16(s->loc.u.section->section_number); break;
|
||||
case COFF_SymbolLocation_Abs: d->section_number = COFF_Symbol_AbsSection16; break;
|
||||
case COFF_SymbolLocation_Undef: d->section_number = COFF_Symbol_UndefinedSection; break;
|
||||
case COFF_SymbolLocation_Common: d->section_number = COFF_Symbol_UndefinedSection; break;
|
||||
}
|
||||
d->type = s->type;
|
||||
d->storage_class = s->storage_class;
|
||||
d->aux_symbol_count = 0;
|
||||
|
||||
|
||||
U64 start_symbol_idx = symbol_idx;
|
||||
if (s->storage_class == COFF_SymStorageClass_WeakExternal) {
|
||||
if (s->aux_symbols.node_count > 0) {
|
||||
@@ -106,7 +107,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
COFF_SymbolWeakExt *d_weak = push_array(scratch.arena, COFF_SymbolWeakExt, 1);
|
||||
d_weak->tag_index = s_weak->tag ? s_weak->tag->idx : max_U32;
|
||||
d_weak->characteristics = s_weak->characteristics;
|
||||
|
||||
|
||||
str8_list_push(scratch.arena, &symbol_table, str8_struct(d_weak));
|
||||
symbol_idx += 1;
|
||||
}
|
||||
@@ -114,32 +115,32 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
if (s->aux_symbols.node_count > 0) {
|
||||
Assert(s->loc.type == COFF_SymbolLocation_Section);
|
||||
COFF_ObjSection *sect = s->loc.u.section;
|
||||
|
||||
|
||||
COFF_ObjSymbolSecDef *s_sd = (COFF_ObjSymbolSecDef *)s->aux_symbols.first->string.str;
|
||||
COFF_SymbolSecDef *d_sd = push_array(scratch.arena, COFF_SymbolSecDef, 1);
|
||||
|
||||
|
||||
d_sd->length = safe_cast_u32(sect->data.total_size);
|
||||
d_sd->number_of_relocations = (U16)sect->reloc_count;
|
||||
d_sd->check_sum = 0;
|
||||
d_sd->number_lo = s_sd->selection == COFF_ComdatSelect_Associative ? safe_cast_u16(s_sd->associate->section_number) : 0;
|
||||
d_sd->selection = s_sd->selection;
|
||||
|
||||
|
||||
str8_list_push(scratch.arena, &symbol_table, str8_struct(d_sd));
|
||||
symbol_idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
U8 processed_aux_symbol_count = (U8)(symbol_idx - start_symbol_idx);
|
||||
|
||||
|
||||
for (U64 aux_idx = processed_aux_symbol_count; aux_idx < s->aux_symbols.node_count; aux_idx += 1) {
|
||||
COFF_Symbol16 *a = push_array(scratch.arena, COFF_Symbol16, 1);
|
||||
str8_list_push(scratch.arena, &symbol_table, str8_struct(a));
|
||||
}
|
||||
|
||||
|
||||
d->aux_symbol_count = (U8)s->aux_symbols.node_count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// file header
|
||||
//
|
||||
@@ -152,35 +153,35 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
file_header->optional_header_size = 0;
|
||||
file_header->flags = 0;
|
||||
str8_list_push(scratch.arena, &srl, str8_struct(file_header));
|
||||
|
||||
|
||||
//
|
||||
// section table
|
||||
//
|
||||
|
||||
|
||||
COFF_SectionHeader *sectab = push_array(scratch.arena, COFF_SectionHeader, obj_sections_count);
|
||||
str8_list_push(scratch.arena, &srl, str8_array(sectab, obj_sections_count));
|
||||
{
|
||||
for (U64 sect_idx = 0; sect_idx < obj_sections_count; sect_idx += 1) {
|
||||
COFF_ObjSection *s = obj_sections[sect_idx];
|
||||
COFF_SectionHeader *d = §ab[sect_idx];
|
||||
|
||||
|
||||
// section name
|
||||
String8 sect_name = s->name;
|
||||
if (sect_name.size > sizeof(d->name)) {
|
||||
U64 sect_name_off = string_table.total_size;
|
||||
str8_list_push_cstr(scratch.arena, &string_table, sect_name);
|
||||
|
||||
|
||||
sect_name = push_str8f(scratch.arena, "/%u", sect_name_off);
|
||||
AssertAlways(sect_name.size <= sizeof(d->name));
|
||||
}
|
||||
|
||||
|
||||
// alloc zero nodes
|
||||
for (String8Node *data_n = s->data.first; data_n != 0; data_n = data_n->next) {
|
||||
if (data_n->string.str == 0 && data_n->string.size > 0) {
|
||||
data_n->string = str8(push_array(scratch.arena, U8, data_n->string.size), data_n->string.size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// section data
|
||||
U64 data_foff = 0;
|
||||
U64 data_size = 0;
|
||||
@@ -189,7 +190,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
data_size = s->data.total_size;
|
||||
str8_list_concat_in_place(&srl, &s->data);
|
||||
}
|
||||
|
||||
|
||||
// section relocs
|
||||
U64 relocs_foff = 0;
|
||||
if (s->reloc_count) {
|
||||
@@ -206,7 +207,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
relocs_foff = srl.total_size;
|
||||
str8_list_push(scratch.arena, &srl, str8_array(relocs, s->reloc_count));
|
||||
}
|
||||
|
||||
|
||||
// section header
|
||||
MemoryCopyStr8(d->name, sect_name);
|
||||
MemoryZeroTyped(d->name + sect_name.size, sizeof(d->name) - sect_name.size);
|
||||
@@ -221,7 +222,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
d->flags = s->flags;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// symbol table
|
||||
//
|
||||
@@ -229,7 +230,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
file_header->symbol_table_foff = srl.total_size;
|
||||
str8_list_concat_in_place(&srl, &symbol_table);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// string table
|
||||
//
|
||||
@@ -237,12 +238,12 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
*string_table_size = safe_cast_u32(string_table.total_size);
|
||||
str8_list_concat_in_place(&srl, &string_table);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// join
|
||||
//
|
||||
String8 obj = str8_list_join(arena, &srl, 0);
|
||||
|
||||
|
||||
scratch_end(scratch);
|
||||
return obj;
|
||||
}
|
||||
@@ -253,15 +254,15 @@ coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_Sect
|
||||
COFF_ObjSectionNode *sect_n = push_array(obj_writer->arena, COFF_ObjSectionNode, 1);
|
||||
SLLQueuePush(obj_writer->sect_first, obj_writer->sect_last, sect_n);
|
||||
obj_writer->sect_count += 1;
|
||||
|
||||
|
||||
COFF_ObjSection *sect = §_n->v;
|
||||
sect->name = name;
|
||||
sect->flags = flags;
|
||||
|
||||
|
||||
if (data.size) {
|
||||
str8_list_push(obj_writer->arena, §->data, data);
|
||||
}
|
||||
|
||||
|
||||
return sect;
|
||||
}
|
||||
|
||||
@@ -271,14 +272,14 @@ coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value,
|
||||
COFF_ObjSymbolNode *n = push_array(obj_writer->arena, COFF_ObjSymbolNode, 1);
|
||||
SLLQueuePush(obj_writer->symbol_first, obj_writer->symbol_last, n);
|
||||
obj_writer->symbol_count += 1;
|
||||
|
||||
|
||||
COFF_ObjSymbol *s = &n->v;
|
||||
s->name = name;
|
||||
s->value = value;
|
||||
s->loc = loc;
|
||||
s->type = type;
|
||||
s->storage_class = storage_class;
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -307,9 +308,9 @@ coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32
|
||||
COFF_SymbolLocation loc = {0};
|
||||
loc.type = COFF_SymbolLocation_Section;
|
||||
loc.u.section = section;
|
||||
|
||||
|
||||
COFF_SymbolType symtype = {0};
|
||||
|
||||
|
||||
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, off, loc, symtype, COFF_SymStorageClass_Static);
|
||||
return s;
|
||||
}
|
||||
@@ -341,13 +342,13 @@ coff_obj_writer_push_symbol_weak(COFF_ObjWriter *obj_writer, String8 name, COFF_
|
||||
COFF_SymbolLocation loc = {0};
|
||||
COFF_SymbolType symtype = {0};
|
||||
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, COFF_Symbol_UndefinedSection, loc, symtype, COFF_SymStorageClass_WeakExternal);
|
||||
|
||||
|
||||
COFF_ObjSymbolWeak *weak_ext = push_array(obj_writer->arena, COFF_ObjSymbolWeak, 1);
|
||||
weak_ext->tag = tag;
|
||||
weak_ext->characteristics = characteristics;
|
||||
|
||||
|
||||
str8_list_push(obj_writer->arena, &s->aux_symbols, str8_struct(weak_ext));
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -398,10 +399,10 @@ coff_obj_writer_push_symbol_sect(COFF_ObjWriter *obj_writer, String8 name, COFF_
|
||||
COFF_SymbolLocation loc = {0};
|
||||
loc.type = COFF_SymbolLocation_Section;
|
||||
loc.u.section = sect;
|
||||
|
||||
|
||||
// strip align flags
|
||||
COFF_SectionFlags expected_flags = sect->flags & ~(COFF_SectionFlag_AlignMask << COFF_SectionFlag_AlignShift);
|
||||
|
||||
|
||||
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, expected_flags, loc, type, COFF_SymStorageClass_Section);
|
||||
return s;
|
||||
}
|
||||
@@ -430,12 +431,12 @@ coff_obj_writer_section_push_reloc(COFF_ObjWriter *obj_writer, COFF_ObjSection *
|
||||
COFF_ObjRelocNode *reloc_n = push_array(obj_writer->arena, COFF_ObjRelocNode, 1);
|
||||
SLLQueuePush(sect->reloc_first, sect->reloc_last, reloc_n);
|
||||
sect->reloc_count += 1;
|
||||
|
||||
|
||||
COFF_ObjReloc *reloc = &reloc_n->v;
|
||||
reloc->apply_off = apply_off;
|
||||
reloc->symbol = symbol;
|
||||
reloc->type = type;
|
||||
|
||||
|
||||
return reloc;
|
||||
}
|
||||
|
||||
@@ -444,9 +445,9 @@ coff_obj_writer_section_push_reloc_addr32(COFF_ObjWriter *obj_writer, COFF_ObjSe
|
||||
{
|
||||
COFF_RelocType reloc_type = 0;
|
||||
switch (obj_writer->machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr32; break;
|
||||
default: { NotImplemented; } break;
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr32; break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return coff_obj_writer_section_push_reloc(obj_writer, sect, apply_off, symbol, reloc_type);
|
||||
}
|
||||
@@ -456,9 +457,9 @@ coff_obj_writer_section_push_reloc_addr(COFF_ObjWriter *obj_writer, COFF_ObjSect
|
||||
{
|
||||
COFF_RelocType reloc_type = 0;
|
||||
switch (obj_writer->machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr64; break;
|
||||
default: { NotImplemented; } break;
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr64; break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return coff_obj_writer_section_push_reloc(obj_writer, sect, apply_off, symbol, reloc_type);
|
||||
}
|
||||
@@ -468,9 +469,9 @@ coff_obj_writer_section_push_reloc_voff(COFF_ObjWriter *obj_writer, COFF_ObjSect
|
||||
{
|
||||
COFF_RelocType reloc_type = 0;
|
||||
switch (obj_writer->machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr32Nb; break;
|
||||
default: { NotImplemented; } break;
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr32Nb; break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return coff_obj_writer_section_push_reloc(obj_writer, sect, apply_off, symbol, reloc_type);
|
||||
}
|
||||
|
||||
@@ -3991,8 +3991,8 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *
|
||||
String8 filename_normalized = push_str8_copy(scratch.arena, filename);
|
||||
for(U64 idx = 0; idx < filename_normalized.size; idx += 1)
|
||||
{
|
||||
filename_normalized.str[idx] = char_to_lower(filename_normalized.str[idx]);
|
||||
filename_normalized.str[idx] = char_to_correct_slash(filename_normalized.str[idx]);
|
||||
filename_normalized.str[idx] = lower_from_char(filename_normalized.str[idx]);
|
||||
filename_normalized.str[idx] = correct_slash_from_char(filename_normalized.str[idx]);
|
||||
}
|
||||
|
||||
// rjf: filename -> src_id
|
||||
|
||||
@@ -37,7 +37,7 @@ d_hash_from_seed_string__case_insensitive(U64 seed, String8 string)
|
||||
U64 result = seed;
|
||||
for(U64 i = 0; i < string.size; i += 1)
|
||||
{
|
||||
result = ((result << 5) + result) + char_to_lower(string.str[i]);
|
||||
result = ((result << 5) + result) + lower_from_char(string.str[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ di_hash_from_seed_string(U64 seed, String8 string, StringMatchFlags match_flags)
|
||||
U64 result = seed;
|
||||
for(U64 i = 0; i < string.size; i += 1)
|
||||
{
|
||||
result = ((result << 5) + result) + ((match_flags & StringMatchFlag_CaseInsensitive) ? char_to_lower(string.str[i]) : string.str[i]);
|
||||
result = ((result << 5) + result) + ((match_flags & StringMatchFlag_CaseInsensitive) ? lower_from_char(string.str[i]) : string.str[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+3
-7
@@ -35,13 +35,9 @@ internal String8List
|
||||
os_string_list_from_modifiers(Arena *arena, OS_Modifiers modifiers)
|
||||
{
|
||||
String8List result = {0};
|
||||
String8 modifier_strs[] =
|
||||
{
|
||||
str8_lit("Ctrl"),
|
||||
str8_lit("Shift"),
|
||||
str8_lit("Alt"),
|
||||
};
|
||||
str8_list_from_flags(arena, &result, modifiers, modifier_strs, ArrayCount(modifier_strs));
|
||||
if(modifiers & OS_Modifier_Ctrl) { str8_list_push(arena, &result, str8_lit("Ctrl")); }
|
||||
if(modifiers & OS_Modifier_Shift) { str8_list_push(arena, &result, str8_lit("Shift")); }
|
||||
if(modifiers & OS_Modifier_Alt) { str8_list_push(arena, &result, str8_lit("Alt")); }
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,481 +0,0 @@
|
||||
internal String8
|
||||
rc_data_from_file_path(Arena *arena, String8 path)
|
||||
{
|
||||
String8 data = os_data_from_file_path(arena, path);
|
||||
if (data.size == 0) {
|
||||
fprintf(stderr, "error: unable to read file %.*s\n", str8_varg(path));
|
||||
os_abort(1);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
internal RC_Context
|
||||
rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
if (cmdl->inputs.node_count > 2) {
|
||||
fprintf(stderr, "error: too many input files on the command line.\n");
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
B32 is_pe_present = 0;
|
||||
B32 is_pdb_present = 0;
|
||||
B32 is_elf_present = 0;
|
||||
B32 is_elf_debug_present = 0;
|
||||
String8 pe_name = {0};
|
||||
String8 pe_data = {0};
|
||||
String8 pdb_name = {0};
|
||||
String8 pdb_data = {0};
|
||||
String8 elf_name = {0};
|
||||
String8 elf_data = {0};
|
||||
String8 elf_debug_name = {0};
|
||||
String8 elf_debug_data = {0};
|
||||
|
||||
//
|
||||
// Set typed inputs
|
||||
//
|
||||
if (cmd_line_has_flag(cmdl, str8_lit("pe"))) {
|
||||
pe_name = cmd_line_string(cmdl, str8_lit("pe"));
|
||||
pe_data = rc_data_from_file_path(arena, pe_name);
|
||||
if (!pe_check_magic(pe_data)) {
|
||||
fprintf(stderr, "error: -pe:%.*s is not of PE format\n", str8_varg(pe_name));
|
||||
os_abort(1);
|
||||
}
|
||||
is_pe_present = 1;
|
||||
}
|
||||
if (cmd_line_has_flag(cmdl, str8_lit("pdb"))) {
|
||||
pdb_name = cmd_line_string(cmdl, str8_lit("pdb"));
|
||||
pdb_data = rc_data_from_file_path(arena, pdb_name);
|
||||
if (!msf_check_magic_20(pdb_data) && !msf_check_magic_70(pdb_data)) {
|
||||
fprintf(stderr, "error: -pdb:%.*s is not of PDB format\n", str8_varg(pdb_name));
|
||||
os_abort(1);
|
||||
}
|
||||
is_pdb_present = 1;
|
||||
}
|
||||
if (cmd_line_has_flag(cmdl, str8_lit("elf"))) {
|
||||
elf_name = cmd_line_string(cmdl, str8_lit("elf"));
|
||||
elf_data = rc_data_from_file_path(arena, elf_name);
|
||||
if (!elf_check_magic(elf_data)) {
|
||||
fprintf(stderr, "error: -elf:%.*s is not of ELF format\n", str8_varg(elf_name));
|
||||
os_abort(1);
|
||||
}
|
||||
is_elf_present = 1;
|
||||
}
|
||||
if (cmd_line_has_flag(cmdl, str8_lit("elf_debug"))) {
|
||||
elf_debug_name = cmd_line_string(cmdl, str8_lit("elf_debug"));
|
||||
elf_debug_data = rc_data_from_file_path(arena, elf_debug_name);
|
||||
if (!elf_check_magic(elf_debug_data)) {
|
||||
fprintf(stderr, "error: -elf_debug:%.*s is not of ELF format\n", str8_varg(elf_debug_name));
|
||||
os_abort(1);
|
||||
}
|
||||
is_elf_debug_present = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Pick conversion driver
|
||||
//
|
||||
RC_Driver driver = RC_Driver_Null;
|
||||
if (cmd_line_has_flag(cmdl, str8_lit("driver"))) {
|
||||
String8 driver_name = cmd_line_string(cmdl, str8_lit("driver"));
|
||||
if (str8_match(driver_name, str8_lit("dwarf"), StringMatchFlag_CaseInsensitive)) {
|
||||
driver = RC_Driver_Dwarf;
|
||||
} else if (str8_match(driver_name, str8_lit("pdb"), StringMatchFlag_CaseInsensitive)) {
|
||||
driver = RC_Driver_Pdb;
|
||||
} else {
|
||||
fprintf(stderr, "error: unknown driver \"%.*s\"\n", str8_varg(driver_name));
|
||||
os_abort(1);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Load inputs
|
||||
//
|
||||
for (String8Node *input_n = cmdl->inputs.first; input_n != 0; input_n = input_n->next) {
|
||||
String8 input_data = os_data_from_file_path(arena, input_n->string);
|
||||
|
||||
if (input_data.size == 0) {
|
||||
fprintf(stderr, "unable to read input %.*s\n", str8_varg(input_n->string));
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
if (pe_check_magic(input_data)) {
|
||||
if (is_pe_present) {
|
||||
fprintf(stderr, "error: too many PE files are specified on the command line\n");
|
||||
fprintf(stderr, " selected: %.*s\n", str8_varg(pe_name));
|
||||
fprintf(stderr, " current: %.*s\n", str8_varg(input_n->string));
|
||||
os_abort(1);
|
||||
}
|
||||
pe_data = input_data;
|
||||
pe_name = input_n->string;
|
||||
is_pe_present = 1;
|
||||
} else if (elf_check_magic(input_data)) {
|
||||
ELF_Bin elf = elf_bin_from_data(input_data);
|
||||
B32 is_dwarf_present = dw_is_dwarf_present_from_bin(input_data, &elf);
|
||||
if (is_dwarf_present) {
|
||||
if (is_elf_debug_present) {
|
||||
fprintf(stderr, "error: ambiguous input, both ELFs have DWARF debug sections, please use --elf:<path> --elf_debug:<path> to clarify inputs.\n");
|
||||
os_abort(1);
|
||||
}
|
||||
elf_debug_name = input_n->string;
|
||||
elf_debug_data = input_data;
|
||||
is_elf_debug_present = 1;
|
||||
} else {
|
||||
elf_name = input_n->string;
|
||||
elf_data = input_data;
|
||||
is_elf_present = 1;
|
||||
}
|
||||
} else if (msf_check_magic_20(input_data) || msf_check_magic_70(input_data)) {
|
||||
if (is_pdb_present) {
|
||||
fprintf(stderr, "error: too many PDB files are specified on the command line\n");
|
||||
fprintf(stderr, " selected: %.*s\n", str8_varg(pdb_name));
|
||||
fprintf(stderr, " current: %.*s\n", str8_varg(input_n->string));
|
||||
continue;
|
||||
}
|
||||
pdb_name = input_n->string;
|
||||
pdb_data = input_data;
|
||||
is_pdb_present = 1;
|
||||
} else {
|
||||
fprintf(stderr, "error: unknown file format %.*s\n", str8_varg(input_n->string));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Validate input combos
|
||||
//
|
||||
if ((is_pe_present || is_pdb_present) && (is_elf_present || is_elf_debug_present)) {
|
||||
fprintf(stderr, "error: invalid combination of inputs provided, we convert only (PE|PDB) or (ELF|ELF_DEBUG) at a time.\n");
|
||||
if (is_pe_present) {
|
||||
fprintf(stderr, " PE: %.*s\n", str8_varg(pe_name));
|
||||
}
|
||||
if (is_pdb_present) {
|
||||
fprintf(stderr, " PDB: %.*s\n", str8_varg(pdb_name));
|
||||
}
|
||||
if (is_elf_present) {
|
||||
fprintf(stderr, " ELF: %.*s\n", str8_varg(elf_name));
|
||||
}
|
||||
if (is_elf_debug_present) {
|
||||
fprintf(stderr, " ELF Debug: %.*s\n", str8_varg(elf_debug_name));
|
||||
}
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
if (is_pe_present && (is_elf_present || is_elf_debug_present)) {
|
||||
fprintf(stderr, "error: command line has too many image types specified.\n");
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
|
||||
ExecutableImageKind image = ExecutableImageKind_Null;
|
||||
String8 image_name = {0};
|
||||
String8 image_data = {0};
|
||||
String8 debug_name = {0};
|
||||
String8 debug_data = {0};
|
||||
|
||||
B32 check_guid = 0;
|
||||
Guid pe_pdb_guid = {0};
|
||||
|
||||
B32 elf_has_debug_link = 0;
|
||||
ELF_GnuDebugLink debug_link = {0};
|
||||
|
||||
//
|
||||
// Input has PE/COFF
|
||||
//
|
||||
if (is_pe_present) {
|
||||
image = ExecutableImageKind_CoffPe;
|
||||
image_name = pe_name;
|
||||
image_data = pe_data;
|
||||
|
||||
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, pe_data);
|
||||
String8 raw_debug_dir = str8_substr(pe_data, pe.data_dir_franges[PE_DataDirectoryIndex_DEBUG]);
|
||||
PE_DebugInfoList debug_dir = pe_debug_info_list_from_raw_debug_dir(scratch.arena, pe_data, raw_debug_dir);
|
||||
for (PE_DebugInfoNode *debug_n = debug_dir.first; debug_n != 0; debug_n = debug_n->next) {
|
||||
PE_DebugInfo *debug = &debug_n->v;
|
||||
if (debug->header.type == PE_DebugDirectoryType_CODEVIEW) {
|
||||
if (debug->u.codeview.magic == PE_CODEVIEW_PDB70_MAGIC) {
|
||||
check_guid = 1;
|
||||
pe_pdb_guid = debug->u.codeview.pdb70.header.guid;
|
||||
|
||||
if (!is_pdb_present) {
|
||||
pdb_name = debug->u.codeview.pdb70.path;
|
||||
pdb_data = rc_data_from_file_path(arena, pdb_name);
|
||||
is_pdb_present = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (driver == RC_Driver_Null || driver == RC_Driver_Dwarf) {
|
||||
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, pe_data);
|
||||
String8 raw_section_table = str8_substr(pe_data, pe.section_table_range);
|
||||
String8 string_table = str8_substr(pe_data, pe.string_table_range);
|
||||
U64 section_count = raw_section_table.size / sizeof(COFF_SectionHeader);
|
||||
COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str;
|
||||
if (dw_is_dwarf_present_coff_section_table(pe_data, string_table, section_count, section_table)) {
|
||||
driver = RC_Driver_Dwarf;
|
||||
debug_name = pe_name;
|
||||
debug_data = pe_data;
|
||||
goto driver_found;
|
||||
} else if (driver == RC_Driver_Dwarf) {
|
||||
fprintf(stderr, "error: image doesn't have DWARF debug sections.\n");
|
||||
os_abort(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_elf_present || is_elf_debug_present) {
|
||||
if (driver != RC_Driver_Null && driver != RC_Driver_Dwarf) {
|
||||
fprintf(stderr, "error: ELF inputs are only supported when using DWARF driver.\n");
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
//
|
||||
// Load image ELF
|
||||
//
|
||||
ELF_Bin elf = elf_bin_from_data(elf_data);
|
||||
B32 has_elf_dwarf = dw_is_dwarf_present_from_elf_bin(elf_data, &elf);
|
||||
|
||||
//
|
||||
// ELF doesn't have debug info and no .debug was specified on command line,
|
||||
// try to load .debug via debug link
|
||||
//
|
||||
if (is_elf_present && !is_elf_debug_present) {
|
||||
elf_has_debug_link = elf_parse_debug_link(elf_data, &elf, &debug_link);
|
||||
}
|
||||
if (elf_has_debug_link) {
|
||||
elf_debug_data = rc_data_from_file_path(arena, debug_link.path);
|
||||
is_elf_debug_present = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Load .debug ELF
|
||||
//
|
||||
ELF_Bin elf_debug = elf_bin_from_data(elf_debug_data);
|
||||
B32 has_elf_debug_dwarf = dw_is_dwarf_present_from_elf_bin(elf_debug_data, &elf_debug);
|
||||
|
||||
//
|
||||
// Input is image ELF and .debug ELF
|
||||
//
|
||||
B32 is_split_elf = is_elf_present && is_elf_debug_present && !has_elf_dwarf && has_elf_debug_dwarf;
|
||||
if (is_split_elf) {
|
||||
driver = RC_Driver_Dwarf;
|
||||
image = ELF_HdrIs64Bit(elf.hdr.e_ident) ? ExecutableImageKind_Elf64 : ExecutableImageKind_Elf32;
|
||||
image_name = elf_name;
|
||||
image_data = elf_data;
|
||||
debug_name = elf_debug_name;
|
||||
debug_data = elf_debug_data;
|
||||
goto driver_found;
|
||||
}
|
||||
|
||||
//
|
||||
// Input ELF is image with debug info
|
||||
//
|
||||
B32 is_monolithic_elf = is_elf_present && !is_elf_debug_present && has_elf_dwarf;
|
||||
if (is_monolithic_elf) {
|
||||
driver = RC_Driver_Dwarf;
|
||||
image = ELF_HdrIs64Bit(elf.hdr.e_ident) ? ExecutableImageKind_Elf64 : ExecutableImageKind_Elf32;
|
||||
image_name = elf_name;
|
||||
image_data = elf_data;
|
||||
debug_name = elf_name;
|
||||
debug_data = elf_data;
|
||||
goto driver_found;
|
||||
}
|
||||
|
||||
//
|
||||
// Input ELF is .debug
|
||||
//
|
||||
B32 is_debug_elf = !is_elf_present && is_elf_debug_present && has_elf_debug_dwarf;
|
||||
if (is_debug_elf) {
|
||||
driver = RC_Driver_Dwarf;
|
||||
image = ELF_HdrIs64Bit(elf_debug.hdr.e_ident) ? ExecutableImageKind_Elf64 : ExecutableImageKind_Elf32;
|
||||
debug_name = elf_debug_name;
|
||||
debug_data = elf_debug_data;
|
||||
goto driver_found;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Input is PDB
|
||||
//
|
||||
if (is_pdb_present) {
|
||||
if (driver == RC_Driver_Null || driver == RC_Driver_Pdb) {
|
||||
driver = RC_Driver_Pdb;
|
||||
debug_name = pdb_name;
|
||||
debug_data = pdb_data;
|
||||
goto driver_found;
|
||||
} else if (driver == RC_Driver_Dwarf) {
|
||||
fprintf(stderr, "error: unable to select DWARF conversion driver because convert doesn't support PDB as input format.\n");
|
||||
os_abort(1);
|
||||
} else {
|
||||
InvalidPath;
|
||||
}
|
||||
}
|
||||
|
||||
driver_found:;
|
||||
|
||||
//
|
||||
// Handle -out param
|
||||
//
|
||||
String8 out_name = {0};
|
||||
if (cmd_line_has_flag(cmdl, str8_lit("out"))) {
|
||||
out_name = cmd_line_string(cmdl, str8_lit("out"));
|
||||
if (out_name.size == 0) {
|
||||
fprintf(stderr, "error: -out parameter doesn't have a value\n");
|
||||
os_abort(1);
|
||||
}
|
||||
} else {
|
||||
if (image_name.size) {
|
||||
out_name = path_replace_file_extension(arena, image_name, str8_lit("rdi"));
|
||||
} else {
|
||||
out_name = path_replace_file_extension(arena, debug_name, str8_lit("rdi"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Validate driver input
|
||||
//
|
||||
if (driver == RC_Driver_Pdb &&
|
||||
!is_pdb_present && (is_elf_present || is_elf_debug_present)) {
|
||||
fprintf(stderr, "error: DWARF is an invalid input for PDB driver\n");
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
|
||||
RC_Context ctx = {0};
|
||||
ctx.driver = driver;
|
||||
ctx.image = image;
|
||||
ctx.image_name = image_name;
|
||||
ctx.image_data = image_data;
|
||||
ctx.debug_name = debug_name;
|
||||
ctx.debug_data = debug_data;
|
||||
ctx.flags = RC_Flag_Strings|
|
||||
RC_Flag_IndexRuns|
|
||||
RC_Flag_BinarySections|
|
||||
RC_Flag_Units|
|
||||
RC_Flag_Procedures|
|
||||
RC_Flag_GlobalVariables|
|
||||
RC_Flag_ThreadVariables|
|
||||
RC_Flag_Scopes|
|
||||
RC_Flag_Locals|
|
||||
RC_Flag_Types|
|
||||
RC_Flag_UDTs|
|
||||
RC_Flag_LineInfo|
|
||||
RC_Flag_GlobalVariableNameMap|
|
||||
RC_Flag_ThreadVariableNameMap|
|
||||
RC_Flag_ProcedureNameMap|
|
||||
RC_Flag_TypeNameMap|
|
||||
RC_Flag_LinkNameProcedureNameMap|
|
||||
RC_Flag_NormalSourcePathNameMap;
|
||||
if (check_guid) {
|
||||
ctx.flags |= RC_Flag_CheckPdbGuid;
|
||||
ctx.guid = pe_pdb_guid;
|
||||
}
|
||||
if (elf_has_debug_link) {
|
||||
ctx.flags |= RC_Flag_CheckElfChecksum;
|
||||
ctx.debug_link = debug_link;
|
||||
}
|
||||
ctx.out_name = out_name;
|
||||
|
||||
scratch_end(scratch);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
internal String8List
|
||||
rc_run(Arena *arena, RC_Context *rc)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
ProfBegin("Convert");
|
||||
RDIM_LocalState *local_state = rdim_local_init();
|
||||
RDIM_BakeParams *convert2bake = 0;
|
||||
switch (rc->driver) {
|
||||
case RC_Driver_Null: break;
|
||||
case RC_Driver_Dwarf: convert2bake = d2r_convert(scratch.arena, local_state, rc); break;
|
||||
case RC_Driver_Pdb: convert2bake = p2r_convert(scratch.arena, local_state, rc); break;
|
||||
}
|
||||
ProfEnd();
|
||||
|
||||
if (rc->errors.node_count) {
|
||||
NotImplemented;
|
||||
}
|
||||
|
||||
ProfBegin("Bake");
|
||||
RDIM_BakeResults bake2srlz = rdim_bake(local_state, convert2bake);
|
||||
ProfEnd();
|
||||
|
||||
ProfBegin("Serialize Bake");
|
||||
RDIM_SerializedSectionBundle srlz2file = rdim_serialized_section_bundle_from_bake_results(&bake2srlz);
|
||||
ProfEnd();
|
||||
|
||||
RDIM_SerializedSectionBundle srlz2file_compressed = srlz2file;
|
||||
if (rc->flags & RC_Flag_Compress) {
|
||||
ProfBegin("Compress");
|
||||
srlz2file_compressed = rdim_compress(scratch.arena, &srlz2file);
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
ProfBegin("Serialize");
|
||||
String8List raw_rdi = rdim_file_blobs_from_section_bundle(scratch.arena, &srlz2file_compressed);
|
||||
ProfEnd();
|
||||
|
||||
scratch_end(scratch);
|
||||
return raw_rdi;
|
||||
}
|
||||
|
||||
internal String8
|
||||
rc_rdi_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
RC_Context rc = rc_context_from_cmd_line(scratch.arena, cmdl);
|
||||
String8List raw_rdi = rc_run(scratch.arena, &rc);
|
||||
String8 result = str8_list_join(arena, &raw_rdi, 0);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
rc_main(CmdLine *cmdl)
|
||||
{
|
||||
B32 do_help = (cmd_line_has_flag(cmdl, str8_lit("help")) ||
|
||||
cmd_line_has_flag(cmdl, str8_lit("h")) ||
|
||||
cmd_line_has_flag(cmdl, str8_lit("?")) ||
|
||||
cmdl->argc == 1);
|
||||
if (do_help) {
|
||||
fprintf(stderr, "--- Help ---------------------------------------------------------------------\n");
|
||||
fprintf(stderr, " %s\n\n", BUILD_TITLE_STRING_LITERAL);
|
||||
fprintf(stderr, " Usage: radcon [Options] [Files]\n\n");
|
||||
fprintf(stderr, " Options:\n");
|
||||
fprintf(stderr, " -pe:<path> Path to Win32 executable image\n");
|
||||
fprintf(stderr, " -pdb:<path> Path to PDB\n");
|
||||
fprintf(stderr, " -elf:<path> Path to ELF\n");
|
||||
fprintf(stderr, " -elf_debug:<path> Path to ELF with debug info\n");
|
||||
fprintf(stderr, " -out:<path> Path at which the output RDI debug info will be written\n");
|
||||
fprintf(stderr, " -driver:<PDB|DWARF> Sets converter for debug info\n");
|
||||
} else {
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
|
||||
// make converter context
|
||||
RC_Context rc = rc_context_from_cmd_line(scratch.arena, cmdl);
|
||||
|
||||
// make RDI from context
|
||||
String8List raw_rdi = rc_run(scratch.arena, &rc);
|
||||
|
||||
// output RDI
|
||||
if (rc.errors.node_count == 0) {
|
||||
if (!os_write_data_list_to_file_path(rc.out_name, raw_rdi)) {
|
||||
str8_list_pushf(scratch.arena, &rc.errors, "no write access to path %.*s", str8_varg(rc.out_name));
|
||||
}
|
||||
}
|
||||
|
||||
// report any errors
|
||||
for (String8Node *error_n = rc.errors.first; error_n != 0; error_n = error_n->next) {
|
||||
fprintf(stderr, "error: %.*s\n", str8_varg(error_n->string));
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef RADCON_H
|
||||
#define RADCON_H
|
||||
|
||||
typedef U32 RC_Flags;
|
||||
enum
|
||||
{
|
||||
RC_Flag_Strings = (1 << 0),
|
||||
RC_Flag_IndexRuns = (1 << 1),
|
||||
RC_Flag_BinarySections = (1 << 2),
|
||||
RC_Flag_Units = (1 << 3),
|
||||
RC_Flag_Procedures = (1 << 4),
|
||||
RC_Flag_GlobalVariables = (1 << 5),
|
||||
RC_Flag_ThreadVariables = (1 << 6),
|
||||
RC_Flag_Scopes = (1 << 7),
|
||||
RC_Flag_Locals = (1 << 8),
|
||||
RC_Flag_Types = (1 << 9),
|
||||
RC_Flag_UDTs = (1 << 10),
|
||||
RC_Flag_LineInfo = (1 << 11),
|
||||
RC_Flag_GlobalVariableNameMap = (1 << 12),
|
||||
RC_Flag_ThreadVariableNameMap = (1 << 13),
|
||||
RC_Flag_ProcedureNameMap = (1 << 14),
|
||||
RC_Flag_TypeNameMap = (1 << 15),
|
||||
RC_Flag_LinkNameProcedureNameMap= (1 << 16),
|
||||
RC_Flag_NormalSourcePathNameMap = (1 << 17),
|
||||
RC_Flag_Compress = (1 << 18),
|
||||
RC_Flag_StrictDwarfParse = (1 << 19),
|
||||
RC_Flag_Deterministic = (1 << 20),
|
||||
RC_Flag_CheckPdbGuid = (1 << 21),
|
||||
RC_Flag_CheckElfChecksum = (1 << 22),
|
||||
RC_Flag_All = 0xffffffff,
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RC_Driver_Null,
|
||||
RC_Driver_Dwarf,
|
||||
RC_Driver_Pdb,
|
||||
} RC_Driver;
|
||||
|
||||
typedef struct RC_Context
|
||||
{
|
||||
ExecutableImageKind image;
|
||||
RC_Driver driver;
|
||||
String8 image_name;
|
||||
String8 image_data;
|
||||
String8 debug_name;
|
||||
String8 debug_data;
|
||||
String8 out_name;
|
||||
RC_Flags flags;
|
||||
Guid guid;
|
||||
ELF_GnuDebugLink debug_link;
|
||||
String8List errors;
|
||||
} RC_Context;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal RC_Context rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl);
|
||||
internal String8List rc_run(Arena *arena, RC_Context *rc);
|
||||
internal String8 rc_rdi_from_cmd_line(Arena *arena, CmdLine *cmdl);
|
||||
internal void rc_main(CmdLine *cmdl);
|
||||
|
||||
#endif // RADCON_H
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#define BUILD_TITLE "Epic Games Tools (R) RAD Debug Info Converter"
|
||||
#define BUILD_CONSOLE_INTERFACE 1
|
||||
|
||||
////////////////////////////////
|
||||
// Third Party
|
||||
|
||||
#include "third_party/rad_lzb_simple/rad_lzb_simple.h"
|
||||
#include "third_party/rad_lzb_simple/rad_lzb_simple.c"
|
||||
#define XXH_STATIC_LINKING_ONLY
|
||||
#include "third_party/xxHash/xxhash.c"
|
||||
#include "third_party/xxHash/xxhash.h"
|
||||
#define SINFL_IMPLEMENTATION
|
||||
#include "third_party/sinfl/sinfl.h"
|
||||
#include "third_party/radsort/radsort.h"
|
||||
|
||||
////////////////////////////////
|
||||
// RDI Format Library
|
||||
|
||||
#include "lib_rdi_format/rdi_format.h"
|
||||
#include "lib_rdi_format/rdi_format.c"
|
||||
|
||||
////////////////////////////////
|
||||
// Headers
|
||||
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "async/async.h"
|
||||
#include "rdi_make/rdi_make_local.h"
|
||||
#include "linker/hash_table.h"
|
||||
#include "coff/coff.h"
|
||||
#include "coff/coff_parse.h"
|
||||
#include "pe/pe.h"
|
||||
#include "elf/elf.h"
|
||||
#include "elf/elf_parse.h"
|
||||
#include "codeview/codeview.h"
|
||||
#include "codeview/codeview_parse.h"
|
||||
#include "dwarf/dwarf.h"
|
||||
#include "dwarf/dwarf_parse.h"
|
||||
#include "dwarf/dwarf_coff.h"
|
||||
#include "dwarf/dwarf_elf.h"
|
||||
#include "msf/msf.h"
|
||||
#include "msf/msf_parse.h"
|
||||
#include "pdb/pdb.h"
|
||||
#include "pdb/pdb_parse.h"
|
||||
#include "pdb/pdb_stringize.h"
|
||||
#include "radcon.h"
|
||||
#include "radcon_coff.h"
|
||||
#include "radcon_elf.h"
|
||||
#include "radcon_cv.h"
|
||||
#include "radcon_dwarf.h"
|
||||
#include "radcon_pdb.h"
|
||||
|
||||
////////////////////////////////
|
||||
// Implementations
|
||||
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "async/async.c"
|
||||
#include "rdi_make/rdi_make_local.c"
|
||||
#include "linker/hash_table.c"
|
||||
#include "coff/coff.c"
|
||||
#include "coff/coff_parse.c"
|
||||
#include "pe/pe.c"
|
||||
#include "elf/elf.c"
|
||||
#include "elf/elf_parse.c"
|
||||
#include "codeview/codeview.c"
|
||||
#include "codeview/codeview_parse.c"
|
||||
#include "msf/msf.c"
|
||||
#include "msf/msf_parse.c"
|
||||
#include "pdb/pdb.c"
|
||||
#include "pdb/pdb_parse.c"
|
||||
#include "pdb/pdb_stringize.c"
|
||||
#include "dwarf/dwarf.c"
|
||||
#include "dwarf/dwarf_parse.c"
|
||||
#include "dwarf/dwarf_coff.c"
|
||||
#include "dwarf/dwarf_elf.c"
|
||||
#include "radcon.c"
|
||||
#include "radcon_coff.c"
|
||||
#include "radcon_elf.c"
|
||||
#include "radcon_cv.c"
|
||||
#include "radcon_dwarf.c"
|
||||
#include "radcon_pdb.c"
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
entry_point(CmdLine *cmdl)
|
||||
{
|
||||
rc_main(cmdl);
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ rd_format_preamble(Arena *arena, String8List *out, String8 indent, String8 input
|
||||
|
||||
DateTime universal_dt = os_now_universal_time();
|
||||
DateTime local_dt = os_local_time_from_universal(&universal_dt);
|
||||
String8 time = push_date_time_string(scratch.arena, &local_dt);
|
||||
String8 time = string_from_date_time(scratch.arena, &local_dt);
|
||||
String8 full_path = os_full_path_from_path(scratch.arena, input_path);
|
||||
rd_printf("# %S, [%S] %S", time, input_type_string, full_path);
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ entry_point(CmdLine *cmdl)
|
||||
// print run info
|
||||
DateTime now_time_universal = os_now_universal_time();
|
||||
DateTime now_time_local = os_local_time_from_universal_time(&now_time_universal);
|
||||
String8 now_time_str = push_date_time_string(arena, &now_time_local);
|
||||
String8 now_time_str = string_from_date_time(arena, &now_time_local);
|
||||
fprintf(stdout, "Time: %.*s\n", str8_varg(now_time_str));
|
||||
fprintf(stdout, "File: %.*s\n", str8_varg(pdb_name));
|
||||
fprintf(stdout, "Size: %llu (bytes)\n", pdb_data.size);
|
||||
|
||||
Reference in New Issue
Block a user