分享

Introduction to PIC

 oskycar 2014-03-27
Introduction to PIC - (Position Independent Code)
地址无关代码


看到一篇以前不太懂的东西,于是顺手翻译在这儿(不知道是翻译的问题还是别的,发现中文还真是精炼:)。

只是基本的入门知识。



src: http://www./proj/en/hardened/pic-guide.xml



PIC code radically differs from conventional code in the way it calls functions and operates on data variables.

位置无关代码在函数调用和数据访问方面和传统代码有本质上的区别。



It will access these functions and data through an indirection table, the "Global Offset Table" (GOT), by software convention accessible using the reserved name "_GLOBAL_OFFSET_TABLE_".

The exact mechanism used for this is hardware architecture dependent, but usually a special machine register is reserved for setting up the location of the GOT when entering a function.

The rationale behind this indirect addressing is to generate code that can be independently accessed of the actual load address.

位置无关代码通过“全局偏移表”(按照惯例一般会使用_GLOBAL_OFFSET_TABLE_的保留名称)间接访问函数和数据。这种方法一般是依赖与硬件的,但是通常都是使用一个特殊的寄存器去存放“全局偏移表”的位置。我们利用这种机制产生与虚拟装载地址无关的二进制代码。



In a true PIC library without relocations in the text segment, only the symbols exported in the "Global Offset Table" need updating at run-time depending on the current load address of the various shared libraries in the address space of the running process.

在一个无需对代码段进行重定位的PIC库,只有GOT中的符号需要在运行时进行更新。更新的时候根据当前进程的地址空间中的其他的共享库的装载地址来进行。



Likewise, procedure calls to globally defined functions are redirected through the "Procedure Linkage Table" (PLT) residing in the data segment of the core image. Again, this is done to avoid run-time modifications to the text segment.

同样,全局函数调用也被内核映像数据段中的“过程链接表”进行了重定向。这同样也是为了避免在运行时对代码段进行重定位。



The linker-editor allocates the Global Offset Table and Procedure Linkage Table when combining PIC object files into an image suitable for mapping into the process address space. It also collects all symbols that may be needed by the run-time link-editor and stores these along with the image's text and data bits. Another reserved symbol, _DYNAMIC is used to indicate the presence of the run-time linker structures. Whenever _DYNAMIC is relocated to 0, there is no need to invoke the run-time link- editor. If this symbol is non-zero, it points at a data structure from which the location of the necessary relocation- and symbol information can be derived. This is most notably used by the start-up module, crt0, crt1S and more recently Scrt1. The _DYNAMIC structure is conventionally located at the start of the data segment of the image to which it pertains.

当把一个PIC代码链接到一个映像中时,连接器(linker-editor)为负责GOT和PLT的空间分配和其他工作。同时,连接器将所有可能被运行连接器需要的符号存储起来。另外还有一个保留符号_DYNAMIC,用来指明是否需要运行连接器。0代表不需要,非0时指向一个重定位时必须的数据结构。通常在crt0,crt1S(?), Scrt1等代码块中可以看到这种情况。按照管理,_DYNAMIC会放到数据段的开始位置。



On most architectures, when you compile source code to object code, you need to specify whether the object code should be position independent or not. There are occasional architectures which don't make the distinction, usually because all object code is position independent by virtue of the Application Binary Interface (ABI), or less often because the load address of the object is fixed at compile time, which implies that shared libraries are not supported by such a platform). If an object is compiled as position independent code (PIC), then the operating system can load the object at any address in preparation for execution. This involves a time overhead, in replacing direct address references with relative addresses at compile time, and a space overhead, in maintaining information to help the runtime loader fill in the unresolved addresses at runtime. Consequently, PIC objects are usually slightly larger and slower at runtime than the equivalent non-PIC object. The advantage of sharing library code on disk and in memory outweigh these problems as soon as the PIC object code in shared libraries is reused.

在一般的平台上,当你进行编译时,需要指定PIC的选项,很少有平台会忽略这种差异。一般而言,大部分的代码都是位置无关的,很少情况下代码是位置相关的,代码相关也就意味着在这个平台上不支持共享库。为了位置无关性,需要增加相应的全局位置信息以及在运行时对这些信息进行调整,因此PIC会轻微增加代码空间和时间代价,但是共享库的复用带来的好处大大超过了这些。



PIC compilation is exactly what is required for objects which will become part of a shared library. Consequently, libtool builds PIC objects for use in shared libraries and non-PIC objects for use in static libraries. Whenever libtool instructs the compiler to generate a PIC object, it also defines the preprocessor symbol, `PIC', so that assembly code can be aware of whether it will reside in a PIC object or not.

对库而言,位置关联性非常重要,通常,建库工具使用PIC代码建立共享库,非PIC代码建立静态库。当建库工具调用编译器去编译时会指定是否需要PIC的编译选项,因此汇编代码需要注意这点。



Typically, as libtool is compiling sources, it will generate a `.lo' object, as PIC, and a `.o' object, as non-PIC, and then it will use the appropriate one of the pair when linking executables and libraries of various sorts. On architectures where there is no distinction, the `.lo' file is just a soft link to the `.o' file.

在一个典型系统中,一个建库工具会生成两中库,PIC代码(.lo),以及非PIC代码(.o),在链接的时候会根据不同的情况进行选择。在不进行区分PIC的平台上,'.lo'只是'.o'的一个软链接。



In practice, you can link PIC objects into a static archive for a small overhead in execution and load speed, and often you can similarly link non-PIC objects into shared archives.

实际情况中,你可以将PIC代码链接到一个静态库中,这样会代码空间和效率上一些轻微的损失。同样,也可以将非PIC代码链接到共享库。



When you use position-independent code, relocatable references are generated as an indirection that use data in the shared object's data segment. The text segment code remains read-only, and all relocation updates are applied to corresponding entries within the data segment.

当使用位置无关代码时,需要重定位的项被作为引用产生以进行间接访问,这些项被放置在共享库的数据段中。代码段保持只读,所有重定位的结果会更新数据段中的相应项。



If a shared object is built from code that is not position-independent, the text segment will usually require a large number of relocations to be performed at runtime. Although the runtime linker is equipped to handle this, the system overhead this creates can cause serious performance degradation.

如果一个共享库中包含非PIC代码,代码段在运行时将需要进行大量的重定位工作,运行时连接器会完成这项工作,这可能将带来比较严重的性能问题。



You can identify a shared object that requires relocations against its text segment using tools such as 'readelf -d foo' and inspect the output for any TEXTREL entry. The value of the TEXTREL entry is irrelevant. Its presence in a shared object indicates that text relocations exist.

你可以使用工具比如‘readelf -d foo’去分别一个共享库是否需要进行重定位,检查任何和代码段相关项的输出,如果这些项的值是不相关,着表明这个共享库需要进行重定位。(????) 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多