How To Write Shared Libraries(21)

2 Optimizations for DSOs(2)

Which of the two options, -fpic or -fPIC, have to be used must be decided on a case-by-case basis. For some architectures there is no difference at all and people tend to be careless about the use. For most RISC there is a big difference. As an example, this is the code gcc generates for SPARC to read a global variable global when using -fpic:
必须根据具体情况决定必须使用-fpic还是-fpic。对于一些架构来说,根本没有区别,人们往往对其使用漫不经心。对于大多数RISC来说,有一个很大的区别。例如,这是gcc为SPARC在使用-fpic时读取全局变量global而生成的代码:(有道翻译)

sethi %hi(_GLOBAL_OFFSET_TABLE_-4),%l7 
call .LLGETPC0
add %l7,%lo(_GLOBAL_OFFSET_TABLE_+4),%l7 
ld [%l7+global],%g1
ld [%g1],%g1

And this is the code sequence if -fPIC is used:
这是使用-fPIC的代码:

sethi %hi(_GLOBAL_OFFSET_TABLE_-4),%l7 
call .LLGETPC0
add %l7,%lo(_GLOBAL_OFFSET_TABLE_+4),%l7 
sethi %hi(global),%g1
or %g1,%lo(global),%g1
ld [%l7+%g1],%g1
ld [%g1],%g1

In both cases %l7 is loaded with the address of the GOT first. Then the GOT is accessed to get the address of global. While in the -fpic case one instruction is suf- ficient, three instructions are needed in the -fPIC case. The -fpic option tells the compiler that the size of the GOT does not exceed an architecture-specific value (8kB in case of SPARC). If only that many GOT entries can be present the offset from the base of the GOT can be encoded in the instruction itself, i.e., in the ld instruc- tion of the first code sequence above. If -fPIC is used no such limit exists and so the compiler has to be pes- simistic and generate code which can deal with offsets of any size. The difference in the number of instructions in this example correctly suggests that the -fpic should be used at all times unless it is absolutely necessary to use -fPIC. The linker will fail and write out a message when this point is reached and one only has to recompile the code.
在这两种情况下,% 17首先加载GOT的地址。然后访问GOT以获得global的地址。在-fpic情况下一条指令就足够了,而在-fpic情况下需要三条指令。-fpic选项告诉编译器GOT的大小不会超过一个特定于体系结构的值(SPARC是8kB)。如果只有那么多GOT项可以出现,那么从GOT的基值开始的偏移量就可以编码在指令本身中,也就是说,在上面第一个代码序列的ld指令中。如果使用- fpic,则不存在这样的限制,因此编译器必须是类似于pes的,并生成可以处理任何大小偏移量的代码。本例中指令数的差异正确地表明-fpic应该在任何时候都使用,除非绝对需要使用-fpic。当到达此点时,链接器将失败并写出一条消息,只需重新编译代码。(有道翻译)

When writing assembler code by hand it is easy to miss cases where position independent code sequences must be used. The non-PIC sequences look and actually are simpler and more natural. Therefore it is extremely im- portant to in these case to check whether the DSO is marked to contain text relocations. This is easy enough to do:
当手工编写汇编代码时,很容易忽略必须使用位置独立的代码序列的情况。非pic序列看起来更简单、更自然。因此,在这种情况下,检查DSO是否标记为包含文本重定位是极其重要的。这很容易做到:(有道翻译)

readelf -d binary | grep TEXTREL

If this produces any output text relocations are present and one better starts looking what causes them.
如果这产生了任何输出文本重定位,那么最好开始看看是什么导致了它们。(有道翻译)

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