Files
raddebugger/src/linker/lnk.h
T
Nikita Smith d3dedd8bef simplifying symbol table scopes
Linker cannot register extern import symbols initially because
the import object files are not available until all other object files are
resolved. To work around this, we create a stub weak symbol and assign
it to each import symbol. This allows linker to proceed. Once the import
object files are generated, linker replaces the stub symbol with
the actual ones from the import objects.
2025-08-05 08:39:12 -07:00

231 lines
7.9 KiB
C

// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#pragma once
// --- Link --------------------------------------------------------------------
typedef struct LNK_LinkContext
{
LNK_SymbolTable *symtab;
U64 objs_count;
LNK_Obj **objs;
LNK_LibList lib_index[LNK_InputSource_Count];
} LNK_LinkContext;
// -- Image --------------------------------------------------------------------
#define LNK_IMPORT_STUB "*** RAD_IMPORT_STUB ***"
#define LNK_REMOVED_SECTION_NUMBER_32 (U32)-3
#define LNK_REMOVED_SECTION_NUMBER_16 (U16)-3
typedef struct LNK_ImageContext
{
String8 image_data;
LNK_SectionTable *sectab;
} LNK_ImageContext;
typedef struct LNK_SectionDefinition
{
String8 name;
COFF_SectionFlags flags;
U64 contribs_count;
struct LNK_Obj *obj;
U64 obj_sect_idx;
} LNK_SectionDefinition;
typedef struct LNK_CommonBlockContrib
{
struct LNK_Symbol *symbol;
union {
U32 size;
U32 offset;
} u;
} LNK_CommonBlockContrib;
// --- Base Reloc --------------------------------------------------------------
typedef struct LNK_BaseRelocPage
{
U64 voff;
U64List entries_addr32;
U64List entries_addr64;
} LNK_BaseRelocPage;
typedef struct LNK_BaseRelocPageNode
{
struct LNK_BaseRelocPageNode *next;
LNK_BaseRelocPage v;
} LNK_BaseRelocPageNode;
typedef struct LNK_BaseRelocPageList
{
U64 count;
LNK_BaseRelocPageNode *first;
LNK_BaseRelocPageNode *last;
} LNK_BaseRelocPageList;
typedef struct LNK_BaseRelocPageArray
{
U64 count;
LNK_BaseRelocPage *v;
} LNK_BaseRelocPageArray;
// --- Workers Contexts --------------------------------------------------------
typedef struct
{
LNK_SymbolTable *symtab;
LNK_SectionTable *sectab;
U64 objs_count;
LNK_Obj **objs;
U64 function_pad_min;
U64 default_align;
LNK_SectionContrib *null_sc;
LNK_SectionContrib ***sect_map;
HashTable *contribs_ht;
LNK_SectionArray image_sects;
union {
struct {
HashTable **defns;
} gather_sects;
struct {
U64 *counts;
U64 *offsets;
LNK_CommonBlockContrib *contribs;
} common_block;
struct {
LNK_SectionContribChunk **chunks;
} sort_contribs;
struct {
B8 **was_symbol_patched;
LNK_Section *common_block_sect;
Rng1U64 *common_block_ranges;
LNK_CommonBlockContrib *common_block_contribs;
COFF_SymbolValueInterpType fixup_type;
} patch_symtabs;
} u;
} LNK_BuildImageTask;
typedef struct
{
U64 page_size;
Rng1U64 *range_arr;
LNK_BaseRelocPageList *list_arr;
HashTable **page_ht_arr;
B32 is_large_addr_aware;
} LNK_BaseRelocTask;
typedef struct
{
Rng1U64 *ranges;
U64 page_size;
LNK_BaseRelocPageList *list_arr;
LNK_Obj **obj_arr;
HashTable **page_ht_arr;
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;
LNK_Obj **objs;
U64 image_base;
COFF_SectionHeader **image_section_table;
} LNK_ObjRelocPatcher;
typedef struct
{
String8 path;
String8 temp_path;
String8 data;
} LNK_WriteThreadContext;
typedef struct
{
String8 data;
Rng1U64 *ranges;
U128 *hashes;
} LNK_Blake3Hasher;
typedef struct
{
LNK_SymbolTable *symtab;
union {
LNK_ObjNodeArray objs;
LNK_LibNodeArray libs;
} u;
} LNK_SymbolPusher;
// --- Config -----------------------------------------------------------------
internal LNK_Config * lnk_config_from_argcv(Arena *arena, int argc, char **argv);
// --- Entry Point -------------------------------------------------------------
internal void lnk_run(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config);
// --- Path --------------------------------------------------------------------
internal String8 lnk_make_full_path(Arena *arena, PathStyle system_path_style, String8 work_dir, String8 path);
// --- Hasher ------------------------------------------------------------------
internal U128 lnk_blake3_hash_parallel(TP_Context *tp, U64 chunk_count, String8 data);
// --- Manifest ----------------------------------------------------------------
internal String8 lnk_make_linker_manifest(Arena *arena, B32 manifest_uac, String8 manifest_level, String8 manifest_ui_access, String8List manifest_dependency_list);
internal void lnk_merge_manifest_files(String8 mt_path, String8 out_name, String8List manifest_path_list);
internal String8 lnk_manifest_from_inputs(Arena *arena, LNK_IO_Flags io_flags, String8 mt_path, String8 manifest_name, B32 manifest_uac, String8 manifest_level, String8 manifest_ui_access, String8List input_manifest_path_list, String8List deps_list);
// --- Internal Objs -----------------------------------------------------------
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_coff_obj(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 cwd_path, String8 exe_path, String8 pdb_path, String8 cmd_line, String8 obj_name);
// --- 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 LNK_InputObjList lnk_push_linker_symbols(Arena *arena, LNK_Config *config);
internal void lnk_queue_lib_member_input(Arena *arena, PathStyle path_style, LNK_SymbolLib *symbol, LNK_InputImportList *input_import_list, LNK_InputObjList *input_obj_list);
internal LNK_LinkContext lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config);
// --- Win32 Image -------------------------------------------------------------
internal String8List lnk_build_guard_tables(TP_Context *tp, LNK_SectionTable *sectab, LNK_SymbolTable *symtab, U64 objs_count, LNK_Obj **objs, COFF_MachineType machine, String8 entry_point_name, LNK_GuardFlags guard_flags, B32 emit_suppress_flag);
internal String8List lnk_build_base_relocs(TP_Context *tp, TP_Arena *tp_temp, LNK_Config *config, U64 objs_count, LNK_Obj **objs);
internal String8List lnk_build_win32_image_header(Arena *arena, LNK_SymbolTable *symtab, LNK_Config *config, LNK_SectionArray sect_arr, U64 expected_image_header_size);
internal LNK_ImageContext lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolTable *symtab, U64 obj_count, LNK_Obj **objs);
// --- Logger ------------------------------------------------------------------
internal void lnk_log_link_stats(LNK_ObjList obj_list, LNK_LibList *lib_index, LNK_SectionTable *sectab);
internal void lnk_log_timers(void);