CFLAGS+= -fPIC per default?

Joseph Fenton jlfenton at citlink.net
Sun Feb 22 13:27:50 PST 2004


>>Adding CFLAGS= -fPIC to /etc/make.conf may be a local solution but
>>are there any drawbacks by adding something like
>>.if ${ARCH} == "amd64"
>>CFLAGS+= -fPIC
>>.endif
>>
>>to ports/Mk/bsd.port.mk?
>>    
>>
>
>No.. please don't.  Although the AMD64 platform supports PIC addressing 
>modes directly, it is still a penalty.  (Although thankfully, its 
>nowhere near as expensive as it is on i386!)
>
>For example, in libc when built in PIC mode:
>#ifdef PIC
>        movq    PIC_GOT(HIDENAME(curbrk)),%rdx
>        movq    (%rdx),%rax
>#else
>        movq    HIDENAME(curbrk)(%rip),%rax
>#endif
>
>The problem is that we can't be sure that everything will be in +/- 31 
>bit offsets of each other.  This means that PIC objects have to do 
>indirect memory references that aren't required in no-pic mode.
>
>I386 also loses a general purpose register (%ebx) which is why -fpic is 
>more expensive there.  But even though we don't lose a register, its 
>still a cost because of the extra global-offset-table memory 
>references.
>
>Footnote: you just made me wonder about some of these ifdefs..  We 
>shouldn't need them for intra-object references like this.  I'll have 
>to go and look again.
>  
>

Sorry to be anal, but PC-relative addressing is by definition
position-independent code. Who was the bright individual
who decided that when compiling PIC code to NOT use
PC-relative and to NOT use PC-relative for non-PIC code?

This is counter-intuitive. For PIC code, you use PC-relative
addressing in two cases: 1 - the code is guaranteed to be
a constant distance apart, like code in the same section; 2 -
when the loader guarantees the relative position of different
sections, like code and data contained in a ROM.

Case 1 could be violated by the code being too far apart
for PC-relative addressing. This is virtually impossible for
the AMD64 as I doubt we'll see code exceeding 2G in
size in the next several decades. Code is only now exceeding
a few megabytes. Case 2 is usually your problem, which leads
to tables used to hold addresses or offsets.

Both sides of the #ifdef PIC are doing valid PIC code.
PC-relative addressing should be used wherever possible
unless it incurs a speed penalty.

Non-PIC code generally does PC-relative code if it
is faster and is legal, for example, when referring to
code within the same section. When the address must
be set by the loader for non-PIC code, it seems to me
that the fastest code would be like this:

  mov     <imm32>,%rdx
  movq    (%rdx),%rax

or if the address is > 4G

  movq    <imm64>,%rdx
  movq    (%rdx),%rax


The loader would then set the immediate vector upon
loading the sections. This avoids a memory hit for accessing
a table of addresses while only adding at most 5 bytes to the
size of the code. I would probably use this unless the user
is compiling with flags set to compile with minimized code
size.

Sorry to nit-pick like this, but having worked on both Mac
and Amiga ROMs, PIC mode under BSD really seems
backwards to me.



More information about the freebsd-amd64 mailing list