make const data eligible for ICF

This commit is contained in:
Nikita Smith
2026-07-27 14:47:28 -07:00
committed by Ryan Fleury
parent c629c5b10e
commit 2d827ac15d
3 changed files with 23 additions and 6 deletions
+13 -1
View File
@@ -2977,6 +2977,7 @@ typedef enum LNK_ICF_ColorSpace
LNK_ICF_ColorSpace_Code, LNK_ICF_ColorSpace_Code,
LNK_ICF_ColorSpace_Unwind, LNK_ICF_ColorSpace_Unwind,
LNK_ICF_ColorSpace_VFTable, LNK_ICF_ColorSpace_VFTable,
LNK_ICF_ColorSpace_ConstData, // string literals, float consts, const tables (/Gw and /GF)
LNK_ICF_ColorSpace_COUNT, LNK_ICF_ColorSpace_COUNT,
} LNK_ICF_ColorSpace; } LNK_ICF_ColorSpace;
@@ -2989,6 +2990,7 @@ lnk_string_from_icf_color_space(LNK_ICF_ColorSpace color_space)
case LNK_ICF_ColorSpace_Code: { result = str8_lit("Code"); } break; case LNK_ICF_ColorSpace_Code: { result = str8_lit("Code"); } break;
case LNK_ICF_ColorSpace_Unwind: { result = str8_lit("Unwind"); } break; case LNK_ICF_ColorSpace_Unwind: { result = str8_lit("Unwind"); } break;
case LNK_ICF_ColorSpace_VFTable: { result = str8_lit("VFTables"); } break; case LNK_ICF_ColorSpace_VFTable: { result = str8_lit("VFTables"); } break;
case LNK_ICF_ColorSpace_ConstData: { result = str8_lit("ConstData"); } break;
case LNK_ICF_ColorSpace_COUNT: { result = str8_lit("Unknown"); } break; case LNK_ICF_ColorSpace_COUNT: { result = str8_lit("Unknown"); } break;
} }
return result; return result;
@@ -3017,13 +3019,23 @@ lnk_icf_color_space_from_section(LNK_Obj *obj, U32 sect_idx)
if (str8_match(section_name, str8_lit(".xdata"), 0) || str8_match(section_name, str8_lit(".pdata"), 0)) { if (str8_match(section_name, str8_lit(".xdata"), 0) || str8_match(section_name, str8_lit(".pdata"), 0)) {
result = LNK_ICF_ColorSpace_Unwind; result = LNK_ICF_ColorSpace_Unwind;
} else { } else {
// fold MSVC vftables separately from other read-only data
LNK_ObjSymbolRef symlink_ref = {0}; LNK_ObjSymbolRef symlink_ref = {0};
if (lnk_obj_get_comdat_symlink(obj, sect_idx + 1, &symlink_ref)) { if (lnk_obj_get_comdat_symlink(obj, sect_idx + 1, &symlink_ref)) {
String8 symlink_name = lnk_symbol_name_from_coff_symbol_idx(symlink_ref.obj, symlink_ref.symbol_idx); String8 symlink_name = lnk_symbol_name_from_coff_symbol_idx(symlink_ref.obj, symlink_ref.symbol_idx);
// fold MSVC vftables separately from other read-only data
if (str8_starts_with(symlink_name, str8_lit(MSCRT_VFTABLE_SYMBOL_PREFIX))) { if (str8_starts_with(symlink_name, str8_lit(MSCRT_VFTABLE_SYMBOL_PREFIX))) {
result = LNK_ICF_ColorSpace_VFTable; result = LNK_ICF_ColorSpace_VFTable;
} }
// fold ordinary read-only data COMDATs; do not fold declarations and vtables that require unique addresses
else if (!str8_starts_with(symlink_name, str8_lit(MSCRT_VBTABLE_SYMBOL_PREFIX))) {
COFF_ComdatSelectType select = COFF_ComdatSelect_Null;
if (lnk_try_comdat_props_from_section_number(obj, sect_idx + 1, &select, 0, 0, 0)) {
if (select == COFF_ComdatSelect_Any || select == COFF_ComdatSelect_SameSize ||
select == COFF_ComdatSelect_ExactMatch || select == COFF_ComdatSelect_Largest) {
result = LNK_ICF_ColorSpace_ConstData;
}
}
}
} }
} }
} }
+9 -4
View File
@@ -9249,7 +9249,7 @@ TEST(icf_readonly_non_vftable_data_policy)
{ {
U8 data_bytes[] = { 1, 2, 3, 4 }; U8 data_bytes[] = { 1, 2, 3, 4 };
U8 entry_text[] = { 0xc3 }; U8 entry_text[] = { 0xc3 };
U8 addresses[2 * sizeof(U64)] = {0}; U8 addresses[4 * sizeof(U64)] = {0};
T_Ok(t_write_def_obj("icf_rdata_policy.obj", (T_COFF_DefObj){ T_Ok(t_write_def_obj("icf_rdata_policy.obj", (T_COFF_DefObj){
.machine = T_COFF_DefSetMachine(X64), .machine = T_COFF_DefSetMachine(X64),
@@ -9257,12 +9257,15 @@ TEST(icf_readonly_non_vftable_data_policy)
{ "entry", ".text", str8_array_fixed(entry_text), .flags = "rx:code@1" }, { "entry", ".text", str8_array_fixed(entry_text), .flags = "rx:code@1" },
{ "data_a", ".rdata$mn", str8_array_fixed(data_bytes), .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT }, { "data_a", ".rdata$mn", str8_array_fixed(data_bytes), .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT },
{ "data_b", ".rdata$mn", str8_array_fixed(data_bytes), .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT }, { "data_b", ".rdata$mn", str8_array_fixed(data_bytes), .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT },
{ "addresses", ".data", str8_array_fixed(addresses), .flags = "rw:data@1", .relocs = (T_COFF_DefReloc[]){ T_COFF_DefReloc(X64_Addr64, 0, "data_a"), T_COFF_DefReloc(X64_Addr64, 8, "data_b"), {0} } }, { "data_c", ".rdata$mn", str8_array_fixed(data_bytes), .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT },
{ "data_d", ".rdata$mn", str8_array_fixed(data_bytes), .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT },
{ "addresses", ".data", str8_array_fixed(addresses), .flags = "rw:data@1", .relocs = (T_COFF_DefReloc[]){ T_COFF_DefReloc(X64_Addr64, 0, "data_a"), T_COFF_DefReloc(X64_Addr64, 8, "data_b"), T_COFF_DefReloc(X64_Addr64, 16, "data_c"), T_COFF_DefReloc(X64_Addr64, 24, "data_d"), {0} } },
{0} {0}
}, },
.symbols = (T_COFF_DefSymbol[]){ .symbols = (T_COFF_DefSymbol[]){
T_COFF_DefSymbol_Secdef("data_a", COFF_ComdatSelect_NoDuplicates), T_COFF_DefSymbol_Secdef("data_b", COFF_ComdatSelect_NoDuplicates), T_COFF_DefSymbol_Secdef("data_a", COFF_ComdatSelect_NoDuplicates), T_COFF_DefSymbol_Secdef("data_b", COFF_ComdatSelect_NoDuplicates),
T_COFF_DefSymbol_ExternFunc("entry", "entry", 0), T_COFF_DefSymbol_Extern("data_a", "data_a", 0), T_COFF_DefSymbol_Extern("data_b", "data_b", 0), T_COFF_DefSymbol_Extern("addresses", "addresses", 0), T_COFF_DefSymbol_Secdef("data_c", COFF_ComdatSelect_Any), T_COFF_DefSymbol_Secdef("data_d", COFF_ComdatSelect_Any),
T_COFF_DefSymbol_ExternFunc("entry", "entry", 0), T_COFF_DefSymbol_Extern("data_a", "data_a", 0), T_COFF_DefSymbol_Extern("data_b", "data_b", 0), T_COFF_DefSymbol_Extern("data_c", "data_c", 0), T_COFF_DefSymbol_Extern("data_d", "data_d", 0), T_COFF_DefSymbol_Extern("addresses", "addresses", 0),
{0} {0}
} }
})); }));
@@ -9270,11 +9273,13 @@ TEST(icf_readonly_non_vftable_data_policy)
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /opt:ref,icf /include:addresses icf_rdata_policy.obj"); t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /opt:ref,icf /include:addresses icf_rdata_policy.obj");
T_Ok(g_last_exit_code == 0); T_Ok(g_last_exit_code == 0);
U64 vaddrs[2] = {0}; U64 vaddrs[4] = {0};
T_Ok(t_read_exe_data_vaddrs(arena, str8_lit("a.exe"), vaddrs, ArrayCount(vaddrs))); T_Ok(t_read_exe_data_vaddrs(arena, str8_lit("a.exe"), vaddrs, ArrayCount(vaddrs)));
T_Ok(vaddrs[0] != 0); T_Ok(vaddrs[0] != 0);
T_Ok(vaddrs[1] != 0); T_Ok(vaddrs[1] != 0);
T_Ok(vaddrs[0] != vaddrs[1]); T_Ok(vaddrs[0] != vaddrs[1]);
T_Ok(vaddrs[2] != 0);
T_Ok(vaddrs[2] == vaddrs[3]);
} }
TEST(icf_cpp_identical_functions_fold) TEST(icf_cpp_identical_functions_fold)
+1 -1
View File
@@ -35,6 +35,7 @@
// MSVC C++ vftable symbols start with this decorated-name prefix. // MSVC C++ vftable symbols start with this decorated-name prefix.
#define MSCRT_VFTABLE_SYMBOL_PREFIX "??_7" #define MSCRT_VFTABLE_SYMBOL_PREFIX "??_7"
#define MSCRT_VBTABLE_SYMBOL_PREFIX "??_8"
//////////////////////////////// ////////////////////////////////
@@ -380,4 +381,3 @@ mscrt_catch_blocks_from_data_x8664(Arena *arena,
internal String8 mscrt_string_from_eh_adjectives(Arena *arena, MSCRT_EhHandlerTypeFlags adjectives); internal String8 mscrt_string_from_eh_adjectives(Arena *arena, MSCRT_EhHandlerTypeFlags adjectives);
#endif // MSVC_CRT #endif // MSVC_CRT