On 2014-03-27 17:04, Trevor Saunders wrote:
On Thu, Mar 27, 2014 at 02:12:54PM +0400, izbyshev wrote:
Well, actually the documentation at http://gcc.gnu.org/wiki/Visibility
states:
#pragma GCC visibility is stronger than -fvisibility; it affects extern
declarations as well. -fvisibility only affects definitions, so that
existing code can be recompiled with minimal changes.
that seems kind of crazy and unfortunate.

Well, the last sentence hints that the reason is to allow people to easily use shared libraries that don't use visibility attribute (yet). If -fvisibility=hidden acted like #pragma, all symbols declared in public headers of such libraries would become hidden, and the binary of any project that includes such headers could not be linked. In firefox, this behavior is emulated by including #pragma before every translation unit and then solving the described problem via system wrappers. So, even if -fvisibility and #pragma were equivalent (and had the "strong" meaning), we would still have had to use system wrappers!

All in all, it seems that system wrappers are superior (but not
dramatically) unless all internal data used across units is explicitly marked with 'hidden' attribute and issues like with libopus are resolved (by either changing such libs so they don't export symbols when they are built statically or explicitly marking function declarations as hidden at use
sites).
or we get gcc / clang to make -fvisibility=hidden do what we want / add
some new option that does.

Even if we put aside issues with .rela.plt (I agree they are kind of library problem in the case of opus, and I should probably investigate other cases further), we still have a data declarations problem, and IMO we can't make the compiler do what we want since we want too much. Suppose we have a translation unit that includes a bunch of headers containing only declarations. To get the least possible number of data relocations, we'd like to have the following visibility: 1. The public headers from our project with symbols that we want to export: default.
  2. The internal headers from our project: hidden.
3. The public headers from libraries that we will be statically linked to: hidden. 4. The public headers from libraries that we will be dynamically linked to: default.

If we are a good project, we should have explicitly specified default visibility for all declarations from 1, so they are not a problem. But the compiler has no way to distinguish (2, 3) and 4 without some help. So the compiler has to use the same policy for all of them, and the extremes are: * Hide all declarations (#pragma). In this case we have to explicitly exclude 4 (hello, system wrappers). * Hide nothing (-fvisibility=hidden - doesn't affect declarations). Here we get the overhead from 2 and 3.

I can't think of any 'mixed' policy that the compiler could use. One alternative would be to use the 'hide nothing' policy and wrap headers from 2 and 3 with 'push(hidden)' and 'pop' pragmas. I'm not sure that this is better than system wrappers, but it is probably easier to track headers from firefox tree than external ones. I should see how the system wrappers generator is implemented to check this out.

--
Alexey Izbyshev

_______________________________________________
dev-builds mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-builds

Reply via email to