How To Write Shared Libraries(31)

2.2.5 Use Export Maps(2)

A DSO containing definitions for all these functions and members should only export the function foo and the destructor(s) of baz and baz::s. An export map to achieve this could look like this:
DSO定义和许多函数,只有foo和baz的destructor和baz::需要导出。一个相应的导出文件如下:

{
global:
    extern "C++" {
      foo*;
baz::baz*;
baz::s* };
local: *; };

The use of extern "C++" tells the linker to match the following patterns with demangled C++ names. The first entry foo* matches the first global function in the example. The second entry matches the constructor(s) of baz and the third entry matches the function baz::s.
使用extern "C++"标记使用c++命名语法处理。foo*匹配示例的第一个函数。第一个匹配baz的构造函数,第三个匹配baz::s.
Note that patterns are used in all cases.
没有匹配所有的情况。(待完善)
This is necessary since foo, baz::baz, and baz::s are not the complete names. The function parameter are also encoded in the mangled name and must be matched. It is not possible to match complete demangled C++ names since the current linker implementation refuses to allow non-alphanumeric characters. Using pattern might have unwanted effects. If there is another member function in baz starting with the letter ‘s’ it will also be exported. And one last oddity should be mentioned: currently the linker requires that there is no semicolon after the last entry in the C++ block.
这是必要的,因为foo、baz::baz、baz::s不是编译过程使用的名字。函数的参数也会编译到名字里需要匹配。不可能使用完整的编译名字,因为现在连接器允许非字母数字的字符。使用模式匹配可能有意外效果。如果baz中有其他s开头的函数也会导出。最后需要注意的是:现在的连接器要求没有分号。

Using export maps seems like a very desirable solution.
使用导出表似乎是一个不错的解决方案。
The sources do not have to be made less readable using attribute declarations or eventually pragmas.
不必使用属性声明或最终的语用来降低源的可读性。(有道翻译)
All the knowledge of the ABI is kept locally in the export map file. But this process has one fundamental problem: exactly because the sources are not modified the final code is not optimal. The linker is used only after the compiler already did its work and the once generated code cannot be optimized significantly.
所有的ABI相关的内容都在导出文件中。但是这样处理有一个基本问题:代码没有被修改,所有没有优化。连接器只用于在编译完成后使用,生成的代码不会优化到最佳。

In our running example the compiler must generate the code for the next function under the worst case scenario assumption that the variable last is exported. This means the code sequence using @GOTOFF which was mentioned before cannot be generated. Instead the normal two instruction sequence using @GOT must be generated.
在我们的示例中编译器必须假定会导出来处理函数next。这就意味着GOTOFF无法使用。使用GOT替代。

This is what the linker will see when it gets instructed to hide the symbol last. The linker will not touch the actual code. Code relaxation here would require substantial analysis of the following code which is in theory possible but not implemented. But the linker will not generate the normal R 386 GLOB DAT relocation either. Since the symbol is not exported no interposition is allowed. The position of the local definition relative to the start of the DSO is known and so the linker will generate a relative relocation.
这是使用隐藏语法时使用的指令。连接器不操作实际代码。代码关系分析理论可能,实际没有实现。但连接器不会生成一般的386 GLOB DAT。语法不会导出,没有指令。可能的本地调用关系在开始时了解,所有连接器生成一个关系重定位。

For function calls the result is often as good as it gets. The code generated by the compiler for a PC-relative jump and a jump through the PLT is identical. It is just the code which is called (the target function versus the code in the PLT) which makes the difference. The code is only not optimal in one case: if the function call is the only reason the PIC register is loaded. For a call to a local function this is not necessary and loading the PIC is just a waste of time and code.
对于函数调用,这样的结果再好不过。编译器生成代码带有pc跳转指令和一个PLT指令。只是调用目标有区别。只有一中情况没有优化:函数调用PIC寄存器。(待完善)本地函数这不必要,加载PIC至少浪费时间和代码空间。

To summarize, for variables the use of symbol maps creates larger and less efficient code, adds an entry in the GOT, and adds a relative relocation. For functions the generated code sometimes contains unnecessary loads of the PIC. One normal relocation is converted into a relative relocation and one PLT entry is removed. This is one relative relocation worse than the previous methods.
总结来说,变量使用map文件会输出更大的效率更低的代码,增加GOT和重定位。函数使用map文件输出一般代码有时包含不必要的PIC信息。普通的重定位转为关系定位,PLT移除。这种重定位若与之前的方法。
These deficiencies are the reason why it is much preferable to tell the compiler what is going on since after the compiler finished its work certain decisions cannot be re- verted anymore.
这些缺陷是为什么告诉编译器正在发生什么是更好的原因,因为在编译器完成它的工作后,某些决定不能再被逆转了。(有道翻译)

你可能感兴趣的:(How To Write Shared Libraries(31))