From c1f1f943e150d41b0481b343fb5e05bcd418fe35 Mon Sep 17 00:00:00 2001 From: Gunther Nikl Date: Mon, 17 Nov 2014 20:24:28 +0000 Subject: [PATCH] Backport fixes for PR gas/3041 (bfd assembler): [gas] 2010-09-09 Gunther Nikl * gas/config/tc-m68k.c (tc_gen_reloc): Handle references to defined weak symbols first if generating an a.out object. 2009-10-013 Vincent Riviere PR gas/3041 * config/tc-m68k.c (tc_gen_reloc): Fix addend for relocations located in data section an referencing a weak symbol. 2007-05-15 Vincent Riviere PR gas/3041 * config/tc-m68k.c (relaxable_symbol): Make sure that the correct addend is stored for relocs against weak symbols. (md_apply_fix): So not loose track of addend for relocs against weak symbols. 2007-05-03 Vincent Riviere Nick Clifton PR gas/3041 * config/tc-m68k.c (relaxable_symbol): Do not relax weak symbols. (tc_gen_reloc): Adjust the addend of relocs against weak symbols. (md_apply_fix): Put zero values into the frags referencing weak symbols. [bfd] 2007-05-03 Vincent Riviere Nick Clifton PR gas/3041 * aoutx.h (swap_std_reloc_out): Treat relocs against weak symbols in the same way as relocs against external symbols. Weak fixes for the non-bfd assembler: * gas/config/tc-m68k.h (S_IS_WEAK): Define for !BFD_ASSEMBLER. * gas/config/tc-m68k.c (tc_aout_fix_to_chars): Check weak symbol state. * gas/write.c (fixup_segment): Treat a weak symbol as undefined. --- bfd/aoutx.h | 5 ++++- gas/config/tc-m68k.c | 47 ++++++++++++++++++++++++++++++++++++++++---- gas/config/tc-m68k.h | 2 ++ gas/write.c | 2 +- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/bfd/aoutx.h b/bfd/aoutx.h index c1175fe..f3faca6 100644 --- a/bfd/aoutx.h +++ b/bfd/aoutx.h @@ -2105,7 +2105,10 @@ NAME(aout,swap_std_reloc_out) (abfd, g, natptr) if (bfd_is_com_section (output_section) || bfd_is_abs_section (output_section) - || bfd_is_und_section (output_section)) + || bfd_is_und_section (output_section) + /* PR gas/3041 a.out relocs against weak symbols + must be treated as if they were against externs. */ + || (sym->flags & BSF_WEAK)) { if (bfd_abs_section_ptr->symbol == sym) { diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index c35a024..b58305f 100644 --- a/gas/config/tc-m68k.c +++ b/gas/config/tc-m68k.c @@ -910,7 +910,9 @@ tc_m68k_fix_adjustable (fixP) #define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC -#define relaxable_symbol(symbol) 1 +/* PR gas/3041 Weak symbols are not relaxable + because they must be treated as extern. */ +#define relaxable_symbol(symbol) (!(S_IS_WEAK (symbol))) #endif /* OBJ_ELF */ @@ -1017,7 +1019,34 @@ tc_gen_reloc (section, fixp) *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; #ifndef OBJ_ELF - if (fixp->fx_pcrel) + if (OUTPUT_FLAVOR == bfd_target_aout_flavour + && fixp->fx_addsy + && S_IS_WEAK (fixp->fx_addsy) + && ! bfd_is_und_section (S_GET_SEGMENT (fixp->fx_addsy))) + { + /* PR gas/3041 References to weak symbols must be treated as extern + in order to be overridable by the linker, even if they are defined + in the same object file. So the original addend must be written + "as is" into the output section without further processing. + The addend value must be hacked here in order to force + bfd_install_relocation() to write the original value into the + output section. + 1) MD_APPLY_SYM_VALUE() is set to 1 for m68k/a.out, so the symbol + value has already been added to the addend in fixup_segment(). We + have to remove it. + 2) bfd_install_relocation() will incorrectly treat this symbol as + resolved, so it will write the symbol value plus its addend and + section VMA. As a workaround we can tweak the addend value here in + order to get the original value in the section after the call to + bfd_install_relocation(). */ + reloc->addend = fixp->fx_addnumber + /* Fix because of MD_APPLY_SYM_VALUE() */ + - S_GET_VALUE (fixp->fx_addsy) + /* Fix for bfd_install_relocation() */ + - (S_GET_VALUE (fixp->fx_addsy) + + S_GET_SEGMENT (fixp->fx_addsy)->vma); + } + else if (fixp->fx_pcrel) reloc->addend = fixp->fx_addnumber; else reloc->addend = 0; @@ -4332,6 +4361,14 @@ md_apply_fix3 (fixP, valP, seg) S_SET_WEAK (fixP->fx_addsy); return; } +#elif defined(OBJ_AOUT) && defined(BFD_ASSEMBLER) + /* PR gas/3041 Do not fix frags referencing a weak symbol. */ + if (fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy)) + { + memset (buf, 0, fixP->fx_size); + fixP->fx_addnumber = val; /* Remember value for emit_reloc. */ + return; + } #endif #ifdef BFD_ASSEMBLER @@ -4900,6 +4937,7 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file) static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2}; long r_symbolnum; + int r_extern; know (fixP->fx_addsy != NULL); @@ -4907,7 +4945,8 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file) fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, 4); - r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) + r_extern = !S_IS_DEFINED (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy) ? 1 : 0; + r_symbolnum = (r_extern == 0 ? S_GET_TYPE (fixP->fx_addsy) : fixP->fx_addsy->sy_number); @@ -4915,7 +4954,7 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file) where[5] = (r_symbolnum >> 8) & 0x0ff; where[6] = r_symbolnum & 0x0ff; where[7] = (((fixP->fx_pcrel << 7) & 0x80) | ((nbytes_r_length[fixP->fx_size] << 5) & 0x60) | - (((!S_IS_DEFINED (fixP->fx_addsy)) << 4) & 0x10) | ((fixP->tc_fix_data << 3) & 0x08)); + ((r_extern << 4) & 0x10) | ((fixP->tc_fix_data << 3) & 0x08)); } #endif diff --git a/gas/config/tc-m68k.h b/gas/config/tc-m68k.h index 4004288..d4d0ce6 100644 --- a/gas/config/tc-m68k.h +++ b/gas/config/tc-m68k.h @@ -201,6 +201,8 @@ extern void m68k_elf_final_processing PARAMS ((void)); #define RELAX_RELOC_PC16 0 #define RELAX_RELOC_PC32 0 +#define S_IS_WEAK(sym) /**/S_GET_WEAK(sym) + #endif /* ! BFD_ASSEMBLER */ #define DIFF_EXPR_OK diff --git a/gas/write.c b/gas/write.c index f987745..7d2fc65 100644 --- a/gas/write.c +++ b/gas/write.c @@ -2633,7 +2633,7 @@ fixup_segment (fixP, this_segment) } if (fixP->fx_addsy != NULL) - add_symbol_segment = S_GET_SEGMENT (fixP->fx_addsy); + add_symbol_segment = S_IS_WEAK (fixP->fx_addsy) ? undefined_section : S_GET_SEGMENT (fixP->fx_addsy); if (fixP->fx_subsy != NULL) {