Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20150414042107.GA18755@brightrain.aerifal.cx>
Date: Tue, 14 Apr 2015 00:21:07 -0400
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Direction on GNUC features, visibility, __libc struct hacks

A few of the recent commits introduced unconditional visibility
attributes in some places, whereas in the past they were conditional
on compiler versions, so I'd like to clarify what's going on with
that.

For a shared libc.so, having visibility is essential to providing a
compatible ABI. Without it, some symbols which need to exist
internally for libc with specific names (like __stack_chk_fail_local
and math symbols pulled in from libgcc) would become public ABI for
libc.so. It's plausible that some future compiler could offer it via a
different syntactical mechanism than the GNUC __attribute__ system,
but unless this happens I don't want to spend effort being
gratuitously general. So for now, visibility attributes will be used
unconditionally where needed for SHARED libc.

What's less clear is what to do with uses that are not needed.

Now that the dynamic linker fully relocates ldso/libc itself before
making any external calls, the whole libc.h mechanism of hiding
important globals inside a hidden struct (with fallback to ugly
accessor function for theoretical compilers that lack visibility but
somehow can make a working libc.so) is completely unnecessary. These
globals could all be split up into their own named objects. In
particular the global locale object could probably be optimized out of
some static binaries.

What I found more troubling is that we have a number of other broken
uses of visibility, like in src/internal/syscall.h, where the
declaration of a symbol specifies hidden visibility but the point of
definition does not. This often happens when the declaration is in C
and the definition is in asm (__syscall) or vice versa (access of
__hwcap as if it were .hidden, by arm setjmp asm). Most or all of this
inconsistent usage of visibility has been papered over by
-Bsymbolic-functions, which binds the symbols at ld time and prevents
the TEXTRELs or linking errors that would otherwise arise due to the
inconsistency. Playing with building without -Bsymbolic-functions, I
ran into a lot of such problems, and the number increases drastically
if you use an old toolchain (like the GPLv2 one from Aboriginal
Linux) that's less forgiving about the mismatches.

Yet another related issue is all the places where i386 asm makes
function calls to external, public symbols (like sigprocmask, exp2l,
etc.) without @PLT. Using @PLT would be undesirable because it would
require loading %ebx with the GOT pointer in all this asm (which is
shared between PIC and non-PIC builds).

Some ideas for fixes:

For things that semantically should be hidden, it seems pretty simple:
just make sure the declaration and definition are consistent and both
are hidden. This is a bit of work but not too bad.

For things that are just bypassing PLT/GOT access bloat, on the other
hand, I don't see a really good solution. In some cases (where both
the caller and callee are asm, like expl/exp2l) we could add extra
hidden symbols to use for the call instead of the public symbol, but
that seems ugly. That doesn't really work for calls to public
functions written in C though. An alternative approach is to declare
the target symbol .protected from the calling asm. Even with old
binutils, this seems to produce the desired results, but the final
symbol in the .so does come out marked PROTECTED which may be weird.

The other solution would be to just phase out these types of calls.

I'll start by making some cleanups/fixes that should be
uncontroversial we try to figure out what to do with the rest.

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.