diff --git a/src/base/base_core.h b/src/base/base_core.h index a5b2a964..0cb16243 100644 --- a/src/base/base_core.h +++ b/src/base/base_core.h @@ -199,7 +199,7 @@ #define EachNonZeroEnumVal(type, it) (type it = (type)1; it < type##_COUNT; it = (type)(it+1)) #define EachInRange(it, range) (U64 it = (range).min; it < (range).max; it += 1) #define EachNode(it, T, first) (T *it = first; it != 0; it = it->next) -#define EachBit(it, flags) (U64 (_i_) = (flags), it = (flags) & -(flags); (_i_) != 0; (_i_) &= ((_i_) - 1), it = (flags) & -(flags)) +#define EachBit(it, flags) (U64 (_i_) = (flags), it = (_i_) & -(_i_); (_i_) != 0; (_i_) &= ((_i_) - 1), it = (_i_) & -(_i_)) //////////////////////////////// //~ rjf: Memory Operation Macros diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 4b72899f..e66833b9 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -1605,7 +1605,7 @@ lnk_load_inputs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer } // by default terminal server is enabled for windows and console applications - if (~config->flags & LNK_ConfigFlag_NoTsAware && ~config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) { + if (~config->flags & LNK_ConfigFlag_NoTsAware && ~config->file_characteristics & PE_ImageFileCharacteristic_DLL) { if (config->subsystem == PE_WindowsSubsystem_WINDOWS_GUI || config->subsystem == PE_WindowsSubsystem_WINDOWS_CUI) { config->dll_characteristics |= PE_DllCharacteristic_TERMINAL_SERVER_AWARE; } @@ -2397,7 +2397,35 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer // was entry point resolved? // if (config->entry_point_name.size == 0 || link->try_to_resolve_entry_point) { - lnk_error(LNK_Error_EntryPoint, "unable to find entry point symbol"); + String8 machine_str = coff_string_from_machine_type(config->machine); + String8 subsystem_str = pe_string_from_subsystem(config->subsystem); + String8Array entry_points = pe_get_entry_point_names(config->machine, config->subsystem, config->file_characteristics); + + String8List list = {0}; + for EachIndex(i, entry_points.count) { str8_list_push(scratch.arena, &list, entry_points.v[i]); } + String8 default_entries = str8_list_join(scratch.arena, &list, &(StringJoin){.sep = ", "}); + + lnk_error(LNK_Error_EntryPoint, + "failed to infer entry point symbol from the inputs\n" + " Machine: %S\n" + " Subsystem: %S\n" + " Subsystem Ver: %llu.%llu\n" + " File Chars: %S\n" + " DLL Chars: %S\n" + " Default Entries: %S\n" + " User Entry: \"%S\"\n" + " Input Obj Count: %S\n" + " Input Lib Count: %S", + machine_str.size ? machine_str : str8_lit("Unknown"), // Machine + subsystem_str.size ? subsystem_str : str8_lit("Unknown"), // Version + config->subsystem_ver.major, config->subsystem_ver.minor, // Subsystem + pe_string_from_file_characteristics(scratch.arena, config->file_characteristics), // File Chars + pe_string_from_dll_characteristics(scratch.arena, config->dll_characteristics), // DLL Chars + default_entries.size ? default_entries : str8_lit("None"), // Default Entry Points + config->entry_point_name, // /ENTRY + str8_from_count(scratch.arena, config->input_list[LNK_Input_Obj].node_count), // Input Objects Count + str8_from_count(scratch.arena, config->input_list[LNK_Input_Lib].node_count) // Input Libs Count + ); } // @@ -6597,7 +6625,7 @@ lnk_run_linker(TP_Context *tp, TP_Arena *arena, LNK_Config *config) // // Import Library // - if (config->build_imp_lib && (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL)) { + if (config->build_imp_lib && (config->file_characteristics & PE_ImageFileCharacteristic_DLL)) { ProfBegin("Build Import Library"); lnk_timer_begin(LNK_Timer_Lib); String8 linker_debug_symbols = lnk_make_linker_debug_symbols(scratch.arena, config->machine); diff --git a/src/linker/lnk_config.c b/src/linker/lnk_config.c index 985e91c6..0aba8f5e 100644 --- a/src/linker/lnk_config.c +++ b/src/linker/lnk_config.c @@ -897,9 +897,9 @@ 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) { + if (config->file_characteristics & PE_ImageFileCharacteristic_DLL) { base_addr = coff_default_dll_base_from_machine(config->machine); - } else if (config->file_characteristics & PE_ImageFileCharacteristic_EXE) { + } else if (config->file_characteristics & PE_ImageFileCharacteristic_EXECUTABLE_IMAGE) { 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 { @@ -1397,7 +1397,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List } break; case LNK_CmdSwitch_Dll: { - config->file_characteristics |= PE_ImageFileCharacteristic_FILE_DLL; + config->file_characteristics |= PE_ImageFileCharacteristic_DLL; } break; case LNK_CmdSwitch_DynamicBase: { @@ -2112,7 +2112,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List } break; case LNK_CmdSwitch_Rad_Exe: { - lnk_cmd_switch_set_flag_16(obj, cmd_switch, value_strings, &config->file_characteristics, PE_ImageFileCharacteristic_EXE); + lnk_cmd_switch_set_flag_16(obj, cmd_switch, value_strings, &config->file_characteristics, PE_ImageFileCharacteristic_EXECUTABLE_IMAGE); } break; case LNK_CmdSwitch_Rad_Guid: { @@ -2638,7 +2638,7 @@ lnk_apply_def_file_to_config(LNK_Config *config, String8 path, LNK_Obj *obj) } if (stmt == LNK_DefFileStmt_Library) { - config->file_characteristics |= PE_ImageFileCharacteristic_FILE_DLL; + config->file_characteristics |= PE_ImageFileCharacteristic_DLL; } if (name.size != 0) { @@ -2775,7 +2775,7 @@ lnk_config_init(LNK_CmdLine cmd_line) // set default manifest resource id if (config->manifest_resource_id == 0) { - if (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) { + if (config->file_characteristics & PE_ImageFileCharacteristic_DLL) { config->manifest_resource_id = push_u64(arena, 2); } else { config->manifest_resource_id = push_u64(arena, 1); @@ -2844,7 +2844,7 @@ lnk_config_init(LNK_CmdLine cmd_line) } // warn about unused large address aware flag - if ((~config->file_characteristics & PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE) && (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL)) { + if ((~config->file_characteristics & PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE) && (config->file_characteristics & PE_ImageFileCharacteristic_DLL)) { lnk_error(LNK_Warning_NoLargeAddressAwarenessForDll, "/LARGEADDRESSAWARE:NO has no effect when specified together with /DLL"); } @@ -2867,7 +2867,7 @@ lnk_config_init(LNK_CmdLine cmd_line) // set flags for /FIXED if (config->flags & LNK_ConfigFlag_Fixed) { - config->file_characteristics |= PE_ImageFileCharacteristic_STRIPPED; + config->file_characteristics |= PE_ImageFileCharacteristic_RELOCS_STRIPPED; config->dll_characteristics &= ~PE_DllCharacteristic_DYNAMIC_BASE; } // if we don't have a fixed image and dynamic base switch @@ -2886,7 +2886,7 @@ lnk_config_init(LNK_CmdLine cmd_line) // handle empty /OUT if (!config->out_path.size) { String8 name = str8_list_first(&config->input_list[LNK_Input_Obj]); - String8 ext = (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) ? str8_lit("dll") : str8_lit("exe"); + String8 ext = (config->file_characteristics & PE_ImageFileCharacteristic_DLL) ? str8_lit("dll") : str8_lit("exe"); config->out_path = path_replace_file_extension(scratch.arena, name, ext); } diff --git a/src/pe/pe.c b/src/pe/pe.c index 85d9ed17..85449aeb 100644 --- a/src/pe/pe.c +++ b/src/pe/pe.c @@ -351,6 +351,24 @@ pe_string_from_load_config_guard_flags(Arena *arena, PE_LoadConfigGuardFlags fla return result; } +internal String8 +pe_string_from_file_characteristics(Arena *arena, PE_ImageFileCharacteristics file_chars) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List result = {0}; + for EachBit(i, file_chars) { + switch (i) { +#define X(ID, VAL, DISPLAY_STRING) case (1 << VAL): str8_list_push(scratch.arena, &result, str8_lit(DISPLAY_STRING)); break; + PE_ImageFileCharacteristic_XList +#undef X + default: str8_list_pushf(scratch.arena, &result, "%llu", i); + } + } + String8 string = str8_list_join(arena, &result, &(StringJoin){.sep=str8_lit(", ")}); + scratch_end(scratch); + return string; +} + internal String8 pe_string_from_dll_characteristics(Arena *arena, PE_DllCharacteristics dll_chars) { @@ -915,7 +933,7 @@ pe_get_entry_point_names(COFF_MachineType machine, { String8Array entry_point_names = {0}; - if (file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) { + if (file_characteristics & PE_ImageFileCharacteristic_DLL) { if (machine == COFF_MachineType_X86) { read_only static String8 dll_entry_point_arr[] = { str8_lit_comp("__DllMainCRTStartup@12"), diff --git a/src/pe/pe.h b/src/pe/pe.h index 378d71ed..be8a34df 100644 --- a/src/pe/pe.h +++ b/src/pe/pe.h @@ -53,25 +53,30 @@ enum PE_WindowsSubsystem_COUNT = 14 }; +#define PE_ImageFileCharacteristic_XList \ + X(RELOCS_STRIPPED , 0 , "Relocations Stripped" ) \ + X(EXECUTABLE_IMAGE , 1 , "Executable" ) \ + X(LINE_NUMS_STRIPPED , 2 , "Line Numbers Stripped" ) \ + X(LOCAL_SYMS_STRIPPED , 3 , "Local Symbols Stripped" ) \ + X(AGGRESSIVE_WS_TRIM , 4 , "Aggressive Working Set Trim") \ + X(LARGE_ADDRESS_AWARE , 5 , "Large Address Aware" ) \ + X(RESERVED , 6 , "Reserved" ) \ + X(BYTES_REVERSED_LO , 7 , "Bytes Reversed Low" ) \ + X(32BIT_MACHINE , 8 , "32-Bit Machine" ) \ + X(DEBUG_STRIPPED , 9 , "Debug Information Stripped" ) \ + X(REMOVABLE_RUN_FROM_SWAP, 10, "Removable: Run from Swap" ) \ + X(NET_RUN_FROM_SWAP , 11, "Network: Run from Swap" ) \ + X(SYSTEM , 12, "System File" ) \ + X(DLL , 13, "DLL" ) \ + X(UP_SYSTEM_ONLY , 14, "Uniprocessor System Only" ) \ + X(BYTES_REVERSED_HI , 15, "Bytes Reversed High" ) + typedef U16 PE_ImageFileCharacteristics; enum { - PE_ImageFileCharacteristic_STRIPPED = (1 << 0), - PE_ImageFileCharacteristic_EXE = (1 << 1), - PE_ImageFileCharacteristic_NUMS_STRIPPED = (1 << 2), - PE_ImageFileCharacteristic_PE_STRIPPED = (1 << 3), - PE_ImageFileCharacteristic_AGGRESIVE_WS_TRIM = (1 << 4), - PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE = (1 << 5), - PE_ImageFileCharacteristic_UNUSED1 = (1 << 6), - PE_ImageFileCharacteristic_BYTES_RESERVED_LO = (1 << 7), - PE_ImageFileCharacteristic_32BIT_MACHINE = (1 << 8), - PE_ImageFileCharacteristic_DEBUG_STRIPPED = (1 << 9), - PE_ImageFileCharacteristic_FILE_REMOVABLE_RUN_FROM_SWAP = (1 << 10), - PE_ImageFileCharacteristic_NET_RUN_FROM_SWAP = (1 << 11), - PE_ImageFileCharacteristic_FILE_SYSTEM = (1 << 12), - PE_ImageFileCharacteristic_FILE_DLL = (1 << 13), - PE_ImageFileCharacteristic_FILE_UP_SYSTEM_ONLY = (1 << 14), - PE_ImageFileCharacteristic_BYTES_RESERVED_HI = (1 << 15), +#define X(ID, VAL, ...) PE_ImageFileCharacteristic_##ID = (1 << VAL), + PE_ImageFileCharacteristic_XList +#undef X }; typedef U16 PE_DllCharacteristics;