This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC 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: %pc relative addressing of string literals/const data


On Tue, Oct 05, 2010 at 10:55:36PM +0200, Joakim Tjernlund wrote:
> Richard Henderson <rth@redhat.com> wrote on 2010/10/05 20:56:55:
> >
> > On 10/05/2010 06:54 AM, Joakim Tjernlund wrote:
> > > Ian Lance Taylor <iant@google.com> wrote on 2010/10/05 15:47:38:
> > >> Joakim Tjernlund <joakim.tjernlund@transmode.se> writes:
> > >>> While doing relocation work on u-boot I often whish for strings/const data
> > >>> to be accessible through %pc relative address rather than and ABS address
> > >>> or through GOT. Has this feature ever been considered by gcc?
> > >>
> > >> The feature can only be supported on processors which are reasonably
> > >> able to support it.  So, what target are you asking about?
> > >
> > > In my case PowerPC but I think most arch's would want this feature.
> > > Is there arch's where this cannot be support at all or just within
> > > some limits? I think within limits could work for small apps
> > > like u-boot.
> >
> > PowerPC doesn't really have the relocations for pc-relative offsets
> > within code -- primarily because it doesn't have pc-relative insns
> > to match.  Nor, unfortunately, does it have got-relative relocations,
> > like some other targets.  These are normally how we get around not
> > having pc-relative relocations and avoiding tables in memory.  C.f.
> >
> >   #pragma GCC visibility push(hidden)
> >   extern int x, y;
> >   int foo(void) { return x + y; }
> >
> > Without pragma (-O2 -fpic):
> > i386:
> >         movl    y@GOT(%ecx), %eax
> >         movl    x@GOT(%ecx), %edx
> >         movl    (%eax), %eax
> >         addl    (%edx), %eax
> >
> > alpha:
> >         ldq $1,y($29)           !literal
> >         ldl $0,0($1)
> >         ldq $1,x($29)           !literal
> >         ldl $1,0($1)
> >         addl $0,$1,$0
> >
> > In both cases here, we have load the address from memory, from
> > the GOT table, then load the data (X or Y) from memory and
> > perform the addition.
> >
> >
> > With pragma:
> > i386:
> >         movl    y@GOTOFF(%ecx), %eax
> >         addl    x@GOTOFF(%ecx), %eax
> >
> > alpha (-fpic):
> >         ldl $1,x($29)           !gprel
> >         ldl $0,y($29)           !gprel
> >         addl $0,$1,$0
> >
> > alpha (-fPIC):
> >         ldah $1,y($29)          !gprelhigh
> >         ldl $0,y($1)            !gprellow
> >         ldah $1,x($29)          !gprelhigh
> >         ldl $1,x($1)            !gprellow
> >         addl $0,$1,$0
> >
> > In all cases here, we've replaced the load from the GOT table
> > with arithmetic.  In the case of i386 this gets folded into the
> > memory reference.  The alpha cases are essentially the same as
> > what ppc could generate if it had the appropriate relocations.
> 
> I don't do x86 or alpha so let me ask: If you run the code on an address
> != link address, will it do the right thing?
> 
> I tested the #pragma/no #pragma on PPC and the resulting code
> was the same:
> /* with #pragma, -fpic -O2 -mregnames
> foo:
> 	stwu %r1,-16(%r1)
> 	mflr %r12
> 	bcl 20,31,.LCF0
> .LCF0:
> 	stw %r30,8(%r1)
> 	mflr %r30
> 	addis %r30,%r30,_GLOBAL_OFFSET_TABLE_-.LCF0@ha
> 	addi %r30,%r30,_GLOBAL_OFFSET_TABLE_-.LCF0@l
> 	mtlr %r12
> 	lwz %r9,y@got(%r30)
> 	lwz %r3,0(%r9)
> 	lwz %r9,x@got(%r30)
> 	lwz %r30,8(%r1)
> 	addi %r1,%r1,16
> 	lwz %r0,0(%r9)
> 	add %r3,%r3,%r0
> 	blr
>  */
> 
> 
> You can get at the GOT table using PC relative addressing so why not
> strings or data in a similar fashion?

Because you access the got with a single (16 bit offset) instructions.
If you add .rodata, .data and .bss, you will likely overflow it 
quite rapidly.

Did you look at -mrelocatable? 

I don't know whether it can solve all your problems (probably not),
and there are regular threats of removing it, or at least there
were, since I see that the documentation was much improved in August. 

Anyway, I used it a decade ago to write a bootloader that:

a) was loaded at an unpredictable and unconfigurable address
depending on the mood of the firmware (really, it depended at 
least on the media from which you booted, even exactly the 
same binary image)

b) the first thing the bootloader did was to run the relocation code
for the adress at which it had been loaded by the firmware and 
find the free memory areas from tables provided by the firmware.
The code in this part could not use any global pointer variable, 
AFAIR, but it was short.

c) the bootloader than moved itself where it could, re ran
the relocation code, and then could finally interact a bit with
the user to change kernel options, uncompress the kernel 
and give it control.

I have not touched the code in 8 or 9 years, but it is still
the bootloader used here by ~20 MVME machines.

	Regards,
	Gabriel


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