Should weak hidden undefined symbol be allowed?

133 views
Skip to first unread message

H.J.

unread,
Feb 24, 2008, 5:05:49 PM2/24/08
to Generic System V Application Binary Interface
The gABI says:

STV_DEFAULT
The visibility of symbols with the STV_DEFAULT attribute is as
specified by the symbol's binding type. That is, global and weak
symbols are visible outside of their defining component (executable
file or shared object). Local symbols are hidden, as described below.
Global and weak symbols are also preemptable, that is, they may by
preempted by definitions of the same name in another component.
...
STV_HIDDEN
A symbol defined in the current component is hidden if its name is
not visible to other components. Such a symbol is necessarily
protected. This attribute may be used to control the external
interface of a component. Note that an object named by such a symbol
may still be referenced from another component if its address is
passed outside.

A hidden symbol contained in a relocatable object must be either
removed or converted to STB_LOCAL binding by the link-editor when the
relocatable object is included in an executable file or shared
object.
...
* First, all of the non-default visibility attributes, when
applied to a symbol reference, imply that a definition to satisfy that
reference must be provided within the current executable or shared
object. If such a symbol reference has no definition within the
component being linked, then the reference must have STB_WEAK binding
and is resolved to zero.
* Second, if any reference to or definition of a name is a symbol
with a non-default visibility attribute, the visibility attribute must
be propagated to the resolving symbol in the linked object. If
different visibility attributes are specified for distinct references
to or definitions of a symbol, the most constraining visibility
attribute must be propagated to the resolving symbol in the linked
object. The attributes, ordered from least to most constraining, are:
STV_PROTECTED, STV_HIDDEN and STV_INTERNAL.

Should weak hidden undefined symbol be allowed? The problem is when
compiler sees a hidden symbol, it assumes
that it will be defined in the same component and optimizes its
access. If the hidden symbol is weak and undefined,
our linker won't report the error since the undefined symbol weak is
allowed. Although its value is 0, it may be
impossible to make its address to 0 in a shared library since the load
address of a shared library isn't known at
link-time.

Does anyone have suggestions?

Thanks.


H.J.

Jim Dehnert

unread,
Feb 25, 2008, 12:05:57 AM2/25/08
to gener...@googlegroups.com
On Sun, Feb 24, 2008 at 2:05 PM, H.J. <hjl....@gmail.com> wrote:
>
> Should weak hidden undefined symbol be allowed? The problem is when
> compiler sees a hidden symbol, it assumes
> that it will be defined in the same component and optimizes its
> access. If the hidden symbol is weak and undefined,
> our linker won't report the error since the undefined symbol weak is
> allowed. Although its value is 0, it may be
> impossible to make its address to 0 in a shared library since the load
> address of a shared library isn't known at
> link-time.

Why does that matter? That's an absolute zero, not a relative zero.

Jim


--
--
Jim Dehnert
deh...@gmail.com
dehn...@acm.org

H.J.

unread,
Feb 25, 2008, 12:32:35 AM2/25/08
to Generic System V Application Binary Interface
On Feb 24, 9:05 pm, "Jim Dehnert" <dehn...@gmail.com> wrote:
> On Sun, Feb 24, 2008 at 2:05 PM, H.J. <hjl.to...@gmail.com> wrote:
>
> > Should weak hidden undefined symbol be allowed? The problem is when
> > compiler sees a hidden symbol, it assumes
> > that it will be defined in the same component and optimizes its
> > access. If the hidden symbol is weak and undefined,
> > our linker won't report the error since the undefined symbol weak is
> > allowed. Although its value is 0, it may be
> > impossible to make its address to 0 in a shared library since the load
> > address of a shared library isn't known at
> > link-time.
>
> Why does that matter? That's an absolute zero, not a relative zero.
>

For

foo ? foo() : puts( "foo == null, skipped." );

if foo is hidden, compiler assumes it will be defined in the same
component. On
x86-64, compiler may generate the following PIC code

leaq foo(%rip), %rax
testq %rax, %rax

PC relative address is used here. It will work correctly if foo is
defined in
the same component. If foo is weak, undefined and hidden. foo will be
zero. For normal executable, since the load address is fixed, llinker
can
turn

leaq foo(%rip), %rax

into

leaq -PC(%rip), %rax

rax will be 0. But for shared library, linker doesn't know the load
address.
To load 0 into %rax, linker will generate relocation in .text section
and
dynamic linker has to modify LEA at run-time to load 0 into rax.

Generate a DSO with DT_TEXTREL isn't very desirable. We want
to avoid it if possible. It is odd to tell compiler that you can't
always
assume a hidden symbol will be defined in the same component
when you access it.

H.J.

H.J.

Daniel Jacobowitz

unread,
Feb 25, 2008, 8:55:02 AM2/25/08
to Generic System V Application Binary Interface
On Feb 25, 12:32 am, "H.J." <hjl.to...@gmail.com> wrote:
> For
>
> foo ? foo() : puts( "foo == null, skipped." );
>
> if foo is hidden, compiler assumes it will be defined in the same
> component. On
> x86-64, compiler may generate the following PIC code
>
> leaq foo(%rip), %rax
> testq %rax, %rax
>
> PC relative address is used here. It will work correctly if foo is
> defined in
> the same component.

As I've said earlier on the binutils list, if the symbol is weak, the
above seems to me to be a compiler bug.

> Generate a DSO with DT_TEXTREL isn't very desirable. We want
> to avoid it if possible. It is odd to tell compiler that you can't
> always
> assume a hidden symbol will be defined in the same component
> when you access it.

No stranger than telling it that the address of a weak symbol can be
NULL.

H.J.

unread,
Feb 25, 2008, 12:06:17 PM2/25/08
to Generic System V Application Binary Interface
>
> > Generate a DSO with DT_TEXTREL isn't very desirable. We want
> > to avoid it if possible. It is odd to tell compiler that you can't
> > always
> > assume a hidden symbol will be defined in the same component
> > when you access it.
>
> No stranger than telling it that the address of a weak symbol can be
> NULL.

My question is if compiler can assume that a hidden symbol is
always defined in the same component. If the answer is no,
a weak hidden symbol doesn't have to be defined in the same
component, then compiler needs to be careful about weak symbol
even if it is hidden. I just want to hear what everyone thinks.

Thanks.

H.J.

Cary Coutant

unread,
Feb 25, 2008, 5:10:44 PM2/25/08
to gener...@googlegroups.com
> My question is if compiler can assume that a hidden symbol is
> always defined in the same component. If the answer is no,
> a weak hidden symbol doesn't have to be defined in the same
> component, then compiler needs to be careful about weak symbol
> even if it is hidden. I just want to hear what everyone thinks.


A hidden symbol must be defined in the same component, *if it is
defined at all*. That last part is the key to the issue. In the case
of a WEAK HIDDEN UNDEF symbol, it is possible for the symbol to remain
undefined (or, looked at another way, it is possible for the symbol to
be defined at link time as an absolute symbol with value 0). I agree
with Daniel; the compiler should be aware of this possibility and
generate code that will not require a dynamic relocation for this case.

-cary

Reply all
Reply to author
Forward
0 new messages