mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-09-24 02:00:05 +00:00
WIP DWARF writer
This commit is contained in:
@@ -64,6 +64,378 @@ T_BeginTest(test_leb128)
|
||||
}
|
||||
T_EndTest;
|
||||
|
||||
internal B32
|
||||
dwt_tags_must_match(DW_WriterTag *writer_tag, DW_TagNode *reader_tag)
|
||||
{
|
||||
B32 is_match = 0;
|
||||
|
||||
// match headers
|
||||
B32 writer_has_children = writer_tag->first_child != 0;
|
||||
if (writer_tag->kind != reader_tag->tag.kind) { goto exit; }
|
||||
if (writer_tag->abbrev_id != reader_tag->tag.abbrev_id) { goto exit; }
|
||||
if (writer_tag->attrib_count != reader_tag->tag.attribs.count) { goto exit; }
|
||||
if (writer_tag->info_off != reader_tag->tag.info_off) { goto exit; }
|
||||
if (writer_has_children != reader_tag->tag.has_children) { goto exit; }
|
||||
|
||||
// match attribs
|
||||
DW_WriterAttrib *writer_attrib = writer_tag->first_attrib;
|
||||
DW_AttribNode *reader_attrib = reader_tag->tag.attribs.first;
|
||||
while (writer_attrib) {
|
||||
if (writer_attrib->kind != reader_attrib->v.attrib_kind) { goto exit; }
|
||||
if (writer_attrib->reader.form.kind != reader_attrib->v.form.kind) { goto exit; }
|
||||
if ( ! dw_form_match(writer_attrib->reader.form, reader_attrib->v.form)) { goto exit; }
|
||||
writer_attrib = writer_attrib->next;
|
||||
reader_attrib = reader_attrib->next;
|
||||
}
|
||||
|
||||
// visit children
|
||||
DW_WriterTag *writer_child = writer_tag->first_child;
|
||||
DW_TagNode *reader_child = reader_tag->first_child;
|
||||
while (writer_child) {
|
||||
if ( ! dwt_tags_must_match(writer_child, reader_child)) { goto exit; }
|
||||
writer_child = writer_child->next;
|
||||
reader_child = reader_child->sibling;
|
||||
}
|
||||
|
||||
is_match = 1;
|
||||
exit:;
|
||||
return is_match;
|
||||
}
|
||||
|
||||
internal DW_Writer *
|
||||
dwt_make_writer(void)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
// define debug info layout
|
||||
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_Last, DW_CompUnitKind_Compile, Arch_x64);
|
||||
{
|
||||
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
|
||||
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit(BUILD_TITLE_STRING_LITERAL));
|
||||
dw_writer_push_attrib_enum(writer, DW_AttribKind_Language, DW_Language_C99);
|
||||
dw_writer_push_attrib_flag(writer, DW_AttribKind_UseUtf8, 1);
|
||||
{
|
||||
DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
|
||||
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1);
|
||||
dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar);
|
||||
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("char"));
|
||||
dw_writer_tag_end(writer);
|
||||
|
||||
dw_writer_tag_begin(writer, DW_TagKind_ConstType);
|
||||
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type);
|
||||
dw_writer_tag_end(writer);
|
||||
|
||||
// test abbrev dedup
|
||||
DW_WriterTag *dup_char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
|
||||
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1);
|
||||
dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar);
|
||||
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("char"));
|
||||
dw_writer_tag_end(writer);
|
||||
|
||||
// simple struct test
|
||||
DW_WriterTag *simple_struct_tag = dw_writer_tag_begin(writer, DW_TagKind_StructureType);
|
||||
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("FooBar"));
|
||||
dw_writer_push_attrib_uint(writer, DW_AttribKind_ByteSize, 90);
|
||||
{
|
||||
dw_writer_tag_begin(writer, DW_TagKind_Member);
|
||||
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("m0"));
|
||||
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type);
|
||||
dw_writer_push_attrib_sint(writer, DW_AttribKind_DataMemberLocation, 0);
|
||||
dw_writer_tag_end(writer);
|
||||
|
||||
dw_writer_tag_begin(writer, DW_TagKind_Member);
|
||||
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("m1"));
|
||||
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type);
|
||||
dw_writer_push_attrib_sint(writer, DW_AttribKind_DataMemberLocation, 10);
|
||||
dw_writer_push_attrib_implicit(writer, DW_AttribKind_ByteSize, 123);
|
||||
dw_writer_tag_end(writer);
|
||||
}
|
||||
dw_writer_tag_end(writer);
|
||||
|
||||
dw_writer_tag_begin(writer, DW_TagKind_SubProgram);
|
||||
dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1);
|
||||
dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1);
|
||||
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x14012f2f0);
|
||||
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x14012f405);
|
||||
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("main"));
|
||||
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, simple_struct_tag);
|
||||
dw_writer_push_attrib_expression(writer, DW_AttribKind_FrameBase, &(DW_ExprEnc)DW_ExprEnc_Op(Reg7), 1);
|
||||
dw_writer_tag_end(writer);
|
||||
}
|
||||
dw_writer_tag_end(writer);
|
||||
}
|
||||
|
||||
{
|
||||
DW_Input input;
|
||||
{
|
||||
OBJ *obj = obj_alloc(0, Arch_x64);
|
||||
OBJ_Section *text_section = obj_push_section(obj, str8_lit(".text"), OBJ_SectionFlag_Read|OBJ_SectionFlag_Exec|OBJ_SectionFlag_Load);
|
||||
str8_serial_push_u8(obj->arena, &text_section->data, 0xc3);
|
||||
obj_push_symbol(obj, str8_lit("entry"), OBJ_SymbolScope_Global, OBJ_RefKind_Section, text_section);
|
||||
|
||||
dw_writer_emit_to_obj(writer, obj);
|
||||
|
||||
String8 raw_coff = coff_from_obj(scratch.arena, obj);
|
||||
COFF_FileHeaderInfo obj_coff_header = coff_file_header_info_from_data(raw_coff);
|
||||
String8 raw_sections = str8_substr(raw_coff, obj_coff_header.section_table_range);
|
||||
U64 section_count = raw_sections.size / sizeof(COFF_SectionHeader);
|
||||
COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_sections.str;
|
||||
String8 string_table = str8_substr(raw_coff, obj_coff_header.string_table_range);
|
||||
input = dw_input_from_coff_section_table(scratch.arena, raw_coff, string_table, section_count, section_table);
|
||||
|
||||
t_write_file(str8_lit("dwarf.obj"), raw_coff);
|
||||
|
||||
obj_release(&obj);
|
||||
}
|
||||
|
||||
DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &input);
|
||||
DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, lu_input, 0, 1);
|
||||
DW_TagTree tag_tree = dw_tag_tree_from_cu(scratch.arena, &input, &cu);
|
||||
AssertAlways(dwt_tags_must_match(writer->root, tag_tree.root));
|
||||
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return writer;
|
||||
}
|
||||
|
||||
T_BeginTest(dwarf_writer)
|
||||
{
|
||||
DW_Writer *writer = dwt_make_writer();
|
||||
|
||||
// validate the writer
|
||||
|
||||
T_Ok(writer->current == 0);
|
||||
T_Ok(writer->format == DW_Format_32Bit);
|
||||
T_Ok(writer->cu_kind == DW_CompUnitKind_Compile);
|
||||
T_Ok(writer->version == DW_Version_5);
|
||||
T_Ok(writer->address_size == 8);
|
||||
T_Ok(writer->abbrev_base_info_off == 8);
|
||||
T_Ok(writer->fixups.count == 0);
|
||||
T_Ok(writer->abbrev_id_map->count == 7);
|
||||
|
||||
DW_WriterTag *comp_unit_tag = writer->root;
|
||||
{
|
||||
T_Ok(comp_unit_tag->kind == DW_TagKind_CompileUnit);
|
||||
T_Ok(comp_unit_tag->next == 0);
|
||||
T_Ok(comp_unit_tag->parent == 0);
|
||||
T_Ok(comp_unit_tag->attrib_count == 3);
|
||||
T_Ok(comp_unit_tag->abbrev_id == 1);
|
||||
T_Ok(comp_unit_tag->info_off == 0xc);
|
||||
|
||||
DW_WriterAttrib *producer_attrib = comp_unit_tag->first_attrib;
|
||||
T_Ok(producer_attrib->kind == DW_AttribKind_Producer);
|
||||
T_Ok(producer_attrib->reader.form.kind == DW_Form_String);
|
||||
T_Ok(str8_match(producer_attrib->writer.form.string, str8_lit(BUILD_TITLE_STRING_LITERAL), 0));
|
||||
|
||||
DW_WriterAttrib *language_attrib = producer_attrib->next;
|
||||
T_Ok(language_attrib->kind == DW_AttribKind_Language);
|
||||
T_Ok(language_attrib->reader.form.kind == DW_Form_Data1);
|
||||
T_Ok(language_attrib->reader.form.data.size == 1);
|
||||
T_Ok(*(U8 *)language_attrib->reader.form.data.str == DW_Language_C99);
|
||||
|
||||
DW_WriterAttrib *use_utf8_attrib = language_attrib->next;
|
||||
T_Ok(use_utf8_attrib->kind == DW_AttribKind_UseUtf8);
|
||||
T_Ok(use_utf8_attrib->reader.form.kind == DW_Form_Flag);
|
||||
T_Ok(use_utf8_attrib->reader.form.flag == 1);
|
||||
}
|
||||
|
||||
DW_WriterTag *char_type_tag = comp_unit_tag->first_child;
|
||||
{
|
||||
T_Ok(char_type_tag->kind == DW_TagKind_BaseType);
|
||||
T_Ok(char_type_tag->next != 0);
|
||||
T_Ok(char_type_tag->parent == comp_unit_tag);
|
||||
T_Ok(char_type_tag->attrib_count == 3);
|
||||
T_Ok(char_type_tag->abbrev_id == 2);
|
||||
T_Ok(char_type_tag->info_off == 0x4d);
|
||||
T_Ok(char_type_tag->first_attrib != char_type_tag->last_attrib);
|
||||
|
||||
DW_WriterAttrib *byte_size_attrib = char_type_tag->first_attrib;
|
||||
T_Ok(byte_size_attrib->kind == DW_AttribKind_ByteSize);
|
||||
T_Ok(byte_size_attrib->reader.form.kind == DW_Form_Data1);
|
||||
T_Ok(byte_size_attrib->reader.form.data.size == 1);
|
||||
T_Ok(*(U8 *)byte_size_attrib->reader.form.data.str == 1);
|
||||
|
||||
DW_WriterAttrib *encoding_attrib = byte_size_attrib->next;
|
||||
T_Ok(encoding_attrib->kind == DW_AttribKind_Encoding);
|
||||
T_Ok(encoding_attrib->reader.form.kind == DW_Form_Data1);
|
||||
T_Ok(encoding_attrib->reader.form.data.size == 1);
|
||||
T_Ok(*(U8 *)encoding_attrib->reader.form.data.str == DW_ATE_SignedChar);
|
||||
|
||||
DW_WriterAttrib *name_attrib = encoding_attrib->next;
|
||||
T_Ok(name_attrib->kind == DW_AttribKind_Name);
|
||||
T_Ok(name_attrib->reader.form.kind == DW_Form_String);
|
||||
T_Ok(str8_match(name_attrib->reader.form.string, str8_lit("char"), 0));
|
||||
}
|
||||
|
||||
DW_WriterTag *const_type_tag = char_type_tag->next;
|
||||
{
|
||||
T_Ok(const_type_tag->kind == DW_TagKind_ConstType);
|
||||
T_Ok(const_type_tag->next != 0);
|
||||
T_Ok(const_type_tag->parent == comp_unit_tag);
|
||||
T_Ok(const_type_tag->attrib_count == 1);
|
||||
T_Ok(const_type_tag->abbrev_id == 3);
|
||||
T_Ok(const_type_tag->info_off == 0x55);
|
||||
T_Ok(const_type_tag->first_attrib && const_type_tag->first_attrib == const_type_tag->last_attrib);
|
||||
|
||||
DW_WriterAttrib *type_attrib = const_type_tag->first_attrib;
|
||||
T_Ok(type_attrib->kind == DW_AttribKind_Type);
|
||||
T_Ok(type_attrib->writer.form.kind == DW_WriterFormKind_Ref);
|
||||
T_Ok(type_attrib->writer.form.ref == char_type_tag);
|
||||
}
|
||||
|
||||
DW_WriterTag *dup_char_type_tag = const_type_tag->next;
|
||||
{
|
||||
T_Ok(dup_char_type_tag->kind == DW_TagKind_BaseType);
|
||||
T_Ok(dup_char_type_tag->next != 0);
|
||||
T_Ok(dup_char_type_tag->parent == comp_unit_tag);
|
||||
T_Ok(dup_char_type_tag->attrib_count == 3);
|
||||
T_Ok(dup_char_type_tag->abbrev_id == 2);
|
||||
T_Ok(dup_char_type_tag->info_off == 0x57);
|
||||
T_Ok(dup_char_type_tag->first_attrib != dup_char_type_tag->last_attrib);
|
||||
|
||||
DW_WriterAttrib *byte_size_attrib = dup_char_type_tag->first_attrib;
|
||||
T_Ok(byte_size_attrib->kind == DW_AttribKind_ByteSize);
|
||||
T_Ok(byte_size_attrib->reader.form.kind == DW_Form_Data1);
|
||||
T_Ok(byte_size_attrib->reader.form.data.size == 1);
|
||||
T_Ok(*(U8 *)byte_size_attrib->reader.form.data.str == 1);
|
||||
|
||||
DW_WriterAttrib *encoding_attrib = byte_size_attrib->next;
|
||||
T_Ok(encoding_attrib->kind == DW_AttribKind_Encoding);
|
||||
T_Ok(encoding_attrib->reader.form.kind == DW_Form_Data1);
|
||||
T_Ok(encoding_attrib->reader.form.data.size == 1);
|
||||
T_Ok(*(U8 *)encoding_attrib->reader.form.data.str == DW_ATE_SignedChar);
|
||||
|
||||
DW_WriterAttrib *name_attrib = encoding_attrib->next;
|
||||
T_Ok(name_attrib->kind == DW_AttribKind_Name);
|
||||
T_Ok(name_attrib->reader.form.kind == DW_Form_String);
|
||||
T_Ok(str8_match(name_attrib->reader.form.string, str8_lit("char"), 0));
|
||||
}
|
||||
|
||||
DW_WriterTag *simple_struct_tag = dup_char_type_tag->next;
|
||||
{
|
||||
T_Ok(simple_struct_tag->kind == DW_TagKind_StructureType);
|
||||
T_Ok(simple_struct_tag->next != 0);
|
||||
T_Ok(simple_struct_tag->parent == comp_unit_tag);
|
||||
T_Ok(simple_struct_tag->attrib_count == 2);
|
||||
T_Ok(simple_struct_tag->abbrev_id == 4);
|
||||
T_Ok(simple_struct_tag->info_off == 0x5f);
|
||||
|
||||
DW_WriterAttrib *simple_struct_name = simple_struct_tag->first_attrib;
|
||||
T_Ok(simple_struct_name->kind == DW_AttribKind_Name);
|
||||
T_Ok(simple_struct_name->reader.form.kind == DW_Form_String);
|
||||
T_Ok(str8_match(simple_struct_name->reader.form.string, str8_lit("FooBar"), 0));
|
||||
|
||||
DW_WriterTag *m0_tag = simple_struct_tag->first_child;
|
||||
{
|
||||
T_Ok(m0_tag->kind == DW_TagKind_Member);
|
||||
T_Ok(m0_tag->parent == simple_struct_tag);
|
||||
T_Ok(m0_tag->attrib_count == 3);
|
||||
T_Ok(m0_tag->info_off == 0x68);
|
||||
T_Ok(m0_tag->abbrev_id == 5);
|
||||
|
||||
DW_WriterAttrib *name = m0_tag->first_attrib;
|
||||
T_Ok(name->kind == DW_AttribKind_Name);
|
||||
T_Ok(name->reader.form.kind == DW_Form_String);
|
||||
T_Ok(str8_match(name->reader.form.string, str8_lit("m0"), 0));
|
||||
|
||||
DW_WriterAttrib *type = name->next;
|
||||
T_Ok(type->kind == DW_AttribKind_Type);
|
||||
T_Ok(type->reader.form.kind == DW_Form_Ref1);
|
||||
T_Ok(type->reader.form.ref == 0x4d);
|
||||
|
||||
DW_WriterAttrib *data_loc = type->next;
|
||||
T_Ok(data_loc->kind == DW_AttribKind_DataMemberLocation);
|
||||
T_Ok(data_loc->reader.form.kind == DW_Form_Data1);
|
||||
T_Ok(data_loc->reader.form.data.size == 1);
|
||||
T_Ok(*(U8 *)data_loc->reader.form.data.str == 0);
|
||||
}
|
||||
|
||||
DW_WriterTag *m1_tag = m0_tag->next;
|
||||
{
|
||||
T_Ok(m1_tag->kind == DW_TagKind_Member);
|
||||
T_Ok(m1_tag->parent == simple_struct_tag);
|
||||
T_Ok(m1_tag->attrib_count == 4);
|
||||
T_Ok(m1_tag->info_off == 0x6e);
|
||||
T_Ok(m1_tag->abbrev_id == 6);
|
||||
|
||||
DW_WriterAttrib *name = m1_tag->first_attrib;
|
||||
T_Ok(name->kind == DW_AttribKind_Name);
|
||||
T_Ok(name->reader.form.kind == DW_Form_String);
|
||||
T_Ok(str8_match(name->reader.form.string, str8_lit("m1"), 0));
|
||||
|
||||
DW_WriterAttrib *type = name->next;
|
||||
T_Ok(type->kind == DW_AttribKind_Type);
|
||||
T_Ok(type->reader.form.kind == DW_Form_Ref1);
|
||||
T_Ok(type->reader.form.ref == 0x4d);
|
||||
|
||||
DW_WriterAttrib *data_loc = type->next;
|
||||
T_Ok(data_loc->kind == DW_AttribKind_DataMemberLocation);
|
||||
T_Ok(data_loc->reader.form.kind == DW_Form_Data1);
|
||||
T_Ok(data_loc->reader.form.data.size == 1);
|
||||
T_Ok(*(U8 *)data_loc->reader.form.data.str == 10);
|
||||
|
||||
DW_WriterAttrib *byte_size = data_loc->next;
|
||||
T_Ok(byte_size->kind == DW_AttribKind_ByteSize);
|
||||
T_Ok(byte_size->reader.form.kind == DW_Form_ImplicitConst);
|
||||
T_Ok(byte_size->reader.form.implicit_const == 123);
|
||||
}
|
||||
}
|
||||
|
||||
DW_WriterTag *main_tag = simple_struct_tag->next;
|
||||
T_Ok(main_tag->next == 0);
|
||||
T_Ok(main_tag->kind == DW_TagKind_SubProgram);
|
||||
T_Ok(main_tag->parent == main_tag->parent);
|
||||
T_Ok(main_tag->abbrev_id == 7);
|
||||
{
|
||||
DW_WriterAttrib *external = main_tag->first_attrib;
|
||||
T_Ok(external->kind == DW_AttribKind_External);
|
||||
T_Ok(external->reader.form.kind == DW_Form_Flag);
|
||||
T_Ok(external->reader.form.flag);
|
||||
|
||||
DW_WriterAttrib *prototyped = external->next;
|
||||
T_Ok(prototyped->kind == DW_AttribKind_Prototyped);
|
||||
T_Ok(prototyped->reader.form.kind == DW_Form_Flag);
|
||||
T_Ok(prototyped->reader.form.flag);
|
||||
|
||||
DW_WriterAttrib *low_pc = prototyped->next;
|
||||
T_Ok(low_pc->kind == DW_AttribKind_LowPc);
|
||||
T_Ok(low_pc->reader.form.kind == DW_Form_Addr);
|
||||
T_Ok(low_pc->reader.form.addr.size == sizeof(U64));
|
||||
T_Ok(*(U64 *)low_pc->reader.form.addr.str == 0x14012f2f0);
|
||||
|
||||
DW_WriterAttrib *high_pc = low_pc->next;
|
||||
T_Ok(high_pc->kind == DW_AttribKind_HighPc);
|
||||
T_Ok(high_pc->reader.form.kind == DW_Form_Addr);
|
||||
T_Ok(high_pc->reader.form.addr.size == sizeof(U64));
|
||||
T_Ok(*(U64 *)high_pc->reader.form.addr.str == 0x14012f405);
|
||||
|
||||
DW_WriterAttrib *name = high_pc->next;
|
||||
T_Ok(name->kind == DW_AttribKind_Name);
|
||||
T_Ok(name->reader.form.kind == DW_Form_String);
|
||||
T_Ok(str8_match(name->reader.form.string, str8_lit("main"), 0));
|
||||
|
||||
DW_WriterAttrib *type = name->next;
|
||||
T_Ok(type->kind == DW_AttribKind_Type);
|
||||
T_Ok(type->reader.form.kind == DW_Form_Ref1);
|
||||
T_Ok(type->reader.form.ref == simple_struct_tag->info_off);
|
||||
|
||||
DW_WriterAttrib *frame_base = type->next;
|
||||
T_Ok(frame_base->kind == DW_AttribKind_FrameBase);
|
||||
T_Ok(frame_base->reader.form.kind == DW_Form_ExprLoc);
|
||||
DW_Expr frame_base_expr = dw_expr_from_data(scratch.arena, writer->format, writer->address_size, frame_base->reader.form.exprloc);
|
||||
T_Ok(frame_base_expr.count == 1);
|
||||
T_Ok(frame_base_expr.first->opcode == DW_ExprOp_Reg7);
|
||||
T_Ok(frame_base_expr.first->operands == 0);
|
||||
T_Ok(frame_base_expr.first->size == 1);
|
||||
T_Ok(frame_base_expr.first->next == 0);
|
||||
T_Ok(frame_base_expr.first->prev == 0);
|
||||
}
|
||||
|
||||
dw_writer_end(&writer);
|
||||
}
|
||||
T_EndTest;
|
||||
|
||||
T_BeginTest(value_in_register)
|
||||
{
|
||||
// setup register context
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "obj/obj.h"
|
||||
#include "linker/base_ext/base_core.h"
|
||||
#include "linker/base_ext/base_arena.h"
|
||||
#include "linker/base_ext/base_arrays.h"
|
||||
@@ -34,6 +35,7 @@
|
||||
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "obj/obj.c"
|
||||
#include "linker/hash_table.c"
|
||||
#include "linker/base_ext/base_core.c"
|
||||
#include "linker/base_ext/base_arena.c"
|
||||
|
||||
Reference in New Issue
Block a user