mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-26 13:35:00 -07:00
on read memory map files
This commit is contained in:
committed by
Ryan Fleury
parent
16e72fd573
commit
46663688e2
+9
-7
@@ -203,6 +203,7 @@ lnk_config_from_argcv(Arena *arena, int argc, char **argv)
|
||||
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SymbolTableCapWeak, "0x3ffff");
|
||||
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SymbolTableCapLib, "0x3ffff");
|
||||
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_DebugAltPath, "%%_RAD_RDI_PATH%%");
|
||||
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_MemoryMapFiles, "");
|
||||
#if BUILD_DEBUG
|
||||
lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Log, "debug");
|
||||
lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Log, "io_write");
|
||||
@@ -435,6 +436,7 @@ lnk_merge_manifest_files(String8 mt_path, String8 out_name, String8List manifest
|
||||
|
||||
internal String8
|
||||
lnk_manifest_from_inputs(Arena *arena,
|
||||
LNK_IO_Flags io_flags,
|
||||
String8 mt_path,
|
||||
String8 manifest_name,
|
||||
B32 manifest_uac,
|
||||
@@ -468,7 +470,7 @@ lnk_manifest_from_inputs(Arena *arena,
|
||||
lnk_merge_manifest_files(mt_path, merged_manifest_path, unique_input_manifest_paths);
|
||||
|
||||
// read mt.exe output from disk
|
||||
manifest_data = lnk_read_data_from_file_path(arena, merged_manifest_path);
|
||||
manifest_data = lnk_read_data_from_file_path(arena, io_flags, merged_manifest_path);
|
||||
if (manifest_data.size == 0) {
|
||||
lnk_error(LNK_Error_Mt, "unable to find mt.exe output manifest on disk, expected path \"%S\"", merged_manifest_path);
|
||||
}
|
||||
@@ -1455,7 +1457,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||
U64 thin_inputs_count = 0;
|
||||
LNK_InputObj **thin_inputs = lnk_thin_array_from_input_obj_list(scratch.arena, unique_obj_input_list, &thin_inputs_count);
|
||||
String8Array thin_input_paths = lnk_path_array_from_input_obj_array(scratch.arena, thin_inputs, thin_inputs_count);
|
||||
String8Array thin_input_datas = lnk_read_data_from_file_path_parallel(tp, tp_arena->v[0], thin_input_paths);
|
||||
String8Array thin_input_datas = lnk_read_data_from_file_path_parallel(tp, tp_arena->v[0], config->io_flags, thin_input_paths);
|
||||
for (U64 thin_input_idx = 0; thin_input_idx < thin_inputs_count; thin_input_idx += 1) {
|
||||
thin_inputs[thin_input_idx]->has_disk_read_failed = thin_input_datas.v[thin_input_idx].size == 0;
|
||||
thin_inputs[thin_input_idx]->data = thin_input_datas.v[thin_input_idx];
|
||||
@@ -1696,7 +1698,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||
|
||||
ProfBegin("Disk Read Libs");
|
||||
String8Array paths = str8_array_from_list(temp.arena, &unique_input_lib_list);
|
||||
String8Array datas = lnk_read_data_from_file_path_parallel(tp, tp_arena->v[0], paths);
|
||||
String8Array datas = lnk_read_data_from_file_path_parallel(tp, tp_arena->v[0], config->io_flags, paths);
|
||||
ProfEnd();
|
||||
|
||||
ProfBegin("Lib Init");
|
||||
@@ -2047,7 +2049,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||
ProfBegin("Embed Manifest");
|
||||
// TODO: currently we convert manifest to res and parse res again, this unnecessary instead push manifest
|
||||
// resource to the tree directly
|
||||
String8 manifest_data = lnk_manifest_from_inputs(scratch.arena, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list);
|
||||
String8 manifest_data = lnk_manifest_from_inputs(scratch.arena, config->io_flags, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list);
|
||||
String8 manifest_res = pe_make_manifest_resource(scratch.arena, *config->manifest_resource_id, manifest_data);
|
||||
str8_list_push(scratch.arena, &res_data_list, manifest_res);
|
||||
str8_list_push(scratch.arena, &res_path_list, str8_lit("* Manifest *"));
|
||||
@@ -2056,7 +2058,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||
case LNK_ManifestOpt_WriteToFile: {
|
||||
ProfBeginDynamic("Write Manifest To: %.*s", str8_varg(config->manifest_name));
|
||||
Temp temp = temp_begin(scratch.arena);
|
||||
String8 manifest_data = lnk_manifest_from_inputs(temp.arena, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list);
|
||||
String8 manifest_data = lnk_manifest_from_inputs(temp.arena, config->io_flags, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list);
|
||||
lnk_write_data_to_file_path(config->manifest_name, str8_zero(), manifest_data);
|
||||
temp_end(temp);
|
||||
ProfEnd();
|
||||
@@ -2072,7 +2074,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||
|
||||
ProfBegin("Load .res files from disk");
|
||||
for (String8Node *node = config->input_list[LNK_Input_Res].first; node != 0; node = node->next) {
|
||||
String8 res_data = lnk_read_data_from_file_path(scratch.arena, node->string);
|
||||
String8 res_data = lnk_read_data_from_file_path(scratch.arena, config->io_flags, node->string);
|
||||
if (res_data.size > 0) {
|
||||
if (pe_is_res(res_data)) {
|
||||
str8_list_push(scratch.arena, &res_data_list, res_data);
|
||||
@@ -5066,7 +5068,7 @@ lnk_run(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||
//
|
||||
// CodeView
|
||||
//
|
||||
LNK_CodeViewInput input = lnk_make_code_view_input(tp, tp_arena, config->lib_dir_list, link_ctx.objs_count, link_ctx.objs);
|
||||
LNK_CodeViewInput input = lnk_make_code_view_input(tp, tp_arena, config->io_flags, config->lib_dir_list, link_ctx.objs_count, link_ctx.objs);
|
||||
CV_DebugT *types = lnk_import_types(tp, tp_arena, &input);
|
||||
|
||||
//
|
||||
|
||||
+1
-1
@@ -188,7 +188,7 @@ internal U128 lnk_blake3_hash_parallel(TP_Context *tp, U64 chunk_count, String8
|
||||
|
||||
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, 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 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 -----------------------------------------------------------
|
||||
|
||||
|
||||
+267
-265
@@ -1,10 +1,8 @@
|
||||
// Copyright (c) 2025 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
// Enum <-> String
|
||||
|
||||
global read_only LNK_CmdSwitch g_cmd_switch_map[] = {
|
||||
global read_only LNK_CmdSwitch g_cmd_switch_map[] =
|
||||
{
|
||||
{ LNK_CmdSwitch_Null, 0, "", "", "" },
|
||||
{ LNK_CmdSwitch_NotImplemented, 0, "NOT_IMPLEMENTED", "", "" },
|
||||
{ LNK_CmdSwitch_Align, 0, "ALIGN", ":#", "" },
|
||||
@@ -123,40 +121,42 @@ global read_only LNK_CmdSwitch g_cmd_switch_map[] = {
|
||||
{ LNK_CmdSwitch_NotImplemented, 0, "WX", "", "" },
|
||||
|
||||
//- internal switches
|
||||
{ LNK_CmdSwitch_Rad_Age, 0, "RAD_AGE", ":#", "Age embeded in EXE and PDB, used to validate incremental build. Default is 1." },
|
||||
{ LNK_CmdSwitch_Rad_BuildInfo, 0, "RAD_BUILD_INFO", "", "Print build info and exit." },
|
||||
{ LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, 0, "RAD_CHECK_UNUSED_DELAY_LOAD_DLL", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_Rad_Map, 0, "RAD_MAP", ":FILENAME", "Emit file with the output image's layout description." },
|
||||
{ LNK_CmdSwitch_Rad_Debug, 0, "RAD_DEBUG", "[:NO]", "Emit RAD debug info file." },
|
||||
{ LNK_CmdSwitch_Rad_DebugAltPath, 0, "RAD_DEBUGALTPATH", "", "" },
|
||||
{ LNK_CmdSwitch_Rad_DebugName, 0, "RAD_DEBUG_NAME", ":FILENAME", "Sets file name for RAD debug info file." },
|
||||
{ LNK_CmdSwitch_Rad_DelayBind, 0, "RAD_DELAY_BIND", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_Rad_DoMerge, 0, "RAD_DO_MERGE", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_Rad_EnvLib, 0, "RAD_ENV_LIB", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_Rad_Exe, 0, "RAD_EXE", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_Rad_Guid, 0, "RAD_GUID", ":{IMAGEBLAKE3|XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX}", "" },
|
||||
{ LNK_CmdSwitch_Rad_LargePages, 0, "RAD_LARGE_PAGES", "[:NO]", "Disabled by default on Windows." },
|
||||
{ LNK_CmdSwitch_Rad_LinkVer, 0, "RAD_LINK_VER", ":##,##", "" },
|
||||
{ LNK_CmdSwitch_Rad_Log, 0, "RAD_LOG", ":{ALL,INPUT_OBJ,INPUT_LIB,IO,LINK_STATS,TIMERS}", "" },
|
||||
{ LNK_CmdSwitch_Rad_MtPath, 0, "RAD_MT_PATH", ":EXEPATH", "Exe path to manifest tool, default: " LNK_MANIFEST_MERGE_TOOL_NAME },
|
||||
{ LNK_CmdSwitch_Rad_OsVer, 0, "RAD_OS_VER", ":##,##", "" },
|
||||
{ LNK_CmdSwitch_Rad_PageSize, 0, "RAD_PAGE_SIZE", ":#", "Must be power of two." },
|
||||
{ LNK_CmdSwitch_Rad_PathStyle, 0, "RAD_PATH_STYLE", ":{WindowsAbsolute|UnixAbsolute}", "" },
|
||||
{ LNK_CmdSwitch_Rad_PdbHashTypeNameLength, 0, "RAD_PDB_HASH_TYPE_NAME_LENGTH", ":#", "Number of hash bytes to use to replace type name. Default 8 bytes (Max 16)." },
|
||||
{ LNK_CmdSwitch_Rad_PdbHashTypeNameMap, 0, "RAD_PDB_HASH_TYPE_NAME_MAP", ":FILENAME", "Produce map file with hash -> type name mappings." },
|
||||
{ LNK_CmdSwitch_Rad_PdbHashTypeNames, 0, "RAD_PDB_HASH_TYPE_NAMES", ":{NONE|LENIENT|FULL}", "Replace type names in LF_STRUCTURE and LF_CLASS with hashes." },
|
||||
{ LNK_CmdSwitch_Rad_RemoveSection, 0, "RAD_REMOVE_SECTION", ":NAME", "Removes a section from output image." },
|
||||
{ LNK_CmdSwitch_Rad_SharedThreadPool, 0, "RAD_SHARED_THREAD_POOL", "[:STRING]", "Default value \"" LNK_DEFAULT_THREAD_POOL_NAME "\"" },
|
||||
{ LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers, 0, "RAD_SHARED_THREAD_POOL_MAX_WORKERS", ":#", "Sets maximum number of workers in a thread pool." },
|
||||
{ LNK_CmdSwitch_Rad_SuppressError, 0, "RAD_SUPPRESS_ERROR", ":#", "" },
|
||||
{ LNK_CmdSwitch_Rad_SymbolTableCapDefined, 0, "RAD_SYMBOL_TABLE_CAP_DEFINED", ":#", "Number of buckets allocated in the symbol table for defined symbols." },
|
||||
{ LNK_CmdSwitch_Rad_SymbolTableCapInternal, 0, "RAD_SYMBOL_TABLE_CAP_INTERNAL", ":#", "Number of buckets allocated in the symbol table for internal symbols." },
|
||||
{ LNK_CmdSwitch_Rad_SymbolTableCapLib, 0, "RAD_SYMBOL_TABLE_CAP_LIB", ":#", "Number of buckets allocated in the symbol table for library symbols." },
|
||||
{ LNK_CmdSwitch_Rad_SymbolTableCapWeak, 0, "RAD_SYMBOL_TABLE_CAP_WEAK", ":#", "Number of buckets allocated in the symbol table for weak symbols." },
|
||||
{ LNK_CmdSwitch_Rad_TargetOs, 0, "RAD_TARGET_OS", ":{WINDOWS,LINUX,MAC}" },
|
||||
{ LNK_CmdSwitch_Rad_Age, 0, "RAD_AGE", ":#", "Age embeded in EXE and PDB, used to validate incremental build. Default is 1." },
|
||||
{ LNK_CmdSwitch_Rad_BuildInfo, 0, "RAD_BUILD_INFO", "", "Print build info and exit." },
|
||||
{ LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, 0, "RAD_CHECK_UNUSED_DELAY_LOAD_DLL", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_Rad_Map, 0, "RAD_MAP", ":FILENAME", "Emit file with the output image's layout description." },
|
||||
{ LNK_CmdSwitch_Rad_MemoryMapFiles, 0, "RAD_MEMORY_MAP_FILES", "[:NO]", "When enabled, files are memory-mapped instead of being read entirely on request." },
|
||||
{ LNK_CmdSwitch_Rad_Debug, 0, "RAD_DEBUG", "[:NO]", "Emit RAD debug info file." },
|
||||
{ LNK_CmdSwitch_Rad_DebugAltPath, 0, "RAD_DEBUGALTPATH", "", "" },
|
||||
{ LNK_CmdSwitch_Rad_DebugName, 0, "RAD_DEBUG_NAME", ":FILENAME", "Sets file name for RAD debug info file." },
|
||||
{ LNK_CmdSwitch_Rad_DelayBind, 0, "RAD_DELAY_BIND", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_Rad_DoMerge, 0, "RAD_DO_MERGE", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_Rad_EnvLib, 0, "RAD_ENV_LIB", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_Rad_Exe, 0, "RAD_EXE", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_Rad_Guid, 0, "RAD_GUID", ":{IMAGEBLAKE3|XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX}", "" },
|
||||
{ LNK_CmdSwitch_Rad_LargePages, 0, "RAD_LARGE_PAGES", "[:NO]", "Disabled by default on Windows." },
|
||||
{ LNK_CmdSwitch_Rad_LinkVer, 0, "RAD_LINK_VER", ":##,##", "" },
|
||||
{ LNK_CmdSwitch_Rad_Log, 0, "RAD_LOG", ":{ALL,INPUT_OBJ,INPUT_LIB,IO,LINK_STATS,TIMERS}", "" },
|
||||
{ LNK_CmdSwitch_Rad_MtPath, 0, "RAD_MT_PATH", ":EXEPATH", "Exe path to manifest tool, default: " LNK_MANIFEST_MERGE_TOOL_NAME },
|
||||
{ LNK_CmdSwitch_Rad_OsVer, 0, "RAD_OS_VER", ":##,##", "" },
|
||||
{ LNK_CmdSwitch_Rad_PageSize, 0, "RAD_PAGE_SIZE", ":#", "Must be power of two." },
|
||||
{ LNK_CmdSwitch_Rad_PathStyle, 0, "RAD_PATH_STYLE", ":{WindowsAbsolute|UnixAbsolute}", "" },
|
||||
{ LNK_CmdSwitch_Rad_PdbHashTypeNameLength, 0, "RAD_PDB_HASH_TYPE_NAME_LENGTH", ":#", "Number of hash bytes to use to replace type name. Default 8 bytes (Max 16)." },
|
||||
{ LNK_CmdSwitch_Rad_PdbHashTypeNameMap, 0, "RAD_PDB_HASH_TYPE_NAME_MAP", ":FILENAME", "Produce map file with hash -> type name mappings." },
|
||||
{ LNK_CmdSwitch_Rad_PdbHashTypeNames, 0, "RAD_PDB_HASH_TYPE_NAMES", ":{NONE|LENIENT|FULL}", "Replace type names in LF_STRUCTURE and LF_CLASS with hashes." },
|
||||
{ LNK_CmdSwitch_Rad_RemoveSection, 0, "RAD_REMOVE_SECTION", ":NAME", "Removes a section from output image." },
|
||||
{ LNK_CmdSwitch_Rad_SectVirtOff, 0, "RAD_SECT_VIRT_OFF", ":#", "Set RVA where section data is placed in memory. For internal use only." },
|
||||
{ LNK_CmdSwitch_Rad_SharedThreadPool, 0, "RAD_SHARED_THREAD_POOL", "[:STRING]", "Default value \"" LNK_DEFAULT_THREAD_POOL_NAME "\"" },
|
||||
{ LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers, 0, "RAD_SHARED_THREAD_POOL_MAX_WORKERS", ":#", "Sets maximum number of workers in a thread pool." },
|
||||
{ LNK_CmdSwitch_Rad_SuppressError, 0, "RAD_SUPPRESS_ERROR", ":#", "" },
|
||||
{ LNK_CmdSwitch_Rad_SymbolTableCapDefined, 0, "RAD_SYMBOL_TABLE_CAP_DEFINED", ":#", "Number of buckets allocated in the symbol table for defined symbols." },
|
||||
{ LNK_CmdSwitch_Rad_SymbolTableCapInternal, 0, "RAD_SYMBOL_TABLE_CAP_INTERNAL", ":#", "Number of buckets allocated in the symbol table for internal symbols." },
|
||||
{ LNK_CmdSwitch_Rad_SymbolTableCapLib, 0, "RAD_SYMBOL_TABLE_CAP_LIB", ":#", "Number of buckets allocated in the symbol table for library symbols." },
|
||||
{ LNK_CmdSwitch_Rad_SymbolTableCapWeak, 0, "RAD_SYMBOL_TABLE_CAP_WEAK", ":#", "Number of buckets allocated in the symbol table for weak symbols." },
|
||||
{ LNK_CmdSwitch_Rad_TargetOs, 0, "RAD_TARGET_OS", ":{WINDOWS,LINUX,MAC}" },
|
||||
{ LNK_CmdSwitch_Rad_WriteTempFiles, 0, "RAD_WRITE_TEMP_FILES", "[:NO]", "When speicifed linker writes image and debug info to temporary files and renames after link is done." },
|
||||
{ LNK_CmdSwitch_Rad_TimeStamp, 0, "RAD_TIME_STAMP", ":#", "Time stamp embeded in EXE and PDB." },
|
||||
{ LNK_CmdSwitch_Rad_Version, 0, "RAD_VERSION", "", "Print version and exit." },
|
||||
{ LNK_CmdSwitch_Rad_TimeStamp, 0, "RAD_TIME_STAMP", ":#", "Time stamp embeded in EXE and PDB." },
|
||||
{ LNK_CmdSwitch_Rad_Version, 0, "RAD_VERSION", "", "Print version and exit." },
|
||||
{ LNK_CmdSwitch_Rad_Workers, 0, "RAD_WORKERS", ":#", "Sets number of workers created in the pool. Number is capped at 1024. When /RAD_SHARED_THREAD_POOL is specified this number cant exceed /RAD_SHARED_THREAD_POOL_MAX_WORKERS." },
|
||||
|
||||
{ LNK_CmdSwitch_Help, 0, "HELP", "", "" },
|
||||
@@ -270,8 +270,6 @@ lnk_type_name_hash_mode_from_string(String8 name)
|
||||
return LNK_TypeNameHashMode_Null;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal LNK_CmdOption *
|
||||
lnk_cmd_line_push_option_if_not_presentf(Arena *arena, LNK_CmdLine *cmd_line, LNK_CmdSwitchType cmd_switch_type, char *param_fmt, ...)
|
||||
{
|
||||
@@ -307,8 +305,6 @@ lnk_cmd_line_has_switch(LNK_CmdLine cmd_line, LNK_CmdSwitchType cmd_switch)
|
||||
return lnk_cmd_line_has_option_string(cmd_line, cmd_switch_name);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
lnk_error_cmd_switch(LNK_ErrorCode code, String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch, char *fmt, ...)
|
||||
{
|
||||
@@ -362,185 +358,6 @@ lnk_error_invalid_uac_ui_access_param(LNK_ErrorCode error_code, String8 obj_path
|
||||
lnk_error_cmd_switch(error_code, obj_path, lib_path, cmd_switch, "invalid param format, expected \"uiAccess={'true'|'false'}\" but got \"%S\"", input);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal String8
|
||||
lnk_get_image_name(LNK_Config *config)
|
||||
{
|
||||
String8 image_name = config->image_name;
|
||||
image_name = str8_skip_last_slash(image_name);
|
||||
image_name = str8_chop_last_dot(image_name);
|
||||
return image_name;
|
||||
}
|
||||
|
||||
internal U64
|
||||
lnk_get_default_function_pad_min(COFF_MachineType machine)
|
||||
{
|
||||
U64 function_pad_min = 0;
|
||||
switch (machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X86: {
|
||||
function_pad_min = 5;
|
||||
} break;
|
||||
case COFF_MachineType_X64: {
|
||||
function_pad_min = 6;
|
||||
} break;
|
||||
default: {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl,
|
||||
str8_zero(),
|
||||
str8_zero(),
|
||||
LNK_CmdSwitch_FunctionPadMin,
|
||||
"default paramter is not defined for: %S",
|
||||
coff_string_from_machine_type(machine));
|
||||
} break;
|
||||
}
|
||||
return function_pad_min;
|
||||
}
|
||||
|
||||
internal U64
|
||||
lnk_get_base_addr(LNK_Config *config)
|
||||
{
|
||||
U64 base_addr = config->user_base_addr;
|
||||
if (base_addr == 0) {
|
||||
if (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) {
|
||||
base_addr = coff_default_dll_base_from_machine(config->machine);
|
||||
} else if (config->file_characteristics & PE_ImageFileCharacteristic_EXE) {
|
||||
if ((~config->file_characteristics & PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE) && config->machine == COFF_MachineType_X64) {
|
||||
base_addr = coff_default_exe_base_from_machine(COFF_MachineType_X86);
|
||||
} else {
|
||||
base_addr = coff_default_exe_base_from_machine(config->machine);
|
||||
}
|
||||
} else {
|
||||
lnk_error(LNK_Error_Cmdl, "image type is not specified.");
|
||||
}
|
||||
}
|
||||
return base_addr;
|
||||
}
|
||||
|
||||
internal Version
|
||||
lnk_get_default_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType machine)
|
||||
{
|
||||
Version ver = make_version(0,0);
|
||||
switch (subsystem) {
|
||||
case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: ver = make_version(1,0); break;
|
||||
|
||||
case PE_WindowsSubsystem_WINDOWS_CUI: {
|
||||
switch (machine) {
|
||||
case COFF_MachineType_X64:
|
||||
case COFF_MachineType_X86: ver = make_version(6,0); break;
|
||||
|
||||
case COFF_MachineType_ArmNt:
|
||||
case COFF_MachineType_Arm64:
|
||||
case COFF_MachineType_Arm: ver = make_version(6,2); break;
|
||||
|
||||
default: lnk_not_implemented("define subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case PE_WindowsSubsystem_WINDOWS_GUI: {
|
||||
switch (machine) {
|
||||
case COFF_MachineType_X64:
|
||||
case COFF_MachineType_X86: ver = make_version(6,0); break;
|
||||
|
||||
case COFF_MachineType_ArmNt:
|
||||
case COFF_MachineType_Arm64:
|
||||
case COFF_MachineType_Arm: ver = make_version(6,2); break;
|
||||
|
||||
default: lnk_not_implemented("define subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case PE_WindowsSubsystem_POSIX_CUI: ver = make_version(19,90); break;
|
||||
|
||||
case PE_WindowsSubsystem_EFI_APPLICATION:
|
||||
case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER:
|
||||
case PE_WindowsSubsystem_EFI_ROM:
|
||||
case PE_WindowsSubsystem_EFI_RUNTIME_DRIVER: ver = make_version(1,0); break;
|
||||
|
||||
case PE_WindowsSubsystem_NATIVE_WINDOWS:
|
||||
case PE_WindowsSubsystem_NATIVE: lnk_not_implemented("detect -drive=WDM switch"); break;
|
||||
|
||||
default: lnk_not_implemented("unknown subsystem kind %u", subsystem); break;
|
||||
}
|
||||
return ver;
|
||||
}
|
||||
|
||||
internal Version
|
||||
lnk_get_min_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType machine)
|
||||
{
|
||||
Version ver = make_version(0,0);
|
||||
switch (subsystem) {
|
||||
case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: ver = make_version(1,0); break;
|
||||
|
||||
case PE_WindowsSubsystem_WINDOWS_CUI: {
|
||||
switch (machine) {
|
||||
case COFF_MachineType_X86: ver = make_version(5,1); break;
|
||||
|
||||
case COFF_MachineType_X64: ver = make_version(5,2); break;
|
||||
|
||||
case COFF_MachineType_ArmNt:
|
||||
case COFF_MachineType_Arm64:
|
||||
case COFF_MachineType_Arm: ver = make_version(6,2); break;
|
||||
|
||||
default: lnk_not_implemented("define min subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case PE_WindowsSubsystem_WINDOWS_GUI: {
|
||||
switch (machine) {
|
||||
case COFF_MachineType_X86: ver = make_version(5,1); break;
|
||||
|
||||
case COFF_MachineType_X64: ver = make_version(5,2); break;
|
||||
|
||||
case COFF_MachineType_ArmNt:
|
||||
case COFF_MachineType_Arm64:
|
||||
case COFF_MachineType_Arm: ver = make_version(6,2); break;
|
||||
|
||||
default: lnk_not_implemented("define min subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case PE_WindowsSubsystem_POSIX_CUI: ver = make_version(1,0); break;
|
||||
|
||||
case PE_WindowsSubsystem_EFI_APPLICATION:
|
||||
case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER:
|
||||
case PE_WindowsSubsystem_EFI_ROM:
|
||||
case PE_WindowsSubsystem_EFI_RUNTIME_DRIVER: ver = make_version(1,0); break;
|
||||
|
||||
case PE_WindowsSubsystem_NATIVE_WINDOWS:
|
||||
case PE_WindowsSubsystem_NATIVE: lnk_not_implemented("detect -drive=WDM switch"); break;
|
||||
|
||||
default: lnk_not_implemented("unknown subsystem kind %u", subsystem);
|
||||
}
|
||||
return ver;
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_do_debug_info(LNK_Config *config)
|
||||
{
|
||||
B32 do_debug_info = config->rad_debug == LNK_SwitchState_Yes ||
|
||||
(config->debug_mode != LNK_DebugMode_None && config->debug_mode != LNK_DebugMode_Null);
|
||||
return do_debug_info;
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_is_thread_pool_shared(LNK_Config *config)
|
||||
{
|
||||
return config->shared_thread_pool_name.size > 0;
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_is_section_removed(LNK_Config *config, String8 section_name)
|
||||
{
|
||||
B32 is_removed = 0;
|
||||
for (String8Node *name_n = config->remove_sections.first; name_n != 0 && !is_removed; name_n = name_n->next) {
|
||||
is_removed = str8_match(section_name, name_n->string, 0);
|
||||
}
|
||||
return is_removed;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal B32
|
||||
lnk_cmd_switch_parse_version(String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch, String8List value_strings, Version *ver_out)
|
||||
{
|
||||
@@ -784,8 +601,6 @@ lnk_cmd_switch_parse_string_copy(Arena *arena, String8 obj_path, String8 lib_pat
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal B32
|
||||
lnk_parse_alt_name_directive(String8 input, LNK_AltName *alt_out)
|
||||
{
|
||||
@@ -947,7 +762,180 @@ lnk_parse_merge_directive(String8 string, LNK_MergeDirective *out)
|
||||
return is_parse_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
internal String8
|
||||
lnk_get_image_name(LNK_Config *config)
|
||||
{
|
||||
String8 image_name = config->image_name;
|
||||
image_name = str8_skip_last_slash(image_name);
|
||||
image_name = str8_chop_last_dot(image_name);
|
||||
return image_name;
|
||||
}
|
||||
|
||||
internal U64
|
||||
lnk_get_default_function_pad_min(COFF_MachineType machine)
|
||||
{
|
||||
U64 function_pad_min = 0;
|
||||
switch (machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X86: {
|
||||
function_pad_min = 5;
|
||||
} break;
|
||||
case COFF_MachineType_X64: {
|
||||
function_pad_min = 6;
|
||||
} break;
|
||||
default: {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl,
|
||||
str8_zero(),
|
||||
str8_zero(),
|
||||
LNK_CmdSwitch_FunctionPadMin,
|
||||
"default paramter is not defined for: %S",
|
||||
coff_string_from_machine_type(machine));
|
||||
} break;
|
||||
}
|
||||
return function_pad_min;
|
||||
}
|
||||
|
||||
internal U64
|
||||
lnk_get_base_addr(LNK_Config *config)
|
||||
{
|
||||
U64 base_addr = config->user_base_addr;
|
||||
if (base_addr == 0) {
|
||||
if (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) {
|
||||
base_addr = coff_default_dll_base_from_machine(config->machine);
|
||||
} else if (config->file_characteristics & PE_ImageFileCharacteristic_EXE) {
|
||||
if ((~config->file_characteristics & PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE) && config->machine == COFF_MachineType_X64) {
|
||||
base_addr = coff_default_exe_base_from_machine(COFF_MachineType_X86);
|
||||
} else {
|
||||
base_addr = coff_default_exe_base_from_machine(config->machine);
|
||||
}
|
||||
} else {
|
||||
lnk_error(LNK_Error_Cmdl, "image type is not specified.");
|
||||
}
|
||||
}
|
||||
return base_addr;
|
||||
}
|
||||
|
||||
internal Version
|
||||
lnk_get_default_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType machine)
|
||||
{
|
||||
Version ver = make_version(0,0);
|
||||
switch (subsystem) {
|
||||
case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: ver = make_version(1,0); break;
|
||||
|
||||
case PE_WindowsSubsystem_WINDOWS_CUI: {
|
||||
switch (machine) {
|
||||
case COFF_MachineType_X64:
|
||||
case COFF_MachineType_X86: ver = make_version(6,0); break;
|
||||
|
||||
case COFF_MachineType_ArmNt:
|
||||
case COFF_MachineType_Arm64:
|
||||
case COFF_MachineType_Arm: ver = make_version(6,2); break;
|
||||
|
||||
default: lnk_not_implemented("define subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case PE_WindowsSubsystem_WINDOWS_GUI: {
|
||||
switch (machine) {
|
||||
case COFF_MachineType_X64:
|
||||
case COFF_MachineType_X86: ver = make_version(6,0); break;
|
||||
|
||||
case COFF_MachineType_ArmNt:
|
||||
case COFF_MachineType_Arm64:
|
||||
case COFF_MachineType_Arm: ver = make_version(6,2); break;
|
||||
|
||||
default: lnk_not_implemented("define subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case PE_WindowsSubsystem_POSIX_CUI: ver = make_version(19,90); break;
|
||||
|
||||
case PE_WindowsSubsystem_EFI_APPLICATION:
|
||||
case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER:
|
||||
case PE_WindowsSubsystem_EFI_ROM:
|
||||
case PE_WindowsSubsystem_EFI_RUNTIME_DRIVER: ver = make_version(1,0); break;
|
||||
|
||||
case PE_WindowsSubsystem_NATIVE_WINDOWS:
|
||||
case PE_WindowsSubsystem_NATIVE: lnk_not_implemented("detect -drive=WDM switch"); break;
|
||||
|
||||
default: lnk_not_implemented("unknown subsystem kind %u", subsystem); break;
|
||||
}
|
||||
return ver;
|
||||
}
|
||||
|
||||
internal Version
|
||||
lnk_get_min_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType machine)
|
||||
{
|
||||
Version ver = make_version(0,0);
|
||||
switch (subsystem) {
|
||||
case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: ver = make_version(1,0); break;
|
||||
|
||||
case PE_WindowsSubsystem_WINDOWS_CUI: {
|
||||
switch (machine) {
|
||||
case COFF_MachineType_X86: ver = make_version(5,1); break;
|
||||
|
||||
case COFF_MachineType_X64: ver = make_version(5,2); break;
|
||||
|
||||
case COFF_MachineType_ArmNt:
|
||||
case COFF_MachineType_Arm64:
|
||||
case COFF_MachineType_Arm: ver = make_version(6,2); break;
|
||||
|
||||
default: lnk_not_implemented("define min subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case PE_WindowsSubsystem_WINDOWS_GUI: {
|
||||
switch (machine) {
|
||||
case COFF_MachineType_X86: ver = make_version(5,1); break;
|
||||
|
||||
case COFF_MachineType_X64: ver = make_version(5,2); break;
|
||||
|
||||
case COFF_MachineType_ArmNt:
|
||||
case COFF_MachineType_Arm64:
|
||||
case COFF_MachineType_Arm: ver = make_version(6,2); break;
|
||||
|
||||
default: lnk_not_implemented("define min subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case PE_WindowsSubsystem_POSIX_CUI: ver = make_version(1,0); break;
|
||||
|
||||
case PE_WindowsSubsystem_EFI_APPLICATION:
|
||||
case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER:
|
||||
case PE_WindowsSubsystem_EFI_ROM:
|
||||
case PE_WindowsSubsystem_EFI_RUNTIME_DRIVER: ver = make_version(1,0); break;
|
||||
|
||||
case PE_WindowsSubsystem_NATIVE_WINDOWS:
|
||||
case PE_WindowsSubsystem_NATIVE: lnk_not_implemented("detect -drive=WDM switch"); break;
|
||||
|
||||
default: lnk_not_implemented("unknown subsystem kind %u", subsystem);
|
||||
}
|
||||
return ver;
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_do_debug_info(LNK_Config *config)
|
||||
{
|
||||
B32 do_debug_info = config->rad_debug == LNK_SwitchState_Yes ||
|
||||
(config->debug_mode != LNK_DebugMode_None && config->debug_mode != LNK_DebugMode_Null);
|
||||
return do_debug_info;
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_is_thread_pool_shared(LNK_Config *config)
|
||||
{
|
||||
return config->shared_thread_pool_name.size > 0;
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_is_section_removed(LNK_Config *config, String8 section_name)
|
||||
{
|
||||
B32 is_removed = 0;
|
||||
for (String8Node *name_n = config->remove_sections.first; name_n != 0 && !is_removed; name_n = name_n->next) {
|
||||
is_removed = str8_match(section_name, name_n->string, 0);
|
||||
}
|
||||
return is_removed;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_print_build_info()
|
||||
@@ -999,8 +987,6 @@ lnk_print_help(void)
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal String8
|
||||
lnk_expand_env_vars_windows(Arena *arena, HashTable *env_vars, String8 string)
|
||||
{
|
||||
@@ -1034,6 +1020,46 @@ lnk_expand_env_vars_windows(Arena *arena, HashTable *env_vars, String8 string)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8List
|
||||
lnk_unwrap_rsp(Arena *arena, String8List arg_list)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
String8List result = {0};
|
||||
|
||||
for (String8Node *curr = arg_list.first; curr != 0; curr = curr->next) {
|
||||
B32 is_rsp = str8_match_lit("@", curr->string, StringMatchFlag_RightSideSloppy);
|
||||
if (is_rsp) {
|
||||
// remove "@"
|
||||
String8 name = str8_skip(curr->string, 1);
|
||||
|
||||
if (os_file_path_exists(name)) {
|
||||
// read rsp from disk
|
||||
String8 file = lnk_read_data_from_file_path(scratch.arena, 0, name);
|
||||
|
||||
// parse rsp
|
||||
String8List rsp_args = lnk_arg_list_parse_windows_rules(scratch.arena, file);
|
||||
|
||||
// handle case where rsp references another rsp
|
||||
String8List list = lnk_unwrap_rsp(arena, rsp_args);
|
||||
|
||||
// push arguments from rsp
|
||||
list = str8_list_copy(arena, &list);
|
||||
str8_list_concat_in_place(&result, &list);
|
||||
} else {
|
||||
lnk_error(LNK_Error_Cmdl, "unable to find rsp: %S", name);
|
||||
}
|
||||
} else {
|
||||
// push regular argument
|
||||
String8 str = push_str8_copy(arena, curr->string);
|
||||
str8_list_push(arena, &result, str);
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_name, String8List value_strings, String8 obj_path, String8 lib_path)
|
||||
{
|
||||
@@ -1634,9 +1660,14 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
config->rad_chunk_map = LNK_SwitchState_Yes;
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_MemoryMapFiles: {
|
||||
lnk_cmd_switch_set_flag_32(obj_path, lib_path, cmd_switch, value_strings, &config->io_flags, LNK_IO_Flags_MemoryMapFiles);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_Debug: {
|
||||
lnk_cmd_switch_parse_flag(obj_path, lib_path, cmd_switch, value_strings, &config->rad_debug);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_DebugName: {
|
||||
// :Rad_DebugAltPath
|
||||
lnk_cmd_switch_parse_string_copy(arena, obj_path, lib_path, cmd_switch, value_strings, &config->rad_debug_name);
|
||||
@@ -1797,6 +1828,17 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
}
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_SectVirtOff: {
|
||||
U64 sect_virt_off;
|
||||
if (lnk_cmd_switch_parse_u64(obj_path, lib_path, cmd_switch, value_strings, §_virt_off, LNK_ParseU64Flag_CheckUnder32bit)) {
|
||||
if (sect_virt_off >= 0x1000) {
|
||||
config->section_virt_off = sect_virt_off;
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj_path, lib_path, cmd_switch, "section virtual offset must be >= 0x1000");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_SharedThreadPool: {
|
||||
if (value_strings.node_count == 0) {
|
||||
config->shared_thread_pool_name = str8_lit(LNK_DEFAULT_THREAD_POOL_NAME);
|
||||
@@ -1892,46 +1934,6 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal String8List
|
||||
lnk_unwrap_rsp(Arena *arena, String8List arg_list)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
String8List result = {0};
|
||||
|
||||
for (String8Node *curr = arg_list.first; curr != 0; curr = curr->next) {
|
||||
B32 is_rsp = str8_match_lit("@", curr->string, StringMatchFlag_RightSideSloppy);
|
||||
if (is_rsp) {
|
||||
// remove "@"
|
||||
String8 name = str8_skip(curr->string, 1);
|
||||
|
||||
if (os_file_path_exists(name)) {
|
||||
// read rsp from disk
|
||||
String8 file = lnk_read_data_from_file_path(scratch.arena, name);
|
||||
|
||||
// parse rsp
|
||||
String8List rsp_args = lnk_arg_list_parse_windows_rules(scratch.arena, file);
|
||||
|
||||
// handle case where rsp references another rsp
|
||||
String8List list = lnk_unwrap_rsp(arena, rsp_args);
|
||||
|
||||
// push arguments from rsp
|
||||
list = str8_list_copy(arena, &list);
|
||||
str8_list_concat_in_place(&result, &list);
|
||||
} else {
|
||||
lnk_error(LNK_Error_Cmdl, "unable to find rsp: %S", name);
|
||||
}
|
||||
} else {
|
||||
// push regular argument
|
||||
String8 str = push_str8_copy(arena, curr->string);
|
||||
str8_list_push(arena, &result, str);
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal LNK_Config *
|
||||
lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line, LNK_CmdLine cmd_line)
|
||||
{
|
||||
|
||||
+49
-53
@@ -3,6 +3,29 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if OS_WINDOWS
|
||||
# define LNK_MANIFEST_MERGE_TOOL_NAME "mt.exe"
|
||||
#elif OS_LINUX || OS_MAC
|
||||
# define LNK_MANIFEST_MERGE_TOOL_NAME "llvm-mt"
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
|
||||
#define LNK_DEFAULT_THREAD_POOL_NAME "RADLINK_THREAD_POOL"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LNK_ParseU64Flag_CheckUnder32bit = (1 << 0),
|
||||
LNK_ParseU64Flag_CheckPow2 = (1 << 1),
|
||||
} LNK_ParseU64Flags;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LNK_SwitchState_Null,
|
||||
LNK_SwitchState_No,
|
||||
LNK_SwitchState_Yes
|
||||
} LNK_SwitchState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LNK_CmdSwitch_Null,
|
||||
@@ -128,7 +151,6 @@ typedef enum
|
||||
LNK_CmdSwitch_Rad_Age,
|
||||
LNK_CmdSwitch_Rad_BuildInfo,
|
||||
LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll,
|
||||
LNK_CmdSwitch_Rad_Map,
|
||||
LNK_CmdSwitch_Rad_Debug,
|
||||
LNK_CmdSwitch_Rad_DebugAltPath,
|
||||
LNK_CmdSwitch_Rad_DebugName,
|
||||
@@ -141,6 +163,8 @@ typedef enum
|
||||
LNK_CmdSwitch_Rad_LinkVer,
|
||||
LNK_CmdSwitch_Rad_Log,
|
||||
LNK_CmdSwitch_Rad_Logo,
|
||||
LNK_CmdSwitch_Rad_Map,
|
||||
LNK_CmdSwitch_Rad_MemoryMapFiles,
|
||||
LNK_CmdSwitch_Rad_MtPath,
|
||||
LNK_CmdSwitch_Rad_OsVer,
|
||||
LNK_CmdSwitch_Rad_PageSize,
|
||||
@@ -177,13 +201,6 @@ typedef struct LNK_CmdSwitch
|
||||
char *desc;
|
||||
} LNK_CmdSwitch;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LNK_SwitchState_Null,
|
||||
LNK_SwitchState_No,
|
||||
LNK_SwitchState_Yes
|
||||
} LNK_SwitchState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LNK_Input_Null,
|
||||
@@ -285,16 +302,6 @@ typedef enum
|
||||
LNK_TypeNameHashMode_Full,
|
||||
} LNK_TypeNameHashMode;
|
||||
|
||||
#if OS_WINDOWS
|
||||
# define LNK_MANIFEST_MERGE_TOOL_NAME "mt.exe"
|
||||
#elif OS_LINUX || OS_MAC
|
||||
# define LNK_MANIFEST_MERGE_TOOL_NAME "llvm-mt"
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
|
||||
#define LNK_DEFAULT_THREAD_POOL_NAME "RADLINK_THREAD_POOL"
|
||||
|
||||
typedef struct LNK_Config
|
||||
{
|
||||
LNK_ConfigFlags flags;
|
||||
@@ -383,15 +390,10 @@ typedef struct LNK_Config
|
||||
String8 temp_rad_debug_name;
|
||||
String8 temp_rad_chunk_map_name;
|
||||
String8List remove_sections;
|
||||
LNK_IO_Flags io_flags;
|
||||
} LNK_Config;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LNK_ParseU64Flag_CheckUnder32bit = (1 << 0),
|
||||
LNK_ParseU64Flag_CheckPow2 = (1 << 1),
|
||||
} LNK_ParseU64Flags;
|
||||
|
||||
////////////////////////////////
|
||||
// --- MSVC Error Codes --------------------------------------------------------
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -518,8 +520,7 @@ typedef enum
|
||||
LNK_MsWarningCode_Lnk4286 = 4286,
|
||||
} LNK_MsErrorCode;
|
||||
|
||||
////////////////////////////////
|
||||
// Enum <-> String
|
||||
// --- Enum <-> String ---------------------------------------------------------
|
||||
|
||||
internal String8 lnk_string_cmd_switch_type(LNK_CmdSwitchType type);
|
||||
internal LNK_CmdSwitchType lnk_cmd_switch_type_from_string(String8 string);
|
||||
@@ -528,36 +529,20 @@ internal LNK_InputType lnk_input_type_from_string(String8 string);
|
||||
internal LNK_DebugMode lnk_debug_mode_from_string(String8 string);
|
||||
internal LNK_TypeNameHashMode lnk_type_name_hash_mode_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
// Command Line Helpers
|
||||
// --- Command Line Helpers ----------------------------------------------------
|
||||
|
||||
internal LNK_CmdOption * lnk_cmd_line_push_option_if_not_presentf(Arena *arena, LNK_CmdLine *cmd_line, LNK_CmdSwitchType cmd_switch_type, char *param_fmt, ...);
|
||||
internal LNK_CmdOption * lnk_cmd_line_push_optionf (Arena *arena, LNK_CmdLine *cmd_line, LNK_CmdSwitchType cmd_switch_type, char *param_fmt, ...);
|
||||
internal B32 lnk_cmd_line_has_switch(LNK_CmdLine cmd_line, LNK_CmdSwitchType cmd_switch_type);
|
||||
|
||||
////////////////////////////////
|
||||
// Errors
|
||||
internal B32 lnk_cmd_line_has_switch(LNK_CmdLine cmd_line, LNK_CmdSwitchType cmd_switch_type);
|
||||
|
||||
// --- Errors ------------------------------------------------------------------
|
||||
|
||||
internal void lnk_error_cmd_switch (LNK_ErrorCode code, String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch, char *fmt, ...);
|
||||
internal void lnk_error_cmd_switch_invalid_param_count(LNK_ErrorCode code, String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch);
|
||||
internal void lnk_error_cmd_switch_invalid_param (LNK_ErrorCode code, String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch, String8 param);
|
||||
|
||||
////////////////////////////////
|
||||
// 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 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 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);
|
||||
|
||||
////////////////////////////////
|
||||
// Specialized Parsers
|
||||
// --- Specialized Parsers ------------------------------------------------------
|
||||
|
||||
internal B32 lnk_cmd_switch_parse_version (String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch, String8List value_strings, Version *ver_out);
|
||||
internal B32 lnk_cmd_switch_parse_tuple (String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch, String8List value_strings, Rng1U64 *tuple_out);
|
||||
@@ -572,17 +557,28 @@ internal void lnk_cmd_switch_set_flag_64 (String8 obj_path, String8 lib_path,
|
||||
internal B32 lnk_cmd_switch_parse_string (String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch, String8List value_strings, String8 *string_out);
|
||||
internal void lnk_cmd_switch_parse_string_copy(Arena *arena, String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch, String8List value_strings, String8 *string_out);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal B32 lnk_parse_alt_name_directive(String8 input, LNK_AltName *alt_out);
|
||||
internal B32 lnk_parse_export_directive_ex(Arena *arena, String8List directive, String8 obj_path, String8 lib_path, PE_ExportParse *export_out);
|
||||
internal B32 lnk_parse_export_directive(Arena *arena, String8 directive, String8 obj_path, String8 lib_path, PE_ExportParse *export_out);
|
||||
|
||||
internal LNK_MergeDirectiveNode * lnk_merge_directive_list_push(Arena *arena, LNK_MergeDirectiveList *list, LNK_MergeDirective data);
|
||||
|
||||
internal B32 lnk_parse_merge_directive(String8 string, LNK_MergeDirective *parse_out);
|
||||
|
||||
////////////////////////////////
|
||||
// --- 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 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 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);
|
||||
|
||||
// --- Config ------------------------------------------------------------------
|
||||
|
||||
internal void lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 name, String8List value_list, String8 obj_path, String8 lib_path);
|
||||
|
||||
internal LNK_Config * lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line, LNK_CmdLine cmd_line);
|
||||
|
||||
|
||||
@@ -360,7 +360,7 @@ lnk_merge_debug_t_and_debug_p(Arena *arena, U64 obj_count, CV_DebugT *debug_t_ar
|
||||
}
|
||||
|
||||
internal LNK_CodeViewInput
|
||||
lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, String8List lib_dir_list, U64 obj_count, LNK_Obj **obj_arr)
|
||||
lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_flags, String8List lib_dir_list, U64 obj_count, LNK_Obj **obj_arr)
|
||||
{
|
||||
ProfBegin("Extract CodeView");
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
@@ -675,7 +675,7 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, String8List lib_dir
|
||||
// read type servers from disk in parallel
|
||||
{
|
||||
ProfBegin("Read External Type Servers");
|
||||
String8Array msf_data_arr = lnk_read_data_from_file_path_parallel(tp, scratch.arena, ts_path_arr);
|
||||
String8Array msf_data_arr = lnk_read_data_from_file_path_parallel(tp, scratch.arena, 0, ts_path_arr);
|
||||
ProfEnd();
|
||||
|
||||
MSF_Parsed **msf_parse_arr = lnk_msf_parsed_from_data_parallel(tp_arena, tp, msf_data_arr);
|
||||
@@ -3315,7 +3315,7 @@ lnk_build_pdb(TP_Context *tp,
|
||||
ProfBegin("Build NatVis");
|
||||
{
|
||||
String8Array natvis_file_path_arr = str8_array_from_list(scratch.arena, &config->natvis_list);
|
||||
String8Array natvis_file_data_arr = lnk_read_data_from_file_path_parallel(tp, scratch.arena, natvis_file_path_arr);
|
||||
String8Array natvis_file_data_arr = lnk_read_data_from_file_path_parallel(tp, scratch.arena, config->io_flags, natvis_file_path_arr);
|
||||
|
||||
for (U64 i = 0; i < natvis_file_data_arr.count; ++i) {
|
||||
String8 natvis_file_path = natvis_file_path_arr.v[i];
|
||||
|
||||
@@ -500,7 +500,7 @@ internal CV_DebugT * lnk_parse_debug_t_sections(TP_Context *tp, TP_Arena *
|
||||
internal CV_SymbolList * lnk_cv_symbol_list_arr_from_debug_s_arr(TP_Context *tp, TP_Arena *arena, U64 obj_count, CV_DebugS *debug_s_arr);
|
||||
internal LNK_PchInfo * lnk_setup_pch(Arena *arena, U64 obj_count, LNK_Obj *obj_arr, CV_DebugT *debug_t_arr, CV_DebugT *debug_p_arr, CV_SymbolListArray *parsed_symbols);
|
||||
|
||||
internal LNK_CodeViewInput lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, String8List lib_dir_list, U64 objs_count, LNK_Obj **objs);
|
||||
internal LNK_CodeViewInput lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_flags, String8List lib_dir_list, U64 objs_count, LNK_Obj **objs);
|
||||
|
||||
internal LNK_LeafRef lnk_leaf_ref(U32 idx, U32 leaf_idx);
|
||||
internal LNK_LeafRef lnk_obj_leaf_ref(U32 obj_idx, U32 leaf_idx);
|
||||
|
||||
+64
-44
@@ -172,31 +172,13 @@ lnk_log_read(String8 path, U64 size)
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_read_data_from_file_path(Arena *arena, String8 path)
|
||||
lnk_read_data_from_file_path(Arena *arena, LNK_IO_Flags io_flags, String8 path)
|
||||
{
|
||||
String8 data = str8_zero();
|
||||
OS_Handle handle = {0};
|
||||
int is_open = lnk_open_file_read((char*)path.str, path.size, &handle, sizeof(handle));
|
||||
if (is_open) {
|
||||
U64 buffer_size = lnk_size_from_file(&handle);
|
||||
U8 *buffer = push_array_no_zero(arena, U8, buffer_size);
|
||||
U64 read_size = lnk_read_file(&handle, buffer, buffer_size);
|
||||
|
||||
data = str8(buffer, read_size);
|
||||
|
||||
lnk_close_file(&handle);
|
||||
|
||||
if (read_size != buffer_size) {
|
||||
lnk_error(LNK_Warning_IllData, "incomplete file read occurred, read %u bytes, expected %u bytes, file %S", path);
|
||||
}
|
||||
|
||||
if (lnk_get_log_status(LNK_Log_IO_Read)) {
|
||||
lnk_log_read(path, data.size);
|
||||
}
|
||||
} else {
|
||||
lnk_error(LNK_Error_FileNotFound, "unable to open file %S", path);
|
||||
}
|
||||
return data;
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
TP_Context *single_thread_ctx = tp_alloc(scratch.arena, 1, 1, str8_zero());
|
||||
String8Array data_arr = lnk_read_data_from_file_path_parallel(single_thread_ctx, arena, io_flags, (String8Array){ .count = 1, .v = &path });
|
||||
scratch_end(scratch);
|
||||
return data_arr.v[0];
|
||||
}
|
||||
|
||||
internal
|
||||
@@ -232,33 +214,72 @@ THREAD_POOL_TASK_FUNC(lnk_data_from_file_path_task)
|
||||
task->data_arr.v[task_id] = str8(buffer, read_size);
|
||||
}
|
||||
|
||||
internal String8Array
|
||||
lnk_read_data_from_file_path_parallel(TP_Context *tp, Arena *arena, String8Array path_arr)
|
||||
internal
|
||||
THREAD_POOL_TASK_FUNC(lnk_memory_map_file_task)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena,1);
|
||||
LNK_DiskReader *task = raw_task;
|
||||
#if _WIN32
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String16 path16 = str16_from_8(scratch.arena, task->path_arr.v[task_id]);
|
||||
HANDLE file_handle = CreateFileW(path16.str, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (file_handle != INVALID_HANDLE_VALUE) {
|
||||
HANDLE mapping_handle = CreateFileMappingA(file_handle, 0, PAGE_WRITECOPY, 0, 0, 0);
|
||||
if (mapping_handle != INVALID_HANDLE_VALUE) {
|
||||
LARGE_INTEGER file_size = {0};
|
||||
GetFileSizeEx(file_handle, &file_size);
|
||||
void *file_data = MapViewOfFile(mapping_handle, FILE_MAP_COPY, 0, 0, file_size.QuadPart);
|
||||
if (file_data) {
|
||||
task->data_arr.v[task_id] = str8(file_data, file_size.QuadPart);
|
||||
}
|
||||
CloseHandle(mapping_handle);
|
||||
}
|
||||
CloseHandle(file_handle);
|
||||
}
|
||||
scratch_end(scratch);
|
||||
#else
|
||||
# error "memory mapping files is not supported on this platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
internal String8Array
|
||||
lnk_read_data_from_file_path_parallel(TP_Context *tp, Arena *arena, LNK_IO_Flags io_flags, String8Array path_arr)
|
||||
{
|
||||
LNK_DiskReader reader = {0};
|
||||
reader.path_arr = path_arr;
|
||||
reader.handle_arr = push_array_no_zero(scratch.arena, OS_Handle, path_arr.count);
|
||||
reader.size_arr = push_array_no_zero(scratch.arena, U64, path_arr.count);
|
||||
|
||||
// open handles and get sizes
|
||||
tp_for_parallel(tp, 0, path_arr.count, lnk_data_size_from_file_path_task, &reader);
|
||||
if (io_flags & LNK_IO_Flags_MemoryMapFiles) {
|
||||
reader.io_flags = io_flags;
|
||||
reader.path_arr = path_arr;
|
||||
reader.data_arr.count = path_arr.count;
|
||||
reader.data_arr.v = push_array(arena, String8, path_arr.count);
|
||||
tp_for_parallel(tp, 0, path_arr.count, lnk_memory_map_file_task, &reader);
|
||||
} else {
|
||||
Temp scratch = scratch_begin(&arena,1);
|
||||
|
||||
// compute file buffer size
|
||||
U64 total_data_size = sum_array_u64(path_arr.count, reader.size_arr);
|
||||
reader.path_arr = path_arr;
|
||||
reader.handle_arr = push_array_no_zero(scratch.arena, OS_Handle, path_arr.count);
|
||||
reader.size_arr = push_array_no_zero(scratch.arena, U64, path_arr.count);
|
||||
|
||||
// assign offsets into file buffer
|
||||
U64 *off_arr = push_array_no_zero(scratch.arena, U64, path_arr.count);
|
||||
MemoryCopyTyped(off_arr, reader.size_arr, path_arr.count);
|
||||
counts_to_offsets_array_u64(path_arr.count, off_arr);
|
||||
// open handles and get sizes
|
||||
tp_for_parallel(tp, 0, path_arr.count, lnk_data_size_from_file_path_task, &reader);
|
||||
|
||||
reader.data_arr = str8_array_reserve(arena, path_arr.count);
|
||||
reader.off_arr = off_arr;
|
||||
reader.buffer = push_array_no_zero(arena, U8, total_data_size);
|
||||
// compute file buffer size
|
||||
U64 total_data_size = sum_array_u64(path_arr.count, reader.size_arr);
|
||||
|
||||
// read files and close handles
|
||||
tp_for_parallel(tp, 0, path_arr.count, lnk_data_from_file_path_task, &reader);
|
||||
// assign offsets into file buffer
|
||||
U64 *off_arr = push_array_no_zero(scratch.arena, U64, path_arr.count);
|
||||
MemoryCopyTyped(off_arr, reader.size_arr, path_arr.count);
|
||||
counts_to_offsets_array_u64(path_arr.count, off_arr);
|
||||
|
||||
reader.io_flags = io_flags;
|
||||
reader.data_arr = str8_array_reserve(arena, path_arr.count);
|
||||
reader.off_arr = off_arr;
|
||||
reader.buffer = push_array_no_zero(arena, U8, total_data_size);
|
||||
|
||||
// read files and close handles
|
||||
tp_for_parallel(tp, 0, path_arr.count, lnk_data_from_file_path_task, &reader);
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
String8Array result = {0};
|
||||
result.count = path_arr.count;
|
||||
@@ -270,7 +291,6 @@ lnk_read_data_from_file_path_parallel(TP_Context *tp, Arena *arena, String8Array
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+11
-3
@@ -2,8 +2,17 @@
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
typedef U32 LNK_IO_Flags;
|
||||
enum
|
||||
{
|
||||
LNK_IO_Flags_MemoryMapFiles = (1 << 0),
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LNK_IO_Flags io_flags;
|
||||
String8Array path_arr;
|
||||
String8Array data_arr;
|
||||
OS_Handle *handle_arr;
|
||||
@@ -30,10 +39,9 @@ internal OS_Handle lnk_file_open_with_rename_permissions(String8 path);
|
||||
internal B32 lnk_file_set_delete_on_close(OS_Handle handle, B32 delete_file);
|
||||
internal B32 lnk_file_rename(OS_Handle handle, String8 new_name);
|
||||
|
||||
internal String8 lnk_read_data_from_file_path(Arena *arena, String8 path);
|
||||
internal String8Array lnk_read_data_from_file_path_parallel(TP_Context *tp, Arena *arena, String8Array path_arr);
|
||||
internal String8 lnk_read_data_from_file_path(Arena *arena, LNK_IO_Flags io_flags, String8 path);
|
||||
internal String8Array lnk_read_data_from_file_path_parallel(TP_Context *tp, Arena *arena, LNK_IO_Flags io_flags, String8Array path_arr);
|
||||
|
||||
internal void lnk_write_data_list_to_file_path(String8 path, String8 temp_path, String8List list);
|
||||
internal void lnk_write_data_to_file_path(String8 path, String8 temp_path, String8 data);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user