.reloc improvement
Maciej W. Rozycki
macro@codesourcery.com
Mon Nov 14 14:23:00 GMT 2011
On Thu, 27 Oct 2011, Maciej W. Rozycki wrote:
> On Tue, 6 Sep 2011, Maciej W. Rozycki wrote:
>
> > On Mon, 22 Aug 2011, Alan Modra wrote:
> >
> > > > Please note that on REL MIPS targets local symbols have to be retained in
> > > > several cases where crucial information is lost if a relocation against
> > > > such a symbol is converted to one against the containing section's symbol.
> > > > This applies to all the PC-relative relocations, where the relocatable
> > > > field is too narrow to hold arbitrary addends, and also, more recently, to
> > > > microMIPS targets, where linker relaxation has to know local symbol
> > > > (label) addresses to perform branch displacement recalculations and to
> > > > make the LUI/ADDIU->ADDIUPC relaxation. The latter is a linker's internal
> > > > limitation and may possibly be lifted (possibly by using the RELA
> > > > representation internally even on REL targets), but the former is an
> > > > inherent problem of the object file format used.
> > > >
> > > > Just making sure these issues are not missed -- I can't have a look at
> > > > your change at the moment and see what exact implications it has, sorry.
> > >
> > > The implication of my change is that the programmer will need to be
> > > careful in choosing symbols used with .reloc. While that isn't ideal,
> > > .reloc is such a low-level interface that you need to know what you're
> > > doing if you use it.
> >
> > Problem is on REL targets some MIPS relocation types can never ever be
> > safely converted to refer to a section symbol + addend instead of the
> > intended symbol. You'd therefore make .reloc useless for these types.
> >
> > Yes, REL shouldn't have been chosen for the MIPS ABI in the first place,
> > with the complication observed here being the tip of an iceberg only, but
> > there you go. The choice was later fixed with the new ABIs made for
> > 64-bit MIPS processors, but the old ABI still remains for 32-bit ones.
> >
> > > Alternatively, I'm quite willing to disable the symbol to section symbol
> > > conversion for REL targets.
> >
> > Good idea, that sounds like a plan to me. That could be made platform
> > specific if that made anybody's life easier.
>
> Where are we with this problem? Your change regressed this program (an
> excerpt from a test case I prepared a while ago and was about to integrate
> with our test suite):
>
> $ cat reloc.s
> .text
>
> .fill 0x1000000
>
> .set micromips
> foo:
> nop32
> .reloc ., R_MICROMIPS_PC23_S2, 0f
> .fill 0
> addiu $2, $pc, 8
> nop32
> 0:
>
> from this:
>
> $ mips-sde-elf-as -32 -o reloc.o reloc.s
> $ mips-sde-elf-objdump -dr reloc.o
>
> reloc.o: file format elf32-tradbigmips
>
>
> Disassembly of section .text:
>
> 00000000 <foo-0x1000000>:
> ...
>
> 01000000 <foo>:
> 1000000: 0000 0000 nop
> 1000004: 7900 0002 addiu v0,$pc,8
> 1000004: R_MICROMIPS_PC23_S2 .L1
> 1000008: 0000 0000 nop
>
> to this:
>
> $ mips-sde-elf-as -o reloc.o reloc.s
> reloc.s: Assembler messages:
> reloc.s:8: Error: relocation overflow
Long time, no response, so I went ahead and implemented this fix. It
unbreaks the test case for me and causes no regressions for mips-sde-elf
(although I have no slightest idea how much coverage in the test suite
.reloc has).
OK to apply? Since this is a regression OK for 2.22 too?
2011-11-14 Maciej W. Rozycki <macro@codesourcery.com>
gas/
write.c (dump_section_relocs): Don't convert PC-relative relocs
that have an in-place addend narrower than the addresses used.
Maciej
binutils-gas-reloc-pcrel-inplace.diff
Index: binutils-fsf-trunk-quilt/gas/write.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/gas/write.c 2011-11-14 13:50:51.000000000 +0000
+++ binutils-fsf-trunk-quilt/gas/write.c 2011-11-14 14:19:07.795860362 +0000
@@ -654,15 +654,21 @@ dump_section_relocs (bfd *abfd ATTRIBUTE
static void
resolve_reloc_expr_symbols (void)
{
+ bfd_vma addr_mask = 1;
struct reloc_list *r;
+ /* Avoid a shift by the width of type. */
+ addr_mask <<= bfd_arch_bits_per_address (stdoutput) - 1;
+ addr_mask <<= 1;
+ addr_mask -= 1;
+
for (r = reloc_list; r; r = r->next)
{
+ reloc_howto_type *howto = r->u.a.howto;
expressionS *symval;
symbolS *sym;
bfd_vma offset, addend;
asection *sec;
- reloc_howto_type *howto;
resolve_symbol_value (r->u.a.offset_sym);
symval = symbol_get_value_expression (r->u.a.offset_sym);
@@ -709,7 +715,16 @@ resolve_reloc_expr_symbols (void)
}
else if (sym != NULL)
{
- if (S_IS_LOCAL (sym) && !symbol_section_p (sym))
+ /* Convert relocs against local symbols to refer to the
+ corresponding section symbol plus offset instead. Keep
+ PC-relative relocs of the REL variety intact though to
+ prevent the offset from overflowing the relocated field,
+ unless it has enough bits to cover the whole address
+ space. */
+ if (S_IS_LOCAL (sym) && !symbol_section_p (sym)
+ && !(howto->partial_inplace
+ && howto->pc_relative
+ && howto->src_mask != addr_mask))
{
asection *symsec = S_GET_SEGMENT (sym);
if (!(((symsec->flags & SEC_MERGE) != 0
@@ -730,8 +745,6 @@ resolve_reloc_expr_symbols (void)
sym = abs_section_sym;
}
- howto = r->u.a.howto;
-
r->u.b.sec = sec;
r->u.b.s = symbol_get_bfdsym (sym);
r->u.b.r.sym_ptr_ptr = &r->u.b.s;
More information about the Binutils
mailing list