mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-17 01:22:24 -07:00
patch section symbol and test for relocations to discarded memory
This commit is contained in:
committed by
Ryan Fleury
parent
40fda5335c
commit
8da56025b3
+57
-16
@@ -1592,7 +1592,7 @@ THREAD_POOL_TASK_FUNC(lnk_emit_base_relocs_from_objs_task)
|
||||
|
||||
COFF_ParsedSymbol symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, r->isymbol);
|
||||
COFF_SymbolValueInterpType symbol_interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
||||
B32 is_symbol_address = symbol_interp == COFF_SymbolValueInterp_Regular;
|
||||
B32 is_symbol_address = symbol_interp != COFF_SymbolValueInterp_Abs;
|
||||
|
||||
if (is_symbol_address) {
|
||||
B32 is_addr32 = 0, is_addr64 = 0;
|
||||
@@ -2155,6 +2155,7 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
|
||||
for (U64 defn_idx = 0; defn_idx < sect_defns_count; defn_idx += 1) {
|
||||
LNK_SectionDefinition *sect_defn = sect_defns[defn_idx];
|
||||
|
||||
// warn about conflicting section flags
|
||||
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
|
||||
LNK_Section *sect = §_n->data;
|
||||
if (str8_match(sect->name, sect_defn->name, 0)) {
|
||||
@@ -2172,6 +2173,7 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
|
||||
}
|
||||
}
|
||||
|
||||
// reserve chunk for contribs
|
||||
LNK_Section *sect = lnk_section_table_search(sectab, sect_defn->name, sect_defn->flags);
|
||||
if (sect == 0) {
|
||||
sect = lnk_section_table_push(sectab, sect_defn->name, sect_defn->flags);
|
||||
@@ -2185,7 +2187,6 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
|
||||
U64 expected_image_header_size;
|
||||
{
|
||||
// gather section contribs
|
||||
@@ -2228,8 +2229,7 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
|
||||
data_n->string = sect_data;
|
||||
|
||||
// fill out contrib
|
||||
LNK_SectionContribChunk *sc_chunk = sect->contribs.first;
|
||||
LNK_SectionContrib *sc = lnk_section_contrib_chunk_push(sc_chunk, 1);
|
||||
LNK_SectionContrib *sc = lnk_section_contrib_chunk_push(sect->contribs.first, 1);
|
||||
sc->align = sc_align;
|
||||
sc->data_list = data_n;
|
||||
sc->u.obj_idx = obj_idx;
|
||||
@@ -2552,17 +2552,19 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
|
||||
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
|
||||
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
||||
if (interp == COFF_SymbolValueInterp_Undefined) {
|
||||
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, symbol.name);
|
||||
if (defn) {
|
||||
COFF_ParsedSymbol defn_symbol = lnk_parsed_symbol_from_coff_symbol_idx(defn->u.defined.obj, defn->u.defined.symbol_idx);
|
||||
if (symbol.storage_class == COFF_SymStorageClass_External) {
|
||||
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, symbol.name);
|
||||
if (defn) {
|
||||
COFF_ParsedSymbol defn_symbol = lnk_parsed_symbol_from_coff_symbol_idx(defn->u.defined.obj, defn->u.defined.symbol_idx);
|
||||
|
||||
if (defn_symbol.storage_class == COFF_SymStorageClass_WeakExternal) {
|
||||
continue;
|
||||
if (defn_symbol.storage_class == COFF_SymStorageClass_WeakExternal) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lnk_patch_weak_external_symbol(obj->header.is_big_obj, symbol.raw_symbol, defn_symbol);
|
||||
} else {
|
||||
// TODO: collect unresolved undefined
|
||||
}
|
||||
|
||||
lnk_patch_weak_external_symbol(obj->header.is_big_obj, symbol.raw_symbol, defn_symbol);
|
||||
} else {
|
||||
// TODO: collect unresolved undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2731,9 +2733,9 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
|
||||
if (~config->flags & LNK_ConfigFlag_Fixed) {
|
||||
String8List base_relocs_data = lnk_build_base_relocs(tp, arena, config, objs_count, objs);
|
||||
if (base_relocs_data.total_size) {
|
||||
LNK_Section *reloc = lnk_section_table_push(sectab, str8_lit(".reloc"), LNK_RELOC_SECTION_FLAGS);
|
||||
LNK_SectionContribChunk *sc_chunk = lnk_section_contrib_chunk_list_push_chunk(sectab->arena, &reloc->contribs, 1);
|
||||
LNK_SectionContrib *sc = lnk_section_contrib_chunk_push(sc_chunk, 1);
|
||||
LNK_Section *reloc = lnk_section_table_push(sectab, str8_lit(".reloc"), LNK_RELOC_SECTION_FLAGS);
|
||||
LNK_SectionContribChunk *first_sc_chunk = lnk_section_contrib_chunk_list_push_chunk(sectab->arena, &reloc->contribs, 1);
|
||||
LNK_SectionContrib *sc = lnk_section_contrib_chunk_push(first_sc_chunk, 1);
|
||||
sc->data_list = base_relocs_data.first;
|
||||
sc->align = 1;
|
||||
sc->u.sort_idx_size = 0;
|
||||
@@ -2790,6 +2792,45 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
|
||||
sects = lnk_section_array_from_list(scratch.arena, sectab->list);
|
||||
}
|
||||
|
||||
// patch section symbols
|
||||
{
|
||||
for (U64 obj_idx = 0; obj_idx < objs_count; obj_idx += 1) {
|
||||
LNK_Obj *obj = objs[obj_idx];
|
||||
|
||||
COFF_ParsedSymbol symbol;
|
||||
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
|
||||
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
|
||||
|
||||
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
||||
if (interp == COFF_SymbolValueInterp_Undefined) {
|
||||
if (symbol.storage_class == COFF_SymStorageClass_Section) {
|
||||
LNK_Section *sect = lnk_section_table_search(sectab, symbol.name, symbol.value);
|
||||
if (sect) {
|
||||
if (~sect->flags & COFF_SectionFlag_MemDiscardable) {
|
||||
LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect);
|
||||
if (obj->header.is_big_obj) {
|
||||
COFF_Symbol32 *symbol32 = symbol.raw_symbol;
|
||||
symbol32->section_number = safe_cast_u32(first_sc->u.sect_idx + 1);
|
||||
symbol32->value = first_sc->u.off;
|
||||
symbol32->storage_class = COFF_SymStorageClass_Static;
|
||||
} else {
|
||||
COFF_Symbol16 *symbol16 = symbol.raw_symbol;
|
||||
symbol16->section_number = safe_cast_u16(first_sc->u.sect_idx + 1);
|
||||
symbol16->value = first_sc->u.off;
|
||||
symbol16->storage_class = COFF_SymStorageClass_Static;
|
||||
}
|
||||
} else {
|
||||
lnk_error_obj(LNK_Error_SectRefsDiscardedMemory, obj, "symbol %S (No. 0x%llx) references section with discard flag", symbol.name, symbol_idx);
|
||||
}
|
||||
} else {
|
||||
lnk_error_obj(LNK_Error_UndefinedSymbol, obj, "undefined section symbol %S (No 0x%llx) refers to section that does not exist", symbol.name, symbol_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String8 image_data = {0};
|
||||
{
|
||||
ProfBegin("Image Fill");
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef enum
|
||||
LNK_Error_LargeAddrAwareRequired,
|
||||
LNK_Error_InvalidPath,
|
||||
LNK_Error_MultiplyDefinedSymbol,
|
||||
LNK_Error_SectRefsDiscardedMemory,
|
||||
LNK_Error_StopLast,
|
||||
|
||||
LNK_Error_First,
|
||||
|
||||
@@ -347,8 +347,14 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
|
||||
case COFF_SymbolValueInterp_Undefined: {
|
||||
LNK_Symbol *s = lnk_symbol_table_search(task->symtab, LNK_SymbolScope_Defined, symbol.name);
|
||||
if (s == 0) {
|
||||
LNK_Symbol *undef = lnk_make_undefined_symbol(arena, symbol.name, obj);
|
||||
lnk_symbol_list_push(arena, &task->undef_lists[worker_id], undef);
|
||||
if (symbol.storage_class == COFF_SymStorageClass_External) {
|
||||
LNK_Symbol *undef = lnk_make_undefined_symbol(arena, symbol.name, obj);
|
||||
lnk_symbol_list_push(arena, &task->undef_lists[worker_id], undef);
|
||||
} else if (symbol.storage_class == COFF_SymStorageClass_Section) {
|
||||
// lookup is performed during image patching step
|
||||
} else {
|
||||
Assert(!"unexpected storage class on undefined symbol");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case COFF_SymbolValueInterp_Debug: {
|
||||
|
||||
@@ -67,34 +67,6 @@ lnk_section_contrib_chunk_list_concat_in_place(LNK_SectionContribChunkList *list
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_section_list_remove(LNK_SectionList *list, LNK_SectionNode *node)
|
||||
{
|
||||
if (list->count > 0) {
|
||||
if (list->first == node) {
|
||||
list->first = list->first->next;
|
||||
list->count -= 1;
|
||||
|
||||
if (list->last == node) {
|
||||
list->last = 0;
|
||||
}
|
||||
} else {
|
||||
for (LNK_SectionNode *curr = list->first, *prev = 0; curr != 0; prev = curr, curr = curr->next) {
|
||||
if (curr == node) {
|
||||
prev->next = curr->next;
|
||||
list->count -= 1;
|
||||
|
||||
if (list->last == curr) {
|
||||
list->last = prev;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal LNK_SectionArray
|
||||
lnk_section_array_from_list(Arena *arena, LNK_SectionList list)
|
||||
{
|
||||
@@ -108,6 +80,17 @@ lnk_section_array_from_list(Arena *arena, LNK_SectionList list)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal LNK_SectionContrib *
|
||||
lnk_get_first_section_contrib(LNK_Section *sect)
|
||||
{
|
||||
if (sect->contribs.chunk_count > 0) {
|
||||
if (sect->contribs.first->count > 0) {
|
||||
return §->contribs.first->v[0];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal LNK_SectionTable *
|
||||
lnk_section_table_alloc(void)
|
||||
{
|
||||
@@ -154,7 +137,7 @@ lnk_section_table_push(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags
|
||||
sect->name = push_str8_copy(sect->arena, name);
|
||||
sect->flags = flags;
|
||||
sect->has_layout = 1;
|
||||
|
||||
|
||||
LNK_SectionList *sect_list = §ab->list;
|
||||
SLLQueuePush(sect_list->first, sect_list->last, sect_node);
|
||||
sect_list->count += 1;
|
||||
@@ -172,18 +155,43 @@ lnk_section_table_remove(LNK_SectionTable *sectab, String8 name)
|
||||
ProfBeginFunction();
|
||||
|
||||
// find node
|
||||
LNK_SectionNode *sect_n;
|
||||
for (sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
|
||||
if (str8_match(sect_n->data.name, name, 0)) {
|
||||
LNK_SectionNode *node;
|
||||
for (node = sectab->list.first; node != 0; node = node->next) {
|
||||
if (str8_match(node->data.name, name, 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// remove node
|
||||
lnk_section_list_remove(§ab->list, sect_n);
|
||||
{
|
||||
LNK_SectionList *list = §ab->list;
|
||||
if (list->count > 0) {
|
||||
if (list->first == node) {
|
||||
list->first = list->first->next;
|
||||
list->count -= 1;
|
||||
|
||||
if (list->last == node) {
|
||||
list->last = 0;
|
||||
}
|
||||
} else {
|
||||
for (LNK_SectionNode *curr = list->first, *prev = 0; curr != 0; prev = curr, curr = curr->next) {
|
||||
if (curr == node) {
|
||||
prev->next = curr->next;
|
||||
list->count -= 1;
|
||||
|
||||
if (list->last == curr) {
|
||||
list->last = prev;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// push to free list
|
||||
SLLQueuePush(sectab->free_list.first, sectab->free_list.last, sect_n);
|
||||
SLLQueuePush(sectab->free_list.first, sectab->free_list.last, node);
|
||||
sectab->free_list.count += 1;
|
||||
|
||||
ProfEnd();
|
||||
|
||||
@@ -68,6 +68,7 @@ typedef struct LNK_Section
|
||||
B32 is_merged;
|
||||
|
||||
LNK_SectionContribChunkList contribs;
|
||||
LNK_SectionContrib *first_contrib_chunk;
|
||||
|
||||
U64 voff;
|
||||
U64 vsize;
|
||||
@@ -113,7 +114,6 @@ internal U16 lnk_default_align_from_machine(COFF_MachineType machine);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void lnk_section_list_remove(LNK_SectionList *list, LNK_SectionNode *node);
|
||||
internal LNK_SectionArray lnk_section_array_from_list(Arena *arena, LNK_SectionList list);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
+13
-10
@@ -891,14 +891,14 @@ t_undef_reloc_section(void)
|
||||
{
|
||||
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64);
|
||||
|
||||
U8 data[] = { 0, 0, 0, 0 };
|
||||
COFF_ObjSection *data_section = t_push_data_section(obj_writer, str8_array_fixed(data));
|
||||
COFF_ObjSymbol *foo = coff_obj_writer_push_symbol_undef_section(obj_writer, str8_lit(".reloc"), LNK_RELOC_SECTION_FLAGS);
|
||||
coff_obj_writer_section_push_reloc(obj_writer, data_section, 0, foo, COFF_Reloc_X64_Addr32Nb);
|
||||
|
||||
U8 text[] = { 0xC3 };
|
||||
COFF_ObjSection *text_section = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), LNK_TEXT_SECTION_FLAGS, str8_array_fixed(text));
|
||||
coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_section);
|
||||
COFF_ObjSymbol *my_entry_symbol = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_section);
|
||||
|
||||
U8 data[8] = { 0 };
|
||||
COFF_ObjSection *data_section = t_push_data_section(obj_writer, str8_array_fixed(data));
|
||||
COFF_ObjSymbol *foo = coff_obj_writer_push_symbol_undef_section(obj_writer, str8_lit(".reloc"), LNK_RELOC_SECTION_FLAGS);
|
||||
coff_obj_writer_section_push_reloc(obj_writer, data_section, 0, foo, COFF_Reloc_X64_Addr64);
|
||||
|
||||
main_obj = coff_obj_writer_serialize(scratch.arena, obj_writer);
|
||||
|
||||
@@ -912,7 +912,11 @@ t_undef_reloc_section(void)
|
||||
t_write_file(str8_lit("sec_defn.obj"), sec_defn_obj);
|
||||
|
||||
int linker_exit_code = t_invoke_linker(str8_lit("/subsystem:console /entry:my_entry /out:a.exe main.obj sec_defn.obj"));
|
||||
if (linker_exit_code == 0) {
|
||||
if (t_ident_linker() == T_Linker_RAD) {
|
||||
if (linker_exit_code != LNK_Error_SectRefsDiscardedMemory) {
|
||||
goto exit;
|
||||
}
|
||||
} else if (linker_exit_code == 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -1428,7 +1432,6 @@ t_import_export(void)
|
||||
|
||||
T_Result result = T_Result_Fail;
|
||||
|
||||
|
||||
String8 export_obj_name = str8_lit("export.obj");
|
||||
String8 export_obj_payload = str8_lit("test");
|
||||
U8 export_text[] = { 0xC3 };
|
||||
@@ -1600,8 +1603,8 @@ entry_point(CmdLine *cmdline)
|
||||
{ "invalid_bss", t_invalid_bss },
|
||||
{ "common_block", t_common_block },
|
||||
//{ "base_relocs", t_base_relocs },
|
||||
{ "simple_lib_test", t_simple_lib_test },
|
||||
{ "import_export", t_import_export },
|
||||
{ "simple_lib_test", t_simple_lib_test },
|
||||
{ "import_export", t_import_export },
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user