match LINK import group placement

This commit is contained in:
Nikita Smith committed 2026-08-25 00:10:29 -07:00
1 parent 0a328898d0
commit c9acc3f1ad
3 files changed
+49 -25

No files matched your search

+25 -23
View File
@@ -5678,7 +5678,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
// Preserve each source section's contribution range across the merge.
ProfBegin("Sort Sections");
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
lnk_sort_section_contribs(&sect_n->data);
lnk_sort_section_contribs(&sect_n->data, 0);
}
ProfEnd();
@@ -5689,7 +5689,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
ProfBegin("Sort Merged Sections");
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
lnk_sort_section_contribs(&sect_n->data);
lnk_sort_section_contribs(&sect_n->data, 1);
}
ProfEnd();
@@ -6190,7 +6190,7 @@ lnk_map_push_symbol_line(Arena *arena, String8List *map, LNK_MapSymbol *symbol)
}
internal String8List
lnk_build_map(Arena *arena, String8 image_data, LNK_Config *config, LNK_SymbolTable *symtab, U64 objs_count, LNK_Obj **objs)
lnk_build_map(Arena *arena, String8 image_data, LNK_Config *config, LNK_SymbolTable *symtab, LNK_SectionTable *sectab, U64 objs_count, LNK_Obj **objs)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
@@ -6212,31 +6212,33 @@ lnk_build_map(Arena *arena, String8 image_data, LNK_Config *config, LNK_SymbolTa
str8_list_pushf(arena, &map, " Start Length Name Class\r\n");
U64 section_cap = 0;
for EachIndex(obj_idx, objs_count) { section_cap += objs[obj_idx]->coff.sections.count_no_null; }
for EachNode(sect_n, LNK_SectionNode, sectab->list.first) { section_cap += sect_n->data.contribs.chunk_count; }
LNK_MapSection *sections = push_array(scratch.arena, LNK_MapSection, section_cap);
U64 section_count = 0;
HashMap *section_maps = push_array(scratch.arena, HashMap, pe.section_count + 1);
for EachIndex(obj_idx, objs_count) {
LNK_Obj *obj = objs[obj_idx];
for LNK_EachCoffSection(it, obj) {
COFF_SectionFlags flags = *it.v.flags;
if (flags & (COFF_SectionFlag_LnkRemove | COFF_SectionFlag_LnkInfo | LNK_SECTION_FLAG_DEBUG)) { continue; }
for EachNode(sect_n, LNK_SectionNode, sectab->list.first) {
LNK_Section *image_section = &sect_n->data;
U32 image_section_number = safe_cast_u32(image_section->sect_idx + 1);
if (image_section_number > pe.section_count) { continue; }
U32 image_section_number = lnk_map_image_section_number_from_voff(image_section_table, pe.section_count, it.v.header->voff);
if (image_section_number == 0) { continue; }
for EachNode(chunk, LNK_SectionContribChunk, image_section->contribs.first) {
String8 name = chunk->sort_idx;
if (name.size == 0) { continue; }
String8 name = lnk_obj_section_name_from_section_number(obj, it.v.section_number);
LNK_MapSection *section = hash_map_search_string_raw(&section_maps[image_section_number], name);
U32 off = safe_cast_u32(it.v.header->voff - image_section_table[image_section_number]->voff);
U32 end = off + it.v.header->vsize;
if (section == 0) {
Assert(section_count < section_cap);
section = &sections[section_count++];
*section = (LNK_MapSection){ name, image_section_number, off, end, !!(flags & COFF_SectionFlag_CntCode) };
hash_map_push_string_raw(scratch.arena, &section_maps[image_section_number], name, section);
} else {
section->off = Min(section->off, off);
section->end = Max(section->end, end);
for EachIndex(sc_idx, chunk->count) {
LNK_SectionContrib *sc = chunk->v[sc_idx];
U32 off = sc->u.off;
U32 end = off + safe_cast_u32(lnk_size_from_section_contrib(sc));
if (section == 0) {
Assert(section_count < section_cap);
section = &sections[section_count++];
*section = (LNK_MapSection){ name, image_section_number, off, end, !!(image_section->flags & COFF_SectionFlag_CntCode) };
hash_map_push_string_raw(scratch.arena, &section_maps[image_section_number], name, section);
} else {
section->off = Min(section->off, off);
section->end = Max(section->end, end);
}
}
}
}
@@ -6489,7 +6491,7 @@ lnk_run_linker(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
// Map
//
if (config->map == LNK_SwitchState_Yes) {
String8List map = lnk_build_map(scratch.arena, image_ctx.image_data, config, symtab, objs_count, objs);
String8List map = lnk_build_map(scratch.arena, image_ctx.image_data, config, symtab, image_ctx.sectab, objs_count, objs);
lnk_write_data_list_to_file_path(config->map_name, config->temp_map_name, map);
}
+15 -2
View File
@@ -331,14 +331,27 @@ lnk_section_contrib_chunk_is_before(void *raw_a, void *raw_b)
return str8_is_before_case_sensitive(&(*a)->sort_idx, &(*b)->sort_idx);
}
internal int
lnk_merged_section_contrib_chunk_is_before(void *raw_a, void *raw_b)
{
LNK_SectionContribChunk **a = raw_a, **b = raw_b;
U64 a_rank = str8_starts_with((*a)->sort_idx, str8_lit(".idata$5")) ? 0 : str8_starts_with((*a)->sort_idx, str8_lit(".idata$")) ? 2 : 1;
U64 b_rank = str8_starts_with((*b)->sort_idx, str8_lit(".idata$5")) ? 0 : str8_starts_with((*b)->sort_idx, str8_lit(".idata$")) ? 2 : 1;
if (a_rank != b_rank) {
return a_rank < b_rank;
}
return str8_is_before_case_sensitive(&(*a)->sort_idx, &(*b)->sort_idx);
}
internal void
lnk_sort_section_contribs(LNK_Section *sect)
lnk_sort_section_contribs(LNK_Section *sect, B32 is_merged_output)
{
ProfBeginFunction();
Temp scratch = scratch_begin(0,0);
LNK_SectionContribChunk **chunks = lnk_array_from_section_contrib_chunk_list(scratch.arena, sect->contribs);
radsort(chunks, sect->contribs.chunk_count, lnk_section_contrib_chunk_is_before);
radsort(chunks, sect->contribs.chunk_count,
is_merged_output ? lnk_merged_section_contrib_chunk_is_before : lnk_section_contrib_chunk_is_before);
// repopulate chunk list in sorted order
sect->contribs.first = 0;
+9
View File
@@ -2312,6 +2312,9 @@ TEST(section_sort)
T_Ok(t_write_def_obj("data.obj", (T_COFF_DefObj){
.machine = T_COFF_DefSetMachine(X64),
.sections = (T_COFF_DefSection[]){
{ "idata_2", ".idata$2", str8_lit("last"), .flags = "rw:data@1" },
{ "idata_5", ".idata$5", str8_lit("first"), .flags = "rw:data@1" },
{ "rdata", ".rdata", str8_lit("middle"), .flags = "r:data@1" },
{ "data_z", ".data$z", str8_lit("five"), .raw_flags = data_flags },
{ "data_a", ".data$a", str8_lit("three"), .raw_flags = data_flags },
{ "data_bbbbb", ".data$bbbbb", str8_lit("four"), .raw_flags = data_flags },
@@ -2347,6 +2350,12 @@ TEST(section_sort)
String8 data = str8_substr(exe, rng_1u64(data_section->foff, data_section->foff + data_section->vsize));
String8 expected_data = str8_lit("onetwothreefourfive");
T_Ok(str8_match(data, expected_data, 0));
COFF_SectionHeader *rdata_section = coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".rdata"));
T_Ok(rdata_section);
String8 rdata = str8_substr(exe, rng_1u64(rdata_section->foff, rdata_section->foff + 15));
T_Ok(str8_match(rdata, str8_lit("firstmiddlelast"), 0));
}
TEST(flag_conf)