From 6a546e1cda2da728edc72305c009236b1ecf51ef Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Wed, 24 Jul 2024 18:38:48 +0200 Subject: Write output into memory --- bxgen.c | 354 ++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 198 insertions(+), 156 deletions(-) (limited to 'bxgen.c') diff --git a/bxgen.c b/bxgen.c index be2b5d0..9acf2d6 100755 --- a/bxgen.c +++ b/bxgen.c @@ -56,7 +56,7 @@ #/ #/ Bugs #/ -#/ - ... +#/ - Segmentation fault when assembling all sections #/ #/ Done features #/ @@ -166,6 +166,7 @@ enum { MAX_OBJECT_FILE_SIZE = 10 * 1024 * 1024, // 10 MB MAX_DEPENDENCIES_SIZE = 50 * 1024 * 1024, // 50 MB MAX_NOT_FOUND_SIZE = 10 * 1024, // 10 KB + MAX_OUTPUT_SIZE = 20 * 1024 * 1024, // 20 MB MAX_PATH_SIZE = 10 * 1024, MAX_LITERAL_SIZE = 400, @@ -381,6 +382,7 @@ typedef struct { i64 max_num_sections; i64 max_num_symbols; i64 max_not_found_size; + i64 max_output_size; u8 * obj_file_buffer; u8 * dependencies_buffer; @@ -388,6 +390,7 @@ typedef struct { i64 * section_addresses; Internal_Symbol_Entry *symbols; c8 * not_found_buffer; + u8 * output_buffer; } Pool; // ================================================================ @@ -1873,56 +1876,31 @@ Symbol_Entry elf_symbol( }; } -Relx_Entry elf_rel( +Relx_Entry elf_relx( Buffer_Context b, Offset_Size symbol_table, Offset_Size string_table, Offset_Size relocations, - i64 rel_index + i64 relx_index, + b8 is_rela ) { - u8 *begin = b.begin + relocations.offset + rel_index * ELF_REL_ENTRY_SIZE; - u8 *end = begin + ELF_REL_ENTRY_SIZE; - - BX_CHECK(end <= b.end, "Buffer overflow", (Rel_Entry) {0}); - 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}); - - i64 rel_offset = read_i64(LE, begin, end); - u32 rel_type = read_u32(LE, begin + 8, end); - i64 rel_sym = (i64) read_u32(LE, begin + 12, end); - - return (Relx_Entry) { - .symbol = elf_symbol(b, symbol_table, string_table, rel_sym), - .offset = rel_offset, - .type = rel_type, - .addent = 0, - }; -} - -Relx_Entry elf_rela( - Buffer_Context b, - Offset_Size symbol_table, - Offset_Size string_table, - Offset_Size relocations, - i64 rela_index -) { - u8 *begin = b.begin + relocations.offset + rela_index * ELF_RELA_ENTRY_SIZE; + u8 *begin = b.begin + relocations.offset + relx_index * (is_rela ? ELF_RELA_ENTRY_SIZE : ELF_REL_ENTRY_SIZE); u8 *end = begin + ELF_RELA_ENTRY_SIZE; - BX_CHECK(end <= b.end, "Buffer overflow", (Rela_Entry) {0}); - 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}); + BX_CHECK(end <= b.end, "Buffer overflow", (Relx_Entry) {0}); + BX_CHECK(end <= b.begin + b.elf.offset + b.elf.size, "Buffer overflow", (Relx_Entry) {0}); + BX_CHECK(end <= b.begin + relocations.offset + relocations.size, "Buffer overflow", (Relx_Entry) {0}); - i64 rela_offset = read_i64(LE, begin, end); - u32 rela_type = read_u32(LE, begin + 8, end); - i64 rela_sym = (i64) read_u32(LE, begin + 12, end); - i64 rela_addent = read_i64(LE, begin + 16, end); + i64 relx_offset = read_i64(LE, begin, end); + u32 relx_type = read_u32(LE, begin + 8, end); + i64 relx_sym = (i64) read_u32(LE, begin + 12, end); + i64 relx_addent = is_rela ? read_i64(LE, begin + 16, end) : 0; return (Relx_Entry) { - .symbol = elf_symbol(b, symbol_table, string_table, rela_sym), - .offset = rela_offset, - .type = rela_type, - .addent = rela_addent, + .symbol = elf_symbol(b, symbol_table, string_table, relx_sym), + .offset = relx_offset, + .type = relx_type, + .addent = relx_addent, }; } @@ -2047,11 +2025,12 @@ void elf_dump(u32 log_level, Buffer_Context b) { BX_LOG(log_level, " - -"); break; + case SEC_REL: case SEC_RELA: { BX_LOG(log_level, " - -"); - for (i64 rela_index = 0; rela_index < section.num_entries; ++rela_index) { - Relx_Entry relx = elf_rela(b, symtab, strtab, section.data, rela_index); + for (i64 relx_index = 0; relx_index < section.num_entries; ++relx_index) { + Relx_Entry relx = elf_relx(b, symtab, strtab, section.data, relx_index, section.type == SEC_RELA); BX_LOG( log_level, @@ -2075,33 +2054,6 @@ void elf_dump(u32 log_level, Buffer_Context b) { BX_LOG(log_level, " - -"); } break; - case SEC_REL: { - BX_LOG(log_level, " - -"); - - for (i64 rel_index = 0; rel_index < section.num_entries; ++rel_index) { - Relx_Entry relx = elf_rel(b, symtab, strtab, section.data, rel_index); - - BX_LOG( - log_level, - " %-16s %08llx <= %s%08llx\x1b[37m%s\x1b[37m \"%s\"", - REL_NAMES[relx.type], - relx.offset, - relx.symbol.bind == BIND_WEAK ? "\x1b[33m" : "\x1b[32m", - relx.symbol.value.offset + elf_section(b, relx.symbol.section).data.offset, - relx.symbol.type == SYM_DATA ? " \x1b[34mdata" : - relx.symbol.type == SYM_COMMON ? " \x1b[32mdata" : - relx.symbol.type == SYM_TLS ? " \x1b[35mdata" : - relx.symbol.type == SYM_PROC ? " \x1b[34mproc" : - relx.symbol.type == SYM_SECTION ? " \x1b[36msect" : - relx.symbol.type == SYM_SPECIFIC ? " \x1b[34mspec" : - " \x1b[33mnone", - elf_name_from_offset(b, relx.symbol.name) - ); - } - - BX_LOG(log_level, " - -"); - } break; - default:; } } @@ -2129,21 +2081,21 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data 0x0f, 0x05, // syscall }; - i64 num_program_headers = 1; + u16 num_program_headers = 1; - i64 data_offset = bx_align(ELF_HEADER_SIZE + ELF_PROGRAM_HEADER_SIZE * num_program_headers, X86_64_ALIGNMENT); - i64 code_size = bx_align(sizeof code, X86_64_ALIGNMENT); - i64 entry_offset = 0; + i64 program_offset = bx_align(ELF_HEADER_SIZE + ELF_PROGRAM_HEADER_SIZE * num_program_headers, X86_64_ALIGNMENT); + i64 code_size = bx_align(sizeof code, X86_64_ALIGNMENT); + i64 entry_offset = 0; - i64 base_address = X86_64_BASE_ADDRESS; - i64 code_address = base_address + data_offset; - i64 entry = code_address + entry_offset; + i64 base_address = X86_64_BASE_ADDRESS; + i64 rotext_address = base_address + program_offset; + i64 entry = rotext_address + entry_offset; Internal_Symbol_Entry sym_printf = {0}; - i64 text_size = code_size; - i64 data_size = 0; - i64 bss_size = 0; + i64 rotext_size = code_size; + i64 rwzval_size = 0; + i64 rwdata_size = 0; i64 rodata_size = 0; // ============================================================== @@ -2250,16 +2202,16 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data continue; if (section.exec) { - pool->section_addresses[num_sections] = base_address + data_offset + text_size; - text_size += bx_align(section.data.size, X86_64_ALIGNMENT); + pool->section_addresses[num_sections] = rotext_size; + rotext_size += bx_align(section.data.size, X86_64_ALIGNMENT); } else if (section.write && section.type == SEC_NOBITS) { - pool->section_addresses[num_sections] = base_address + data_offset + bss_size; - bss_size += bx_align(section.data.size, X86_64_ALIGNMENT); + pool->section_addresses[num_sections] = rwzval_size; + rwzval_size += bx_align(section.data.size, X86_64_ALIGNMENT); } else if (section.write) { - pool->section_addresses[num_sections] = base_address + data_offset + data_size; - data_size += bx_align(section.data.size, X86_64_ALIGNMENT); + pool->section_addresses[num_sections] = rwdata_size; + rwdata_size += bx_align(section.data.size, X86_64_ALIGNMENT); } else if (section.data.size > 0) { - pool->section_addresses[num_sections] = base_address + data_offset + rodata_size; + pool->section_addresses[num_sections] = rodata_size; rodata_size += bx_align(section.data.size, X86_64_ALIGNMENT); } else { BX_LAX(0, "Unsupported section type"); @@ -2268,6 +2220,35 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data } } + i64 rwzval_address = rotext_address + rotext_size; + i64 rwdata_address = rwzval_address + rwzval_size; + i64 rodata_address = rwdata_address + rwdata_size; + + for (i64 elf_index = 0, sec_index_global = 0; elf_index < num_obj_files; ++elf_index) { + Buffer_Context buf = elf_buffer_context(pool, num_obj_files, elf_index); + Offset_Num headers = elf_section_headers(buf); + + for (i64 sec_index = 1; sec_index < headers.num; ++sec_index, ++sec_index_global) { + BX_CHECK(sec_index_global < num_sections, "Buffer overflow",); + + pool->section_addresses[sec_index_global] = 0; + + Section_Header section = elf_section(buf, sec_index); + + if (!section.alloc) + continue; + + if (section.exec) + pool->section_addresses[sec_index_global] += rotext_address; + else if (section.write && section.type == SEC_NOBITS) + pool->section_addresses[sec_index_global] += rwzval_address; + else if (section.write) + pool->section_addresses[sec_index_global] += rwdata_address; + else if (section.data.size > 0) + pool->section_addresses[sec_index_global] += rodata_address; + } + } + // ========================================================== // // Relocate defined symbols @@ -2276,7 +2257,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data Buffer_Context buf = elf_buffer_context(pool, num_obj_files, elf_index); Offset_Num headers = elf_section_headers(buf); - Offset_Size strtab = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data; + Offset_Size strtab = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data; for (i64 sec_index = 1; sec_index < headers.num; ++sec_index) { Section_Header tab = elf_section(buf, sec_index); @@ -2289,12 +2270,17 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data if (sym.section == 0) // undefined symbol continue; + if (sym.section == 65522) // common + continue; - i64 sym_section = sec_index_global + sym.section - 1; - - BX_CHECK(sym_section < pool->max_num_sections, "Buffer overflow",); + i64 sym_section = 0; + i64 sym_address = sym.value.offset; - i64 sym_address = pool->section_addresses[sym_section] + sym.value.offset; + if (sym.section != 65521) { + sym_section = sec_index_global + sym.section - 1; + BX_CHECK(sym_section < num_sections, "Buffer overflow",); + sym_address = pool->section_addresses[sym_section] + sym.value.offset; + } BX_CHECK(num_symbols < pool->max_num_symbols, "Too many symbols",); @@ -2388,9 +2374,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data BX_CHECK(dst_index >= 0 && dst_index < pool->max_num_sections, "Buffer overflow",); for (i64 entry_index = 0; entry_index < src_sec.num_entries; ++entry_index) { - Relx_Entry relx = (src_sec.type == SEC_REL) ? - elf_rel (buf, symtab, strtab, src_sec.data, entry_index) : - elf_rela(buf, symtab, strtab, src_sec.data, entry_index); + Relx_Entry relx = elf_relx(buf, symtab, strtab, src_sec.data, entry_index, src_sec.type == SEC_RELA); c8 *sym_name = elf_name_from_offset(buf, relx.symbol.name); @@ -2414,7 +2398,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data sym_name, sym_name + relx.symbol.name.size ) == NULL) { - BX_LOG(WARNING, "Symbol not found: %s", sym_name); + BX_LOG(WARNING, "Undefined symbol: %s", sym_name); BX_CHECK(not_found_size + relx.symbol.name.size + 1 <= pool->max_not_found_size, "Out of memory",); bx_mem_cpy(pool->not_found_buffer + not_found_size, sym_name, relx.symbol.name.size); not_found_size += relx.symbol.name.size + 1; @@ -2435,13 +2419,13 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data i64 B = pool->section_addresses[dst_index]; // Represents the offset into the global offset table at which the relocation entry's symbol will reside during execution. - i64 G = symbol.address - base_address - data_offset; + i64 G = symbol.address - base_address - program_offset; // Represents the address of the global offset table. - i64 GOT = base_address + data_offset; + i64 GOT = base_address + program_offset; // Represents the place (section offset or address) of the Procedure Linkage Table entry for a symbol. - i64 L = base_address + data_offset; + i64 L = base_address + program_offset; // Represents the place (section offset or address) of the storage unit being relocated (computed using r_offset). i64 P = pool->section_addresses[dst_index] + relx.offset; @@ -2521,90 +2505,144 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data break; } - // ============================================================== - // - // TODO Write sections into the output buffer - // ============================================================== // // Writing the ELF executable // - // TODO Write into memory. + + //i64 output_size = bx_align(program_offset + rotext_size + rwzval_size + rwdata_size + rodata_size, X86_64_ALIGNMENT); + i64 output_size = bx_align(program_offset + code_size, X86_64_ALIGNMENT); + + BX_CHECK(output_size <= pool->max_output_size, "Out of memory",); BX_LOG(VERBOSE, "Total %lld sections", num_sections); BX_LOG(VERBOSE, "Total %lld symbols", num_symbols); BX_LOG(VERBOSE, "Total size"); - BX_LOG(VERBOSE, ".text - %lld bytes", text_size); - BX_LOG(VERBOSE, ".bss - %lld bytes", bss_size); - BX_LOG(VERBOSE, ".data - %lld bytes", data_size); + BX_LOG(VERBOSE, ".rotext - %lld bytes", rotext_size); + BX_LOG(VERBOSE, ".rwzval - %lld bytes", rwzval_size); + BX_LOG(VERBOSE, ".rwdata - %lld bytes", rwdata_size); BX_LOG(VERBOSE, ".rodata - %lld bytes", rodata_size); - BX_CHECK(sym_printf.name_size != 0, "Symbol not found: printf",); + BX_CHECK(sym_printf.name_size != 0, "Undefined symbol: printf",); BX_LOG(VERBOSE, "Found printf: %08llx", sym_printf.address); BX_LOG(VERBOSE, "Writing ELF x86_64 executable"); - #define WRITE(x, n) io_write( io_out, n, x, io_user_data ) - #define WRITE_V(...) io_write( io_out, sizeof((u8[]) {__VA_ARGS__}), (u8[]) {__VA_ARGS__}, io_user_data ) - #define WRITE_DUP(x, n) io_write( io_out, n, (u8[n]) { 0 }, io_user_data ) - #define WRITE_2(x) io_write( io_out, 2, &(u16) { x }, io_user_data ) - #define WRITE_4(x) io_write( io_out, 4, &(u32) { x }, io_user_data ) - #define WRITE_8(x) io_write( io_out, 8, &(u64) { x }, io_user_data ) - // ELF header // - WRITE ( ELF_MAGIC, 4 ); - - WRITE_V( ELF_64 ); - WRITE_V( ELF_2_LE ); - WRITE_V( ELF_VERSION ); - WRITE_V( ELF_SYS_V ); - WRITE_V( ELF_ABI_VERSION ); - - WRITE_DUP(0, 7); // padding - - WRITE_2( ELF_EXECUTABLE ); - WRITE_2( ELF_X86_64 ); - WRITE_4( ELF_VERSION ); - WRITE_8( entry ); - WRITE_8( ELF_HEADER_SIZE ); - WRITE_8( 0 ); // section header offset - WRITE_4( 0 ); // flags - WRITE_2( ELF_HEADER_SIZE ); - WRITE_2( ELF_PROGRAM_HEADER_SIZE ); - WRITE_2( 1 ); // num program headers - WRITE_2( 0 ); // section header size - WRITE_2( 0 ); // num section headers - WRITE_2( 0 ); // string table section header index - - // Program header + u8 *o = pool->output_buffer; + u8 *o_end = o + pool->max_output_size; + + bx_mem_cpy(o, ELF_MAGIC, 4); + + write_u8 (LE, ELF_64, o + 4, o_end); + write_u8 (LE, ELF_2_LE, o + 5, o_end); + write_u8 (LE, ELF_VERSION, o + 6, o_end); + write_u8 (LE, ELF_SYS_V, o + 7, o_end); + write_u8 (LE, ELF_ABI_VERSION, o + 8, o_end); + // 7 bytes - padding + write_u16(LE, ELF_EXECUTABLE, o + 16, o_end); + write_u16(LE, ELF_X86_64, o + 18, o_end); + write_u32(LE, ELF_VERSION, o + 20, o_end); + write_i64(LE, entry, o + 24, o_end); + write_u64(LE, ELF_HEADER_SIZE, o + 32, o_end); // program header offset + // 8 bytes - section header offset o + 40 + // 4 bytes - flags o + 48 + write_u16(LE, ELF_HEADER_SIZE, o + 52, o_end); + write_u16(LE, ELF_PROGRAM_HEADER_SIZE, o + 54, o_end); + write_u16(LE, num_program_headers, o + 56, o_end); + // 2 bytes - section header size o + 58 + // 2 bytes - num section headers o + 60 + // 2 bytes - string table section o + 62 + // header index + + // Program headers // - WRITE_4( 1 ); // type (PT_LOAD) - WRITE_4( 5 ); // flags (PF_X | PF_R) - WRITE_8( data_offset ); - WRITE_8( code_address ); // virtual address - WRITE_8( code_address ); // phisical address - WRITE_8( code_size ); // size in file - WRITE_8( code_size ); // size in memory - WRITE_8( X86_64_ALIGNMENT ); + i64 rotext_offset = program_offset; + i64 rwzval_offset = rotext_offset + rotext_size; + i64 rwdata_offset = rwzval_offset; + i64 rodata_offset = rwdata_offset + rwdata_size; + + // .rotext + write_u32(LE, 1, o + 64, o_end); // type (PT_LOAD) + write_u32(LE, 5, o + 68, o_end); // flags (PF_X | PF_R) + write_i64(LE, rotext_offset, o + 72, o_end); + write_i64(LE, rotext_address, o + 80, o_end); // virtual address + write_i64(LE, rotext_address, o + 88, o_end); // phisical address + write_i64(LE, rotext_size, o + 96, o_end); // size in file + write_i64(LE, rotext_size, o + 104, o_end); // size in memory + write_i64(LE, X86_64_ALIGNMENT, o + 112, o_end); + + /* + // .rwzval + write_u32(LE, 1, o + 120, o_end); // type (PT_LOAD) + write_u32(LE, 6, o + 124, o_end); // flags (PF_R | PF_W) + write_i64(LE, rwzval_offset, o + 128, o_end); + write_i64(LE, rwzval_address, o + 136, o_end); // virtual address + write_i64(LE, rwzval_address, o + 144, o_end); // phisical address + write_i64(LE, 0, o + 152, o_end); // size in file + write_i64(LE, rwzval_size, o + 160, o_end); // size in memory + write_i64(LE, X86_64_ALIGNMENT, o + 168, o_end); + + // .rwdata + write_u32(LE, 1, o + 176, o_end); // type (PT_LOAD) + write_u32(LE, 6, o + 180, o_end); // flags (PF_R | PF_W) + write_i64(LE, rwdata_offset, o + 184, o_end); + write_i64(LE, rwdata_address, o + 192, o_end); // virtual address + write_i64(LE, rwdata_address, o + 200, o_end); // phisical address + write_i64(LE, rwdata_size, o + 208, o_end); // size in file + write_i64(LE, rwdata_size, o + 216, o_end); // size in memory + write_i64(LE, X86_64_ALIGNMENT, o + 224, o_end); + + // .rodata + write_u32(LE, 1, o + 232, o_end); // type (PT_LOAD) + write_u32(LE, 4, o + 236, o_end); // flags (PF_R) + write_i64(LE, rodata_offset, o + 240, o_end); + write_i64(LE, rodata_address, o + 248, o_end); // virtual address + write_i64(LE, rodata_address, o + 256, o_end); // phisical address + write_i64(LE, rodata_size, o + 264, o_end); // size in file + write_i64(LE, rodata_size, o + 272, o_end); // size in memory + write_i64(LE, X86_64_ALIGNMENT, o + 280, o_end); + */ + + //BX_CHECK(rotext_offset >= 288, "Sanity",); // Code // - for (i64 i = data_offset - ELF_HEADER_SIZE - ELF_PROGRAM_HEADER_SIZE; i > 0; --i) - WRITE_V( 0 ); + bx_mem_cpy(o + rotext_offset, code, code_size); + + // ============================================================== + // + // TODO Write sections into the output buffer + + /* + for (i64 elf_index = 0; elf_index < num_obj_files; ++elf_index) { + Buffer_Context buf = elf_buffer_context(pool, num_obj_files, elf_index); + Offset_Num headers = elf_section_headers(buf); - WRITE( code, code_size ); + for (i64 sec_index = 1; sec_index < headers.num; ++sec_index, ++num_sections) { + Section_Header section = elf_section(buf, sec_index); + if (pool->section_addresses[sec_index] == 0 || + !section.alloc || + section.data.size == 0) + continue; + u8 *p = o + (pool->section_addresses[sec_index] - base_address); + BX_CHECK(p >= pool->output_buffer + program_offset, "Buffer overflow",); + BX_CHECK(p + section.data.size <= pool->output_buffer + output_size, "Buffer overflow",); + bx_mem_cpy(p, buf.begin + section.data.offset, section.data.size); + } + } + */ - #undef WRITE_V - #undef WRITE_DUP - #undef WRITE_32 - #undef WRITE_64 + // ============================================================== + // + // Write the output buffer into the file - #undef WRITE + io_write(io_out, output_size, pool->output_buffer, io_user_data); // ============================================================== // @@ -2615,6 +2653,8 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data bx_mem_set(pool->obj_file_offsets, 0, pool->max_num_obj_files * sizeof *pool->obj_file_offsets); bx_mem_set(pool->section_addresses, 0, pool->max_num_sections * sizeof *pool->section_addresses); bx_mem_set(pool->symbols, 0, pool->max_num_symbols * sizeof *pool->symbols); + bx_mem_set(pool->not_found_buffer, 0, pool->max_not_found_size); + bx_mem_set(pool->output_buffer, 0, pool->max_output_size); } i64 io_open_read(i64 name_size, c8 *name, void *user_data) { @@ -2866,6 +2906,7 @@ Pool g_pool = { .max_num_sections = MAX_NUM_SECTIONS, .max_num_symbols = MAX_NUM_SYMBOLS, .max_not_found_size = MAX_NOT_FOUND_SIZE, + .max_output_size = MAX_OUTPUT_SIZE, .obj_file_buffer = (u8[MAX_OBJECT_FILE_SIZE]) {0}, .dependencies_buffer = (u8[MAX_DEPENDENCIES_SIZE]) {0}, @@ -2873,6 +2914,7 @@ Pool g_pool = { .section_addresses = (i64[MAX_NUM_SECTIONS]) {0}, .symbols = (Internal_Symbol_Entry[MAX_NUM_SYMBOLS]) {0}, .not_found_buffer = (c8[MAX_NOT_FOUND_SIZE]) {0}, + .output_buffer = (u8[MAX_OUTPUT_SIZE]) {0}, }; // Handy procedures -- cgit v1.2.3