限制Solaris上的共享库符号可见性

时间:2013-05-27 09:42:21

标签: linker shared-libraries solaris visibility

使用GCC(在Linux上)我可以轻松limit visibilitysymbols in shared个库。

我在Solaris(10)上有哪些选择?

这些GCC功能是否也适用于Solaris上的GCC(尤其是使用Solaris链接器/汇编器的GCC)?

Solaris Studio C编译器/链接器是否提供类似的属性/编译指示来控制符号的可见性(即将默认设置为隐藏并将符号明确标记为可见)?

3 个答案:

答案 0 :(得分:4)

我在Solaris 10机器上测试了一些声明注释方法。令人惊讶的是,Solaris Studio C编译器还支持GCC隐藏功能属性。

使用Solaris as / ld配置的GCC正确实现了visibiltiy函数属性。

因此,使用GCC函数属性语法应该是最方便/可移植的方法,因为它适用于Linux / GCC,Solaris / GCC和Solaris / Sol-Studio。

请参阅下表,了解将功能可见性设置为隐藏的效果概述。

结果

                                                     .dynsym|.symtab
System           Compiler     Visibility      nm     readelf           link-error
                                                     elfdump
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Linux Fedora 17  gcc-4.7.2    not specified   T      GLOBAL DEFAULT    no
Linux Fedora 17  gcc-4.7.2    attr-hidden     t      -|LOCAL DEFAULT   yes
Solaris 10       gcc-4.8      not specified   GLOB   GLOB D            no
Solaris 10       gcc-4.8      attr-hidden     LOCL   -|LOCL H          yes
Solaris 10       cc-12.3      attr-hidden     LOCL   -|LOCL H          yes
Solaris 10       cc-12.3      __hidden        LOCL   -|LOCL H          yes

方法

main.c中:

#include <stdio.h>
#include <stdlib.h>

#include "power3.h"
#include "power2.h"

int main(int argc, char **argv)
{
  printf("Result: %d\n", power3(atoi(argv[1])));
  // should result in a link error when symbol is hidden
  printf("Result: %d\n", power2(atoi(argv[1])));

  return 0;
}

power2.h:

#ifndef POWER2_H
#define POWER2_H

#if !defined(NO_HIDE)
  #if defined(__GNUC__) || defined(FORCE_GCC)
    __attribute__((visibility("hidden")))
    #warning Using GNU-C function attribute
  #elif defined(__SUNPRO_C)
    __hidden
    #warning Using SUNPRO-C qualifier
  #endif
#endif
int
// GCC attribute also possible here
    power2(int x);
#endif

power3.h:

#ifndef POWER3_H
#define POWER3_H
int power3(int x);
#endif

power3.c

#include "power3.h"
#include "power2.h"
int power3(int x)
{
  return power2(x)*x;
}

构建命令:

cc -g   -c -o main.o main.c
cc  -g -fpic -c -o power3.po power3.c
cc  -g -fpic -c -o power2.po power2.c
cc -shared -fpic -o libpower.so power3.po power2.po
cc -L$PWD -Wl,-R$PWD

反思:

在Linux下:

nm libpower.so | grep power
readelf --dyn-sym libpower.so | grep power
readelf -s libpower.so | grep 'FUNC.*power'

在Solaris下:

/usr/ccs/bin/nm libpower.so | grep 'FUNC.*power'
/usr/ccs/bin/elfdump -N .dynsym libpower.so | grep 'FUNC.*power'
elfdump -N .symtab libpower.so | grep 'FUNC.*power'

系统详情:

Solaris 10系统是SPARC计算机,GCC使用as中的ld / /usr/ccs/bin。 Solaris Studio版本为12.3,已应用修补程序(2013/02/04)。

来源

全球开关

为了完整性,功能(和其他符号)的可见性也会受到其他方式的影响:

GCC-method                            Sol equivalent     effect
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
#pragma GCC visibility push(hidden)   -                  everything between push/pop
#pragma GCC visibility pop            -                  has default visibility hidden
#pragma GCC visibility push(default)  -                  ~ default to default-visibility
#pragma GCC visibility pop            -
-fvisibility=hidden                   -xldscope=hidden   sets default visibility of
-fvisibility=default                  -xldscope=global   a translation unit

ELF标准还定义了内部和受保护的符号可见性 - 编译器也理解这些符号可见性,但一般来说它们不太有用。

答案 1 :(得分:3)

另一种选择是使用版本脚本文件。这适用于Linux,Solaris / GCC和Solaris / CC。

实施例

考虑一个共享库,其中只有一个函数power3()应该是全局可用的。它使用power2(),它在另一个翻译单元中定义,power2()应隐藏。

以下版本脚本指定了:

$ cat vscript
{
  global: power3;
  local: *;
};

您可以使用一个文件在Linux和Solaris上进行链接 - Linux / Solaris似乎理解相同的语法结构。

构建命令

System            Compiler   Link command
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Linux Fedora 17   gcc-4.7.2  cc -shared -Wl,--version-script,vscript -fpic -o libpower.so ...
Solaris 10        gcc-4.8*   gcc -shared -Wl,-M,vscript -fpic -o libpower.so ...
Solaris 10        cc 12.3    cc -shared -M vscript -fpic -o libpower.so ...

请注意,Solaris上的GCC配置为使用ld中的as / /usr/ccs/bin

答案 2 :(得分:2)

无法回答有关Solaris上的gcc可见性,但

在Sun Studio中有

  

编译器选项-xldscope,代码属性_ global / _hidden

根据http://lists.qt.nokia.com/public/qt-interest/2010-January/017893.html

http://qt.gitorious.org/qt/qt/merge_requests/433

  

SunStudio自版本8(CC版本5.5)以来,能够通过链接器选项控制ABI中的符号可见性

 -xldscope=[global|symbolic|hidden] 
  

并通过代码“属性”__global,__ symbolic&amp; __hidden。

-xldscope=global maps to GCC's -fvisibility=default 
-xldscope=symbolic maps to GCC's -fvisibility=protected 
-xldscope=hidden maps to GCC's -fvisibility=hidden

__global maps to GCC's __attribute__((visibility("default")) 
__symbolic maps to GCC's __attribute__((visibility("protected")) 
__hidden maps to GCC's __attribute__((visibility("hidden"))

Sun的概述:http://www.oracle.com/technetwork/server-storage/solaris/symbol-scope-140496.html

  

使用Sun Studio C / C ++缩小符号范围Giri Mandalika,2005年5月(2006年3月22日修订)