[llvm-commits] patch: teach deadargelim to work on externally visible functions!
edwintorok at gmail.com
Sat Jan 9 03:50:22 CST 2010
On 2010-01-09 03:48, Chris Lattner wrote:
> On Jan 5, 2010, at 2:58 AM, Török Edwin wrote:
>>>> then why not do further optimizations based on this assumption, and
>>>> really call the function we see
>>>> (instead of going through the .plt and calling whatever that
>>>> resolves to
>>>> at runtime).
>>> Can you elaborate?
>> Currently an externally visible function is called like this (with
>> -fPIC), even when we know
>> the function is in the current module:
>> callq foo at PLT
>> Which does allow for an override at runtime (see example at bottom), but
>> that is not what the optimizer assumed.
> Does GCC do this? This seems "bad". Neither gcc or llvm does the
> equivalent on darwin.
Yes, try compiling my example on Linux, you'll see that you *can*
override those functions.
Its useful if you do hooking via LD_PRELOAD, and you want to intercept
calls from a shared lib to itself,
but not for much else.
>> My suggestion is:
>> - why go through all the trouble of calling it via PLT, and allowing
>> runtime override, when what we really want
>> is call the function we see? We could call it directly, i.e.:
>> callq foo
> This makes sense to me, this is what I thought we did already. :)
>> - from an ELF symbol visibility point of view this would mean the
>> symbols should get protected visibility, instead of default visibility
> How does this affect visibility?
>From the gcc manual:
"On ELF, default visibility means that the declaration is visible to
other modules and, in shared libraries,
means that the declared entity may be overridden."
"Protected visibility is like default visibility except that it
indicates that references within the defining module will
bind to the definition in that module. That is, the declared entity
cannot be overridden by another module."
I don't know if "default" is something needed to respect an ABI, or its
default because gcc chose it to be.
So I had a look here:
It says (refering to -fvisibility):
"The default is unsurprisingly 'default' since that is the behavior of
the compiler before the introduction of this option"
Also "protected" visibility (i.e. not going through the PLT) doesn't
seem like a good idea:
"The generic ELF ABI deﬁnes another visibility mode:
protected [...] This sounds like an ideal mechanism to optimize DSO by
use of exported symbols but it isn’t.
Processing references to protected symbols is even more
expensive than normal lookup. The problem is a require-
ment in the ISO C standard. The standard requires that
function pointers, pointing to the same function, can be
compared for equality. This rule would be violated with a
fast and simple-minded implementation of the protected
visibility. Assume an application which references a pro-
tected function in a DSO. Also in the DSO is another
function which references said function. The pointer in
the application points to the PLT entry for the function
in the application’s PLT. If a protected symbol lookup
would simply return the address of the function inside
the DSO the addresses would differ."
Since Darwin already does the optimization I was talking about, how does
it solve the above issue?
(functions from outside DSO referencing function inside DSO via PLT, and
those inside the DSO
referencing it directly, thus yielding different addresses).
>> - then we would get consistent behavior from optimized and
>> non-optimized code
>> - you get same behavior regardless which file you place your function
>> into, it will always get called directly, instead of indirectly via
>> the PLT
>> Here is an example where the link order of shared libs causes a
>> different function to be called:
> This example has undefined behavior, so it doesn't matter what we
> produce. We should just always generate the faster code. This sounds
> like a pretty serious performance bug on ELF systems.
Agreed, thats why I brought this up.
More information about the llvm-commits