mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
add /FAILIFMISMATCH
This commit is contained in:
+45
-14
@@ -42,8 +42,8 @@ global read_only LNK_CmdSwitch g_cmd_switch_map[] =
|
||||
{ LNK_CmdSwitch_NotImplemented, 0, "EXPORTADMIN", "", "" },
|
||||
{ LNK_CmdSwitch_Experimental, 0, "EXPERIMENTAL", "Not supported." },
|
||||
{ LNK_CmdSwitch_FastFail, 0, "FASTFAIL", "", "Not used." },
|
||||
{ LNK_CmdSwitch_FailIfMismatch, 1, "FAILIFMISMATCH", "{id=value}", "" },
|
||||
{ LNK_CmdSwitch_NotImplemented, 0, "FASTGENPROFILE", "", "" },
|
||||
{ LNK_CmdSwitch_FailIfMismatch, 1, "FAILIFMISMATCH", "", "" },
|
||||
{ LNK_CmdSwitch_FileAlign, 0, "FILEALIGN", ":#", "" },
|
||||
{ LNK_CmdSwitch_Fixed, 0, "FIXED", "[:NO]", "" },
|
||||
{ LNK_CmdSwitch_NotImplemented, 0, "FORCE", "", "" },
|
||||
@@ -398,7 +398,7 @@ lnk_cmd_switch_parse_version(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse major version");
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
|
||||
exit:;
|
||||
@@ -431,7 +431,7 @@ lnk_cmd_switch_parse_tuple(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8Li
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse first parameter \"%S\"", value_strings.first->string);
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -595,7 +595,7 @@ lnk_cmd_switch_parse_string(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8L
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "empty string is not permitted");
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1183,7 +1183,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1240,7 +1240,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid parameter \"%S\"", value_strings.first->string);
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1255,7 +1255,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
|
||||
case LNK_CmdSwitch_Delay: {
|
||||
if (value_strings.node_count == 0 || value_strings.node_count > 1) {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
} else {
|
||||
String8 value = value_strings.first->string;
|
||||
if (str8_match_lit("unload", value, StringMatchFlag_CaseInsensitive)) {
|
||||
@@ -1359,6 +1359,36 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
// do nothing
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_FailIfMismatch: {
|
||||
if (value_strings.node_count != 1) {
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
break;
|
||||
}
|
||||
|
||||
LNK_AltName dir;
|
||||
if ( ! lnk_parse_alt_name_directive(value_strings.first->string, obj, &dir)) {
|
||||
break;
|
||||
}
|
||||
|
||||
LNK_AltName *current = hash_table_search_string_raw(config->fail_if_mismatch_ht, dir.from);
|
||||
if (current) {
|
||||
if ( ! str8_match(current->to, dir.to, 0)) {
|
||||
lnk_error_cmd_switch(LNK_Error_FailIfMismatch, obj, cmd_switch,
|
||||
"'%S=%S' mismatch in:\n"
|
||||
" %S: /FAILIFMISMATCH:%S=%S\n",
|
||||
dir.from, dir.to,
|
||||
lnk_loc_from_obj(scratch.arena, current->obj), current->from, current->to);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
LNK_AltName *n = push_array(config->arena, LNK_AltName, 1);
|
||||
n->from = push_str8_copy(config->arena, dir.from);
|
||||
n->to = push_str8_copy(config->arena, dir.to);
|
||||
n->obj = obj;
|
||||
hash_table_push_string_raw(config->arena, config->fail_if_mismatch_ht, n->from, n);
|
||||
}
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_FileAlign: {
|
||||
lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &config->file_align, LNK_ParseU64Flag_CheckPow2);
|
||||
} break;
|
||||
@@ -1472,7 +1502,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unknown parameter \"%S\"", value_strings.first->string);
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1603,7 +1633,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
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);
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1717,7 +1747,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
if (value_strings.node_count == 0) {
|
||||
config->flags |= LNK_ConfigFlag_WriteImageChecksum;
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1766,7 +1796,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid subsystem \"%S\"", value_strings.first->string);
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1893,7 +1923,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid parameter: \"%S\", expected NO or QUIET", value_strings.first->string);
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1919,7 +1949,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters, expected 1");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1944,7 +1974,7 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse parameter \"%S\"", value_strings.first->string);
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -2095,6 +2125,7 @@ lnk_config_from_cmd_line(String8List raw_cmd_line, LNK_CmdLine cmd_line)
|
||||
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);
|
||||
config->fail_if_mismatch_ht = hash_table_init(arena, 0x100);
|
||||
|
||||
// process command line switches
|
||||
for (LNK_CmdOption *cmd = cmd_line.first_option; cmd != 0; cmd = cmd->next) {
|
||||
|
||||
@@ -50,6 +50,7 @@ typedef enum
|
||||
LNK_CmdSwitch_ErrorReport,
|
||||
LNK_CmdSwitch_Experimental,
|
||||
LNK_CmdSwitch_Export,
|
||||
LNK_CmdSwitch_FailIfMismatch,
|
||||
LNK_CmdSwitch_FastFail,
|
||||
LNK_CmdSwitch_FileAlign,
|
||||
LNK_CmdSwitch_Fixed,
|
||||
@@ -107,7 +108,6 @@ typedef enum
|
||||
LNK_CmdSwitch_EmitVolatileMetadata,
|
||||
LNK_CmdSwitch_ExportAdmin,
|
||||
LNK_CmdSwitch_FastGenProfile,
|
||||
LNK_CmdSwitch_FailIfMismatch,
|
||||
LNK_CmdSwitch_Force,
|
||||
LNK_CmdSwitch_Guard,
|
||||
LNK_CmdSwitch_GuardSym,
|
||||
@@ -416,6 +416,7 @@ typedef struct LNK_Config
|
||||
HashTable *include_symbol_ht;
|
||||
HashTable *delay_load_ht;
|
||||
HashTable *disallow_lib_ht;
|
||||
HashTable *fail_if_mismatch_ht;
|
||||
U64 unresolved_symbol_limit;
|
||||
U64 unresolved_symbol_ref_limit;
|
||||
LNK_SwitchState map_lines_for_unresolved_symbols;
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef enum
|
||||
LNK_Error_AssociativeLoop,
|
||||
LNK_Error_AlternateNameConflict,
|
||||
LNK_Error_RelocationAgainstRemovedSection,
|
||||
LNK_Error_FailIfMismatch,
|
||||
LNK_Error_StopLast,
|
||||
|
||||
LNK_Error_First,
|
||||
|
||||
@@ -40,6 +40,16 @@ t_make_sec_defn_obj(Arena *arena, String8 payload)
|
||||
return obj;
|
||||
}
|
||||
|
||||
internal String8
|
||||
t_make_obj_with_directive(Arena *arena, String8 directive)
|
||||
{
|
||||
COFF_ObjWriter *cow = coff_obj_writer_alloc(0, COFF_MachineType_X64);
|
||||
coff_obj_writer_push_directive(cow, directive);
|
||||
String8 obj = coff_obj_writer_serialize(arena, cow);
|
||||
coff_obj_writer_release(&cow);
|
||||
return obj;
|
||||
}
|
||||
|
||||
internal String8
|
||||
t_make_entry_obj(Arena *arena)
|
||||
{
|
||||
@@ -3856,5 +3866,48 @@ T_BeginTest(opt_ref_dangling_section)
|
||||
}
|
||||
T_EndTest;
|
||||
|
||||
T_BeginTest(fail_if_mismatch)
|
||||
{
|
||||
T_Ok(t_write_entry_obj());
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// try linking two objs with mismatching directives
|
||||
|
||||
String8 a1 = t_make_obj_with_directive(scratch.arena, str8_lit("/FAILIFMISMATCH:a=1"));
|
||||
String8 a2 = t_make_obj_with_directive(scratch.arena, str8_lit("/FAILIFMISMATCH:a=2"));
|
||||
T_Ok(t_write_file(str8_lit("a1.obj"), a1));
|
||||
T_Ok(t_write_file(str8_lit("a2.obj"), a2));
|
||||
|
||||
t_invoke_linkerf("entry.obj a1.obj a2.obj /entry:entry /subsystem:console /out:a2.exe");
|
||||
if (t_id_linker() == T_Linker_RAD) T_Ok(g_last_exit_code == LNK_Error_FailIfMismatch);
|
||||
else T_Ok(g_last_exit_code != 0);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// happy case
|
||||
|
||||
T_Ok(t_write_file(str8_lit("a1_copy.obj"), a1));
|
||||
|
||||
t_invoke_linkerf("entry.obj a1.obj a1_copy.obj /entry:entry /subsystem:console /out:a1.exe");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// test conflicting directives in obj
|
||||
|
||||
String8 conf_dirs = t_make_obj_with_directive(scratch.arena, str8_lit("/FAILIFMISMATCH:a=1 /FAILIFMISMATCH:a=2"));
|
||||
T_Ok(t_write_file(str8_lit("conf_dirs.obj"), conf_dirs));
|
||||
|
||||
t_invoke_linkerf("entry.obj conf_dirs.obj /entry:entry /subsystem:console /out:conf_dirs.exe");
|
||||
if (t_id_linker() == T_Linker_RAD) T_Ok(g_last_exit_code == LNK_Error_FailIfMismatch);
|
||||
else T_Ok(g_last_exit_code != 0);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// passing switch on command line
|
||||
|
||||
t_invoke_linkerf("entry.obj a1.obj /FAILIFMISMATCH:a=2 /out:cmddir.exe");
|
||||
if (t_id_linker() == T_Linker_RAD) T_Ok(g_last_exit_code == LNK_Error_FailIfMismatch);
|
||||
else T_Ok(g_last_exit_code != 0);
|
||||
}
|
||||
T_EndTest;
|
||||
|
||||
#undef T_Group
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ internal COFF_ObjSection * t_push_rdata_section(COFF_ObjWriter *obj_writer, Stri
|
||||
|
||||
internal String8 t_make_entry_obj(Arena *arena);
|
||||
internal String8 t_make_sec_defn_obj(Arena *arena, String8 payload);
|
||||
internal String8 t_make_obj_with_directive(Arena *arena, String8 directive);
|
||||
|
||||
internal B32 t_write_entry_obj(void);
|
||||
internal B32 t_write_entry_obj(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user