如何使用__attribute __((visibility("default"))))? [英] How to use the __attribute__((visibility("default")))?

查看:433
本文介绍了如何使用__attribute __((visibility("default"))))?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很明显,在GNU Wiki中阅读可见性.

Reading Visibility in the GNU wiki, it is clear.

从C ++教程中获取示例

Taking this example from C++ Tutorials

// classes example
#include <iostream>
using namespace std;

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    int area() {return width*height;}
};

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

是否可以如第一个链接中所示公开area()set_values(int,int)本地而不更改代码?

Is it possible to make area() public and set_values(int,int) local as shown in the first link without altering the code?

我写了我的makefile来获取.so

I wrote my makefile to get the .so

someproj.so : someproj.cpp
    g++ --std=c++11 -O3 -fPIC -shared someproj.cpp -o someproj.so

修改为通过添加-fvisibility=hidden

someproj.so : someproj.cpp
    g++ --std=c++11 -O3 -fvisibility=hidden -fPIC -shared someproj.cpp -o someproj.so

是否可以通过修改上面的编译命令来自定义公开哪些功能?

Is it possible to customized which functions are exposed by modifying the compilation command above?

当前使用的是gcc的4.7.2版本

Currently using 4.7.2 version of gcc

推荐答案

是否可以通过修改上面的编译命令来自定义公开哪些功能?

Is it possible to customize which functions are exposed by modifying the compilation command above?

不.编译选项 -fvisibility=[default|internal|hidden|protected] (请注意,这不是 链接选项)使编译器将指定的动态可见性类型分配给 all 全局符号 在编译单元 中生成的,通过反补贴__attribute__((visibility(....)))明确排除的那些 在源代码中应用 .这使您可以回答其他问题:

No. Compilation option -fvisibility=[default|internal|hidden|protected] (and note it is not a linkage option) makes the compiler attribute the specified dynamic visibility type to all global symbols generated in the compilation unit except those that are specifically excluded by having a countervailing __attribute__((visibility(....))) applied in the source code. Which makes the answer to your other question:

是否可以如第一个链接中所示将area()公共和set_values(int,int)设为本地,而无需更改代码?

Is it possible to make area() public and set_values(int,int) local as shown in the first link without altering the code?

也没有.

如何更改源代码以动态生成Rectangle::area() 可见,而所有其他全局符号都被-fvisibility=hidden隐藏以进行动态链接? 这是一个演练:

How would you change the source code to make Rectangle::area() dynamically visible while all other global symbols are hidden for dynamic linkage by -fvisibility=hidden? Here is a walk-through:

让我们开始:

rectangle.cpp(1)

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    int area() {return width*height;}

};

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

并简单地将其编译为PIC rectangle.o这样:

and simply compile it to a PIC rectangle.o so:

$ g++ -Wall -c -fPIC rectangle.cpp

然后检查全局符号表:

$ nm -C rectangle.o
0000000000000000 T Rectangle::set_values(int, int)

请注意,没有Rectangle::area.不适用于 链接完全,因此就不会出现其动态可见性的问题.

Note that Rectangle::area isn't there. It's not available for linkage at all, so the question of its dynamic visibility just does not arise.

那是因为它在类定义中定义为 inline 且从未调用 在编译单元中,因此gcc甚至不需要编译其定义.它消失了 来自目标文件.

That is because it is defined inline in the class definition and never called in the compilation unit, so gcc need not even compile its definition. It vanishes from the object file.

Rectangle::set_values没有内联定义,因此编译器 发出全局符号和定义.

Rectangle::set_values, on the other hand, is not defined inline, so the compiler emits a global symbol and definition.

要使Rectangle::area符合某些可见性类型的条件,我们首先需要 通过未内联定义它来成为全局符号:

To make Rectangle::area eligible for some visibility type, we first need to make it a global symbol by not defining it inline:

rectangle.cpp(2)

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    int area();

};

int Rectangle::area() {return width*height;}

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

重新编译并再次检查全局符号表:

Recompile and again check the global symbol table:

