This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Re: address of function
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Mathieu Lacage <Mathieu dot Lacage at sophia dot inria dot fr>
- Cc: libc-alpha at sources dot redhat dot com
- Date: Tue, 11 Jan 2005 15:30:46 +0100
- Subject: Re: address of function
- References: <1105453031.20548.235.camel@chronos.inria.fr>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Tue, Jan 11, 2005 at 03:16:55PM +0100, Mathieu Lacage wrote:
> I recently noticed that the exact semantics of the "address of function"
> operation in C seem to change slightly depending on the way I have
> compiled the code of my application.
>
> Specifically:
> 1) main code is built with gcc -c -o foo.o foo.c
> I get address of function = address of PLT entry for this function of
> the main executable
>
> 2) main code is built with gcc -fPIC -c -o foo.o foo.c
> I get address of function = address of code of function.
>
> Is there a way to tell the difference at runtime between these two
> cases ? An answer might be to point me to the specific if statement in
> glibc/elf/ directory which differentiates the two types of relocations:
> I have been unable to identify which code does the symbol resolution for
> a relocation entry of type R_386_GLOB_DAT (compilation with -fPIC) as
> opposed to the case where there is no such entry.
The difference is that if address of function is ever taken in non-pic
code in the executable, the SHN_UNDEF symbol in executable's .dynsym
will have non-zero st_value, while if address of a function is never
taken in the executable or only in pic code, the UND symbol will have
st_value 0.
Say for
extern void getpid (void);
void *p;
int main (void)
{
p = getpid;
}
without -fpic, there will be something like:
1: 080482a0 8 FUNC GLOBAL DEFAULT UND getpid@GLIBC_2.0 (2)
in .dynsym while with -fpic:
2: 00000000 8 FUNC GLOBAL DEFAULT UND getpid@GLIBC_2.0 (2)
0x080482a0 is address of the .plt slot.
The reason for this is that in non-pic code, the address of the function
(getpid in this case) needs to be resolved at link time, and the non-zero
st_value tells the dynamic linker to resolve all non-PLT dynamic lookups
to the PLT slot in the binary (C requires the pointer equality).
If there is only pic code taking that address, the address is stored into
a .got slot and therefore can be changed at dynamic link time to the
actual getpid's address, so also all shared libraries can resolve
the function to its real address.
Jakub