How To Write Shared Libraries(45)

2.5 Improving Generated Code(2)

Any solution must avoid the PIC register entirely. We propose two possible ways to improve the situation. First, do not use position-independent code. This will generate code like
解决方案必须阻止PIC。两个方案。第一个使用位置无关代码。生成代码如下:

getfoo:
  movl foo,%eax
  ret

The drawback is that the resulting binary will have text relocations. The page on which this code resides will not be sharable, the memory subsystem is more stressed because of this, a runtime relocation is needed, program startup is slower because of both these points, and security of the program is impacted. Overall, there is a measurable cost associated with not using PIC. This possibility should be avoided whenever possible.
缺点是程序执行代码重定位。代码所在页不能共享,内存尤其关注,运行时重定向,因此进程启动缓慢,影响安全性。使用PIC整体有一个可度量的时间消耗。尽量阻止。
If the DSO is question is only used once at the same time (i.e., there are no additional copies of the same program or other pro- grams using the DSO) the overhead of the copied page is not that bad. Only in case the page has to be evacuated from memory we would see measurable deficits since the page cannot simply be discarded, it must be stored in the disk swap storage.
如果DSO问题只在同一时间使用一次(即,没有使用DSO的相同程序或其他程序的额外副本),复制页面的开销就不会那么糟糕。只有在必须从内存中取出页面的情况下,我们才会看到可测量的缺陷,因为页面不能简单地丢弃,它必须存储在磁盘交换存储中。(有道翻译)

The second proposed solution has a bigger impact on the whole code. Assume this extended example:
第二种方案对代码影响更大。
假设示例如下:

static int foo;
static int bar;
int getfoo (void)
{ return foo; }
int getboth (void)
{ return bar+getfoo(); }

If this code gets translated as is, both functions will load the GOT address to access the global variables.
这里所有代码都需要加载GOT地址操作全局变量。
This can be avoided by putting all variables in a struct and passing the address of the struct to the functions which can use it.
这可以通过将所有变量放入结构体中并将结构体的地址传递给可以使用它的函数来避免。(有道翻译)
For instance, the above code could be rewritten as:
代码重写如下:

static struct globals {
  int foo;
int bar;
} globals;
static int intfoo (struct globals *g)
{ return g->foo; }
int getfoo (void)
{ return intfoo(&globals); }
int getboth (void)
{ return globals.bar+intfoo(&globals); }

The code generated for this example does not compute the GOT address twice for each call to getboth. The function intfoo uses the provided pointer and does not need the GOT address. To preserve the semantics of the first code this additional function had to be introduced; it is now merely a wrapper around intfoo.If it is possible to write the sources for a DSO to have all global variables in a structure and pass the additional parameter to all internal functions, then the benefit on IA-32 can be big.
示例代码不会计算两次的GOT地址。intfoo不需要GOT地址。为了保存语义增加的代码需要分析一下,和intfoo的包装合并了。如果DSO的源码有所有的全局变量,传递增加的参数到内部调用,这对于IA-32架构收益很大。

But it must be kept in mind that the code generated for the changed example is worse than what would be created for the original on most other architectures. As can be seen, in the x86-64 case the extra parameter to intfoo would be pure overhead since we can access global variables without the GOT value. On IA-64 marking getfoo as hidden would allow to avoid the PLT and therefore the gp register is not reloaded during the call to getfoo. Again, the parameter is pure overhead. For this reason it is questionable whether this IA-32 specific optimization should ever be performed. If IA-32 is the by far most important platform it might be an option.
但必须记住这样的修改多于其他架构的原有代码。可以看到,x86-64架构额外的参数开销,因为可以通过全局变量操作内不需要GOT。在IA-64标记getfoo为hidden阻止PLT,因此gp不需要重新加载。再次提醒,参数是纯开销。基于此IA-32是否执行特殊优化成为一个问题。如果IA-32架构比其他重要的多这是一个选择。

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