$ g++ -Wall -c -fPIC rectangle.cpp
$ nm -C rectangle.o
000000000000001a T Rectangle::set_values(int, int)
0000000000000000 T Rectangle::area()

好.现在出现Rectangle::area的全局定义.

Good. Now a global definition of Rectangle::area appears.

接下来,让我们从rectangle.o创建一个共享库librectangle.so:

Next let's make a shared library librectangle.so from rectangle.o:

$ g++ -o librectangle.so --shared rectangle.o

以下是其全局符号表中的Rectangle::*符号:

Here are the Rectangle::* symbols in its global symbol table:

$ nm -C librectangle.so | grep 'Rectangle::'
00000000000005d4 T Rectangle::set_values(int, int)
00000000000005ba T Rectangle::area()

这是 dynamic 符号表中的Rectangle::*符号:

$ nm -CD librectangle.so | grep 'Rectangle::'
00000000000005d4 T Rectangle::set_values(int, int)
00000000000005ba T Rectangle::area()

它们是相同的.

现在让我们隐藏那些用于动态链接的符号.我们需要重新编译 rectangle.cpp 然后重新链接共享库:

Now let's hide those symbols for dynamic linkage. We need to recompile rectangle.cpp then relink the shared library:

$ g++ -Wall -c -fPIC -fvisibility=hidden rectangle.cpp
$ g++ -o librectangle.so --shared rectangle.o

这又是全局符号表中的Rectangle::*符号:

Here again are the Rectangle::* symbols now in the global symbol table:

$ nm -C librectangle.so | grep 'Rectangle::'
0000000000000574 t Rectangle::set_values(int, int)
000000000000055a t Rectangle::area()

它们和以前一样.

这是 dynamic 符号表中的Rectangle::*符号:

$ nm -CD librectangle.so | grep 'Rectangle::'; echo Done
Done

由于-fvisibility=hidden,现在没有 .

最后,让我们动态显示Rectangle::area,让所有内容 其他全局符号动态隐藏.我们需要更改源代码 再次:

Finally, let's make just Rectangle::area dynamically visible, keeping all the other global symbols dynamically hidden. We need to change the source code again:

rectangle.cpp(3)

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    __attribute__((visibility("default"))) int area();

};

int Rectangle::area() {return width*height;}

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

然后重新编译并重新链接:

Then recompile and relink:

$ g++ -Wall -c -fPIC -fvisibility=hidden rectangle.cpp
$ g++ -o librectangle.so --shared rectangle.o

全局符号表仍显示:

$ nm -C librectangle.so | grep 'Rectangle::'
00000000000005a4 t Rectangle::set_values(int, int)
000000000000058a T Rectangle::area()

动态符号表仅显示:

$ nm -CD librectangle.so | grep 'Rectangle::'
000000000000058a T Rectangle::area()

Rectangle::area现在是共享库公开的唯一符号 动态链接.

Rectangle::area is now the only symbol that the shared library exposes for dynamic linkage.

在您开始之前...

关于以下内容的另一件事:

One thing more about:

是否可以如第一个链接中所示将area()公共和set_values(int,int)设为本地,而无需更改代码?

Is it possible to make area() public and set_values(int,int) local as shown in the first link without altering the code?

隐藏用于动态链接的符号不会使其成为 local .动态可见性(默认|内部|隐藏|受保护) 是仅 global 符号的属性.出于链接目的, local 符号不存在.唯一的方法 将符号设置为局部符号,否则将是全局符号:-

Making a symbol hidden for dynamic linkage doesn't make it local. Dynamic visibility (default|internal|hidden|protected) is an attribute of global symbols only. For linkage purposes, local symbols don't exist. The only ways to make a symbol local that would otherwise be global are:-

  • In C or C++ source, qualify its definition with the static keyword
  • In C++ source, enclose its definition in an anonymous namespace

然后,该符号不会出现在全局或动态符号表中.

Then the symbol does not appear in the global, or dynamic, symbol tables.

这篇关于如何使用__attribute __((visibility("default"))))?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