This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Relocation bug


On Sat, Feb 22, 2003 at 07:05:55PM -0800, Eric Christopher wrote:

> This patch:
> 
> http://sources.redhat.com/ml/binutils/2001-01/msg00290.html
> 
> is the one that changed the behavior to what it is currently. It was a
> revert of one of Ralf's patches to which he was cc'd on the mail. From a
> quick look it appears correct, however, I can't find any reasoning other
> than "ABI Compliance" in the patch.

The ABI document (as mentioned a dozen times off the list) is pretty badly
written.  This I think how both Maciej, myself and others got lured into
believing wrong is right and right is wrong.

The ABI describes the two relocation as follows:

  R_MIPS_32      2 T word32 external S + A
                 2 T word32 local    S + A
  R_MIPS_REL32   3 T word32 external A - EA + S
  R_MIPS_REL32   3 T word32 local    A - EA + S

You see both relocations against both local and external symbols need to
perform the same calculation.  What was missed what the definition of the
S operand scattered throughout the document a few pages away:

  S Represents the value of the symbol whose index resides in the relocation
    entry, unless the the symbol is STB_LOCAL and is of type STT_SECTION in
    which case S represents the original sh_addr minus the final sh_addr

There's two issues with that paragraph:

 - "original sh_addr minus the final sh_addr" is wrong and wouldn't result
   in a functioning static linker / dynamic linker.  "final sh_addr minus
   original sh_addr" would be correct.  The 64-bit ABI corrects this
   mistake.
 - People did simply miss this paragraph not noting that the S operand has
   different definitions for two cases.  This in the end is what this bug
   is about and indeed one of the people I was did discuss this with in
   private got caught by this interpretation.

Now only that I recently had to revisit the issue after quite a while I
understood what was going on; the usual comparision with the IRIX linker
supports my theory.

> Taking a look at foo.so:
> 
> [echristo at ghostwheel ~/mips]$
> /ghostwheel/sourceware/builds-rewrite/build-mips/binutils/objdump -R
> foo.so
> 
> foo.so:     file format elf32-bigmips
> 
> DYNAMIC RELOCATION RECORDS
> OFFSET   TYPE              VALUE
> 00000000 R_MIPS_NONE       *ABS*
> 600203d0 R_MIPS_REL32      .data
> 
> And the abi spec (version 3, gotten from Caldera):
> 
> 4-19:
> 
> "The R_MIPS_REL32 relocation type is the only relocation performed by
> the dynamic linker..."
> 
> So, it appears that the behavior is correct according to the abi.

The relocation records themselves are ok.  What's wrong is how linker and
dynamic linker are using them.  It's two bugs - and both are neutralizing
each other.

It also means the binutils ABI MIPS ELF and MIPS IRIX ELF targets are broken
resulting in 1) break support for those binary flavours and 2) in combination
with the matching OpenBSD and GNU Libc bugs somewhat establishing two new
minimally different but incompatible binary flavours.  As for Linux both
flavours are currently actively being shipped by vendors.  It's simply not
yet caused major yelling because most users are not swapping swapping
binaries around.  It's a bloddy mess and I'm trying to stop it before it
gets worse.

> Maciej? Comments?

Maciej agrees that this is wrong behaviour.

(Eric, cgd - This is also the same thing we were discussing under the
subject "R_MIPS_REL64" on the other list, only for o32 this time ...)

The relocation records in the DSO are ok; the problem is the way the 
R_MIPS_32 records in the .o file were processed.  For DSOs they're
converted into R_MIPS_REL32 records.

Test case:

[ralf at dea b0rked]$ cat s.s
	.text
	.word	0, 0, 0, 0

	.data
b0rk:	.word	b0rk + 0x1234

(The .text part isn't necessary for demonstrating this ...)

Broken linker:

[ralf at dea b0rked]$ mips_sb1_fp_be-as -O2 -KPIC -o s.o s.s 
[ralf at dea b0rked]$ mips_sb1_fp_be-ld -shared -o s.so s.o 
[ralf at dea b0rked]$ mips-linux-objdump --full-contents --section=.data s.so 

s.so:     file format elf32-tradbigmips

Contents of section .data:
 403e0 00001234 00000000 00000000 00000000  ...4............
       ^^^^^^^^
0x1234 - just the addend from the .word pseudo op.

Correct linker:

[ralf at dea b0rked]$ mips-linux-objdump --full-contents --section=.data s.so 

s.so:     file format elf32-tradbigmips

Contents of section .data:
 40410 00041644 00000000 00000000 00000000  ...D............
       ^^^^^^^^

Which is the address of .data plus 0x1234.

  Ralf


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]