4

使用 GCC(在 Linux 上),我可以轻松地限制共享库中符号的可见性。

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

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

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

4

3 回答 3

4

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

使用 Solaris as/配置的 GCCld正确实现了 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 是

方法

主.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;
}

电源2.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

电源3.h:

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

电源3.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/ ldfrom /usr/ccs/bin。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 标准还定义了内部和受保护的符号可见性 - 编译器也可以理解,但通常不太有用。

于 2013-05-28T14:07:22.133 回答
3

另一种选择是使用版本脚本文件。这适用于 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 配置为使用ld/ asfrom /usr/ccs/bin

于 2013-05-28T16:41:09.790 回答
2

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

在太阳工作室有

编译器选项 -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

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

于 2013-05-27T10:21:11.740 回答