mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-09 19:11:38 -07:00
WIP: reorder input and library search order to match MSVC behavior
This commit is contained in:
committed by
Ryan Fleury
parent
240935f0cc
commit
1aac27095e
+52
-11
@@ -211,11 +211,18 @@ hash_table_search_u64(HashTable *ht, U64 key_u64)
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal void *
|
||||
hash_table_search_u64_raw(HashTable *ht, U64 key_u64)
|
||||
internal KeyValuePair *
|
||||
hash_table_search_raw(HashTable *ht, void *key)
|
||||
{
|
||||
KeyValuePair *kv = hash_table_search_u64(ht, key_u64);
|
||||
return kv ? kv->value_raw : 0;
|
||||
U64 hash = hash_table_hasher(str8_struct(&key));
|
||||
U64 ibucket = hash % ht->cap;
|
||||
BucketList *bucket = ht->buckets + ibucket;
|
||||
for (BucketNode *n = bucket->first; n != 0; n = n->next) {
|
||||
if (n->v.key_raw == key) {
|
||||
return &n->v;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal KeyValuePair *
|
||||
@@ -230,13 +237,6 @@ hash_table_search_path(HashTable *ht, String8 path)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void *
|
||||
hash_table_search_path_raw(HashTable *ht, String8 path)
|
||||
{
|
||||
KeyValuePair *kv = hash_table_search_path(ht, path);
|
||||
return kv ? kv->value_raw : 0;
|
||||
}
|
||||
|
||||
internal B32
|
||||
hash_table_search_path_u64(HashTable *ht, String8 key, U64 *value_out)
|
||||
{
|
||||
@@ -250,6 +250,27 @@ hash_table_search_path_u64(HashTable *ht, String8 key, U64 *value_out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal void *
|
||||
hash_table_search_u64_raw(HashTable *ht, U64 key_u64)
|
||||
{
|
||||
KeyValuePair *kv = hash_table_search_u64(ht, key_u64);
|
||||
return kv ? kv->value_raw : 0;
|
||||
}
|
||||
|
||||
internal void *
|
||||
hash_table_search_path_raw(HashTable *ht, String8 path)
|
||||
{
|
||||
KeyValuePair *kv = hash_table_search_path(ht, path);
|
||||
return kv ? kv->value_raw : 0;
|
||||
}
|
||||
|
||||
internal void *
|
||||
hash_table_search_raw_raw(HashTable *ht, void *key)
|
||||
{
|
||||
KeyValuePair *kv = hash_table_search_raw(ht, key);
|
||||
return kv ? kv->value_raw : 0;
|
||||
}
|
||||
|
||||
internal B32
|
||||
hash_table_search_string_u64(HashTable *ht, String8 key, U64 *value_out)
|
||||
{
|
||||
@@ -283,6 +304,13 @@ hash_table_push_u32_u32(Arena *arena, HashTable *ht, U32 key, U32 value)
|
||||
return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_u32 = key, .value_u32 = value });
|
||||
}
|
||||
|
||||
internal BucketNode *
|
||||
hash_table_push_raw_raw(Arena *arena, HashTable *ht, void *key, void *value)
|
||||
{
|
||||
U64 hash = hash_table_hasher(str8_struct(&key));
|
||||
return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_raw = key, .value_raw = value });
|
||||
}
|
||||
|
||||
internal B32
|
||||
hash_table_search_string_string(HashTable *ht, String8 key, String8 *value_out)
|
||||
{
|
||||
@@ -381,6 +409,19 @@ key_value_pairs_from_hash_table(Arena *arena, HashTable *ht)
|
||||
return pairs;
|
||||
}
|
||||
|
||||
internal void *
|
||||
keys_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.key_raw;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void *
|
||||
values_from_hash_table_raw(Arena *arena, HashTable *ht)
|
||||
{
|
||||
|
||||
@@ -87,6 +87,7 @@ internal U64 * keys_from_hash_table_u64 (Arena *arena, HashTable
|
||||
internal String8 keys_from_hash_table_str8 (Arena *arena, HashTable *ht);
|
||||
internal KeyValuePair * key_value_pairs_from_hash_table(Arena *arena, HashTable *ht);
|
||||
|
||||
internal void * keys_from_hash_table_raw(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);
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
<Type Name="LNK_ExportParseList">
|
||||
<AlternativeType Name="LNK_InputObjList"/>
|
||||
<AlternativeType Name="LNK_InputList"/>
|
||||
<AlternativeType Name="LNK_LibMemberRefList"/>
|
||||
<DisplayString>{{count={count} first={first} last={last} }}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
@@ -92,6 +94,38 @@
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="LNK_SymbolHashTrieChunkList">
|
||||
<Expand>
|
||||
<Item Name="[chunk count]">count</Item>
|
||||
<CustomListItems MaxItemsPerView="5000">
|
||||
<Variable Name="node" InitialValue="first"/>
|
||||
<Variable Name="idx" InitialValue="0"/>
|
||||
<Loop>
|
||||
<Break Condition="node == 0"/>
|
||||
<Exec>idx = 0</Exec>
|
||||
<Loop>
|
||||
<Break Condition="idx >= node->count"/>
|
||||
<Item>node->v[idx]</Item>
|
||||
<Exec>idx += 1</Exec>
|
||||
</Loop>
|
||||
<Exec>node = node->next</Exec>
|
||||
</Loop>
|
||||
</CustomListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="LNK_SymbolHashTrieChunk">
|
||||
<DisplayString>{count,cap,v}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[count]">count</Item>
|
||||
<Item Name="[cap]">cap</Item>
|
||||
<ArrayItems>
|
||||
<Size>count</Size>
|
||||
<ValuePointer>v</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="RDIB_VariableChunkList">
|
||||
<AlternativeType Name="RDIB_UnitChunkList"/>
|
||||
<AlternativeType Name="RDIB_LineTableChunkList"/>
|
||||
|
||||
+1176
-1176
File diff suppressed because it is too large
Load Diff
+119
-33
@@ -3,21 +3,99 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// --- Link --------------------------------------------------------------------
|
||||
// --- Input -------------------------------------------------------------------
|
||||
|
||||
typedef struct LNK_LibMemberRef
|
||||
{
|
||||
LNK_Lib *lib;
|
||||
U32 member_idx;
|
||||
|
||||
struct LNK_LibMemberRef *next;
|
||||
} LNK_LibMemberRef;
|
||||
|
||||
typedef struct LNK_LibMemberRefList
|
||||
{
|
||||
U64 count;
|
||||
LNK_LibMemberRef *first;
|
||||
LNK_LibMemberRef *last;
|
||||
} LNK_LibMemberRefList;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LNK_InputSource_CmdLine, // specified on command line
|
||||
LNK_InputSource_Default, // specified through defaultlib switch
|
||||
LNK_InputSource_Obj, // refrenced from objects
|
||||
LNK_InputSource_Count
|
||||
} LNK_InputSourceType;
|
||||
|
||||
typedef struct LNK_Input
|
||||
{
|
||||
String8 path;
|
||||
String8 data;
|
||||
B32 disallow;
|
||||
B32 is_thin;
|
||||
B32 has_disk_read_failed;
|
||||
B32 exclude_from_debug_info;
|
||||
LNK_LibMemberRef *trigger;
|
||||
void *loaded_input;
|
||||
|
||||
struct LNK_Input *next;
|
||||
} LNK_Input;
|
||||
|
||||
typedef struct LNK_InputList
|
||||
{
|
||||
U64 count;
|
||||
LNK_Input *first;
|
||||
LNK_Input *last;
|
||||
} LNK_InputList;
|
||||
|
||||
typedef struct LNK_InputPtrArray
|
||||
{
|
||||
U64 count;
|
||||
LNK_Input **v;
|
||||
} LNK_InputPtrArray;
|
||||
|
||||
typedef struct LNK_Inputer
|
||||
{
|
||||
Arena *arena;
|
||||
|
||||
LNK_InputList objs;
|
||||
HashTable *objs_ht;
|
||||
LNK_InputList new_objs;
|
||||
|
||||
HashTable *libs_ht;
|
||||
HashTable *missing_lib_ht;
|
||||
LNK_InputList libs;
|
||||
LNK_InputList new_libs[LNK_InputSource_Count];
|
||||
} LNK_Inputer;
|
||||
|
||||
// --- Image Link -------------------------------------------------------------
|
||||
|
||||
#define LNK_IMPORT_STUB "*** RAD_IMPORT_STUB ***"
|
||||
#define LNK_NULL_SYMBOL "*** RAD_NULL_SYMBOL ***"
|
||||
|
||||
#define LNK_SECTION_FLAG_IS_LIVE (1 << 0)
|
||||
|
||||
typedef struct LNK_LinkContext
|
||||
typedef struct LNK_ImportTables
|
||||
{
|
||||
LNK_SymbolTable *symtab;
|
||||
U64 objs_count;
|
||||
LNK_Obj **objs;
|
||||
LNK_LibList lib_index[LNK_InputSource_Count];
|
||||
} LNK_LinkContext;
|
||||
Arena *arena;
|
||||
HashTable *static_imports;
|
||||
HashTable *delayed_imports;
|
||||
HashTable *import_stub_ht;
|
||||
} LNK_ImportTables;
|
||||
|
||||
// -- Image --------------------------------------------------------------------
|
||||
typedef struct LNK_Link
|
||||
{
|
||||
LNK_ObjList objs;
|
||||
LNK_LibList libs;
|
||||
LNK_IncludeSymbolNode **last_include;
|
||||
String8Node **last_cmd_lib;
|
||||
String8Node **last_default_lib;
|
||||
String8Node **last_obj_lib;
|
||||
B32 try_to_resolve_entry_point;
|
||||
} LNK_Link;
|
||||
|
||||
// -- Image Layout ------------------------------------------------------------
|
||||
|
||||
#define LNK_REMOVED_SECTION_NUMBER_32 (U32)-3
|
||||
#define LNK_REMOVED_SECTION_NUMBER_16 (U16)-3
|
||||
@@ -135,24 +213,6 @@ typedef struct
|
||||
B32 is_large_addr_aware;
|
||||
} LNK_ObjBaseRelocTask;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LNK_InputObjList input_obj_list;
|
||||
U64 input_imports_count;
|
||||
LNK_InputImport *input_imports;
|
||||
LNK_InputImportList input_import_list;
|
||||
LNK_SymbolList unresolved_symbol_list;
|
||||
} LNK_SymbolFinderResult;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PathStyle path_style;
|
||||
LNK_SymbolTable *symtab;
|
||||
LNK_SymbolNodeArray lookup_node_arr;
|
||||
LNK_SymbolFinderResult *result_arr;
|
||||
Rng1U64 *range_arr;
|
||||
} LNK_SymbolFinder;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
String8 image_data;
|
||||
@@ -203,17 +263,43 @@ internal String8 lnk_make_null_obj(Arena *arena);
|
||||
internal String8 lnk_make_res_obj(Arena *arena, String8List res_file_list, String8List res_path_list, COFF_MachineType machine, U32 time_stamp, String8 work_dir, PathStyle system_path_style, String8 obj_name);
|
||||
internal String8 lnk_make_linker_obj(Arena *arena, LNK_Config *config);
|
||||
|
||||
// --- Inputer -----------------------------------------------------------------
|
||||
|
||||
internal void lnk_input_list_push_node(LNK_InputList *list, LNK_Input *node);
|
||||
internal void lnk_input_list_concat_in_place(LNK_InputList *list, LNK_InputList *to_concat);
|
||||
internal LNK_InputPtrArray lnk_array_from_input_list(Arena *arena, LNK_InputList list);
|
||||
|
||||
internal LNK_Inputer * lnk_inputer_init(void);
|
||||
|
||||
internal LNK_Input * lnk_input_push(Arena *arena, LNK_InputList *list, String8 path, String8 data);
|
||||
internal LNK_Input * lnk_inputer_push_linkgen(Arena *arena, LNK_InputList *list, String8 path, String8 data);
|
||||
internal LNK_Input * lnk_inputer_push_thin(Arena *arena, LNK_InputList *list, HashTable *ht, String8 full_path);
|
||||
|
||||
internal LNK_Input * lnk_inputer_push_obj(LNK_Inputer *inputer, LNK_LibMemberRef *trigger, String8 path, String8 data);
|
||||
internal LNK_Input * lnk_inputer_push_obj_linkgen(LNK_Inputer *inputer, LNK_LibMemberRef *trigger, String8 path, String8 data);
|
||||
internal LNK_Input * lnk_inputer_push_obj_thin(LNK_Inputer *inputer, LNK_LibMemberRef *trigger, String8 path);
|
||||
|
||||
internal LNK_Input * lnk_inputer_push_lib(LNK_Inputer *inputer, LNK_InputSourceType input_source, String8 path, String8 data);
|
||||
internal LNK_Input * lnk_inputer_push_lib_linkgen(LNK_Inputer *inputer, LNK_InputSourceType input_source, String8 path, String8 data);
|
||||
internal LNK_Input * lnk_inputer_push_lib_thin(LNK_Inputer *inputer, LNK_Config *config, LNK_InputSourceType input_source, String8 lib_path);
|
||||
|
||||
internal B32 lnk_inputer_has_items(LNK_Inputer *inputer);
|
||||
internal LNK_InputPtrArray lnk_inputer_flush(Arena *arena, TP_Context *tp, LNK_Inputer *inputer, LNK_IO_Flags io_flags, LNK_InputList *all_inputs, LNK_InputList *new_inputs);
|
||||
|
||||
// --- Link Context ------------------------------------------------------------
|
||||
|
||||
internal String8 lnk_get_lib_name(String8 path);
|
||||
internal B32 lnk_is_lib_disallowed(HashTable *disallow_lib_ht, String8 path);
|
||||
internal B32 lnk_is_lib_loaded(HashTable *loaded_lib_ht, String8 lib_path);
|
||||
internal void lnk_push_disallow_lib(Arena *arena, HashTable *disallow_lib_ht, String8 path);
|
||||
internal void lnk_push_loaded_lib(Arena *arena, HashTable *loaded_lib_ht, String8 path);
|
||||
internal void lnk_lib_member_ref_list_push_node(LNK_LibMemberRefList *list, LNK_LibMemberRef *node);
|
||||
internal int lnk_lib_member_ref_is_before(void *raw_a, void *raw_b);
|
||||
internal LNK_LibMemberRef ** lnk_array_from_lib_member_list(Arena *arena, LNK_LibMemberRefList list);
|
||||
|
||||
internal void lnk_queue_lib_member_for_input(Arena *arena, LNK_Config *config, LNK_Symbol *pull_in_ref, LNK_Lib *lib, U32 member_idx, LNK_InputImportList *input_import_list, LNK_InputObjList *input_obj_list);
|
||||
internal LNK_ObjNode * lnk_load_objs (TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab, LNK_Link *link, U64 *objs_count_out);
|
||||
internal void lnk_load_libs (TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_Link *link);
|
||||
internal void lnk_link_inputs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab, LNK_Link *link, LNK_ImportTables *imps);
|
||||
internal LNK_Link * lnk_link_image (TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab);
|
||||
|
||||
internal LNK_LinkContext lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config);
|
||||
// --- Optimizations -----------------------------------------------------------
|
||||
|
||||
internal void lnk_opt_ref(TP_Context *tp, LNK_SymbolTable *symtab, LNK_Config *config, LNK_ObjList objs);
|
||||
|
||||
// --- Win32 Image -------------------------------------------------------------
|
||||
|
||||
|
||||
+102
-50
@@ -944,6 +944,57 @@ lnk_is_dll_delay_load(LNK_Config *config, String8 dll_name)
|
||||
return hash_table_search_path_u64(config->delay_load_ht, dll_name, 0);
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_get_lib_name(String8 path)
|
||||
{
|
||||
static String8 LIB_EXT = str8_lit_comp(".LIB");
|
||||
|
||||
// strip path
|
||||
String8 name = str8_skip_last_slash(path);
|
||||
|
||||
// strip extension
|
||||
String8 name_ext = str8_postfix(name, LIB_EXT.size);
|
||||
if (str8_match(name_ext, LIB_EXT, StringMatchFlag_CaseInsensitive)) {
|
||||
name = str8_chop(name, LIB_EXT.size);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_push_disallow_lib(LNK_Config *config, String8 path)
|
||||
{
|
||||
String8 lib_name = lnk_get_lib_name(path);
|
||||
hash_table_push_path_u64(config->arena, config->disallow_lib_ht, lib_name, 0);
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_is_lib_disallowed(LNK_Config *config, String8 path)
|
||||
{
|
||||
String8 lib_name = lnk_get_lib_name(path);
|
||||
return hash_table_search_path(config->disallow_lib_ht, lib_name) != 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_include_symbol(LNK_Config *config, String8 name, LNK_Obj *obj)
|
||||
{
|
||||
// is this a duplicate symbol?
|
||||
if (hash_table_search_string_raw(config->include_symbol_ht, name, 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
name = push_str8_copy(config->arena, name);
|
||||
|
||||
LNK_IncludeSymbolNode *node = push_array(config->arena, LNK_IncludeSymbolNode, 1);
|
||||
node->v.name = name;
|
||||
node->v.obj = obj;
|
||||
|
||||
SLLQueuePush(config->include_symbol_list.first, config->include_symbol_list.last, node);
|
||||
config->include_symbol_list.count += 1;
|
||||
|
||||
hash_table_push_string_raw(config->arena, config->include_symbol_ht, name, node);
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_print_build_info()
|
||||
{
|
||||
@@ -1068,9 +1119,9 @@ lnk_unwrap_rsp(Arena *arena, String8List arg_list)
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_name, String8List value_strings, LNK_Obj *obj)
|
||||
lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List value_strings, LNK_Obj *obj)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena,1);
|
||||
Temp scratch = scratch_begin(&config->arena, 1);
|
||||
|
||||
LNK_CmdSwitchType cmd_switch = lnk_cmd_switch_type_from_string(cmd_name);
|
||||
|
||||
@@ -1111,12 +1162,12 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
lnk_error_obj(LNK_Error_AlternateNameConflict, obj, "conflicting alternative name: existing '%S=%S' vs. new '%S=%S'", alt_name.from, to_extant, alt_name.from, alt_name.to);
|
||||
}
|
||||
} else {
|
||||
hash_table_push_string_string(arena, config->alt_name_ht, alt_name.from, alt_name.to);
|
||||
hash_table_push_string_string(config->arena, config->alt_name_ht, alt_name.from, alt_name.to);
|
||||
|
||||
alt_name.from = push_str8_copy(arena, alt_name.from);
|
||||
alt_name.to = push_str8_copy(arena, alt_name.to);
|
||||
alt_name.from = push_str8_copy(config->arena, alt_name.from);
|
||||
alt_name.to = push_str8_copy(config->arena, alt_name.to);
|
||||
|
||||
LNK_AltNameNode *alt_name_n = push_array(arena, LNK_AltNameNode, 1);
|
||||
LNK_AltNameNode *alt_name_n = push_array(config->arena, LNK_AltNameNode, 1);
|
||||
alt_name_n->data = alt_name;
|
||||
|
||||
SLLQueuePush(config->alt_name_list.first, config->alt_name_list.last, alt_name_n);
|
||||
@@ -1182,7 +1233,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_DefaultLib: {
|
||||
String8List default_lib_list = str8_list_copy(arena, &value_strings);
|
||||
String8List default_lib_list = str8_list_copy(config->arena, &value_strings);
|
||||
if (obj) {
|
||||
str8_list_concat_in_place(&config->input_obj_lib_list, &default_lib_list);
|
||||
} else {
|
||||
@@ -1208,9 +1259,9 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
case LNK_CmdSwitch_DelayLoad: {
|
||||
for (String8Node *name_n = value_strings.first; name_n != 0; name_n = name_n->next) {
|
||||
if (hash_table_search_path_u64(config->delay_load_ht, name_n->string, 0)) { continue; }
|
||||
String8 name = push_str8_copy(arena, name_n->string);
|
||||
hash_table_push_path_u64(arena, config->delay_load_ht, name, 0);
|
||||
str8_list_push(arena, &config->delay_load_dll_list, name);
|
||||
String8 name = push_str8_copy(config->arena, name_n->string);
|
||||
hash_table_push_path_u64(config->arena, config->delay_load_ht, name, 0);
|
||||
str8_list_push(config->arena, &config->delay_load_dll_list, name);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1228,7 +1279,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
|
||||
case LNK_CmdSwitch_Entry: {
|
||||
String8 new_entry_point_name = {0};
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &new_entry_point_name);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &new_entry_point_name);
|
||||
|
||||
if (config->entry_point_name.size) {
|
||||
lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "unable to redefine entry point \"%S\" to \"%S\"", config->entry_point_name, new_entry_point_name);
|
||||
@@ -1240,7 +1291,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
|
||||
case LNK_CmdSwitch_Export: {
|
||||
PE_ExportParse export_parse = {0};
|
||||
if (lnk_parse_export_directive_ex(arena, value_strings, obj, &export_parse)) {
|
||||
if (lnk_parse_export_directive_ex(config->arena, value_strings, obj, &export_parse)) {
|
||||
PE_ExportParseNode *exp_n = 0;
|
||||
String8 export_name = pe_name_from_export_parse(&export_parse);
|
||||
hash_table_search_string_raw(config->export_ht, export_name, &exp_n);
|
||||
@@ -1248,13 +1299,13 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
if (exp_n == 0) {
|
||||
// make sure export is defined
|
||||
if (!export_parse.is_forwarder) {
|
||||
str8_list_push(arena, &config->include_symbol_list, export_parse.name);
|
||||
lnk_include_symbol(config, export_parse.name, 0);
|
||||
}
|
||||
|
||||
// push new export
|
||||
exp_n = pe_export_parse_list_push(arena, &config->export_symbol_list, export_parse);
|
||||
exp_n = pe_export_parse_list_push(config->arena, &config->export_symbol_list, export_parse);
|
||||
|
||||
hash_table_push_string_raw(arena, config->export_ht, export_name, exp_n);
|
||||
hash_table_push_string_raw(config->arena, config->export_ht, export_name, exp_n);
|
||||
} else {
|
||||
B32 is_ambiguous = 1;
|
||||
PE_ExportParse *extant_export = &exp_n->data;
|
||||
@@ -1352,19 +1403,12 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_ImpLib: {
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &config->imp_lib_name);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->imp_lib_name);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Include: {
|
||||
for (String8Node *value_n = value_strings.first; value_n != 0; value_n = value_n->next) {
|
||||
// is this a duplicate symbol?
|
||||
if (hash_table_search_string_raw(config->include_symbol_ht, value_n->string, 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String8 include_symbol = push_str8_copy(arena, value_n->string);
|
||||
hash_table_push_string_raw(arena, config->include_symbol_ht, include_symbol, 0);
|
||||
str8_list_push(arena, &config->include_symbol_list, include_symbol);
|
||||
lnk_include_symbol(config, value_n->string, obj);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1386,7 +1430,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_LibPath: {
|
||||
String8List lib_dir_list = str8_list_copy(arena, &value_strings);
|
||||
String8List lib_dir_list = str8_list_copy(config->arena, &value_strings);
|
||||
for (String8Node *dir_n = lib_dir_list.first; dir_n != 0; dir_n = dir_n->next) {
|
||||
if (!os_folder_path_exists(dir_n->string)) {
|
||||
String8 full_path = os_full_path_from_path(scratch.arena, dir_n->string);
|
||||
@@ -1426,7 +1470,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
if (res_id_arr.count == 2) {
|
||||
U64 resource_id;
|
||||
if (try_u64_from_str8_c_rules(res_id_arr.v[1], &resource_id)) {
|
||||
config->manifest_resource_id = push_u64(arena, resource_id);
|
||||
config->manifest_resource_id = push_u64(config->arena, resource_id);
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse resource_id \"%S\"", res_id_arr.v[1]);
|
||||
}
|
||||
@@ -1455,7 +1499,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_ManifestDependency: {
|
||||
String8List manifest_dependency_list = str8_list_copy(arena, &value_strings);
|
||||
String8List manifest_dependency_list = str8_list_copy(config->arena, &value_strings);
|
||||
str8_list_concat_in_place(&config->manifest_dependency_list, &manifest_dependency_list);
|
||||
|
||||
if (config->manifest_opt == LNK_ManifestOpt_Null) {
|
||||
@@ -1464,7 +1508,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_ManifestFile: {
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &config->manifest_name);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->manifest_name);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_ManifestInput: {
|
||||
@@ -1488,7 +1532,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
str8_match_lit("'requireAdministrator'", level, 0)) {
|
||||
// manifest level was parsed!
|
||||
config->manifest_uac = 1;
|
||||
config->manifest_level = push_str8_copy(arena, level);
|
||||
config->manifest_level = push_str8_copy(config->arena, level);
|
||||
if (param_arr.count > 1) {
|
||||
String8 ui_access_param = param_arr.v[1];
|
||||
String8List ui_access_list = str8_split_by_string_chars(scratch.arena, ui_access_param, str8_lit("="), 0);
|
||||
@@ -1497,7 +1541,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
if (str8_match_lit("'true'", ui_access, 0) ||
|
||||
str8_match_lit("'false'", ui_access, 0)) {
|
||||
// ui access was parsed!
|
||||
config->manifest_ui_access = push_str8_copy(arena, ui_access);
|
||||
config->manifest_ui_access = push_str8_copy(config->arena, ui_access);
|
||||
} else {
|
||||
lnk_error_invalid_uac_ui_access_param(LNK_Error_Cmdl, obj, cmd_switch, ui_access_param);
|
||||
}
|
||||
@@ -1531,9 +1575,9 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
if (value_strings.node_count == 1) {
|
||||
LNK_MergeDirective merge = {0};
|
||||
if (lnk_parse_merge_directive(value_strings.first->string, obj, &merge)) {
|
||||
merge.src = push_str8_copy(arena, merge.src);
|
||||
merge.dst = push_str8_copy(arena, merge.dst);
|
||||
lnk_merge_directive_list_push(arena, &config->merge_list, merge);
|
||||
merge.src = push_str8_copy(config->arena, merge.src);
|
||||
merge.dst = push_str8_copy(config->arena, merge.dst);
|
||||
lnk_merge_directive_list_push(config->arena, &config->merge_list, merge);
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters %d", value_strings.node_count);
|
||||
@@ -1549,7 +1593,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
}
|
||||
}
|
||||
|
||||
String8List natvis_list = str8_list_copy(arena, &value_strings);
|
||||
String8List natvis_list = str8_list_copy(config->arena, &value_strings);
|
||||
str8_list_concat_in_place(&config->natvis_list, &natvis_list);
|
||||
} break;
|
||||
|
||||
@@ -1558,8 +1602,13 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
if (value_strings.node_count == 0) {
|
||||
config->no_default_libs = 1;
|
||||
} else {
|
||||
String8List no_default_lib_list = str8_list_copy(arena, &value_strings);
|
||||
str8_list_concat_in_place(&config->disallow_lib_list, &no_default_lib_list);
|
||||
for (String8Node *lib_n = value_strings.first; lib_n != 0; lib_n = lib_n->next) {
|
||||
String8 lib_name = lnk_get_lib_name(lib_n->string);
|
||||
if (hash_table_search_path_raw(config->disallow_lib_ht, lib_name)) {
|
||||
continue;
|
||||
}
|
||||
hash_table_push_path_raw(config->arena, config->disallow_lib_ht, lib_name, 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1614,16 +1663,16 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Out: {
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &config->image_name);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->image_name);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Pdb: {
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &config->pdb_name);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->pdb_name);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_PdbAltPath: {
|
||||
// see :PdbAltPath
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &config->pdb_alt_path);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->pdb_alt_path);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_PdbPageSize: {
|
||||
@@ -1723,7 +1772,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_Map: {
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &config->rad_chunk_map_name);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->rad_chunk_map_name);
|
||||
config->rad_chunk_map = LNK_SwitchState_Yes;
|
||||
} break;
|
||||
|
||||
@@ -1737,11 +1786,11 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
|
||||
case LNK_CmdSwitch_Rad_DebugName: {
|
||||
// :Rad_DebugAltPath
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &config->rad_debug_name);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->rad_debug_name);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_DebugAltPath: {
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &config->rad_debug_alt_path);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->rad_debug_alt_path);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_DelayBind: {
|
||||
@@ -1839,7 +1888,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_MtPath: {
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &config->mt_path);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->mt_path);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_OsVer: {
|
||||
@@ -1880,7 +1929,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_PdbHashTypeNameMap: {
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj, cmd_switch, value_strings, &config->pdb_hash_type_name_map);
|
||||
lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->pdb_hash_type_name_map);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_PdbHashTypeNameLength: {
|
||||
@@ -1890,8 +1939,8 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
case LNK_CmdSwitch_Rad_RemoveSection: {
|
||||
String8 sect_name = {0};
|
||||
if (lnk_cmd_switch_parse_string(obj, cmd_switch, value_strings, §_name)) {
|
||||
sect_name = push_str8_copy(arena, sect_name);
|
||||
str8_list_push(arena, &config->remove_sections, sect_name);
|
||||
sect_name = push_str8_copy(config->arena, sect_name);
|
||||
str8_list_push(config->arena, &config->remove_sections, sect_name);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1991,12 +2040,14 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
}
|
||||
|
||||
internal LNK_Config *
|
||||
lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line, LNK_CmdLine cmd_line)
|
||||
lnk_config_from_cmd_line(String8List raw_cmd_line, LNK_CmdLine cmd_line)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
LNK_Config *config = push_array(arena, LNK_Config, 1);
|
||||
Arena *arena = arena_alloc();
|
||||
LNK_Config *config = push_array(arena, LNK_Config, 1);
|
||||
config->arena = arena;
|
||||
config->raw_cmd_line = str8_list_copy(arena, &raw_cmd_line);
|
||||
config->work_dir = os_get_current_path(arena);
|
||||
config->build_imp_lib = 1;
|
||||
@@ -2012,10 +2063,11 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line, LNK_CmdLine cmd
|
||||
config->alt_name_ht = hash_table_init(arena, 0x100);
|
||||
config->include_symbol_ht = hash_table_init(arena, 0x100);
|
||||
config->delay_load_ht = hash_table_init(arena, 0x100);
|
||||
config->disallow_lib_ht = hash_table_init(arena, 0x100);
|
||||
|
||||
// process command line switches
|
||||
for (LNK_CmdOption *cmd = cmd_line.first_option; cmd != 0; cmd = cmd->next) {
|
||||
lnk_apply_cmd_option_to_config(arena, config, cmd->string, cmd->value_strings, 0);
|
||||
lnk_apply_cmd_option_to_config(config, cmd->string, cmd->value_strings, 0);
|
||||
}
|
||||
|
||||
// :manifest_input
|
||||
|
||||
+34
-8
@@ -249,6 +249,25 @@ typedef enum
|
||||
LNK_ManifestOpt_No,
|
||||
} LNK_ManifestOpt;
|
||||
|
||||
typedef struct LNK_IncludeSymbol
|
||||
{
|
||||
String8 name;
|
||||
struct LNK_Obj *obj;
|
||||
} LNK_IncludeSymbol;
|
||||
|
||||
typedef struct LNK_IncludeSymbolNode
|
||||
{
|
||||
struct LNK_IncludeSymbolNode *next;
|
||||
LNK_IncludeSymbol v;
|
||||
} LNK_IncludeSymbolNode;
|
||||
|
||||
typedef struct LNK_IncludeSymbolList
|
||||
{
|
||||
U64 count;
|
||||
LNK_IncludeSymbolNode *first;
|
||||
LNK_IncludeSymbolNode *last;
|
||||
} LNK_IncludeSymbolList;
|
||||
|
||||
typedef struct LNK_AltName
|
||||
{
|
||||
String8 from;
|
||||
@@ -304,6 +323,7 @@ typedef enum
|
||||
|
||||
typedef struct LNK_Config
|
||||
{
|
||||
Arena *arena;
|
||||
LNK_ConfigFlags flags;
|
||||
LNK_DebugMode debug_mode;
|
||||
LNK_SwitchState opt_ref;
|
||||
@@ -362,7 +382,6 @@ typedef struct LNK_Config
|
||||
String8List input_list[LNK_Input_Count];
|
||||
String8List input_obj_lib_list;
|
||||
String8List input_default_lib_list;
|
||||
String8List disallow_lib_list;
|
||||
String8List delay_load_dll_list;
|
||||
String8List natvis_list;
|
||||
String8 manifest_name;
|
||||
@@ -375,7 +394,7 @@ typedef struct LNK_Config
|
||||
String8 rad_chunk_map_name;
|
||||
String8 rad_debug_name;
|
||||
String8 rad_debug_alt_path;
|
||||
String8List include_symbol_list;
|
||||
LNK_IncludeSymbolList include_symbol_list;
|
||||
LNK_AltNameList alt_name_list;
|
||||
LNK_MergeDirectiveList merge_list;
|
||||
U64 symbol_table_cap_defined;
|
||||
@@ -397,6 +416,7 @@ typedef struct LNK_Config
|
||||
HashTable *alt_name_ht;
|
||||
HashTable *include_symbol_ht;
|
||||
HashTable *delay_load_ht;
|
||||
HashTable *disallow_lib_ht;
|
||||
} LNK_Config;
|
||||
|
||||
// --- MSVC Error Codes --------------------------------------------------------
|
||||
@@ -573,20 +593,26 @@ internal LNK_MergeDirectiveNode * lnk_merge_directive_list_push(Arena *arena, LN
|
||||
|
||||
// --- Getters -----------------------------------------------------------------
|
||||
|
||||
internal String8 lnk_get_image_name(LNK_Config *config);
|
||||
internal U64 lnk_get_default_function_pad_min(COFF_MachineType machine);
|
||||
internal U64 lnk_get_base_addr(LNK_Config *config);
|
||||
internal String8 lnk_get_image_name (LNK_Config *config);
|
||||
internal U64 lnk_get_default_function_pad_min (COFF_MachineType machine);
|
||||
internal U64 lnk_get_base_addr (LNK_Config *config);
|
||||
internal Version lnk_get_default_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType machine);
|
||||
internal Version lnk_get_min_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType machine);
|
||||
internal Version lnk_get_min_subsystem_version (PE_WindowsSubsystem subsystem, COFF_MachineType machine);
|
||||
|
||||
internal B32 lnk_do_debug_info (LNK_Config *config);
|
||||
internal B32 lnk_is_thread_pool_shared(LNK_Config *config);
|
||||
internal B32 lnk_is_section_removed (LNK_Config *config, String8 section_name);
|
||||
internal B32 lnk_is_dll_delay_load (LNK_Config *config, String8 dll_name);
|
||||
|
||||
internal String8 lnk_get_lib_name (String8 path);
|
||||
internal void lnk_push_disallow_lib(LNK_Config *config, String8 path);
|
||||
internal B32 lnk_is_lib_disallowed(LNK_Config *config, String8 path);
|
||||
|
||||
internal void lnk_include_symbol(LNK_Config *config, String8 name, struct LNK_Obj *obj);
|
||||
|
||||
// --- Config ------------------------------------------------------------------
|
||||
|
||||
internal void lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 name, String8List value_list, struct LNK_Obj *obj);
|
||||
internal void lnk_apply_cmd_option_to_config(LNK_Config *config, String8 name, String8List value_list, struct LNK_Obj *obj);
|
||||
|
||||
internal LNK_Config * lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line, LNK_CmdLine cmd_line);
|
||||
internal LNK_Config * lnk_config_from_cmd_line(String8List raw_cmd_line, LNK_CmdLine cmd_line);
|
||||
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
// Copyright (c) 2025 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal void
|
||||
lnk_error_input_obj(LNK_ErrorCode code, LNK_InputObj *input, char *fmt, ...)
|
||||
{
|
||||
va_list args; va_start(args, fmt);
|
||||
lnk_error_with_loc_fv(code, input->path, input->lib ? input->lib->path : str8_zero(), fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_string_from_input_source(LNK_InputSourceType input_source)
|
||||
{
|
||||
String8 result = str8_zero();
|
||||
switch (input_source) {
|
||||
case LNK_InputSource_CmdLine: result = str8_lit("CmdLine"); break;
|
||||
case LNK_InputSource_Default: result = str8_lit("Default"); break;
|
||||
case LNK_InputSource_Obj: result = str8_lit("Obj"); break;
|
||||
default: InvalidPath;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_input_obj_list_push_node(LNK_InputObjList *list, LNK_InputObj *node)
|
||||
{
|
||||
SLLQueuePush(list->first, list->last, node);
|
||||
++list->count;
|
||||
}
|
||||
|
||||
internal LNK_InputObj *
|
||||
lnk_input_obj_list_push(Arena *arena, LNK_InputObjList *list)
|
||||
{
|
||||
LNK_InputObj *node = push_array(arena, LNK_InputObj, 1);
|
||||
lnk_input_obj_list_push_node(list, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_input_obj_list_concat_in_place(LNK_InputObjList *list, LNK_InputObjList *to_concat)
|
||||
{
|
||||
SLLConcatInPlace(list, to_concat);
|
||||
}
|
||||
|
||||
internal LNK_InputObj **
|
||||
lnk_array_from_input_obj_list(Arena *arena, LNK_InputObjList list)
|
||||
{
|
||||
LNK_InputObj **result = push_array_no_zero(arena, LNK_InputObj *, list.count);
|
||||
U64 i = 0;
|
||||
for (LNK_InputObj *n = list.first; n != 0; n = n->next, ++i) {
|
||||
Assert(i < list.count);
|
||||
result[i] = n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal LNK_InputObj **
|
||||
lnk_thin_array_from_input_obj_list(Arena *arena, LNK_InputObjList list, U64 *count_out)
|
||||
{
|
||||
for (LNK_InputObj *input = list.first; input != 0; input = input->next) {
|
||||
if (input->is_thin) { *count_out += 1; }
|
||||
}
|
||||
LNK_InputObj **thin_inputs = push_array(arena, LNK_InputObj *, *count_out);
|
||||
U64 input_idx = 0;
|
||||
for (LNK_InputObj *input = list.first; input != 0; input = input->next) {
|
||||
if (input->is_thin) { thin_inputs[input_idx++] = input; }
|
||||
}
|
||||
return thin_inputs;
|
||||
}
|
||||
|
||||
internal String8Array
|
||||
lnk_path_array_from_input_obj_array(Arena *arena, LNK_InputObj **arr, U64 count)
|
||||
{
|
||||
String8Array paths = {0};
|
||||
paths.count = count;
|
||||
paths.v = push_array(arena, String8, count);
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
paths.v[i] = arr[i]->path;
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
internal int
|
||||
lnk_input_obj_compar(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
LNK_InputObj * const *a = raw_a, * const *b = raw_b;
|
||||
return u64_compar(&(*a)->input_idx, &(*b)->input_idx);
|
||||
}
|
||||
|
||||
internal int
|
||||
lnk_input_obj_compar_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
LNK_InputObj **a = raw_a, **b = raw_b;
|
||||
return lnk_input_obj_compar(a, b) < 0;
|
||||
}
|
||||
|
||||
internal LNK_InputObjList
|
||||
lnk_list_from_input_obj_arr(LNK_InputObj **arr, U64 count)
|
||||
{
|
||||
LNK_InputObjList list = {0};
|
||||
for (U64 i = 0; i < count; ++i) {
|
||||
SLLQueuePush(list.first, list.last, arr[i]);
|
||||
++list.count;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
internal LNK_InputObjList
|
||||
lnk_input_obj_list_from_string_list(Arena *arena, String8List list)
|
||||
{
|
||||
LNK_InputObjList input_list = {0};
|
||||
for (String8Node *path = list.first; path != 0; path = path->next) {
|
||||
LNK_InputObj *input = lnk_input_obj_list_push(arena, &input_list);
|
||||
input->is_thin = 1;
|
||||
input->dedup_id = path->string;
|
||||
input->path = path->string;
|
||||
}
|
||||
return input_list;
|
||||
}
|
||||
|
||||
internal LNK_InputImportNode *
|
||||
lnk_input_import_list_push(Arena *arena, LNK_InputImportList *list)
|
||||
{
|
||||
LNK_InputImportNode *node = push_array(arena, LNK_InputImportNode, 1);
|
||||
SLLQueuePush(list->first, list->last, node);
|
||||
list->count += 1;
|
||||
return node;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_input_import_list_concat_in_place(LNK_InputImportList *list, LNK_InputImportList *to_concat)
|
||||
{
|
||||
SLLConcatInPlace(list, to_concat);
|
||||
}
|
||||
|
||||
internal LNK_InputImportNode **
|
||||
lnk_input_import_arr_from_list(Arena *arena, LNK_InputImportList list)
|
||||
{
|
||||
LNK_InputImportNode **result = push_array_no_zero(arena, LNK_InputImportNode *, list.count);
|
||||
U64 idx = 0;
|
||||
for (LNK_InputImportNode *node = list.first; node != 0; node = node->next) {
|
||||
Assert(idx < list.count);
|
||||
result[idx++] = node;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal LNK_InputImportList
|
||||
lnk_list_from_input_import_arr(LNK_InputImportNode **arr, U64 count)
|
||||
{
|
||||
LNK_InputImportList list = {0};
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
SLLQueuePush(list.first, list.last, arr[i]);
|
||||
list.count += 1;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
int
|
||||
lnk_input_import_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
LNK_InputImport *a = *(LNK_InputImport **)raw_a;
|
||||
LNK_InputImport *b = *(LNK_InputImport **)raw_b;
|
||||
return a->input_idx < b->input_idx;
|
||||
}
|
||||
|
||||
int
|
||||
lnk_input_import_node_compar(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
LNK_InputImportNode * const *a = raw_a;
|
||||
LNK_InputImportNode * const *b = raw_b;
|
||||
return u64_compar(&(*a)->data.input_idx, &(*b)->data.input_idx);
|
||||
}
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
// Copyright (c) 2025 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LNK_InputSource_CmdLine, // specified on command line
|
||||
LNK_InputSource_Default, // specified through defaultlib switch
|
||||
LNK_InputSource_Obj, // refrenced from objects
|
||||
LNK_InputSource_Count
|
||||
} LNK_InputSourceType;
|
||||
|
||||
typedef String8Node LNK_InputLib;
|
||||
typedef String8List LNK_InputLibList;
|
||||
|
||||
typedef struct LNK_InputImport
|
||||
{
|
||||
String8 coff_import;
|
||||
U64 input_idx;
|
||||
struct LNK_Lib *lib;
|
||||
} LNK_InputImport;
|
||||
|
||||
typedef struct LNK_InputImportNode
|
||||
{
|
||||
struct LNK_InputImportNode *next;
|
||||
LNK_InputImport data;
|
||||
} LNK_InputImportNode;
|
||||
|
||||
typedef struct LNK_InputImportList
|
||||
{
|
||||
U64 count;
|
||||
LNK_InputImportNode *first;
|
||||
LNK_InputImportNode *last;
|
||||
} LNK_InputImportList;
|
||||
|
||||
typedef struct LNK_InputObj
|
||||
{
|
||||
String8 path;
|
||||
String8 dedup_id;
|
||||
String8 data;
|
||||
B8 is_thin;
|
||||
B8 exclude_from_debug_info;
|
||||
B8 has_disk_read_failed;
|
||||
struct LNK_Lib *lib;
|
||||
U64 input_idx;
|
||||
struct LNK_InputObj *next;
|
||||
} LNK_InputObj;
|
||||
|
||||
typedef struct LNK_InputObjList
|
||||
{
|
||||
U64 count;
|
||||
LNK_InputObj *first;
|
||||
LNK_InputObj *last;
|
||||
} LNK_InputObjList;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void lnk_error_input_obj(LNK_ErrorCode code, LNK_InputObj *input, char *fmt, ...);
|
||||
|
||||
internal String8 lnk_string_from_input_source(LNK_InputSourceType input_source);
|
||||
|
||||
internal void lnk_input_obj_list_push_node(LNK_InputObjList *list, LNK_InputObj *node);
|
||||
internal LNK_InputObj * lnk_input_obj_list_push(Arena *arena, LNK_InputObjList *list);
|
||||
internal void lnk_input_obj_list_concat_in_place(LNK_InputObjList *list, LNK_InputObjList *to_concat);
|
||||
|
||||
internal LNK_InputObj ** lnk_array_from_input_obj_list(Arena *arena, LNK_InputObjList list);
|
||||
internal LNK_InputObj ** lnk_thin_array_from_input_obj_list(Arena *arena, LNK_InputObjList list, U64 *count_out);
|
||||
internal String8Array lnk_path_array_from_input_obj_array(Arena *arena, LNK_InputObj **arr, U64 count);
|
||||
internal LNK_InputObjList lnk_list_from_input_obj_arr(LNK_InputObj **arr, U64 count);
|
||||
internal LNK_InputObjList lnk_input_obj_list_from_string_list(Arena *arena, String8List list);
|
||||
|
||||
internal LNK_InputImportNode * lnk_input_import_list_push(Arena *arena, LNK_InputImportList *list);
|
||||
internal void lnk_input_import_list_concat_in_place(LNK_InputImportList *list, LNK_InputImportList *to_concat);
|
||||
internal LNK_InputImportNode ** lnk_input_import_arr_from_list(Arena *arena, LNK_InputImportList list);
|
||||
internal LNK_InputImportList lnk_list_from_input_import_arr(LNK_InputImportNode **arr, U64 count);
|
||||
|
||||
+33
-16
@@ -10,8 +10,7 @@ lnk_lib_node_is_before(void *a, void *b)
|
||||
internal int
|
||||
lnk_lib_node_ptr_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
LNK_LibNode **a = raw_a, **b = raw_b;
|
||||
return lnk_lib_node_is_before(*a, *b);
|
||||
return raw_a < raw_b;
|
||||
}
|
||||
|
||||
internal B32
|
||||
@@ -117,7 +116,7 @@ lnk_lib_from_data(Arena *arena, String8 data, String8 path, LNK_Lib *lib_out)
|
||||
lib_out->symbol_count = symbol_count;
|
||||
lib_out->member_offsets = member_offsets;
|
||||
lib_out->symbol_indices = symbol_indices;
|
||||
lib_out->was_member_queued = push_array(arena, B8, member_count);
|
||||
lib_out->was_member_linked = push_array(arena, LNK_Symbol *, member_count);
|
||||
lib_out->symbol_names = symbol_names;
|
||||
lib_out->long_names = parse.long_names;
|
||||
|
||||
@@ -128,13 +127,13 @@ lnk_lib_from_data(Arena *arena, String8 data, String8 path, LNK_Lib *lib_out)
|
||||
internal
|
||||
THREAD_POOL_TASK_FUNC(lnk_lib_initer)
|
||||
{
|
||||
LNK_LibIniter *task = raw_task;
|
||||
LNK_LibIniter *task = raw_task;
|
||||
LNK_Input *input = task->inputs[task_id];
|
||||
|
||||
U64 lib_node_idx = ins_atomic_u64_inc_eval(&task->next_free_lib_idx)-1;
|
||||
LNK_LibNode *lib_node = &task->free_libs[lib_node_idx];
|
||||
lib_node->data.input_idx = task_id;
|
||||
|
||||
B32 is_valid_lib = lnk_lib_from_data(arena, task->data_arr[task_id], task->path_arr[task_id], &lib_node->data);
|
||||
B32 is_valid_lib = lnk_lib_from_data(arena, input->data, input->path, &lib_node->data);
|
||||
if (is_valid_lib) {
|
||||
U64 valid_lib_idx = ins_atomic_u64_inc_eval(&task->valid_libs_count)-1;
|
||||
task->valid_libs[valid_lib_idx] = lib_node;
|
||||
@@ -144,6 +143,17 @@ THREAD_POOL_TASK_FUNC(lnk_lib_initer)
|
||||
}
|
||||
}
|
||||
|
||||
internal LNK_Lib **
|
||||
lnk_array_from_lib_list(Arena *arena, LNK_LibList list)
|
||||
{
|
||||
LNK_Lib **arr = push_array_no_zero(arena, LNK_Lib *, list.count);
|
||||
U64 idx = 0;
|
||||
for (LNK_LibNode *node = list.first; node != 0; node = node->next, ++idx) {
|
||||
arr[idx] = &node->data;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_lib_list_push_node(LNK_LibList *list, LNK_LibNode *node)
|
||||
{
|
||||
@@ -152,32 +162,31 @@ lnk_lib_list_push_node(LNK_LibList *list, LNK_LibNode *node)
|
||||
}
|
||||
|
||||
internal LNK_LibNodeArray
|
||||
lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, String8Array data_arr, String8Array path_arr)
|
||||
lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, U64 inputs_count, LNK_Input **inputs)
|
||||
{
|
||||
Temp scratch = scratch_begin(arena->v, arena->count);
|
||||
|
||||
Assert(data_arr.count == path_arr.count);
|
||||
U64 lib_count = data_arr.count;
|
||||
U64 lib_id_base = list->count;
|
||||
|
||||
// parse libs in parallel
|
||||
LNK_LibIniter task = {0};
|
||||
task.free_libs = push_array(arena->v[0], LNK_LibNode, lib_count);
|
||||
task.valid_libs = push_array(scratch.arena, LNK_LibNode *, lib_count);
|
||||
task.invalid_libs = push_array(scratch.arena, LNK_LibNode *, lib_count);
|
||||
task.data_arr = data_arr.v;
|
||||
task.path_arr = path_arr.v;
|
||||
tp_for_parallel(tp, arena, lib_count, lnk_lib_initer, &task);
|
||||
task.free_libs = push_array(arena->v[0], LNK_LibNode, inputs_count);
|
||||
task.valid_libs = push_array(scratch.arena, LNK_LibNode *, inputs_count);
|
||||
task.invalid_libs = push_array(scratch.arena, LNK_LibNode *, inputs_count);
|
||||
task.inputs = inputs;
|
||||
tp_for_parallel(tp, arena, inputs_count, lnk_lib_initer, &task);
|
||||
|
||||
// report invalid libs
|
||||
radsort(task.invalid_libs, task.invalid_libs_count, lnk_lib_node_ptr_is_before);
|
||||
for EachIndex(i, task.invalid_libs_count) {
|
||||
U64 input_idx = task.invalid_libs[i]->data.input_idx;
|
||||
lnk_error(LNK_Error_InvalidLib, "%S: failed to parse library", path_arr.v[input_idx]);
|
||||
lnk_error(LNK_Error_InvalidLib, "%S: failed to parse library", inputs[input_idx]->path);
|
||||
}
|
||||
|
||||
// push parsed libs
|
||||
radsort(task.valid_libs, task.valid_libs_count, lnk_lib_node_ptr_is_before);
|
||||
for EachIndex(i, task.valid_libs_count) {
|
||||
task.valid_libs[i]->data.input_idx = lib_id_base + i;
|
||||
lnk_lib_list_push_node(list, task.valid_libs[i]);
|
||||
}
|
||||
|
||||
@@ -187,6 +196,14 @@ lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, S
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_flag_member_as_queued(LNK_Lib *lib, U32 member_idx, LNK_Symbol *trigger)
|
||||
{
|
||||
LNK_Symbol *slot = ins_atomic_ptr_eval_cond_assign(&lib->was_member_linked[member_idx], trigger, 0);
|
||||
B32 is_first_queue_attempt = (slot == 0);
|
||||
return is_first_queue_attempt;
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_search_lib(LNK_Lib *lib, String8 symbol_name, U32 *member_idx_out)
|
||||
{
|
||||
|
||||
+12
-10
@@ -11,7 +11,7 @@ typedef struct LNK_Lib
|
||||
U32 symbol_count;
|
||||
U32 *member_offsets;
|
||||
U16 *symbol_indices;
|
||||
B8 *was_member_queued;
|
||||
LNK_Symbol **was_member_linked;
|
||||
String8Array symbol_names;
|
||||
String8 long_names;
|
||||
U64 input_idx;
|
||||
@@ -40,14 +40,13 @@ typedef struct LNK_LibList
|
||||
|
||||
typedef struct
|
||||
{
|
||||
String8 *data_arr;
|
||||
String8 *path_arr;
|
||||
U64 next_free_lib_idx;
|
||||
U64 valid_libs_count;
|
||||
U64 invalid_libs_count;
|
||||
LNK_LibNode *free_libs;
|
||||
LNK_LibNode **valid_libs;
|
||||
LNK_LibNode **invalid_libs;
|
||||
struct LNK_Input **inputs;
|
||||
U64 next_free_lib_idx;
|
||||
U64 valid_libs_count;
|
||||
U64 invalid_libs_count;
|
||||
LNK_LibNode *free_libs;
|
||||
LNK_LibNode **valid_libs;
|
||||
LNK_LibNode **invalid_libs;
|
||||
} LNK_LibIniter;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -56,8 +55,11 @@ internal int lnk_lib_node_is_before(void *a, void *b);
|
||||
internal int lnk_lib_node_ptr_is_before(void *raw_a, void *raw_b);
|
||||
|
||||
internal B32 lnk_lib_from_data(Arena *arena, String8 data, String8 path, LNK_Lib *lib_out);
|
||||
internal LNK_Lib ** lnk_array_from_lib_list(Arena *arena, LNK_LibList list);
|
||||
internal void lnk_lib_list_push_node(LNK_LibList *list, LNK_LibNode *node);
|
||||
internal LNK_LibNodeArray lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, String8Array data_arr, String8Array path_arr);
|
||||
internal LNK_LibNodeArray lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, U64 inputs_count, struct LNK_Input **inputs);
|
||||
|
||||
internal B32 lnk_flag_member_as_queued(LNK_Lib *lib, U32 member_idx, LNK_Symbol *trigger);
|
||||
|
||||
internal B32 lnk_search_lib(LNK_Lib *lib, String8 symbol_name, U32 *member_idx_out);
|
||||
|
||||
|
||||
+50
-41
@@ -11,6 +11,14 @@ lnk_error_obj(LNK_ErrorCode code, LNK_Obj *obj, char *fmt, ...)
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_error_input_obj(LNK_ErrorCode code, LNK_Input *input, char *fmt, ...)
|
||||
{
|
||||
va_list args; va_start(args, fmt);
|
||||
lnk_error_with_loc_fv(code, input->path, input->trigger->lib ? input->trigger->lib->path : str8_zero(), fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
internal LNK_Obj **
|
||||
lnk_array_from_obj_list(Arena *arena, LNK_ObjList list)
|
||||
{
|
||||
@@ -26,9 +34,8 @@ internal
|
||||
THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
||||
{
|
||||
LNK_ObjIniter *task = raw_task;
|
||||
LNK_InputObj *input = task->inputs[task_id];
|
||||
LNK_Obj *obj = &task->objs.v[task_id].data;
|
||||
U64 obj_idx = task->obj_id_base + task_id;
|
||||
LNK_Input *input = task->inputs[task_id];
|
||||
LNK_Obj *obj = &task->objs[task_id].data;
|
||||
|
||||
ProfBeginV("Init Obj [%S%s%S]", input->lib_path, (input->lib_path.size ? ": " : 0), input->path);
|
||||
|
||||
@@ -281,58 +288,60 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
||||
// fill out obj
|
||||
obj->data = input->data;
|
||||
obj->path = push_str8_copy(arena, input->path);
|
||||
obj->lib = input->lib;
|
||||
obj->input_idx = obj_idx;
|
||||
obj->lib = input->trigger ? input->trigger->lib : 0;
|
||||
obj->header = header;
|
||||
obj->comdats = comdats;
|
||||
obj->exclude_from_debug_info = input->exclude_from_debug_info;
|
||||
obj->hotpatch = hotpatch;
|
||||
obj->associated_sections = associated_sections;
|
||||
obj->node = &task->objs[task_id];
|
||||
obj->trigger_symbol = input->trigger;
|
||||
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
internal LNK_ObjNodeArray
|
||||
lnk_obj_list_push_parallel(TP_Context *tp,
|
||||
TP_Arena *arena,
|
||||
LNK_ObjList *list,
|
||||
COFF_MachineType machine,
|
||||
U64 input_count,
|
||||
LNK_InputObj **inputs)
|
||||
internal LNK_ObjNode *
|
||||
lnk_obj_from_input_many(TP_Context *tp, TP_Arena *arena, COFF_MachineType machine, U64 inputs_count, LNK_Input **inputs)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
|
||||
// store base id
|
||||
U64 obj_id_base = list->count;
|
||||
|
||||
// reserve obj nodes
|
||||
LNK_ObjNodeArray objs = {0};
|
||||
if (input_count > 0) {
|
||||
objs.count = input_count;
|
||||
objs.v = push_array(arena->v[0], LNK_ObjNode, input_count);
|
||||
for (LNK_ObjNode *ptr = objs.v, *opl = objs.v + input_count; ptr < opl; ++ptr) {
|
||||
SLLQueuePush(list->first, list->last, ptr);
|
||||
}
|
||||
list->count += input_count;
|
||||
LNK_ObjNode *objs = 0;
|
||||
if (inputs_count) {
|
||||
objs = push_array(arena->v[0], LNK_ObjNode, inputs_count);
|
||||
tp_for_parallel(tp, arena, inputs_count, lnk_obj_initer, &(LNK_ObjIniter){ .inputs = inputs, .objs = objs, .machine = machine });
|
||||
}
|
||||
|
||||
// fill out & run task
|
||||
LNK_ObjIniter task = {0};
|
||||
task.inputs = inputs;
|
||||
task.obj_id_base = obj_id_base;
|
||||
task.objs = objs;
|
||||
task.machine = machine;
|
||||
tp_for_parallel(tp, arena, input_count, lnk_obj_initer, &task);
|
||||
|
||||
ProfEnd();
|
||||
return objs;
|
||||
}
|
||||
|
||||
internal LNK_ObjNode *
|
||||
lnk_obj_from_input(Arena *arena, COFF_MachineType machine, LNK_Input *input)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
TP_Context *tp = tp_alloc(scratch.arena, 1, 1, str8_zero());
|
||||
TP_Arena tp_arena = { .count = 1, .v = &arena };
|
||||
LNK_ObjNode *result = lnk_obj_from_input_many(tp, &tp_arena, machine, 1, &input);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_obj_list_push_node_many(LNK_ObjList *list, U64 count, LNK_ObjNode *nodes)
|
||||
{
|
||||
for EachIndex(i, count) {
|
||||
DLLPushBack(list->first, list->last, &nodes[i]);
|
||||
}
|
||||
list->count += count;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_obj_list_push_node(LNK_ObjList *list, LNK_ObjNode *node)
|
||||
{
|
||||
lnk_obj_list_push_node_many(list, 1, node);
|
||||
}
|
||||
|
||||
internal
|
||||
THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
|
||||
{
|
||||
LNK_InputCoffSymbolTable *task = raw_task;
|
||||
LNK_Obj *obj = &task->objs.v[task_id].data;
|
||||
LNK_Obj *obj = task->objs[task_id];
|
||||
COFF_ParsedSymbol symbol = {0};
|
||||
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
|
||||
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
|
||||
@@ -400,17 +409,17 @@ internal
|
||||
THREAD_POOL_TASK_FUNC(lnk_assign_comdat_symlinks_task)
|
||||
{
|
||||
LNK_InputCoffSymbolTable *task = raw_task;
|
||||
LNK_Obj *obj = &task->objs.v[task_id].data;
|
||||
LNK_Obj *obj = task->objs[task_id];
|
||||
obj->symlinks = lnk_symlinks_from_obj(arena, task->symtab, obj);
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_input_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, LNK_ObjNodeArray objs)
|
||||
lnk_push_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, U64 objs_count, LNK_Obj **objs)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
LNK_InputCoffSymbolTable task = { .symtab = symtab, .objs = objs };
|
||||
tp_for_parallel(tp, arena, objs.count, lnk_input_coff_symbol_table, &task);
|
||||
tp_for_parallel(tp, arena, objs.count, lnk_assign_comdat_symlinks_task, &task);
|
||||
tp_for_parallel(tp, arena, objs_count, lnk_input_coff_symbol_table, &task);
|
||||
tp_for_parallel(tp, arena, objs_count, lnk_assign_comdat_symlinks_task, &task);
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
|
||||
+26
-19
@@ -7,21 +7,25 @@
|
||||
|
||||
typedef struct LNK_Obj
|
||||
{
|
||||
String8 data;
|
||||
String8 path;
|
||||
struct LNK_Lib *lib;
|
||||
U32 input_idx;
|
||||
COFF_FileHeaderInfo header;
|
||||
U32 *comdats;
|
||||
B8 hotpatch;
|
||||
B8 exclude_from_debug_info;
|
||||
U32Node **associated_sections;
|
||||
LNK_SymbolHashTrie **symlinks;
|
||||
String8 path;
|
||||
String8 data;
|
||||
struct LNK_Lib *lib;
|
||||
struct LNK_LibMemberRef *trigger_symbol;
|
||||
U32 input_idx;
|
||||
COFF_FileHeaderInfo header;
|
||||
U32 *comdats;
|
||||
B8 hotpatch;
|
||||
B8 exclude_from_debug_info;
|
||||
U32Node **associated_sections;
|
||||
LNK_SymbolHashTrie **symlinks;
|
||||
|
||||
struct LNK_ObjNode *node;
|
||||
} LNK_Obj;
|
||||
|
||||
typedef struct LNK_ObjNode
|
||||
{
|
||||
struct LNK_ObjNode *next;
|
||||
struct LNK_ObjNode *prev;
|
||||
LNK_Obj data;
|
||||
} LNK_ObjNode;
|
||||
|
||||
@@ -63,16 +67,16 @@ typedef struct LNK_DirectiveInfo
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LNK_InputObj **inputs;
|
||||
LNK_ObjNodeArray objs;
|
||||
U64 obj_id_base;
|
||||
U32 machine;
|
||||
struct LNK_Input **inputs;
|
||||
LNK_ObjNode *objs;
|
||||
U64 obj_id_base;
|
||||
U32 machine;
|
||||
} LNK_ObjIniter;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LNK_SymbolTable *symtab;
|
||||
LNK_ObjNodeArray objs;
|
||||
LNK_SymbolTable *symtab;
|
||||
LNK_Obj **objs;
|
||||
} LNK_InputCoffSymbolTable;
|
||||
|
||||
typedef struct
|
||||
@@ -86,12 +90,15 @@ typedef struct
|
||||
// --- Error -------------------------------------------------------------------
|
||||
|
||||
internal void lnk_error_obj(LNK_ErrorCode code, LNK_Obj *obj, char *fmt, ...);
|
||||
internal void lnk_error_input_obj(LNK_ErrorCode code, struct LNK_Input *input, char *fmt, ...);
|
||||
|
||||
// --- Input -------------------------------------------------------------------
|
||||
|
||||
internal LNK_Obj ** lnk_array_from_obj_list(Arena *arena, LNK_ObjList list);
|
||||
internal LNK_ObjNodeArray lnk_obj_list_push_parallel(TP_Context *tp, TP_Arena *tp_arena, LNK_ObjList *obj_list, COFF_MachineType machine, U64 input_count, LNK_InputObj **inputs);
|
||||
internal void lnk_input_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, LNK_ObjNodeArray objs);
|
||||
internal LNK_Obj ** lnk_array_from_obj_list(Arena *arena, LNK_ObjList list);
|
||||
internal void lnk_obj_list_push_node_many(LNK_ObjList *list, U64 count, LNK_ObjNode *nodes);
|
||||
internal void lnk_obj_list_push_node(LNK_ObjList *list, LNK_ObjNode *node);
|
||||
|
||||
internal void lnk_inputer_push_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, U64 objs_count, LNK_ObjNode *objs);
|
||||
|
||||
// --- Metadata ----------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -15,7 +15,18 @@ internal B32
|
||||
lnk_symbol_defined_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
LNK_Symbol *a = raw_a, *b = raw_b;
|
||||
return a->defined.obj->input_idx < b->defined.obj->input_idx;
|
||||
|
||||
|
||||
U32 a_lib_input_idx = a->defined.obj->lib ? a->defined.obj->lib->input_idx : 0;
|
||||
U32 b_lib_input_idx = b->defined.obj->lib ? b->defined.obj->lib->input_idx : 0;
|
||||
|
||||
if (a_lib_input_idx == b_lib_input_idx) {
|
||||
if (a->defined.obj->input_idx == b->defined.obj->input_idx) {
|
||||
return a->defined.symbol_idx < b->defined.symbol_idx;
|
||||
}
|
||||
return a->defined.obj->input_idx < b->defined.obj->input_idx;
|
||||
}
|
||||
return a_lib_input_idx < b_lib_input_idx;
|
||||
}
|
||||
|
||||
internal B32
|
||||
|
||||
@@ -14,6 +14,7 @@ typedef struct LNK_SymbolDefined
|
||||
typedef struct LNK_Symbol
|
||||
{
|
||||
String8 name;
|
||||
B8 is_lib_member_linked;
|
||||
LNK_SymbolDefined defined;
|
||||
} LNK_Symbol;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user