mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-05 05:18:40 +00:00
replaced dependency on linker's chunking for resource serialization
with COFF obj writer
This commit is contained in:
committed by
Ryan Fleury
parent
55c76db902
commit
c45088b546
@@ -3,8 +3,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MemoryCopyStr8(dst, s) MemoryCopy(dst, (s).str, (s).size)
|
||||
|
||||
internal int str8_compar(String8 a, String8 b, B32 ignore_case);
|
||||
internal int str8_compar_ignore_case(const void *a, const void *b);
|
||||
internal int str8_compar_case_sensitive(const void *a, const void *b);
|
||||
|
||||
@@ -270,6 +270,19 @@ hash_table_search_string_u64(HashTable *ht, String8 key, U64 *value_out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal B32
|
||||
hash_table_search_string_raw(HashTable *ht, String8 key, void **value_out)
|
||||
{
|
||||
KeyValuePair *result = hash_table_search_string(ht, key);
|
||||
if (result) {
|
||||
if (value_out) {
|
||||
*value_out = result->value_raw;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal int
|
||||
@@ -327,6 +340,18 @@ key_value_pairs_from_hash_table(Arena *arena, HashTable *ht)
|
||||
return pairs;
|
||||
}
|
||||
|
||||
internal void *
|
||||
values_from_hash_table_raw(Arena *arena, HashTable *ht)
|
||||
{
|
||||
void **result = push_array(arena, void *, ht->count);
|
||||
for (U64 bucket_idx = 0, cursor = 0; bucket_idx < ht->cap; ++bucket_idx) {
|
||||
for (BucketNode *n = ht->buckets[bucket_idx].first; n != 0; n = n->next) {
|
||||
Assert(cursor < ht->count);
|
||||
result[cursor++] = n->v.value_raw;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#include "third_party/radsort/radsort.h"
|
||||
|
||||
internal void
|
||||
|
||||
@@ -81,6 +81,8 @@ internal U32 * keys_from_hash_table_u32 (Arena *arena, HashTable
|
||||
internal U64 * keys_from_hash_table_u64 (Arena *arena, HashTable *ht);
|
||||
internal KeyValuePair * key_value_pairs_from_hash_table(Arena *arena, HashTable *ht);
|
||||
|
||||
internal void * values_from_hash_table_raw(Arena *arena, HashTable *ht);
|
||||
|
||||
internal void sort_key_value_pairs_as_u32(KeyValuePair *pairs, U64 count);
|
||||
internal void sort_key_value_pairs_as_u64(KeyValuePair *pairs, U64 count);
|
||||
|
||||
|
||||
+145
-398
@@ -33,11 +33,16 @@
|
||||
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "path/path.h"
|
||||
#include "hash_table.h"
|
||||
#include "coff/coff.h"
|
||||
#include "coff/coff_enum.h"
|
||||
#include "coff/coff_parse.h"
|
||||
#include "coff/coff_obj_writer.h"
|
||||
#include "pe/pe.h"
|
||||
#include "codeview/codeview.h"
|
||||
#include "codeview/codeview_parse.h"
|
||||
#include "codeview/codeview_enum.h"
|
||||
#include "msf/msf.h"
|
||||
#include "msf/msf_parse.h"
|
||||
#include "pdb/pdb.h"
|
||||
@@ -45,10 +50,15 @@
|
||||
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "path/path.c"
|
||||
#include "hash_table.c"
|
||||
#include "coff/coff.c"
|
||||
#include "coff/coff_enum.c"
|
||||
#include "coff/coff_parse.c"
|
||||
#include "coff/coff_obj_writer.c"
|
||||
#include "pe/pe.c"
|
||||
#include "codeview/codeview.c"
|
||||
#include "codeview/codeview_enum.c"
|
||||
#include "codeview/codeview_parse.c"
|
||||
#include "msf/msf.c"
|
||||
#include "msf/msf_parse.c"
|
||||
@@ -63,14 +73,15 @@
|
||||
// RDI
|
||||
|
||||
#include "rdi/rdi_overrides.h"
|
||||
#include "lib_rdi/rdi.h"
|
||||
#include "lib_rdi/rdi.c"
|
||||
#include "lib_rdi_format/rdi_format.h"
|
||||
#include "rdi/rdi.h"
|
||||
#include "lib_rdi_format/rdi_format.c"
|
||||
#include "rdi/rdi.c"
|
||||
|
||||
////////////////////////////////
|
||||
// Code Base Extensions
|
||||
|
||||
#include "base_ext/base_inc.h"
|
||||
#include "hash_table.h"
|
||||
#include "thread_pool/thread_pool.h"
|
||||
#include "codeview_ext/codeview.h"
|
||||
#include "pdb_ext/msf_builder.h"
|
||||
@@ -79,7 +90,6 @@
|
||||
#include "pdb_ext/pdb_builder.h"
|
||||
|
||||
#include "base_ext/base_inc.c"
|
||||
#include "hash_table.c"
|
||||
#include "thread_pool/thread_pool.c"
|
||||
#include "codeview_ext/codeview.c"
|
||||
#include "pdb_ext/msf_builder.c"
|
||||
@@ -406,87 +416,61 @@ lnk_res_number_id_is_before(void *raw_a, void *raw_b)
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_serialize_pe_resource_tree(LNK_SectionTable *sectab, LNK_SymbolTable *symtab, PE_ResourceDir *root_dir)
|
||||
lnk_serialize_pe_resource_tree(COFF_ObjWriter *obj_writer, PE_ResourceDir *root_dir)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
LNK_Section *dir_sect = lnk_section_table_push(sectab, str8_lit(".rsrc$01"), LNK_RSRC_SECTION_FLAGS);
|
||||
LNK_Section *data_sect = lnk_section_table_push(sectab, str8_lit(".rsrc$02"), LNK_RSRC_SECTION_FLAGS);
|
||||
|
||||
LNK_Chunk *dir_tree_chunk = lnk_section_push_chunk_list(dir_sect, dir_sect->root, str8_zero());
|
||||
LNK_Chunk *dir_data_chunk = lnk_section_push_chunk_list(dir_sect, dir_sect->root, str8_zero());
|
||||
LNK_Chunk *dir_string_chunk = lnk_section_push_chunk_list(dir_sect, dir_sect->root, str8_zero());
|
||||
|
||||
dir_tree_chunk->sort_idx = str8_lit("a");
|
||||
dir_string_chunk->sort_idx = str8_lit("b");
|
||||
dir_data_chunk->sort_idx = str8_lit("c");
|
||||
|
||||
PE_Resource root_wrapper = {0};
|
||||
root_wrapper.id.type = COFF_ResourceIDType_Number;
|
||||
root_wrapper.id.u.number = 0;
|
||||
root_wrapper.kind = PE_ResDataKind_DIR;
|
||||
root_wrapper.u.dir = root_dir;
|
||||
|
||||
struct Stack {
|
||||
struct Stack *next;
|
||||
U64 arr_idx;
|
||||
U64 res_idx[2];
|
||||
PE_ResourceArray res_arr[2];
|
||||
LNK_Chunk *coff_entry_array_chunk;
|
||||
LNK_Chunk *coff_entry_chunk;
|
||||
struct Stack *next;
|
||||
U64 arr_idx;
|
||||
U64 res_idx[2];
|
||||
PE_ResourceArray res_arr[2];
|
||||
COFF_ResourceDirEntry *coff_entry_arr[2];
|
||||
};
|
||||
struct Stack *stack = push_array(scratch.arena, struct Stack, 1);
|
||||
stack->res_arr[0].count = 1;
|
||||
stack->res_arr[0].v = &root_wrapper;
|
||||
struct Stack *stack = push_array(scratch.arena, struct Stack, 1);
|
||||
// init stack
|
||||
{
|
||||
PE_Resource root_wrapper = {0};
|
||||
root_wrapper.id.type = COFF_ResourceIDType_Number;
|
||||
root_wrapper.id.u.number = 0;
|
||||
root_wrapper.kind = PE_ResDataKind_DIR;
|
||||
root_wrapper.u.dir = root_dir;
|
||||
|
||||
COFF_ResourceDirEntry root_dir = {0};
|
||||
|
||||
stack->res_arr[0].count = 1;
|
||||
stack->res_arr[0].v = &root_wrapper;
|
||||
|
||||
stack->coff_entry_arr[0] = &root_dir;
|
||||
stack->coff_entry_arr[1] = 0;
|
||||
}
|
||||
|
||||
COFF_ObjSection *rsrc1 = coff_obj_writer_push_section(obj_writer, str8_lit(".rsrc$01"), LNK_RSRC1_SECTION_FLAGS, str8_zero());
|
||||
COFF_ObjSection *rsrc2 = coff_obj_writer_push_section(obj_writer, str8_lit(".rsrc$02"), LNK_RSRC2_SECTION_FLAGS, str8_zero());
|
||||
|
||||
U64 total_res_count = 0;
|
||||
|
||||
while (stack) {
|
||||
while (stack->arr_idx < ArrayCount(stack->res_arr)) {
|
||||
while (stack->res_idx[stack->arr_idx] < stack->res_arr[stack->arr_idx].count) {
|
||||
PE_Resource *res = &stack->res_arr[stack->arr_idx].v[stack->res_idx[stack->arr_idx]];
|
||||
++stack->res_idx[stack->arr_idx];
|
||||
|
||||
String8 flag_name = push_str8f(symtab->arena->v[0], "flag_%u", total_res_count);
|
||||
String8 offset_name = push_str8f(symtab->arena->v[0], "offset_%u", total_res_count);
|
||||
++total_res_count;
|
||||
|
||||
if (stack->coff_entry_array_chunk) {
|
||||
COFF_ResourceDirEntry *entry = push_array(dir_sect->arena, COFF_ResourceDirEntry, 1);
|
||||
stack->coff_entry_chunk = lnk_section_push_chunk_data(dir_sect, stack->coff_entry_array_chunk, str8_struct(entry), str8_zero());
|
||||
|
||||
switch (res->id.type) {
|
||||
case COFF_ResourceIDType_Number: {
|
||||
entry->name.id = res->id.u.number;
|
||||
} break;
|
||||
for (; stack; ) {
|
||||
for (; stack->arr_idx < ArrayCount(stack->res_arr); stack->arr_idx += 1) {
|
||||
for (; stack->res_idx[stack->arr_idx] < stack->res_arr[stack->arr_idx].count; ) {
|
||||
U64 res_idx = stack->res_idx[stack->arr_idx]++;
|
||||
PE_Resource *res = &stack->res_arr[stack->arr_idx].v[res_idx];
|
||||
|
||||
case COFF_ResourceIDType_String: {
|
||||
// TODO: we can make string table smaller by reusing offsets for same strings
|
||||
|
||||
// not sure why high bit has to be turned on here since number id and string id entries are
|
||||
// in separate arrays but windows doesn't treat name offset like string without this bit.
|
||||
entry->name.offset |= (1 << 31);
|
||||
|
||||
// make chunk and symbol
|
||||
String8 res_name = coff_resource_string_from_str8(dir_sect->arena, res->id.u.string);
|
||||
LNK_Chunk *name_chunk = lnk_section_push_chunk_data(dir_sect, dir_string_chunk, res_name, str8_zero());
|
||||
LNK_Symbol *name_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], str8_lit("COFF_RESOURCE_ID_STRING"), LNK_DefinedSymbolVisibility_Static, 0, name_chunk, 0, 0, 0);
|
||||
{
|
||||
COFF_ResourceDirEntry *coff_entry = &stack->coff_entry_arr[stack->arr_idx][res_idx];
|
||||
|
||||
// patch COFF_ResourceDirEntry.name.offset
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, name.offset), name_symbol);
|
||||
} break;
|
||||
// assign entry data offset
|
||||
coff_entry->id.data_entry_offset = safe_cast_u32(rsrc1->data.total_size);
|
||||
|
||||
case COFF_ResourceIDType_Null: break;
|
||||
|
||||
default: InvalidPath;
|
||||
// set directory flag
|
||||
if (res->kind == PE_ResDataKind_DIR) {
|
||||
coff_entry->id.data_entry_offset |= COFF_Resource_SubDirFlag;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (res->kind) {
|
||||
case PE_ResDataKind_DIR: {
|
||||
// initialize directory header
|
||||
COFF_ResourceDirTable *dir_header = push_array(dir_sect->arena, COFF_ResourceDirTable, 1);
|
||||
// fill out directory header
|
||||
COFF_ResourceDirTable *dir_header = push_array(obj_writer->arena, COFF_ResourceDirTable, 1);
|
||||
dir_header->characteristics = res->u.dir->characteristics;
|
||||
dir_header->time_stamp = res->u.dir->time_stamp;
|
||||
dir_header->major_version = res->u.dir->major_version;
|
||||
@@ -494,65 +478,71 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *sectab, LNK_SymbolTable *symtab
|
||||
dir_header->name_entry_count = res->u.dir->named_list.count;
|
||||
dir_header->id_entry_count = res->u.dir->id_list.count;
|
||||
|
||||
// push sub directory chunk layout
|
||||
LNK_Chunk *dir_node_chunk = lnk_section_push_chunk_list(dir_sect, dir_tree_chunk, str8_zero());
|
||||
dir_node_chunk->align = COFF_ResourceAlign;
|
||||
LNK_Chunk *dir_header_chunk = lnk_section_push_chunk_data(dir_sect, dir_node_chunk, str8_struct(dir_header), str8_zero());
|
||||
LNK_Chunk *entry_array_chunk = lnk_section_push_chunk_list(dir_sect, dir_node_chunk, str8_zero());
|
||||
lnk_chunk_set_debugf(dir_sect->arena, dir_header_chunk, "DIR_HEADER_CHUNK");
|
||||
lnk_chunk_set_debugf(dir_sect->arena, entry_array_chunk, "DIR_ENTRY_ARRAY_CHUNK");
|
||||
|
||||
// push symbols to patch coff entry
|
||||
LNK_Symbol *flag_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], flag_name, LNK_DefinedSymbolVisibility_Internal, 0, COFF_Resource_SubDirFlag);
|
||||
LNK_Symbol *offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], offset_name, LNK_DefinedSymbolVisibility_Internal, 0, dir_header_chunk, 0, 0, 0);
|
||||
lnk_symbol_table_push(symtab, flag_symbol); // set high bit to indicate directory
|
||||
lnk_symbol_table_push(symtab, offset_symbol); // write offset for this directory
|
||||
|
||||
// patch resource dir header
|
||||
if (stack->coff_entry_chunk) {
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_ResourceDirEntry, id.data_entry_offset), flag_symbol);
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, id.data_entry_offset), offset_symbol);
|
||||
}
|
||||
|
||||
// sort entries by id
|
||||
// sort input resources
|
||||
PE_ResourceArray named_array = pe_resource_list_to_array(scratch.arena, &res->u.dir->named_list);
|
||||
PE_ResourceArray id_array = pe_resource_list_to_array(scratch.arena, &res->u.dir->id_list);
|
||||
radsort(named_array.v, named_array.count, lnk_res_string_id_is_before);
|
||||
radsort(id_array.v, id_array.count, lnk_res_number_id_is_before);
|
||||
radsort(id_array.v, id_array.count, lnk_res_number_id_is_before);
|
||||
|
||||
// frame for sub directory
|
||||
struct Stack *frame = push_array(scratch.arena, struct Stack, 1);
|
||||
frame->coff_entry_array_chunk = entry_array_chunk;
|
||||
frame->res_arr[0] = named_array;
|
||||
frame->res_arr[1] = id_array;
|
||||
// allocate COFF entries
|
||||
COFF_ResourceDirEntry *named_entries = push_array(obj_writer->arena, COFF_ResourceDirEntry, named_array.count);
|
||||
COFF_ResourceDirEntry *id_entries = push_array(obj_writer->arena, COFF_ResourceDirEntry, id_array.count);
|
||||
|
||||
// push header and entries
|
||||
str8_list_push(obj_writer->arena, &rsrc1->data, str8_struct(dir_header));
|
||||
str8_list_push(obj_writer->arena, &rsrc1->data, str8_array(named_entries, named_array.count));
|
||||
str8_list_push(obj_writer->arena, &rsrc1->data, str8_array(id_entries, id_array.count));
|
||||
|
||||
// fill out named ids
|
||||
for (U64 i = 0; i < named_array.count; i += 1) {
|
||||
PE_Resource src = named_array.v[i];
|
||||
COFF_ResourceDirEntry *dst = &named_entries[i];
|
||||
|
||||
// append resource name
|
||||
U32 res_name_off = safe_cast_u32(rsrc1->data.total_size);
|
||||
String8 res_name = coff_resource_string_from_str8(obj_writer->arena, res->id.u.string);
|
||||
str8_list_push(obj_writer->arena, &rsrc1->data, res_name);
|
||||
|
||||
// not sure why high bit has to be turned on here since number id and string id entries are
|
||||
// in separate arrays but windows doesn't treat name offset like string without this bit.
|
||||
dst->name.offset = (1 << 31) | res_name_off;
|
||||
}
|
||||
|
||||
// fill out number ids
|
||||
for (U64 i = 0; i < id_array.count; i += 1) {
|
||||
PE_Resource src = id_array.v[i];
|
||||
COFF_ResourceDirEntry *dst = &id_entries[i];
|
||||
dst->name.id = src.id.u.number;
|
||||
}
|
||||
|
||||
// fill out sub directory stack frame
|
||||
struct Stack *frame = push_array(scratch.arena, struct Stack, 1);
|
||||
frame->res_arr[0] = named_array;
|
||||
frame->res_arr[1] = id_array;
|
||||
frame->coff_entry_arr[0] = named_entries;
|
||||
frame->coff_entry_arr[1] = id_entries;
|
||||
SLLStackPush(stack, frame);
|
||||
} goto yeild; // recurse to sub directory
|
||||
} goto yield; // recurse to sub directory
|
||||
|
||||
case PE_ResDataKind_COFF_RESOURCE: {
|
||||
COFF_ResourceDataEntry *coff_resource_data_entry = push_array(dir_sect->arena, COFF_ResourceDataEntry, 1);
|
||||
coff_resource_data_entry->data_size = res->u.coff_res.data.size;
|
||||
coff_resource_data_entry->data_voff = 0; // relocated
|
||||
coff_resource_data_entry->code_page = 0; // TODO: whats this for? (lld-link writes zero)
|
||||
// fill out resource header
|
||||
COFF_ResourceDataEntry *coff_res = push_array(obj_writer->arena, COFF_ResourceDataEntry, 1);
|
||||
coff_res->data_size = res->u.coff_res.data.size;
|
||||
coff_res->data_voff = 0; // relocated
|
||||
coff_res->code_page = 0; // TODO: whats this for? (lld-link writes zero)
|
||||
|
||||
// push layout chunks
|
||||
LNK_Chunk *coff_resource_data_entry_chunk = lnk_section_push_chunk_data(dir_sect, dir_data_chunk, str8_struct(coff_resource_data_entry), str8_zero());
|
||||
LNK_Chunk *resource_data_chunk = lnk_section_push_chunk_data(data_sect, data_sect->root, res->u.coff_res.data, str8_zero());
|
||||
// emit symbol for resource data
|
||||
U32 resdat_off = safe_cast_u32(rsrc2->data.total_size);
|
||||
COFF_ObjSymbol *resdat = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("resdat"), resdat_off, rsrc2);
|
||||
|
||||
// windows errors out on unaligned data
|
||||
coff_resource_data_entry_chunk->align = COFF_ResourceAlign;
|
||||
resource_data_chunk->align = COFF_ResourceAlign;
|
||||
// emit reloc for 'data_voff'
|
||||
U64 apply_off = rsrc1->data.total_size + OffsetOf(COFF_ResourceDataEntry, data_voff);
|
||||
U32 apply_off32 = safe_cast_u32(apply_off);
|
||||
coff_obj_writer_section_push_reloc(obj_writer, rsrc1, apply_off32, resdat, COFF_Reloc_X64_Addr32Nb);
|
||||
|
||||
// relocate data
|
||||
String8 resource_data_symbol_name = push_str8f(symtab->arena->v[0], "$R%06X", total_res_count);
|
||||
LNK_Symbol *resource_data_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], resource_data_symbol_name, LNK_DefinedSymbolVisibility_Static, 0, resource_data_chunk, 0, 0, 0);
|
||||
lnk_section_push_reloc(dir_sect, coff_resource_data_entry_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(COFF_ResourceDataEntry, data_voff), resource_data_symbol);
|
||||
|
||||
// push symbol for data offset relocation
|
||||
LNK_Symbol *coff_data_offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], offset_name, LNK_DefinedSymbolVisibility_Internal, 0, coff_resource_data_entry_chunk, 0, 0, 0);
|
||||
lnk_symbol_table_push(symtab, coff_data_offset_symbol);
|
||||
|
||||
Assert(stack->coff_entry_chunk);
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, id.data_entry_offset), coff_data_offset_symbol);
|
||||
// push resource entry & data
|
||||
str8_list_push(obj_writer->arena, &rsrc1->data, str8_struct(coff_res));
|
||||
str8_list_push(obj_writer->arena, &rsrc2->data, res->u.coff_res.data);
|
||||
} break;
|
||||
|
||||
case PE_ResDataKind_NULL: break;
|
||||
@@ -561,10 +551,9 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *sectab, LNK_SymbolTable *symtab
|
||||
case PE_ResDataKind_COFF_LEAF: InvalidPath;
|
||||
}
|
||||
}
|
||||
++stack->arr_idx;
|
||||
}
|
||||
SLLStackPop(stack);
|
||||
yeild:;
|
||||
yield:;
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
@@ -572,20 +561,20 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *sectab, LNK_SymbolTable *symtab
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_add_resource_debug_s(LNK_SectionTable *sectab,
|
||||
LNK_SymbolTable *symtab,
|
||||
String8 obj_path,
|
||||
String8 cwd_path,
|
||||
String8 exe_path,
|
||||
CV_Arch arch,
|
||||
String8List res_file_list,
|
||||
MD5Hash *res_hash_array)
|
||||
lnk_add_resource_debug_s(COFF_ObjWriter *obj_writer,
|
||||
String8 obj_path,
|
||||
String8 cwd_path,
|
||||
String8 exe_path,
|
||||
CV_Arch arch,
|
||||
String8List res_file_list,
|
||||
MD5Hash *res_hash_array)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
|
||||
// init serial for tables
|
||||
String8List string_srl, file_srl; MemoryZeroStruct(&string_srl); MemoryZeroStruct(&file_srl);
|
||||
String8List string_srl = {0};
|
||||
String8List file_srl = {0};
|
||||
str8_serial_begin(scratch.arena, &string_srl);
|
||||
str8_serial_begin(scratch.arena, &file_srl);
|
||||
|
||||
@@ -620,7 +609,7 @@ lnk_add_resource_debug_s(LNK_SectionTable *sectab,
|
||||
1, 0, 1, 0,
|
||||
version_string);
|
||||
|
||||
String8List env_list; MemoryZeroStruct(&env_list);
|
||||
String8List env_list = {0};
|
||||
str8_list_push(scratch.arena, &env_list, str8_lit("cwd"));
|
||||
str8_list_push(scratch.arena, &env_list, cwd_path);
|
||||
str8_list_push(scratch.arena, &env_list, str8_lit("exe"));
|
||||
@@ -629,18 +618,18 @@ lnk_add_resource_debug_s(LNK_SectionTable *sectab,
|
||||
str8_list_push(scratch.arena, &env_list, str8_lit(""));
|
||||
String8 envblock_data = cv_make_envblock(scratch.arena, env_list);
|
||||
|
||||
String8 obj_symbol = cv_make_symbol(scratch.arena, CV_SymKind_OBJNAME, obj_data);
|
||||
String8 comp_symbol = cv_make_symbol(scratch.arena, CV_SymKind_COMPILE3, comp_data);
|
||||
String8 obj_symbol = cv_make_symbol(scratch.arena, CV_SymKind_OBJNAME, obj_data);
|
||||
String8 comp_symbol = cv_make_symbol(scratch.arena, CV_SymKind_COMPILE3, comp_data);
|
||||
String8 envblock_symbol = cv_make_symbol(scratch.arena, CV_SymKind_ENVBLOCK, envblock_data);
|
||||
|
||||
String8List symbol_srl; MemoryZeroStruct(&symbol_srl);
|
||||
String8List symbol_srl = {0};
|
||||
str8_serial_begin(scratch.arena, &symbol_srl);
|
||||
str8_serial_push_string(scratch.arena, &symbol_srl, obj_symbol);
|
||||
str8_serial_push_string(scratch.arena, &symbol_srl, comp_symbol);
|
||||
str8_serial_push_string(scratch.arena, &symbol_srl, envblock_symbol);
|
||||
|
||||
// build code view sub-sections
|
||||
String8List sub_sect_srl; MemoryZeroStruct(&sub_sect_srl);
|
||||
String8List sub_sect_srl = {0};
|
||||
str8_serial_begin(scratch.arena, &sub_sect_srl);
|
||||
CV_Signature sig = CV_Signature_C13;
|
||||
str8_serial_push_struct(scratch.arena, &sub_sect_srl, &sig);
|
||||
@@ -666,20 +655,18 @@ lnk_add_resource_debug_s(LNK_SectionTable *sectab,
|
||||
str8_serial_push_data_list(scratch.arena, &sub_sect_srl, symbol_srl.first);
|
||||
str8_serial_push_align(scratch.arena, &sub_sect_srl, CV_C13SubSectionAlign);
|
||||
|
||||
LNK_Section *debug_s = lnk_section_table_push(sectab, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS);
|
||||
String8 sub_sect_data = str8_serial_end(debug_s->arena, &sub_sect_srl);
|
||||
lnk_section_push_chunk_data(debug_s, debug_s->root, sub_sect_data, str8_zero());
|
||||
String8 sub_sect_data = str8_serial_end(obj_writer->arena, &sub_sect_srl);
|
||||
coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS, sub_sect_data);
|
||||
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_make_res_obj(TP_Context *tp,
|
||||
Arena *arena,
|
||||
lnk_make_res_obj(Arena *arena,
|
||||
PE_ResourceDir *root_dir,
|
||||
COFF_MachineType machine,
|
||||
COFF_TimeStamp time_stamp,
|
||||
COFF_MachineType machine,
|
||||
String8 path,
|
||||
String8 cwd_path,
|
||||
String8 exe_path,
|
||||
@@ -687,262 +674,23 @@ lnk_make_res_obj(TP_Context *tp,
|
||||
MD5Hash *res_hash_array)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
static const U64 sect_virt_align = 1;
|
||||
static const U64 sect_file_align = 1;
|
||||
|
||||
TP_Arena *temp_tp_arena = push_array(scratch.arena, TP_Arena, 1);
|
||||
temp_tp_arena->v = push_array(scratch.arena, Arena *, 1);
|
||||
temp_tp_arena->count = 1;
|
||||
temp_tp_arena->v[0] = arena_alloc();
|
||||
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine);
|
||||
|
||||
// obj features
|
||||
coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("@feat.00"), COFF_SymStorageClass_Static, MSCRT_FeatFlag_HAS_SAFE_SEH|MSCRT_FeatFlag_UNKNOWN_4);
|
||||
|
||||
LNK_SymbolTable *symtab = lnk_symbol_table_init(temp_tp_arena);
|
||||
LNK_SectionTable *sectab = lnk_section_table_alloc(0, sect_virt_align, sect_file_align);
|
||||
LNK_Section *header_sect = lnk_section_table_push(sectab, str8_lit(".null"), 0);
|
||||
// serialize resource tree
|
||||
lnk_serialize_pe_resource_tree(obj_writer, root_dir);
|
||||
|
||||
// push resource debug info
|
||||
lnk_add_resource_debug_s(obj_writer, path, cwd_path, exe_path, cv_arch_from_coff_machine(machine), res_file_list, res_hash_array);
|
||||
|
||||
// finalize obj
|
||||
String8 res_obj = coff_obj_writer_serialize(arena, obj_writer);
|
||||
|
||||
lnk_serialize_pe_resource_tree(sectab, symtab, root_dir);
|
||||
|
||||
CV_Arch cv_arch = cv_arch_from_coff_machine(machine);
|
||||
lnk_add_resource_debug_s(sectab, symtab, path, cwd_path, exe_path, cv_arch, res_file_list, res_hash_array);
|
||||
|
||||
// register section symbols (after this point don't push new sections)
|
||||
for (LNK_SectionNode *sect_node = sectab->list.first; sect_node != 0; sect_node = sect_node->next) {
|
||||
LNK_Section *sect = §_node->data;
|
||||
lnk_symbol_table_push_defined_chunk(symtab, sect->name, LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0);
|
||||
}
|
||||
sectab->null_sect = lnk_section_list_remove(§ab->list, str8_lit(".null"));
|
||||
lnk_section_table_build_data(tp, sectab, machine);
|
||||
lnk_section_table_push_null(sectab);
|
||||
lnk_section_table_assign_indices(sectab);
|
||||
LNK_Section **sect_id_map = lnk_sect_id_map_from_section_table(scratch.arena, sectab);
|
||||
|
||||
COFF_Symbol16List coff_symbol_list = {0};
|
||||
|
||||
COFF_Symbol16 coff_feat00 = {0};
|
||||
MemoryCopyStr8(&coff_feat00.name, str8_lit("@feat.00"));
|
||||
coff_feat00.value = MSCRT_FeatFlag_HAS_SAFE_SEH|MSCRT_FeatFlag_UNKNOWN_4;
|
||||
coff_feat00.section_number = COFF_Symbol_AbsSection16;
|
||||
coff_feat00.storage_class = COFF_SymStorageClass_Static;
|
||||
coff_symbol16_list_push(scratch.arena, &coff_symbol_list, coff_feat00);
|
||||
|
||||
// emit coff symbols for section definitions
|
||||
for (LNK_SectionNode *sect_node = sectab->list.first; sect_node != 0; sect_node = sect_node->next) {
|
||||
LNK_Section *sect = §_node->data;
|
||||
if (sect == header_sect) continue;
|
||||
if (!sect->emit_header) continue;
|
||||
|
||||
U64 reloc_count = 0;
|
||||
LNK_Symbol *coff_reloc_count_symbol = lnk_symbol_table_searchf(symtab, LNK_SymbolScopeFlag_Internal, "%S.coff_relocs[].count", sect->name);
|
||||
if (coff_reloc_count_symbol) {
|
||||
reloc_count = coff_reloc_count_symbol->u.defined.u.va;
|
||||
}
|
||||
|
||||
U64 sect_size = lnk_virt_size_from_chunk_ref(sect_id_map, sect->root->ref);
|
||||
|
||||
COFF_Symbol16 coff_sect_symbol = {0};
|
||||
Assert(sect->name.size <= 8);
|
||||
MemoryCopyStr8(&coff_sect_symbol.name, sect->name);
|
||||
coff_sect_symbol.value = 0;
|
||||
coff_sect_symbol.section_number = sect->isect;
|
||||
coff_sect_symbol.aux_symbol_count = 1;
|
||||
coff_sect_symbol.storage_class = COFF_SymStorageClass_Static;
|
||||
|
||||
Assert(sect->isect <= max_U16);
|
||||
COFF_SymbolSecDef secdef = {0};
|
||||
secdef.length = safe_cast_u32(sect_size);
|
||||
secdef.number_lo = sect->isect;
|
||||
secdef.number_of_relocations = safe_cast_u32(reloc_count);
|
||||
|
||||
coff_symbol16_list_push(scratch.arena, &coff_symbol_list, coff_sect_symbol);
|
||||
coff_symbol16_list_push(scratch.arena, &coff_symbol_list, *((COFF_Symbol16*)&secdef));
|
||||
}
|
||||
|
||||
// convert relocations and symbols to coff format
|
||||
{
|
||||
for (LNK_SectionNode *sect_node = sectab->list.first; sect_node != 0; sect_node = sect_node->next) {
|
||||
LNK_Section *sect = §_node->data;
|
||||
|
||||
// filter out resource relocations
|
||||
LNK_RelocList reloc_list = {0};
|
||||
LNK_RelocList res_data_reloc_list = {0};
|
||||
for (LNK_Reloc *reloc = sect->reloc_list.first; reloc != 0; reloc = reloc->next) {
|
||||
B32 is_reloc_symbol = str8_match_lit("$R", reloc->symbol->name, StringMatchFlag_RightSideSloppy);
|
||||
LNK_Reloc *dst;
|
||||
if (is_reloc_symbol) {
|
||||
dst = lnk_reloc_list_push(sect->arena, &res_data_reloc_list);
|
||||
} else {
|
||||
dst = lnk_reloc_list_push(sect->arena, &reloc_list);
|
||||
}
|
||||
dst->chunk = reloc->chunk;
|
||||
dst->type = reloc->type;
|
||||
dst->apply_off = reloc->apply_off;
|
||||
dst->symbol = reloc->symbol;
|
||||
}
|
||||
sect->reloc_list = reloc_list;
|
||||
|
||||
COFF_RelocList coff_reloc_list = {0};
|
||||
for (LNK_Reloc *reloc = res_data_reloc_list.first; reloc != 0; reloc = reloc->next) {
|
||||
LNK_Symbol *symbol = reloc->symbol;
|
||||
|
||||
Assert(LNK_Symbol_IsDefined(symbol->type));
|
||||
Assert(symbol->u.defined.value_type == LNK_DefinedSymbolValue_Chunk);
|
||||
LNK_DefinedSymbol *def = &symbol->u.defined;
|
||||
|
||||
// resolve symbol offset
|
||||
LNK_Section *symbol_sect = lnk_sect_from_chunk_ref(sect_id_map, def->u.chunk->ref);
|
||||
U64 chunk_off = lnk_off_from_chunk_ref(sect_id_map, def->u.chunk->ref);
|
||||
U64 symbol_offset = chunk_off + def->u.chunk_offset;
|
||||
U64 symbol_idx = coff_symbol_list.count;
|
||||
|
||||
// push coff symbol
|
||||
COFF_Symbol16 coff_symbol = {0};
|
||||
Assert(symbol->name.size <= 8);
|
||||
String8 symbol_name = push_str8f(scratch.arena, "$R%06X", symbol_offset);
|
||||
MemoryCopyStr8(&coff_symbol.name, symbol_name);
|
||||
coff_symbol.value = symbol_offset;
|
||||
coff_symbol.section_number = symbol_sect->isect;
|
||||
coff_symbol.storage_class = COFF_SymStorageClass_Static;
|
||||
coff_symbol16_list_push(scratch.arena, &coff_symbol_list, coff_symbol);
|
||||
|
||||
// push coff reloc
|
||||
U64 reloc_off = lnk_off_from_chunk_ref(sect_id_map, reloc->chunk->ref);
|
||||
reloc_off += reloc->apply_off;
|
||||
|
||||
COFF_Reloc coff_reloc = {0};
|
||||
coff_reloc.apply_off = reloc_off;
|
||||
coff_reloc.isymbol = safe_cast_u32(symbol_idx);
|
||||
coff_reloc.type = lnk_ext_reloc_type_to_coff(machine, reloc->type);
|
||||
coff_reloc_list_push(scratch.arena, &coff_reloc_list, coff_reloc);
|
||||
}
|
||||
|
||||
if (coff_reloc_list.count == 0) continue;
|
||||
|
||||
// push section for relocation data
|
||||
String8 sect_name = push_str8f(sectab->arena, "%S.relocs", sect->name);
|
||||
LNK_Section *reloc_sect = lnk_section_table_push(sectab, sect_name, 0);
|
||||
reloc_sect->emit_header = 0;
|
||||
|
||||
// push chunk layout for relocations
|
||||
LNK_Chunk *reloc_array_chunk = lnk_section_push_chunk_list(reloc_sect, reloc_sect->root, str8_zero());
|
||||
for (COFF_RelocNode *i = coff_reloc_list.first; i != 0; i = i->next) {
|
||||
String8 reloc_data = push_str8_copy(reloc_sect->arena, str8_struct(&i->data));
|
||||
lnk_section_push_chunk_data(reloc_sect, reloc_array_chunk, reloc_data, str8_zero());
|
||||
}
|
||||
|
||||
// emit symbols for coff section header patch
|
||||
String8 coff_reloc_symbol_name = push_str8f(symtab->arena->v[0], "%S.coff_reloc[]", sect->name);
|
||||
String8 coff_reloc_count_symbol_name = push_str8f(symtab->arena->v[0], "%S.coff_reloc[].count", sect->name);
|
||||
LNK_Symbol *coff_reloc_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], coff_reloc_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, reloc_array_chunk, 0, 0, 0);
|
||||
LNK_Symbol *coff_reloc_count_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], coff_reloc_count_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, coff_reloc_list.count);
|
||||
lnk_symbol_table_push(symtab, coff_reloc_symbol);
|
||||
lnk_symbol_table_push(symtab, coff_reloc_count_symbol);
|
||||
}
|
||||
}
|
||||
|
||||
LNK_Section *misc_sect = lnk_section_table_push(sectab, str8_lit(".misc"), COFF_SectionFlag_LnkInfo|COFF_SectionFlag_LnkRemove);
|
||||
misc_sect->emit_header = 0;
|
||||
|
||||
// serialize coff symbol list
|
||||
String8List srl = {0};
|
||||
str8_serial_begin(scratch.arena, &srl);
|
||||
for (COFF_Symbol16Node *i = coff_symbol_list.first; i != 0; i = i->next) {
|
||||
str8_serial_push_struct(scratch.arena, &srl, &i->data);
|
||||
}
|
||||
String8 coff_symbol_table_data = str8_serial_end(scratch.arena, &srl);
|
||||
LNK_Chunk *coff_symbol_table_chunk = lnk_section_push_chunk_data(misc_sect, misc_sect->root, coff_symbol_table_data, str8_zero());
|
||||
LNK_Symbol *coff_symbol_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], str8_lit("COFF_SYMBOL_TABLE"), LNK_DefinedSymbolVisibility_Internal, 0, coff_symbol_table_chunk, 0, 0, 0);
|
||||
lnk_symbol_table_push(symtab, coff_symbol_table_symbol);
|
||||
|
||||
LNK_Symbol *coff_symbol_count_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], str8_lit("COFF_SYMBOL_COUNT"), LNK_DefinedSymbolVisibility_Internal, 0, coff_symbol_list.count);
|
||||
lnk_symbol_table_push(symtab, coff_symbol_count_symbol);
|
||||
|
||||
// build obj header
|
||||
{
|
||||
// init header
|
||||
COFF_FileHeader *file_header = push_array(header_sect->arena, COFF_FileHeader, 1);
|
||||
file_header->machine = machine;
|
||||
file_header->section_count = 0; // relocated
|
||||
file_header->time_stamp = time_stamp;
|
||||
file_header->symbol_table_foff = 0; // relocated
|
||||
file_header->symbol_count = 0; // relocated
|
||||
file_header->optional_header_size = 0; // no PE header in obj
|
||||
file_header->flags = COFF_FileHeaderFlag_32BitMachine;
|
||||
|
||||
// push coff header chunk
|
||||
String8 file_header_data = str8_struct(file_header);
|
||||
LNK_Chunk *file_header_chunk = lnk_section_push_chunk_data(header_sect, header_sect->root, file_header_data, str8_zero());
|
||||
|
||||
// relocate coff header fields
|
||||
lnk_section_push_reloc_undefined(header_sect, file_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_FileHeader, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal);
|
||||
lnk_section_push_reloc(header_sect, file_header_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(COFF_FileHeader, symbol_table_foff), coff_symbol_table_symbol);
|
||||
lnk_section_push_reloc(header_sect, file_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_FileHeader, symbol_count), coff_symbol_count_symbol);
|
||||
|
||||
// push coff header symbol
|
||||
LNK_Symbol *file_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], str8_lit(LNK_COFF_FILE_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, file_header_chunk, 0, 0, 0);
|
||||
lnk_symbol_table_push(symtab, file_header_symbol);
|
||||
}
|
||||
|
||||
// build section headers
|
||||
{
|
||||
LNK_Chunk *coff_section_header_array_chunk = lnk_section_push_chunk_list(header_sect, header_sect->root, str8_zero());
|
||||
for (LNK_SectionNode *sect_node = sectab->list.first; sect_node != 0; sect_node = sect_node->next) {
|
||||
if (sect_node == sectab->null_sect) continue;
|
||||
if (!sect_node->data.emit_header) continue;
|
||||
LNK_Section *sect = §_node->data;
|
||||
|
||||
// init section header
|
||||
COFF_SectionHeader *coff_sect_header = push_array(header_sect->arena, COFF_SectionHeader, 1);
|
||||
Assert(sect->name.size <= sizeof(coff_sect_header->name));
|
||||
MemoryCopyStr8(&coff_sect_header->name[0], sect->name);
|
||||
coff_sect_header->flags = sect->flags;
|
||||
coff_sect_header->vsize = 0; // ignored
|
||||
coff_sect_header->voff = 0; // ignored
|
||||
coff_sect_header->fsize = 0; // relocated
|
||||
coff_sect_header->foff = 0; // relocated
|
||||
coff_sect_header->relocs_foff = 0; // relocated
|
||||
coff_sect_header->lines_foff = 0; // obsolete
|
||||
coff_sect_header->line_count = 0; // obsolete
|
||||
coff_sect_header->reloc_count = 0; // relocated
|
||||
|
||||
// push section header chunk
|
||||
String8 coff_sect_header_data = str8_struct(coff_sect_header);
|
||||
String8 sort_index = lnk_make_section_sort_index(header_sect->arena, str8_zero(), 0, sect->isect);
|
||||
LNK_Chunk *coff_sect_header_chunk = lnk_section_push_chunk_data(header_sect, coff_section_header_array_chunk, coff_sect_header_data, sort_index);
|
||||
lnk_chunk_set_debugf(header_sect->arena, coff_sect_header_chunk, "%S", sect->name);
|
||||
|
||||
// patch reloc fields
|
||||
if (sect->reloc_list.count) {
|
||||
String8 coff_reloc_symbol_name = push_str8f(scratch.arena, "%S.coff_reloc[]", sect->name);
|
||||
String8 coff_reloc_count_symbol_name = push_str8f(scratch.arena, "%S.coff_reloc[].count", sect->name);
|
||||
lnk_section_push_reloc_undefined(header_sect, coff_sect_header_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(COFF_SectionHeader, relocs_foff), coff_reloc_symbol_name, LNK_SymbolScopeFlag_Internal);
|
||||
lnk_section_push_reloc_undefined(header_sect, coff_sect_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_SectionHeader, reloc_count), coff_reloc_count_symbol_name, LNK_SymbolScopeFlag_Internal);
|
||||
}
|
||||
|
||||
// patch file fields
|
||||
if (~sect->flags & COFF_SectionFlag_CntUninitializedData) {
|
||||
LNK_Symbol *sect_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Internal, sect->name);
|
||||
lnk_section_push_reloc(header_sect, coff_sect_header_chunk, LNK_Reloc_CHUNK_SIZE_FILE_32, OffsetOf(COFF_SectionHeader, fsize), sect_symbol);
|
||||
lnk_section_push_reloc(header_sect, coff_sect_header_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(COFF_SectionHeader, foff), sect_symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// push section header count symbol
|
||||
U64 symbol_count = coff_section_header_array_chunk->u.list->count;
|
||||
LNK_Symbol *coff_section_header_count_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, symbol_count);
|
||||
lnk_symbol_table_push(symtab, coff_section_header_count_symbol);
|
||||
}
|
||||
|
||||
lnk_section_table_assign_indices(sectab);
|
||||
lnk_section_table_build_data(tp, sectab, machine);
|
||||
lnk_section_table_assign_file_offsets(sectab);
|
||||
String8 res_obj = lnk_section_table_serialize(tp, arena, sectab, machine);
|
||||
sect_id_map = lnk_sect_id_map_from_section_table(scratch.arena, sectab);
|
||||
lnk_patch_relocs_linker(tp, symtab, sectab, sect_id_map, res_obj, 0);
|
||||
lnk_section_table_release(§ab);
|
||||
|
||||
arena_release(temp_tp_arena->v[0]);
|
||||
scratch_end(scratch);
|
||||
coff_obj_writer_release(&obj_writer);
|
||||
|
||||
ProfEnd();
|
||||
return res_obj;
|
||||
}
|
||||
@@ -986,11 +734,10 @@ lnk_obj_from_res_file_list(TP_Context *tp,
|
||||
String8List exe_path_strs = {0};
|
||||
str8_list_push(scratch.arena, &exe_path_strs, process_info->binary_path);
|
||||
String8 exe_path = str8_list_first(&exe_path_strs);
|
||||
String8 res_obj = lnk_make_res_obj(tp,
|
||||
arena,
|
||||
String8 res_obj = lnk_make_res_obj(arena,
|
||||
root_dir,
|
||||
machine,
|
||||
time_stamp,
|
||||
machine,
|
||||
obj_name,
|
||||
work_dir,
|
||||
exe_path,
|
||||
|
||||
+5
-3
@@ -89,6 +89,8 @@
|
||||
#define LNK_IDATA_SECTION_FLAGS LNK_DATA_SECTION_FLAGS
|
||||
#define LNK_DEBUG_DIR_SECTION_FLAGS LNK_DATA_SECTION_FLAGS
|
||||
#define LNK_RSRC_SECTION_FLAGS LNK_DATA_SECTION_FLAGS
|
||||
#define LNK_RSRC1_SECTION_FLAGS (LNK_DATA_SECTION_FLAGS | COFF_SectionFlags_PackAlign(COFF_SectionAlign_4Bytes))
|
||||
#define LNK_RSRC2_SECTION_FLAGS (LNK_DATA_SECTION_FLAGS | COFF_SectionFlags_PackAlign(COFF_SectionAlign_4Bytes))
|
||||
#define LNK_XDATA_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS
|
||||
#define LNK_PDATA_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS
|
||||
#define LNK_EDATA_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS
|
||||
@@ -262,9 +264,9 @@ internal void lnk_merge_manifest_files(String8 mt_path, String8 out_name, Str
|
||||
////////////////////////////////
|
||||
// Resources
|
||||
|
||||
internal void lnk_serialize_pe_resource_tree(LNK_SectionTable *sectab, LNK_SymbolTable *symtab, PE_ResourceDir *root_dir);
|
||||
internal void lnk_add_resource_debug_s(LNK_SectionTable *sectab, LNK_SymbolTable *symtab, String8 obj_path, String8 cwd_path, String8 exe_path, CV_Arch arch, String8List res_file_list, MD5Hash *res_hash_array);
|
||||
internal String8 lnk_make_res_obj(TP_Context *tp, Arena *arena, PE_ResourceDir *root_dir, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 path, String8 cwd_path, String8 exe_path, String8List res_file_list, MD5Hash *res_hash_array);
|
||||
internal void lnk_serialize_pe_resource_tree(COFF_ObjWriter *obj_writer, PE_ResourceDir *root_dir);
|
||||
internal void lnk_add_resource_debug_s(COFF_ObjWriter *obj_writer, String8 obj_path, String8 cwd_path, String8 exe_path, CV_Arch arch, String8List res_file_list, MD5Hash *res_hash_array);
|
||||
internal String8 lnk_make_res_obj(Arena *arena, PE_ResourceDir *root_dir, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 path, String8 cwd_path, String8 exe_path, String8List res_file_list, MD5Hash *res_hash_array);
|
||||
internal String8 lnk_obj_from_res_file_list(TP_Context *tp, Arena *arena, LNK_SectionTable *sectab, LNK_SymbolTable *symtab, String8List res_file_list, String8List res_path_list, COFF_MachineType machine, U32 time_stamp, String8 work_dir, PathStyle system_path_style, String8 obj_name);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user