From 2e8e8e17abebc5d10241abac0b7b9ecd41c11a57 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Fri, 19 Jul 2024 07:04:50 +0200 Subject: Use i64 for all offsets and indices; Use buffers from the pool; Cleanup --- bxgen.c | 218 ++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 123 insertions(+), 95 deletions(-) (limited to 'bxgen.c') diff --git a/bxgen.c b/bxgen.c index 5390a6b..8ee878f 100755 --- a/bxgen.c +++ b/bxgen.c @@ -177,10 +177,13 @@ enum { UNIT_LIBRARY_STATIC, UNIT_LIBRARY_DYNAMIC, - // String tables + // Buffers // - STRING_TABLE_ALIGNMENT = 16, // TODO + MAX_OBJECT_FILE_SIZE = 10 * 1024 * 1024, + MAX_NUM_OBJECT_FILES = 10 * 1024, + MAX_DEPENDENCIES_SIZE = 300 * 1024 * 1024, + STRING_TABLE_ALIGNMENT = 16, // TODO // Entity types // @@ -340,9 +343,20 @@ typedef struct { // We use one single large memory block for *everything*. typedef struct { + // Semantic graph entities i64 num_entities; i64 capacity; Entity *entities; + + // Linker buffers + // TODO Use string table for buffers also. + + i64 max_obj_file_size; + u8 * obj_file_buffer; + i64 max_dependencies_size; + u8 * dependencies_buffer; + i64 max_num_obj_files; + i64 *obj_file_offsets; } Pool; // ================================================================ @@ -536,7 +550,7 @@ c8 *bx_find_char(c8 *s, c8 *s_end, c8 c) { return *s == c ? s : NULL; } -u64 bx_u64_from_str(c8 *s, c8 *s_end) { +i64 bx_i64_from_str(c8 *s, c8 *s_end) { BX_CHECK(s != NULL && s_end != NULL, "Invalid arguments", 0); BX_CHECK(s < s_end, "Buffer overflow", 0); BX_CHECK(*s >= '0' && *s <= '9', "Parsing failed", 0); @@ -1385,8 +1399,8 @@ c8 SECTION_STRTAB[] = ".strtab"; c8 SECTION_SHSTRTAB[] = ".shstrtab"; typedef struct { - u64 offset; - u64 size; + i64 offset; + i64 size; } Offset_Size; typedef struct { @@ -1396,8 +1410,8 @@ typedef struct { } Buffer_Context; typedef struct { - u64 offset; - u16 num; + i64 offset; + i64 num; } Offset_Num; typedef struct { @@ -1406,9 +1420,9 @@ typedef struct { b8 alloc; b8 write; b8 exec; - u64 alignment; - u64 entry_size; - u32 num_entries; + i64 alignment; + i64 entry_size; + i64 num_entries; Offset_Size data; } Section_Header; @@ -1421,35 +1435,41 @@ typedef struct { typedef struct { Symbol_Entry symbol; - u64 dst; + i64 dst; u32 type; } Rel_Entry; typedef struct { Symbol_Entry symbol; - u64 dst; + i64 dst; u32 type; i64 addent; } Rela_Entry; // ================================================================ -u32 ar_find_symbol_offset_by_name(u8 *ar_symbol_table, u8 *ar_end, c8 *name, c8 *name_end) { +i64 ar_find_symbol_offset_by_name( + u8 *ar_symbol_table, + u8 *ar_end, + c8 *name, + c8 *name_end +) { BX_CHECK(ar_symbol_table != NULL, "Invalid arguments", -1); BX_CHECK(name != NULL, "Invalid arguments", -1); BX_CHECK(name_end > name, "Invalid arguments", -1); - u32 num = read_u32((LE & ~BYTE_ORDER_MASK) | BYTE_BE, ar_symbol_table, ar_end); - + i64 num = (i64) read_u32((LE & ~BYTE_ORDER_MASK) | BYTE_BE, ar_symbol_table, ar_end); i64 len = name_end - name; c8 *s = (c8 *) (ar_symbol_table + 4 * (num + 1)); - u32 index = 0; + i64 index = 0; for (; index < num; ++index) { BX_CHECK(s + len <= (c8 *) ar_end, "Buffer overflow", -1); + if (s[len] == '\0' && bx_mem_eq(s, name, len)) - return read_u32((LE & ~BYTE_ORDER_MASK) | BYTE_BE, ar_symbol_table + 4 * (index + 1), ar_end); + return (i64) read_u32((LE & ~BYTE_ORDER_MASK) | BYTE_BE, ar_symbol_table + 4 * (index + 1), ar_end); + while (*s != '\0' && s < (c8 *) ar_end) ++s; BX_CHECK(s < (c8 *) ar_end, "Buffer overflow", -1); @@ -1469,14 +1489,14 @@ Offset_Num elf_section_headers( BX_CHECK(end <= b.end, "Buffer overflow", (Offset_Num) {0}); return (Offset_Num) { - .offset = b.elf.offset + read_u64(LE, begin + 40, end), - .num = read_u16(LE, begin + 60, end), + .offset = b.elf.offset + read_i64(LE, begin + 40, end), + .num = (i64) read_u16(LE, begin + 60, end), }; } -u64 elf_section_header_offset( +i64 elf_section_header_offset( Buffer_Context b, - u16 index + i64 index ) { return elf_section_headers(b).offset + ELF_SECTION_HEADER_SIZE * index; } @@ -1486,22 +1506,23 @@ Offset_Size elf_section_names_data( ) { u8 *elf_begin = b.begin + b.elf.offset; u8 *elf_end = elf_begin + b.elf.size; + BX_CHECK(elf_end <= b.end, "Buffer overflow", (Offset_Size) {0}); - u16 string_table_index = read_u16(LE, elf_begin + 62, elf_end); + i64 string_table_index = (i64) read_u16(LE, elf_begin + 62, elf_end); u8 *begin = b.begin + elf_section_header_offset(b, string_table_index); return (Offset_Size) { - .offset = b.elf.offset + read_u64(LE, begin + 24, elf_end), - .size = read_u64(LE, begin + 32, elf_end), + .offset = b.elf.offset + read_i64(LE, begin + 24, elf_end), + .size = read_i64(LE, begin + 32, elf_end), }; } Offset_Size elf_name_in_string_table( Buffer_Context b, Offset_Size string_table, - u32 name_offset + i64 name_offset ) { if (name_offset == 0) return (Offset_Size) { @@ -1518,10 +1539,10 @@ Offset_Size elf_name_in_string_table( }; } -u16 elf_find_section_index_by_name( +i64 elf_find_section_index_by_name( Buffer_Context b, c8 * name, - u32 name_size + i64 name_size ) { BX_CHECK(name != NULL, "Invalid arguments", 0); @@ -1531,9 +1552,9 @@ u16 elf_find_section_index_by_name( Offset_Num headers = elf_section_headers(b); Offset_Size names = elf_section_names_data(b); - for (u16 i = 0; i < headers.num; ++i) { + for (i64 i = 0; i < headers.num; ++i) { u8 *begin = b.begin + headers.offset + i * ELF_SECTION_HEADER_SIZE; - u32 name_index = read_u32(LE, begin, b.end); + i64 name_index = (i64) read_u32(LE, begin, b.end); Offset_Size s = elf_name_in_string_table(b, names, name_index); if (s.size == name_size && @@ -1546,17 +1567,17 @@ u16 elf_find_section_index_by_name( Section_Header elf_section( Buffer_Context b, - u16 index + i64 index ) { Offset_Size names = elf_section_names_data(b); u8 * begin = b.begin + elf_section_header_offset(b, index); u8 * end = b.begin + b.elf.offset + b.elf.size; BX_CHECK(end <= b.end, "Buffer overflow", (Section_Header) {0}); - u32 name_index = read_u32(LE, begin, end); - u64 size = read_u64(LE, begin + 32, end); - u64 entry_size = read_u64(LE, begin + 56, end); - u32 num_entries = entry_size > 0 ? (size / entry_size) : 0; + i64 name_index = (i64) read_u32(LE, begin, end); + i64 size = read_i64(LE, begin + 32, end); + i64 entry_size = read_i64(LE, begin + 56, end); + i64 num_entries = entry_size > 0 ? (size / entry_size) : 0; u32 type = read_u32(LE, begin + 4, end); u64 flags = read_u64(LE, begin + 8, end); @@ -1576,11 +1597,11 @@ Section_Header elf_section( .alloc = (flags & 2) == 2, .write = (flags & 1) == 1, .exec = (flags & 4) == 4, - .alignment = read_u64(LE, begin + 48, end), + .alignment = read_i64(LE, begin + 48, end), .entry_size = entry_size, .num_entries = num_entries, .data = { - .offset = b.elf.offset + read_u64(LE, begin + 24, end), + .offset = b.elf.offset + read_i64(LE, begin + 24, end), .size = size, }, }; @@ -1589,7 +1610,7 @@ Section_Header elf_section( Section_Header elf_find_section_by_name( Buffer_Context b, c8 * name, - u32 name_size + i64 name_size ) { return elf_section(b, elf_find_section_index_by_name(b, name, name_size)); } @@ -1610,7 +1631,7 @@ c8 *elf_name_from_offset( Offset_Size elf_find_related_data( Buffer_Context b, - u16 section_index + i64 section_index ) { Offset_Size src_name = elf_section(b, section_index).name; Section_Header dst = elf_section(b, section_index - 1); @@ -1622,9 +1643,9 @@ Offset_Size elf_find_related_data( dst.name.size)) return dst.data; - u64 num_sections = elf_section_headers(b).num; + i64 num_sections = elf_section_headers(b).num; - for (u16 i = 0; i < num_sections; ++i) { + for (i64 i = 0; i < num_sections; ++i) { if (i == section_index || i + 1 == section_index) continue; dst = elf_section(b, i); @@ -1645,7 +1666,7 @@ Symbol_Entry elf_symbol( Buffer_Context b, Offset_Size symbol_table, Offset_Size string_table, - u16 symbol_index + i64 symbol_index ) { u8 *begin = b.begin + symbol_table.offset + symbol_index * ELF_SYMBOL_ENTRY_SIZE; u8 *end = b.begin + symbol_table.offset + symbol_table.size; @@ -1653,11 +1674,11 @@ Symbol_Entry elf_symbol( BX_CHECK(end <= b.end, "Buffer overflow", (Symbol_Entry) {0}); BX_CHECK(end <= b.begin + b.elf.offset + b.elf.size, "Buffer overflow", (Symbol_Entry) {0}); - u32 sym_name = read_u32(LE, begin, end); + i64 sym_name = (i64) read_u32(LE, begin, end); u8 sym_info = read_u8 (LE, begin + 4, end); - u16 sym_shndx = read_u16(LE, begin + 6, end); - u64 sym_value = read_u64(LE, begin + 8, end); - u64 sym_size = read_u64(LE, begin + 16, end); + i64 sym_shndx = (i64) read_u16(LE, begin + 6, end); + i64 sym_value = read_i64(LE, begin + 8, end); + i64 sym_size = read_i64(LE, begin + 16, end); Offset_Size dst = sym_shndx < elf_section_headers(b).num ? elf_section(b, sym_shndx).data @@ -1696,7 +1717,7 @@ Rel_Entry elf_rel( Offset_Size string_table, Offset_Size relocations, Offset_Size dst, - u16 rel_index + i64 rel_index ) { u8 *begin = b.begin + relocations.offset + rel_index * ELF_REL_ENTRY_SIZE; u8 *end = begin + ELF_REL_ENTRY_SIZE; @@ -1705,9 +1726,9 @@ Rel_Entry elf_rel( BX_CHECK(end <= b.begin + b.elf.offset + b.elf.size, "Buffer overflow", (Rel_Entry) {0}); BX_CHECK(end <= b.begin + relocations.offset + relocations.size, "Buffer overflow", (Rel_Entry) {0}); - u64 rel_offset = read_u64(LE, begin, end); + i64 rel_offset = read_i64(LE, begin, end); u32 rel_type = read_u32(LE, begin + 8, end); - u32 rel_sym = read_u32(LE, begin + 12, end); + i64 rel_sym = (i64) read_u32(LE, begin + 12, end); BX_CHECK(rel_offset < dst.size, "Buffer overflow", (Rel_Entry) {0}); @@ -1724,7 +1745,7 @@ Rela_Entry elf_rela( Offset_Size string_table, Offset_Size relocations, Offset_Size dst, - u16 rela_index + i64 rela_index ) { u8 *begin = b.begin + relocations.offset + rela_index * ELF_RELA_ENTRY_SIZE; u8 *end = begin + ELF_RELA_ENTRY_SIZE; @@ -1733,9 +1754,9 @@ Rela_Entry elf_rela( BX_CHECK(end <= b.begin + b.elf.offset + b.elf.size, "Buffer overflow", (Rela_Entry) {0}); BX_CHECK(end <= b.begin + relocations.offset + relocations.size, "Buffer overflow", (Rela_Entry) {0}); - u64 rela_offset = read_u64(LE, begin, end); + i64 rela_offset = read_i64(LE, begin, end); u32 rela_type = read_u32(LE, begin + 8, end); - u32 rela_sym = read_u32(LE, begin + 12, end); + i64 rela_sym = (i64) read_u32(LE, begin + 12, end); i64 rela_addent = read_i64(LE, begin + 16, end); BX_CHECK(rela_offset < dst.size, "Buffer overflow", (Rel_Entry) {0}); @@ -1750,14 +1771,14 @@ Rela_Entry elf_rela( Symbol_Entry elf_find_symbol_by_name( Buffer_Context b, - u32 symbol_table_index, + i64 symbol_table_index, Offset_Size string_table, c8 * name, - u32 name_size + i64 name_size ) { Section_Header symbol_table = elf_section(b, symbol_table_index); - for (u32 i = 0; i < symbol_table.num_entries; ++i) { + for (i64 i = 0; i < symbol_table.num_entries; ++i) { Symbol_Entry sym = elf_symbol(b, symbol_table.data, string_table, i); BX_CHECK(b.begin + sym.name.offset + name_size <= b.end, "Buffer overflow", (Symbol_Entry) {0}); @@ -1779,6 +1800,10 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data BX_CHECK(pool->entities[unit].unit.entry_point_index != UNDEFINED, "No entry point",); BX_CHECK(target == (FORMAT_ELF | ARCH_X86_64), "Target not supported",); + BX_CHECK(pool->obj_file_buffer != NULL, "No object file buffer",); + BX_CHECK(pool->dependencies_buffer != NULL, "No dependencies buffer",); + BX_CHECK(pool->obj_file_offsets != NULL, "No object file offsets buffer",); + // ============================================================== #define WRITE(x, n) io_write( io_out, n, x, io_user_data ) @@ -1794,13 +1819,13 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data 0x0f, 0x05, // syscall }; - u64 code_offset = bx_align(ELF_HEADER_SIZE + ELF_PROGRAM_HEADER_SIZE, X86_64_ALIGNMENT); - u64 code_size = bx_align(sizeof code, X86_64_ALIGNMENT); - u64 entry_offset = 0; + i64 code_offset = bx_align(ELF_HEADER_SIZE + ELF_PROGRAM_HEADER_SIZE, X86_64_ALIGNMENT); + i64 code_size = bx_align(sizeof code, X86_64_ALIGNMENT); + i64 entry_offset = 0; - u64 base_address = X86_64_BASE_ADDRESS; - u64 code_address = base_address + code_offset; - u64 entry = code_address + entry_offset; + i64 base_address = X86_64_BASE_ADDRESS; + i64 code_address = base_address + code_offset; + i64 entry = code_address + entry_offset; BX_CHECK((code_offset % X86_64_ALIGNMENT) == 0, "Invalid alignment",); BX_CHECK((code_size % X86_64_ALIGNMENT) == 0, "Invalid alignment",); @@ -1864,16 +1889,12 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data // Intermediate buffer // - u8 static im_buffer[1024 * 1024 * 300]; // 300 MB - i64 static im_offsets[10000]; - i64 im_num = 0; - i64 im_size = 0; + i64 im_num = 0; + i64 im_size = 0; // Read all dependency files into the memory // { - u8 static in_buffer[1024 * 1024 * 100]; // 100 MB - Unit *u = &pool->entities[unit].unit; for (i64 link_index = 0; link_index < u->num_links; ++link_index) { @@ -1889,10 +1910,10 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data io_seek(f, 0, IO_SEEK_END, io_user_data); i64 in_size = io_tell(f, io_user_data); - BX_CHECK(in_size <= (i64) (sizeof in_buffer), "AR file too big",); + BX_CHECK(in_size <= pool->max_obj_file_size, "AR file too big",); io_seek(f, 0, IO_SEEK_BEGIN, io_user_data); - i64 n = io_read(f, in_size, in_buffer, io_user_data); + i64 n = io_read(f, in_size, pool->obj_file_buffer, io_user_data); BX_CHECK(n == in_size, "Read failed",); io_close(f, io_user_data); @@ -1901,8 +1922,8 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data // // Read AR library - u8 *ar_begin = in_buffer; - u8 *ar_end = in_buffer + in_size; + u8 *ar_begin = pool->obj_file_buffer; + u8 *ar_end = pool->obj_file_buffer + in_size; BX_CHECK(bx_mem_eq(ar_begin, AR_MAGIC, 8), "Invalid AR file",); @@ -1914,12 +1935,12 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data u8 *f_end = f_begin + 58; u8 *f_data = f_begin + 60; - u64 size = bx_u64_from_str((c8 *) f_size, (c8 *) f_size + 10); + i64 size = bx_i64_from_str((c8 *) f_size, (c8 *) f_size + 10); size = bx_align(size, 2); BX_CHECK(bx_mem_eq(f_end, "\x60\x0a", 2), "Invalid AR file",); - BX_CHECK(f_begin + size <= ar_end, "Buffer overflow",); + BX_CHECK(f_begin + size <= ar_end, "Buffer overflow",); if (!bx_mem_eq(f_id, AR_SYMBOL_TABLE, 16) && !bx_mem_eq(f_id, AR_STRING_TABLE, 16)) { @@ -1927,14 +1948,14 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data i64 delta_size = bx_align(size, X86_64_ALIGNMENT); - BX_CHECK(im_size + delta_size < (i64) (sizeof im_buffer), "Out of memory",); - BX_CHECK(im_num + 1 < (i64) (sizeof im_offsets / sizeof *im_offsets), "Out of memory",); + BX_CHECK(im_size + delta_size < pool->max_dependencies_size, "Out of memory",); + BX_CHECK(im_num + 1 < pool->max_num_obj_files, "Out of memory",); - bx_mem_cpy(im_buffer + im_size, f_data, size); + bx_mem_cpy(pool->dependencies_buffer + im_size, f_data, size); - im_offsets[im_num] = im_size; + pool->obj_file_offsets[im_num] = im_size; im_size += delta_size; - im_offsets[++im_num] = im_size; + pool->obj_file_offsets[++im_num] = im_size; } f_begin = f_data + size; @@ -1946,8 +1967,8 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data // Process ELF object files for (i64 elf_index = 0; elf_index < im_num; ++elf_index) { - u8 *elf_begin = im_buffer + im_offsets[elf_index]; - u8 *elf_end = im_buffer + im_offsets[elf_index + 1]; + u8 *elf_begin = pool->dependencies_buffer + pool->obj_file_offsets[elf_index]; + u8 *elf_end = pool->dependencies_buffer + pool->obj_file_offsets[elf_index + 1]; u8 osabi = read_u8(LE, elf_begin + 7, elf_end); @@ -1965,20 +1986,20 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data BX_CHECK( read_u16(LE, elf_begin + 18, elf_end) == ELF_X86_64, "Unsupported ELF file",); BX_CHECK( read_u32(LE, elf_begin + 20, elf_end) == ELF_VERSION, "Unsupported ELF file",); - BX_LAX( read_u64(LE, elf_begin + 24, elf_end) == 0, "Invalid ELF file"); // entry - BX_LAX( read_u64(LE, elf_begin + 32, elf_end) == 0, "Invalid ELF file"); // program header offset - BX_LAX( read_u32(LE, elf_begin + 48, elf_end) == 0, "Invalid ELF file"); // flags - BX_LAX( read_u16(LE, elf_begin + 52, elf_end) == ELF_HEADER_SIZE, "Invalid ELF file"); - BX_LAX( read_u16(LE, elf_begin + 54, elf_end) == 0, "Invalid ELF file"); // program header size - BX_LAX( read_u16(LE, elf_begin + 56, elf_end) == 0, "Invalid ELF file"); // num program headers - BX_LAX( read_u16(LE, elf_begin + 58, elf_end) == ELF_SECTION_HEADER_SIZE, "Invalid ELF file"); + BX_LAX( read_u64(LE, elf_begin + 24, elf_end) == 0, "Invalid entry point"); + BX_LAX( read_u64(LE, elf_begin + 32, elf_end) == 0, "Invalid program header offset"); + BX_LAX( read_u32(LE, elf_begin + 48, elf_end) == 0, "Invalid flags"); + BX_LAX( read_u16(LE, elf_begin + 52, elf_end) == ELF_HEADER_SIZE, "Invalid ELF header size"); + BX_LAX( read_u16(LE, elf_begin + 54, elf_end) == 0, "Invalid program header size"); + BX_LAX( read_u16(LE, elf_begin + 56, elf_end) == 0, "Invalid num program headers"); + BX_LAX( read_u16(LE, elf_begin + 58, elf_end) == ELF_SECTION_HEADER_SIZE, "Invalid section header size"); Buffer_Context buf = { - .begin = im_buffer, - .end = im_buffer + im_offsets[im_num], + .begin = pool->dependencies_buffer, + .end = pool->dependencies_buffer + pool->obj_file_offsets[im_num], .elf = { - .offset = im_offsets[elf_index], - .size = im_offsets[elf_index + 1] - im_offsets[elf_index], + .offset = pool->obj_file_offsets[elf_index], + .size = pool->obj_file_offsets[elf_index + 1] - pool->obj_file_offsets[elf_index], }, }; @@ -1986,7 +2007,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data Offset_Size symbol_names = {0}; Offset_Size symbols = {0}; - for (u16 sec_index = 0; sec_index < section_headers.num; ++sec_index) { + for (i64 sec_index = 0; sec_index < section_headers.num; ++sec_index) { Section_Header section = elf_section(buf, sec_index); if (section.type == SEC_SYMBOLS || @@ -2051,7 +2072,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data printf("\n"); - for (u32 sym_index = 0; sym_index < section.num_entries; ++sym_index) { + for (i64 sym_index = 0; sym_index < section.num_entries; ++sym_index) { Symbol_Entry sym = elf_symbol(buf, section.data, symbol_names, (u16) sym_index); c8 *name = elf_name_from_offset(buf, sym.name); @@ -2109,7 +2130,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data printf("\n"); - for (u32 rela_index = 0; rela_index < section.num_entries; ++rela_index) { + for (i64 rela_index = 0; rela_index < section.num_entries; ++rela_index) { Rela_Entry rela = elf_rela(buf, symbols, symbol_names, section.data, dst, rela_index); printf(" %-16s", REL_NAMES[rela.type]); @@ -2154,7 +2175,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data printf("\n"); - for (u32 rel_index = 0; rel_index < section.num_entries; ++rel_index) { + for (i64 rel_index = 0; rel_index < section.num_entries; ++rel_index) { Rel_Entry rel = elf_rel(buf, symbols, symbol_names, section.data, dst, rel_index); printf(" %-16s", REL_NAMES[rel.type]); @@ -2435,7 +2456,14 @@ Pool g_pool = { // Reallocate the memory block when necessary. .capacity = MAX_NUM_ENTITIES, - .entities = (Entity[MAX_NUM_ENTITIES]) { 0 }, + .entities = (Entity[MAX_NUM_ENTITIES]) {0}, + + .max_obj_file_size = MAX_OBJECT_FILE_SIZE, + .obj_file_buffer = (u8[MAX_OBJECT_FILE_SIZE]) {0}, + .max_dependencies_size = MAX_DEPENDENCIES_SIZE, + .dependencies_buffer = (u8[MAX_DEPENDENCIES_SIZE]) {0}, + .max_num_obj_files = MAX_NUM_OBJECT_FILES, + .obj_file_offsets = (i64[MAX_NUM_OBJECT_FILES]) {0}, }; // Handy procedures -- cgit v1.2.3