mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-11-15 02:30:11 -08:00
radlink: satisfy default-library names with explicitly supplied paths
This commit is contained in:
1 parent
8d23d31097
commit
3093f23de8
3 files changed
+88
No files matched your search
@@ -818,6 +818,7 @@ lnk_inputer_init(void)
|
||||
inputer->arena = arena;
|
||||
inputer->objs_ht = hash_table_init(arena, 0x20000);
|
||||
inputer->libs_ht = hash_table_init(arena, 0x1000);
|
||||
inputer->cmd_lib_names_ht = hash_table_init(arena, 0x100);
|
||||
inputer->missing_lib_ht = hash_table_init(arena, 0x100);
|
||||
return inputer;
|
||||
}
|
||||
@@ -928,6 +929,13 @@ lnk_inputer_push_lib_thin(LNK_Inputer *inputer, LNK_Config *config, LNK_InputSou
|
||||
if (lnk_is_lib_disallowed(config, path)) {
|
||||
goto exit;
|
||||
}
|
||||
// An explicitly supplied library also satisfies a bare /DEFAULTLIB name,
|
||||
// even when its directory is not on LIBPATH. Do not strip directory parts
|
||||
// from the request: path-qualified defaults still name distinct libraries.
|
||||
input = hash_table_search_path_raw(inputer->cmd_lib_names_ht, path);
|
||||
if (input) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
// was library already loaded?
|
||||
@@ -964,6 +972,14 @@ lnk_inputer_push_lib_thin(LNK_Inputer *inputer, LNK_Config *config, LNK_InputSou
|
||||
}
|
||||
|
||||
exit:;
|
||||
if (input && input_source == LNK_InputSource_CmdLine) {
|
||||
// Keep basename aliases separate from path identity so two explicitly
|
||||
// supplied libraries with the same basename can both be linked.
|
||||
String8 name = str8_skip_last_slash(input->path);
|
||||
if (!hash_table_search_path(inputer->cmd_lib_names_ht, name)) {
|
||||
hash_table_push_path_raw(inputer->arena, inputer->cmd_lib_names_ht, name, input);
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ typedef struct LNK_Inputer
|
||||
LNK_InputList new_objs;
|
||||
|
||||
HashTable *libs_ht;
|
||||
HashTable *cmd_lib_names_ht;
|
||||
HashTable *missing_lib_ht;
|
||||
LNK_InputList libs;
|
||||
LNK_InputList new_libs[LNK_InputSource_Count];
|
||||
|
||||
@@ -2663,6 +2663,77 @@ TEST(base_relocs)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(default_lib_matches_explicit_path)
|
||||
{
|
||||
COFF_ObjWriter *entry = coff_obj_writer_alloc(0, COFF_MachineType_X64);
|
||||
COFF_ObjSection *text = coff_obj_writer_push_section(entry, str8_lit(".text"),
|
||||
COFF_SectionFlag_CntCode|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemExecute|COFF_SectionFlag_Align1Bytes,
|
||||
str8_lit("\x31\xc0\xc3"));
|
||||
coff_obj_writer_push_symbol_extern_func(entry, str8_lit("entry"), 0, text);
|
||||
T_Ok(t_write_file(str8_lit("entry.obj"), coff_obj_writer_serialize(arena, entry)));
|
||||
coff_obj_writer_release(&entry);
|
||||
char *dirs[] = {"sdk libs", "other libs"};
|
||||
char *symbols[] = {"first_provider", "second_provider"};
|
||||
for EachIndex(i, ArrayCount(dirs)) {
|
||||
T_Ok(make_directory(t_make_file_path(arena, str8_cstring(dirs[i]))));
|
||||
COFF_ObjWriter *obj = coff_obj_writer_alloc(0, COFF_MachineType_X64);
|
||||
coff_obj_writer_push_symbol_abs(obj, str8_cstring(symbols[i]), 1, COFF_SymStorageClass_External);
|
||||
COFF_LibWriter *lib = coff_lib_writer_alloc();
|
||||
coff_lib_writer_push_obj(lib, str8_lit("provider.obj"), coff_obj_writer_serialize(arena, obj));
|
||||
T_Ok(t_write_file(str8f(arena, "%s/provider.lib", dirs[i]), coff_lib_writer_serialize(arena, lib, 0, 0, 1)));
|
||||
coff_lib_writer_release(&lib);
|
||||
coff_obj_writer_release(&obj);
|
||||
}
|
||||
|
||||
char *args = "/subsystem:console /entry:entry /out:default.exe entry.obj /include:first_provider";
|
||||
String8 paths[] = {str8_lit("sdk libs/provider.lib"), t_make_file_path(arena, str8_lit("sdk libs/provider.lib"))};
|
||||
// Debug builds also write normal progress to stderr; reject only the missing-library diagnostic.
|
||||
char *names[] = {"provider.lib", "PROVIDER.LIB", "provider"};
|
||||
// RAD accepts an omitted extension; LLD checks visited names before adding it.
|
||||
U64 name_count = t_id_linker() == Linker_radlink ? ArrayCount(names) : 2;
|
||||
for EachIndex(path_idx, ArrayCount(paths)) {
|
||||
for EachIndex(name_idx, name_count) {
|
||||
t_invoke_linkerf("%s \"%S\" /defaultlib:%s", args, paths[path_idx], names[name_idx]);
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library"), 0) == g_errors.size);
|
||||
}
|
||||
}
|
||||
|
||||
// Embedded directives use a separate input-source queue from /DEFAULTLIB.
|
||||
COFF_ObjWriter *directive = coff_obj_writer_alloc(0, COFF_MachineType_X64);
|
||||
coff_obj_writer_push_directive(directive, str8_lit("/DEFAULTLIB:provider.lib"));
|
||||
T_Ok(t_write_file(str8_lit("directive.obj"), coff_obj_writer_serialize(arena, directive)));
|
||||
coff_obj_writer_release(&directive);
|
||||
t_invoke_linkerf("%s \"%S\" directive.obj", args, paths[1]);
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library"), 0) == g_errors.size);
|
||||
|
||||
// A basename match must not swallow another explicitly named library, or a
|
||||
// path-qualified default, with the same basename but a different provider.
|
||||
t_invoke_linkerf("%s \"%S\" \"other libs/provider.lib\" /include:second_provider", args, paths[1]);
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library"), 0) == g_errors.size);
|
||||
t_invoke_linkerf("%s \"%S\" /defaultlib:\"other libs/provider.lib\" /include:second_provider", args, paths[1]);
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library"), 0) == g_errors.size);
|
||||
|
||||
// Missing defaults must still warn; explicit bare paths are not defaults.
|
||||
t_invoke_linkerf("%s \"%S\" /defaultlib:missing_provider.lib", args, paths[1]);
|
||||
if (t_id_linker() == Linker_radlink) {
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library `missing_provider.lib`"), 0) < g_errors.size);
|
||||
} else {
|
||||
T_Ok(g_last_exit_code != 0);
|
||||
}
|
||||
t_invoke_linkerf("%s \"%S\" provider.lib", args, paths[1]);
|
||||
if (t_id_linker() == Linker_radlink) {
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library `provider.lib`"), 0) < g_errors.size);
|
||||
} else {
|
||||
T_Ok(g_last_exit_code != 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(simple_lib_test)
|
||||
{
|
||||
String8 test_payload = str8_lit("The quick brown fox jumps over the lazy dog");
|
||||
|
||||
Reference in new issue
Block a user