This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: REL vs. RELA: how to choose?
- To: Nick Clifton <nickc at redhat dot com>
- Subject: Re: REL vs. RELA: how to choose?
- From: Doug Evans <dje at transmeta dot com>
- Date: Wed, 14 Feb 2001 20:43:32 -0800 (PST)
- Cc: greg at mcgary dot org, binutils at sources dot redhat dot com
- References: <200102150025.QAA00635@elmo.cygnus.com>
Very good analysis of why RELA is better.
[I didn't actually follow the math. You're on the right track though
so I'm assuming you got it right.]
Note that the mips and m32r ports are REL
but they do get the 16 hi + 16 lo case correct.
[At least I think it's mips. I copied some port when
I made it work for the m32r and I think it was mips.]
Nick Clifton writes:
> One reason for preferring RELA relocations is that the REL format can
> have some hidden restrictions. Consider for example an ISA where a 32
> bit constant cannot be loaded by a single instruction but has to be
> done in two parts - a high 16 bit load followed by a low 16 bit load.
> The assembler to load the address of element 0xffffff of an array 'foo'
> into register 1 might look something like this:
>
> LOAD_HI r1, hi(foo + 0xffffff)
> ADD r1, lo(foo + 0xffffff)
>
> which would generate two separate relocs, one for the hi() expression
> and one for the lo() expression. If the file format uses REL
> relocations then the 0xffffff value would have to be stored in the
> LOAD_HI or ADD instructions, which presumably only have a 16 bit
> relocatable field - not big enough to hold 0xffff.
>
> In theory though, you could split the constant between the two relocs,
> like this:
>
> LOAD_HI r1, 0xff
> RELOC_HIGH_16_BITS (foo)
> ADD r1, 0xffff
> RELOC_LOW_16_BITS (foo)
>
> But the problem here is overflow. Suppose the address of 'foo' is
> 0x000000001. The computation for the RELOC_HIGH_16_BITS will be:
>
> ((0xff << 16) + 0x00000001) >> 16
> or
> 0x00ff
>
> but the computation for the RELOC_LOW_16_BITS will be:
>
> (0xffff + 0x00000001) & 0xffff
> or
> 0x0000
>
> So the final address loaded into register 1 will be:
>
> 0x00ff0000
> +0x00000000
> ----------
> 0x00ff0000
>
> instead of the correct address of:
>
> 0x00ffffff
> +0x00000001
> ----------
> 0x01000000
>
> So the RELOC_LOW_16_BITS needs to be able to tell the
> RELOC_HIGH_16_BITS that its computation overflow, which can be tricky
> if the two relocs are not next to each other, and very tricky when
> clever compiler decide that multiple references to elements of 'foo'
> can be optimised into only on LOAD_HI with multiple ADD instructions
> afterwards...
>
> Cheers
> Nick
>
>