【问题标题】:Limiting shared library symbol visibility on Solaris限制 Solaris 上的共享库符号可见性
【发布时间】:2013-05-22 03:30:43
【问题描述】:

使用 GCC(在 Linux 上)我可以轻松地 limit visibility symbols in shared 库。

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

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

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

【问题讨论】:

    标签: linker shared-libraries solaris visibility


    【解决方案1】:

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

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

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

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

    结果

    .dynsym|.symtab 系统编译器可见性 nm readelf 链接错误 精灵转储 ―――――――――――――――――――――――――――――――――――――――――――――――― ―――――――――――――――――――――――――――――――― Linux Fedora 17 gcc-4.7.2 未指定 T GLOBAL DEFAULT no Linux Fedora 17 gcc-4.7.2 attr-hidden t -|LOCAL DEFAULT 是 未指定 Solaris 10 gcc-4.8 GLOB GLOB D 否 Solaris 10 gcc-4.8 attr-hidden LOCL -|LOCL H 是 Solaris 10 cc-12.3 attr-hidden LOCL -|LOCL H 是 Solaris 10 cc-12.3 __hidden LOCL -|LOCL H 是

    方法

    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 使用来自/usr/ccs/binas/ld。 Solaris Studio 版本是 12.3,应用了补丁 (2013/02/04)。

    来源

    全局开关

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

    GCC-method Sol等效效果 ―――――――――――――――――――――――――――――――――――――――――――――――― ―――――――――――――――――――――――――――――――――― #pragma GCC 可见性 push(hidden) - push/pop 之间的一切 #pragma GCC visibility pop - 隐藏默认可见性 #pragma GCC 可见性推送(默认) - ~ 默认为默认可见性 #pragma GCC 可见性弹出 - -fvisibility=hidden -xldscope=hidden 设置默认可见性 -fvisibility=default -xldscope=global 一个翻译单元

    ELF 标准还定义了内部和受保护的符号可见性 - 编译器也可以理解,但通常不太有用。

    【讨论】:

    • Solaris Studio 版本支持 gcc 属性的一个子集,并且该子集在不同版本之间不断增长,因此如果您在代码库中执行此操作,可能需要检查 Studio 版本使用不同版本的编译器进行编译。例如see X.Org's X11/Xfuncproto.h header checks for __attribute((noreturn)).
    • 看起来__attribute__((visibility("default"))) 的行为与编译器手册似乎指出的__global 不同。后者在使用-xldscope=hidden 时仍然将其导出为全局符号,但前者似乎等同于根本不指定属性。
    • 奇怪的是,当您使用该属性和 -xldscope=hidden 编译时不使用链接时,GNU nm 将符号视为全局符号,但在将其链接到库后,符号变为本地符号,而我我不完全确定为什么。
    【解决方案2】:

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

    示例

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

    以下版本脚本指定:

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

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

    构建命令

    系统编译器链接命令 ―――――――――――――――――――――――――――――――――――――――――――――――― ―――――――――――――――――――――――――――――――――――――――――― 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 配置为使用来自 /usr/ccs/binld/as

    【讨论】:

    • 它有效,我喜欢它是可能的,但我完全期望-xldscope=hidden 至少部分等同于这样做。编译器手册声称它是一个链接器标志,但我通过运行单独的编译/链接步骤(每个都有这个标志)进行了测试;编译步骤使用该标志,但链接步骤不会将任何不同的东西传递给链接器。
    【解决方案3】:

    无法回答有关 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 和 __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 日修订)

    【讨论】:

      猜你喜欢
      • 2022-01-22
      • 2021-07-27
      • 2022-01-08
      • 2014-12-07
      • 2019-08-02
      • 1970-01-01
      • 2020-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多