Date: Sun, 22 Feb 2004 14:27:34 -0700 From: Joseph Fenton <jlfenton@citlink.net> To: freebsd-amd64@freebsd.org Subject: Re: CFLAGS+= -fPIC per default? Message-ID: <40391EC6.7010808@citlink.net> In-Reply-To: <20040222185212.EB6BE16A4D1@hub.freebsd.org> References: <20040222185212.EB6BE16A4D1@hub.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
>>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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?40391EC6.7010808>