How To Write Shared Libraries(24)

2.2.1 Use static

The easiest way to not export a variable or function is to define it with file-local scope. In C and C++ this is done by defining it with static, in C++ additionally using anonymous namespaces. This is for many people obvious but unfortunately not for all. Many consider adding static as optional. This is true when considering only the C semantics of the code.
最容易的处理方式是把函数和变量都设置为文件内部可见。在c/c++使用static实现,在c++中还可以通过匿名命名空间实现。这对一些人来说很熟悉,但不是所有人都熟悉。许多人认为static是可选项。对于c语法来说确实如此。

If in our example neither last or next are needed outside the file we can change the source to:
在示例代码中如果last和next都不需要导出,修改如下:

static int last;
static int next (void) {
  return ++last;
}
int index (int scale) {
  return next () << scale;
}

Compiled in the same way as before we see that all the relocations introduced by our example code vanished. I.e., we are left with six relocations and three PLT entries. The code to access last now looks like this:
和之前同样的方式编译发现重定位消失了。剩下6个重定位和3个PLT。操作last的代码样式如下:

movl  last@GOTOFF(%ebx), %eax
incl  %eax
movl  %eax, last@GOTOFF(%ebx)

The code improved by avoiding the step which loads the address of the variable from the GOT. Instead, both mem- ory accesses directly address the variable in memory. At link-time the variable location has a fixed offset from the PIC register, indicated symbolically by last@GOTOFF. By adding the value to the PIC register value we get the address of last. Since the value is known at link-time this construct does not need a relocation at run-time.
代码通过减少一个变量从GOT定位的过程提高了性能。替换为直接操作相应变量内存地址。链接时变量地址是在栈针地址上直接添加一个固定的偏移地址,通过last@GOTOFF标识。通过增加偏移获取变量地址。由于这个值在链接时已知所有无需重定位过程。

The situation is similar for the call to next. The IA-32 architecture, like many others, knows a PC-relative ad- dressing mode for jumps and calls. Therefore the com- piler can generate a simple jump instruction
调用next的过程类似。IA-32架构和其他一些一样,使用PC-relative地址模式跳转调用指令。因此编译器简单生成一个跳转指令

 call next

and the assembler generates a PC-relative call. The dif- ference between the address of the instruction following the call and the address of next is constant at link-time and therefore also does not need any relocation. Another advantage is that, in the case of IA-32, the PIC register does not have to be set up before the jump. If the com- piler wouldn’t know the jump target is in the same DSO the PIC register would have to be set up. Other architec- tures have similar requirements.
汇编器生成一个PC-relative 调用。不同点在于next是一个常量地址,链接时不需要重定位过程。另一个提高是,在IA-32架构中PIC register在跳转前不需要设置。如果编译器不知道跳转的目标地址需要设置PIC register。其他架构有相似的实现。

The generated code is optimal. The compiler might even consider inlining some code if it finds that this is bene- ficial. It is always advised that the programmer places the various variable and function definitions in the same file as the references and then define the referenced ob- jects as static. When generating the production bina- ries it might even be desirable to merge as many input files as possible together to mark as many objects as pos- sible static. Unless one is comfortable with one giant file there is a limit on how many functions can be grouped together. It is not necessary to continue the process ad in- finitum since there are other ways to achieve the same result (minus inlining).
这样生成的代码是优化过的。编译器甚至在任务优化的点生成一些内联实现。建议开发者总是定位变量和函数为static,只在本文件中使用。当生成二进制文件时总是希望更多的static文件合并。除非超过函数组织的个数限制。并不总是需要使用这种方式,除了内联还有其他方式可以实现优化。

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