This is the mail archive of the binutils@sourceware.cygnus.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]

Re: Reloc changes to bfd/elf32-mips.c


> Cc: gavin@cygnus.com, binutils@sourceware.cygnus.com, brendan@cygnus.com
> X-URL: http://www.codesourcery.com
> Organization: CodeSourcery, LLC
> From: Mark Mitchell <mark@codesourcery.com>
> Date: Tue, 28 Sep 1999 00:59:56 -0700
> X-Dispatcher: imput version 990425(IM115)
> 
> 
> I'm confused on a couple of points.
> 
>   @@ -6557,6 +6556,7 @@ _bfd_mips_elf_relocate_section (output_b
> 	 int r_type = ELF32_R_TYPE (rel->r_info);
> 
> 	 /* Find the relocation howto for this relocation.  */
>   +#ifndef BFD64
> 	 if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
> 	  /* Some 32-bit code uses R_MIPS_64.  In particular, people use
> 	     64-bit code, but make sure all their addresses are in the 
>   @@ -6566,6 +6566,7 @@ _bfd_mips_elf_relocate_section (output_b
> 	     stored value is sign-extended to 64 bits.  */
> 	  howto = elf_mips_howto_table + R_MIPS_32;
> 	 else
>   +#endif
> 	  howto = mips_rtype_to_howto (r_type);
> 
> That's fine by me, in that I never understood exactly what was going
> on there.  But, I don't think it's right.  The idea here is that
> 32-bit object code can still use R_MIPS_64, according to Ian.  So, I
> don't think BFD64 (which says something about how many bits you have
> when you're compiling BFD) is the right thing.

What I think this code was trying to do was make a R_MIPS_64 reloc
work when you have a 32-bit BFD.  If you have a 64-bit BFD, none of
this is necessary, and you can just do the right thing.  The object
format size is irrelevant, you'd have to do a similar thing to make a
R_MIPS_64 reloc work in an elf64 file with a 32-bit BFD (but you'd have
to do many many other things too).

The original code used the R_MIPS_32 howto for a R_MIPS_64 reloc, but
if you do that the addend gets computed wrong in big-endian files
because BFD thinks the addend is 32 bits long and only sees the high
32 bits which are not usually helpful.  It's also possible to usefully
have a R_MIPS_64 reloc with a full 64-bit addend, eg if you write

0:   .dword 0f+0xa000000000000000

I don't know why anyone bothered to do this in the first place, there
aren't that many compilers left that don't support 64-bit values; but
it must have been useful for someone so I left the code in.

>   @@ -6628,26 +6629,11 @@ _bfd_mips_elf_relocate_section (output_b
> 		    l &= lo16_howto->src_mask;
> 		    l = mips_elf_sign_extend (l, 16);
> 
>   -		  /* Save the high-order bit for later.  When we
>   -		     encounter the R_MIPS_LO16 relocation we will need
>   -		     them again.  */
> 		    addend <<= 16;
>   -		  last_hi16_addend = addend;
>   -		  last_hi16_addend_valid_p = true;
> 
> 		    /* Compute the combined addend.  */
> 		    addend += l;
> 		  }
>   -	      else if (r_type == R_MIPS_LO16) 
>   -		{
>   -		  /* Used the saved HI16 addend.  */
>   -		  if (!last_hi16_addend_valid_p)
>   -		    {
>   -		      bfd_set_error (bfd_error_bad_value);
>   -		      return false;
>   -		    }
>   -		  addend |= last_hi16_addend;
>   -		}
> 		else if (r_type == R_MIPS16_GPREL)
> 		  {
> 		    /* The addend is scrambled in the object file.  See
> 
> Why is all this code going away?  This looks like it will make
> R_MIPS_LO16 not work in .rel sections.  The addend for the LO16
> relocation is the combination of bits in the HI16 and LO16 relocs, I
> think.

The addend for the LO16 reloc can be considered as just the bits in
the LO16 reloc; we only care about the least-significant 16 bits.
HI16 relocs are different because there can be a carry from the lower
16 bits.

The problem it fixes is that the assembler does not sort LO16 relocs
so that they all come after some HI16 reloc that matches them; it
sorts HI16 relocs so that they all come before some LO16 reloc that
matches.

For instance, the following .s file:

l1:     b       l2
l3:     lw      $5,%lo(l1+0x10004)($2)
        b       l4
l2:     lui     $2,%hi(l1+0x10004)
        add     $3,$2,$3
        lw      $4,%lo(l1+0x10004)($3)
        b       l3
l4:

produces the following relocs from gas:

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE 
000000000000000c R_MIPS_LO16       .text
0000000000000010 R_MIPS_HI16       .text
000000000000001c R_MIPS_LO16       .text

Contents of section .text:
 0000 10000003 00000000 10000005 8c450004  .............E..
 0010 3c020001 00431820 1000fffb 8c640004  <....C. .....d..

which used to cause ld to fail with an error.  gcc can generate
control flows like this (although some of the branches have to be
conditional).

-- 
Geoffrey Keating <geoffk@cygnus.com>

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