mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-04 12:58:41 +00:00
handle COMDAT Associative selection
This commit is contained in:
committed by
Ryan Fleury
parent
69d4e31b15
commit
bf25b5b249
@@ -2201,6 +2201,44 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
|
|||||||
U64 objs_count = obj_list.count;
|
U64 objs_count = obj_list.count;
|
||||||
LNK_Obj **objs = lnk_obj_arr_from_list(scratch.arena, obj_list);
|
LNK_Obj **objs = lnk_obj_arr_from_list(scratch.arena, obj_list);
|
||||||
|
|
||||||
|
ProfBegin("Remove Associatives");
|
||||||
|
{
|
||||||
|
for (U64 obj_idx = 0; obj_idx < objs_count; obj_idx += 1) {
|
||||||
|
LNK_Obj *obj = objs[obj_idx];
|
||||||
|
String8 string_table = str8_substr(obj->data, obj->header.string_table_range);
|
||||||
|
String8 symbol_table = str8_substr(obj->data, obj->header.symbol_table_range);
|
||||||
|
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) {
|
||||||
|
// find associate section head section index
|
||||||
|
U32 head_sect_idx = max_U32;
|
||||||
|
for (U64 current_sect_idx = sect_idx;;) {
|
||||||
|
U32 symbol_idx = obj->comdats[current_sect_idx];
|
||||||
|
if (symbol_idx == max_U32) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
COFF_ParsedSymbol symbol = coff_parse_symbol(obj->header, string_table, symbol_table, symbol_idx);
|
||||||
|
COFF_ComdatSelectType selection = COFF_ComdatSelect_Null;
|
||||||
|
U32 section_number = 0;
|
||||||
|
coff_parse_secdef(symbol, obj->header.is_big_obj, &selection, §ion_number, 0, 0);
|
||||||
|
if (selection != COFF_ComdatSelect_Associative) {
|
||||||
|
head_sect_idx = current_sect_idx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_sect_idx = section_number-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head_sect_idx != max_U32) {
|
||||||
|
// flag current section with remove if head section was removed
|
||||||
|
COFF_SectionHeader *head_sect_header = lnk_coff_section_header_from_section_number(obj, head_sect_idx+1);
|
||||||
|
COFF_SectionHeader *curr_sect_header = lnk_coff_section_header_from_section_number(obj, sect_idx+1);
|
||||||
|
curr_sect_header->flags |= (head_sect_header->flags & COFF_SectionFlag_LnkRemove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProfEnd();
|
||||||
|
|
||||||
{
|
{
|
||||||
ProfBegin("Define And Count Sections");
|
ProfBegin("Define And Count Sections");
|
||||||
Temp temp = temp_begin(scratch.arena);
|
Temp temp = temp_begin(scratch.arena);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ typedef enum
|
|||||||
LNK_Error_IllegalRelocation,
|
LNK_Error_IllegalRelocation,
|
||||||
LNK_Error_CircularMerge,
|
LNK_Error_CircularMerge,
|
||||||
LNK_Error_UnresolvedSymbol,
|
LNK_Error_UnresolvedSymbol,
|
||||||
|
LNK_Error_AssociativeLoop,
|
||||||
LNK_Error_StopLast,
|
LNK_Error_StopLast,
|
||||||
|
|
||||||
LNK_Error_First,
|
LNK_Error_First,
|
||||||
|
|||||||
+81
-5
@@ -116,6 +116,35 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// error check symbols
|
||||||
|
//
|
||||||
|
{
|
||||||
|
COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(input->data, header.section_table_range).str;
|
||||||
|
String8 string_table = str8_substr(input->data, header.string_table_range);
|
||||||
|
String8 symbol_table = str8_substr(input->data, header.symbol_table_range);
|
||||||
|
COFF_ParsedSymbol symbol;
|
||||||
|
for (U64 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
|
||||||
|
symbol = coff_parse_symbol(header, string_table, symbol_table, symbol_idx);
|
||||||
|
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
||||||
|
if (interp == COFF_SymbolValueInterp_Regular) {
|
||||||
|
if (symbol.section_number == 0 || symbol.section_number > header.section_count_no_null) {
|
||||||
|
lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "symbol %S (No. 0x%x) points to an out of bounds section 0x%x", symbol.name, symbol_idx, symbol.section_number);
|
||||||
|
}
|
||||||
|
if (symbol.storage_class == COFF_SymStorageClass_Static && symbol.aux_symbol_count > 0) {
|
||||||
|
COFF_ComdatSelectType select;
|
||||||
|
U32 section_number = 0;
|
||||||
|
coff_parse_secdef(symbol, header.is_big_obj, &select, §ion_number, 0, 0);
|
||||||
|
if (select == COFF_ComdatSelect_Associative) {
|
||||||
|
if (section_number == 0 || section_number > header.section_count_no_null) {
|
||||||
|
lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "section definition symbol %S (No. 0x%x) associates with an out of bounds section 0x%x", symbol.name, symbol_idx, symbol.section_number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// create symbol links to COMDAT sections
|
// create symbol links to COMDAT sections
|
||||||
//
|
//
|
||||||
@@ -128,11 +157,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
|||||||
String8 symbol_table = str8_substr(input->data, header.symbol_table_range);
|
String8 symbol_table = str8_substr(input->data, header.symbol_table_range);
|
||||||
COFF_ParsedSymbol symbol;
|
COFF_ParsedSymbol symbol;
|
||||||
for (U64 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
|
for (U64 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
|
||||||
if (header.is_big_obj) {
|
symbol = coff_parse_symbol(header, string_table, symbol_table, symbol_idx);
|
||||||
symbol = coff_parse_symbol32(string_table, (COFF_Symbol32 *)symbol_table.str + symbol_idx);
|
|
||||||
} else {
|
|
||||||
symbol = coff_parse_symbol16(string_table, (COFF_Symbol16 *)symbol_table.str + symbol_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
||||||
if (interp == COFF_SymbolValueInterp_Regular) {
|
if (interp == COFF_SymbolValueInterp_Regular) {
|
||||||
@@ -162,6 +187,57 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// COMDAT loop checker
|
||||||
|
//
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
|
||||||
|
String8 string_table = str8_substr(input->data, header.string_table_range);
|
||||||
|
String8 symbol_table = str8_substr(input->data, header.symbol_table_range);
|
||||||
|
HashTable *visited_sections = hash_table_init(scratch.arena, 32);
|
||||||
|
for (U64 sect_idx = 0; sect_idx < header.section_count_no_null; sect_idx += 1) {
|
||||||
|
for (U32 curr_section = sect_idx;;) {
|
||||||
|
U32 symbol_idx = comdats[curr_section];
|
||||||
|
|
||||||
|
// is section COMDAT?
|
||||||
|
if (symbol_idx == max_U32) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract COMDAT info for current section
|
||||||
|
COFF_ParsedSymbol symbol = coff_parse_symbol(header, string_table, symbol_table, symbol_idx);
|
||||||
|
COFF_ComdatSelectType select = COFF_ComdatSelect_Null;
|
||||||
|
U32 section_number = 0;
|
||||||
|
coff_parse_secdef(symbol, header.is_big_obj, &select, §ion_number, 0, 0);
|
||||||
|
|
||||||
|
if (select != COFF_ComdatSelect_Associative) {
|
||||||
|
// section terminates at non-associative COMDAT -- no loop
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// was section visited? -- loop found
|
||||||
|
if (hash_table_search_u64(visited_sections, curr_section)) {
|
||||||
|
COFF_ParsedSymbol symbol = coff_parse_symbol(header, string_table, symbol_table, comdats[sect_idx]);
|
||||||
|
lnk_error_with_loc(LNK_Error_AssociativeLoop, input->path, input->lib_path, "section symbol %S (No. 0x%x) does not terminate on a non-associate COMDAT symbol", symbol.name, comdats[sect_idx]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// track visited sections
|
||||||
|
hash_table_push_u64_u64(scratch.arena, visited_sections, curr_section, 0);
|
||||||
|
|
||||||
|
// follow association
|
||||||
|
Assert(section_number > 0);
|
||||||
|
curr_section = section_number-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// purge hash table for next run
|
||||||
|
hash_table_purge(visited_sections);
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
// fill out obj
|
// fill out obj
|
||||||
obj->data = input->data;
|
obj->data = input->data;
|
||||||
obj->path = push_str8_copy(arena, input->path);
|
obj->path = push_str8_copy(arena, input->path);
|
||||||
|
|||||||
@@ -229,13 +229,11 @@ lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src)
|
|||||||
can_replace = 0;
|
can_replace = 0;
|
||||||
}
|
}
|
||||||
// weak vs regular,common,abs
|
// weak vs regular,common,abs
|
||||||
else if (dst_interp == COFF_SymbolValueInterp_Weak &&
|
else if (dst_interp == COFF_SymbolValueInterp_Weak && (src_interp == COFF_SymbolValueInterp_Regular || src_interp == COFF_SymbolValueInterp_Common || src_interp == COFF_SymbolValueInterp_Abs)) {
|
||||||
(src_interp == COFF_SymbolValueInterp_Regular || src_interp == COFF_SymbolValueInterp_Common || src_interp == COFF_SymbolValueInterp_Abs)) {
|
|
||||||
can_replace = 1;
|
can_replace = 1;
|
||||||
}
|
}
|
||||||
// regular,common vs regular,common
|
// regular,common vs regular,common
|
||||||
else if ((dst_interp == COFF_SymbolValueInterp_Regular || dst_interp == COFF_SymbolValueInterp_Common) &&
|
else if ((dst_interp == COFF_SymbolValueInterp_Regular || dst_interp == COFF_SymbolValueInterp_Common) && (src_interp == COFF_SymbolValueInterp_Regular || src_interp == COFF_SymbolValueInterp_Common)) {
|
||||||
(src_interp == COFF_SymbolValueInterp_Regular || src_interp == COFF_SymbolValueInterp_Common)) {
|
|
||||||
U32 dst_comdat_symbol_idx = dst_obj->comdats[dst_parsed.section_number-1];
|
U32 dst_comdat_symbol_idx = dst_obj->comdats[dst_parsed.section_number-1];
|
||||||
U32 src_comdat_symbol_idx = src_obj->comdats[src_parsed.section_number-1];
|
U32 src_comdat_symbol_idx = src_obj->comdats[src_parsed.section_number-1];
|
||||||
if (dst_comdat_symbol_idx == ~0 || src_comdat_symbol_idx == ~0) {
|
if (dst_comdat_symbol_idx == ~0 || src_comdat_symbol_idx == ~0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user