Project

General

Profile

Actions

Bug #6730

open

visibility issues in public header definitions: difference between -fvisibility=hidden and #pragma GCC visibility push(hidden) overriding the default

Added by Richard PALO about 5 years ago. Updated about 5 years ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
-
Start date:
2016-03-07
Due date:
% Done:

0%

Estimated time:
Difficulty:
Medium
Tags:
needs-triage
Gerrit CR:

Description

The is an apparently long known issue with the the public headers which
pokes its head out when linking...

It is best shown by example:

$ cat thidden.c 
#ifdef HIDE 
#pragma GCC visibility push(hidden)
#endif

#include <string.h>

int __attribute__((visibility("default"))) 
thidden(void)
{
    char foo[]="hello world";

    return ((int)strlen(foo));    
}

from gcc:

6.61.13 Visibility Pragmas

#pragma GCC visibility push(visibility)
#pragma GCC visibility pop
    This pragma allows the user to set the visibility for multiple declarations without having to give each a visibility attribute (see Function Attributes).

    In C++, ‘#pragma GCC visibility’ affects only namespace-scope declarations. Class members and template specializations are not affected; if you want to override the visibility for a particular member or instantiation, you must use an attribute. 

to see the problem, I'll use the '-fvisibility=hidden' style (which works okay) and
a macro called HIDE to invoke the pragma above.

$ gcc -fvisibility=hidden -fPIC -DPIC  thidden.c -c -o thidden-fvis.o
$ gcc -DHIDE -fPIC -DPIC  thidden.c -c -o thidden-HIDE.o
$ nm thidden-fvis.o 

thidden-fvis.o:

[Index]   Value      Size      Type  Bind  Other Shndx   Name

[5]    |         0|         0|SECT |LOCL |0    |5      |
[2]    |         0|         0|SECT |LOCL |0    |1      |
[3]    |         0|         0|SECT |LOCL |0    |3      |
[4]    |         0|         0|SECT |LOCL |0    |4      |
[7]    |         0|         0|NOTY |GLOB |0    |UNDEF  |_GLOBAL_OFFSET_TABLE_
[8]    |         0|         0|NOTY |GLOB |0    |UNDEF  |strlen
[6]    |         0|        60|FUNC |GLOB |0    |1      |thidden
[1]    |         0|         0|FILE |LOCL |0    |ABS    |thidden.c
$ nm thidden-HIDE.o 

thidden-HIDE.o:

[Index]   Value      Size      Type  Bind  Other Shndx   Name

[5]    |         0|         0|SECT |LOCL |0    |5      |
[2]    |         0|         0|SECT |LOCL |0    |1      |
[3]    |         0|         0|SECT |LOCL |0    |3      |
[4]    |         0|         0|SECT |LOCL |0    |4      |
[7]    |         0|         0|NOTY |GLOB |0    |UNDEF  |_GLOBAL_OFFSET_TABLE_
[8]    |         0|         0|NOTY |GLOB |2    |UNDEF  |strlen
[6]    |         0|        54|FUNC |GLOB |0    |1      |thidden
[1]    |         0|         0|FILE |LOCL |0    |ABS    |thidden.c

notice in the latter the value '2' meaning hidden for 'strlen'

This means at link time:

$ gcc -fvisibility=hidden -fPIC -DPIC -shared thidden.c 
$#okay but
$ gcc -DHIDE -fPIC -DPIC -shared thidden.c 
Undefined            first referenced
 symbol                  in file
strlen                              /tmp/cc3iaykX.o  (symbol scope specifies local binding)
ld: fatal: symbol referencing errors. No output written to a.out
collect2: error: ld returned 1 exit status

This seems to imply we need to protect our headers.

I notice that NetBSD/FreeBSD define a number of useful macros in sys/cdefs.h
that expound a portable manner to avoid this sort situation in illumos.

Actions #1

Updated by Richard PALO about 5 years ago

oups, namely the ultimate definitions of _BEGIN_DECLS and _END_DECLS

Actions

Also available in: Atom PDF