assign layout offsets and sizes to merged sections

This commit is contained in:
Nikita Smith
2025-05-16 13:33:09 -07:00
committed by Ryan Fleury
parent f75cdd23d7
commit 03e4958190
4 changed files with 95 additions and 32 deletions
+34 -17
View File
@@ -2281,6 +2281,11 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
{
ProfBegin("Finalize Sections Layout");
// merge sections
if (config->flags & LNK_ConfigFlag_Merge) {
lnk_section_table_merge(sectab, config->merge_list);
}
// sort contribs
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
for (LNK_SectionContribChunk *sc_chunk = sect_n->data.contribs.first; sc_chunk != 0; sc_chunk = sc_chunk->next) {
@@ -2289,32 +2294,31 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
}
}
// merge sections
if (config->flags & LNK_ConfigFlag_Merge) {
lnk_section_table_merge(sectab, config->merge_list);
}
// assign contribs offsets, sizes, and section indices
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
lnk_finalize_section_layout(sectab, &sect_n->data, config->file_align);
}
// remove empty sections
String8List empty_sect_list = {0};
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
LNK_Section *sect = &sect_n->data;
if (sect->vsize == 0) {
str8_list_push(scratch.arena, &empty_sect_list, sect->name);
{
String8List empty_sect_list = {0};
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
LNK_Section *sect = &sect_n->data;
if (sect->vsize == 0) {
str8_list_push(scratch.arena, &empty_sect_list, sect->name);
}
}
for (String8Node *name_n = empty_sect_list.first; name_n != 0; name_n = name_n->next) {
lnk_section_table_remove(sectab, name_n->string);
}
}
for (String8Node *name_n = empty_sect_list.first; name_n != 0; name_n = name_n->next) {
lnk_section_table_remove(sectab, name_n->string);
}
// assign section indices to sections
U64 sect_idx = 0;
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
sect_n->data.sect_idx = sect_idx++;
{
U64 sect_idx = 0;
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
sect_n->data.sect_idx = sect_idx++;
}
}
// assign section indices to contribs
@@ -2327,6 +2331,19 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
}
}
// assing layout offsets and sizes to merged sections
for (LNK_SectionNode *sect_n = sectab->merge_list.first; sect_n != 0; sect_n = sect_n->next) {
LNK_Section *sect = &sect_n->data;
LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect);
LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(sect);
LNK_Section *final_sect = lnk_finalized_section_from_id(sectab, sect->merge_id);
sect->voff = final_sect->voff + first_sc->u.off;
sect->vsize = (last_sc->u.off - first_sc->u.off) + last_sc->u.size;
sect->foff = final_sect->foff + first_sc->u.off;
sect->fsize = (last_sc->u.off - first_sc->u.off) + last_sc->u.size;
sect->sect_idx = final_sect->sect_idx;
}
ProfEnd();
}
@@ -3054,7 +3071,7 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
ProfEnd();
}
// patch Debug
// patch debug
{
LNK_Section *debug_dir_sect = lnk_section_table_search(sectab, str8_lit(".RAD_LINKER_DEBUG_DIR"), PE_RDATA_SECTION_FLAGS);
if (debug_dir_sect) {
+2 -3
View File
@@ -1436,12 +1436,11 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
case LNK_CmdSwitch_Merge: {
if (value_strings.node_count == 1) {
LNK_MergeDirective merge = {0};;
LNK_MergeDirective merge = {0};
if (lnk_parse_merge_directive(push_str8_copy(arena, value_strings.first->string), &merge)) {
lnk_merge_directive_list_push(arena, &config->merge_list, merge);
} else {
lnk_error_cmd_switch(LNK_Warning_InvalidMergeDirectiveFormat, obj_path, lib_path, cmd_switch, "invalid merge directive format expected \"/MERGE:FROM=TO\" but got \"%S\"",
value_strings.first->string);
lnk_error_cmd_switch(LNK_Warning_InvalidMergeDirectiveFormat, obj_path, lib_path, cmd_switch, "unable to parse merge directive, expected format \"/MERGE:FROM=TO\" but got \"%S\"", value_strings.first->string);
}
} else {
lnk_error_cmd_switch(LNK_Error_Cmdl, obj_path, lib_path, cmd_switch, "invalid number of parameters %d", value_strings.node_count);
+44 -4
View File
@@ -91,6 +91,17 @@ lnk_get_first_section_contrib(LNK_Section *sect)
return 0;
}
internal LNK_SectionContrib *
lnk_get_last_section_contrib(LNK_Section *sect)
{
if (sect->contribs.chunk_count > 0) {
if (sect->contribs.last->count > 0) {
return sect->contribs.last->v[0];
}
}
return 0;
}
internal LNK_SectionTable *
lnk_section_table_alloc(void)
{
@@ -148,7 +159,7 @@ lnk_section_table_push(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags
return sect;
}
internal void
internal LNK_SectionNode *
lnk_section_table_remove(LNK_SectionTable *sectab, String8 name)
{
ProfBeginFunction();
@@ -190,6 +201,7 @@ lnk_section_table_remove(LNK_SectionTable *sectab, String8 name)
}
ProfEnd();
return node;
}
internal LNK_Section *
@@ -210,8 +222,12 @@ lnk_section_table_search(LNK_SectionTable *sectab, String8 full_or_partial_name,
}
internal LNK_SectionArray
lnk_section_table_search_many(Arena *arena, LNK_SectionTable *sectab, String8 name)
lnk_section_table_search_many(Arena *arena, LNK_SectionTable *sectab, String8 full_or_partial_name)
{
String8 name = {0};
String8 postfix = {0};
coff_parse_section_name(full_or_partial_name, &name, &postfix);
U64 match_count = 0;
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
if (str8_match(sect_n->data.name, name, 0)) {
@@ -223,7 +239,7 @@ lnk_section_table_search_many(Arena *arena, LNK_SectionTable *sectab, String8 na
if (match_count > 0) {
result.count = 0;
result.v = push_array(arena, LNK_Section *, match_count);
result.v = push_array(arena, LNK_Section *, match_count);
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
if (str8_match(sect_n->data.name, name, 0)) {
@@ -307,9 +323,14 @@ lnk_section_table_merge(LNK_SectionTable *sectab, LNK_MergeDirectiveList merge_l
// merge section with destination
lnk_section_contrib_chunk_list_concat_in_place(&dst->contribs, &src->contribs);
src->is_merged = 1;
src->merge_id = dst->id;
// remove from output section list
lnk_section_table_remove(sectab, src->name);
LNK_SectionNode *merge_node = lnk_section_table_remove(sectab, src->name);
// move node to the merge list
SLLQueuePush(sectab->merge_list.first, sectab->merge_list.last, merge_node);
sectab->merge_list.count += 1;
}
}
scratch_end(scratch);
@@ -387,3 +408,22 @@ lnk_assign_section_file_space(LNK_Section *sect, U64 *foff_cursor)
}
}
internal LNK_Section *
lnk_finalized_section_from_id(LNK_SectionTable *sectab, U64 id)
{
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
if (sect_n->data.id == id) {
return &sect_n->data;
}
}
for (LNK_SectionNode *sect_n = sectab->merge_list.first; sect_n != 0; sect_n = sect_n->next) {
if (sect_n->data.id == id) {
return lnk_finalized_section_from_id(sectab, sect_n->data.merge_id);
}
}
return 0;
}
+15 -8
View File
@@ -60,12 +60,12 @@ typedef struct LNK_SectionDefinition
typedef struct LNK_Section
{
U64 id;
String8 name;
COFF_SectionFlags flags;
B32 has_layout;
B32 is_merged;
U64 id;
String8 name;
COFF_SectionFlags flags;
B32 has_layout;
B32 is_merged;
U64 merge_id;
LNK_SectionContribChunkList contribs;
U64 voff;
@@ -101,7 +101,7 @@ typedef struct LNK_SectionTable
U64 id_max;
U64 next_sect_idx;
LNK_SectionList list;
LNK_SectionList free_list;
LNK_SectionList merge_list;
HashTable *sect_ht; // name -> LNK_Section *
} LNK_SectionTable;
@@ -116,11 +116,18 @@ internal LNK_SectionArray lnk_section_array_from_list(Arena *arena, LNK_SectionL
////////////////////////////////
internal LNK_SectionContrib * lnk_get_last_section_contrib(LNK_Section *sect);
internal LNK_SectionTable * lnk_section_table_alloc(void);
////////////////////////////////
internal LNK_SectionTable * lnk_section_table_alloc(void);
internal void lnk_section_table_release(LNK_SectionTable **st_ptr);
internal LNK_Section * lnk_section_table_push(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags flags);
internal void lnk_section_table_remove(LNK_SectionTable *sectab, String8 name);
internal LNK_SectionNode * lnk_section_table_remove(LNK_SectionTable *sectab, String8 name);
internal LNK_Section * lnk_section_table_search(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags flags);
internal LNK_SectionArray lnk_section_table_search_many(Arena *arena, LNK_SectionTable *sectab, String8 full_or_partial_name);
internal void lnk_section_table_merge(LNK_SectionTable *sectab, LNK_MergeDirectiveList merge_list);
internal LNK_SectionArray lnk_section_table_get_output_sections(Arena *arena, LNK_SectionTable *sectab);
internal LNK_Section * lnk_finalized_section_from_id(LNK_SectionTable *sectab, U64 id);