[llvm-commits] patch: teach deadargelim to work on externally visible functions!
Török Edwin
edwintorok at gmail.com
Sat Jan 9 01:56:08 PST 2010
On 2010-01-09 11:50, Török Edwin wrote:
> 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:
> http://people.redhat.com/drepper/dsohowto.pdf
>
> 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 defines another visibility mode:
> protected [...] This sounds like an ideal mechanism to optimize DSO by
> avoiding the
> 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).
>
>
On a second thought, this could be solved by going through the PLT
when taking the address of a function, but when calling the function
directly
we skip the PLT.
>>> - 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.
>
>
On 2010-01-09 04:34, Dan Gohman wrote:
> It may be as simple as this:
>
> --- lib/Target/X86/X86ISelLowering.cpp (revision 93032)
> +++ lib/Target/X86/X86ISelLowering.cpp (working copy)
> @@ -1984,6 +1984,7 @@
> // we don't need to use the PLT - we can directly call it.
> if (Subtarget->isTargetELF() &&
> getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
> + (GV->isDeclaration() || GV->isWeakForLinker()) &&
> GV->hasDefaultVisibility() && !GV->hasLocalLinkage()) {
> OpFlags = X86II::MO_PLT;
> } else if (Subtarget->isPICStyleStubAny() &&
>
> At least, this does the right thing on the most trivial testcase,
> and it's the same logic that the Darwin code uses, 5 lines later. Can
> someone familiar with this check this?
>
Do function pointers still get the address foo at PLT?
If yes then it should address my concern above.
Best regards,
--Edwin
More information about the llvm-commits
mailing list