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: Change to GOT initialization?


On Wed, Nov 27, 2002 at 01:26:24PM -0800, Jason R Thorpe wrote:
> The way we compute our relocation base is:
> 
>         bl      _GLOBAL_OFFSET_TABLE_@local-4
>         mflr    %r31                    # r31 = (real) GOT
>         lwz     %r30,_GLOBAL_OFFSET_TABLE_@got(31)
>                                         # the linker thought GOT were ...
>         subf    %r4,%r30,%r31           # r4 = relocbase
> 
> ...but this falls over completely, because 0 ends up being loaded
> info %r30, so we can't compute the relocbase (nor can we compute
> the real address of _DYNAMIC, since we don't know the relocbase to
> add to the base-relative offset in _DYNAMIC's GOT entry).
> 
> So, I guess I have two questions:
> 
> 	1. Can anyone tell me when this change was made, and why?

http://sources.redhat.com/ml/binutils/2002-09/msg00322.html
http://sources.redhat.com/ml/libc-alpha/2002-09/msg00630.html

> 	2. Can anyone suggest a way for me to deal with the problem
> 	   (I guess the question really is: Can anyone suggest another
> 	   way for me to compute the relocbase?)

Extract from glibc/sysdeps/powerpc/powerpc32/dl-machine.h

     Instead, we use the following trick:

     The linker puts the _link-time_ address of _DYNAMIC at the first
     word in the GOT. We could branch to that address, if we wanted,
     by using an @local reloc; the linker works this out, so it's safe
     to use now. We can't, of course, actually branch there, because
     we'd cause an illegal instruction exception; so we need to compute
     the address ourselves. That gives us the following code: */

  /* Get address of the 'b _DYNAMIC@local'...  */
  asm ("bl 0f ;"
       "b _DYNAMIC@local;"
       "0:"
       : "=l"(branchaddr));

  /* ... and the address of the GOT.  */
  asm (" bl _GLOBAL_OFFSET_TABLE_-4@local"
       : "=l"(got));

  /* So now work out the difference between where the branch actually points,
     and the offset of that location in memory from the start of the file.  */
  return ((Elf32_Addr)branchaddr - *got
	  + ((int)(*branchaddr << 6 & 0xffffff00) >> 6));
}

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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