链接器和链接过程概览


 
 
开发者在c/c++源文件和头文件中编写程序。部分程序可用汇编编写,并放在相应的汇编源文件中。开发者为make工具创建一个makefile文件,这样可以轻松追踪文件的修改并根据需要调用编译器和汇编器重新build源文件。编译器和汇编器从这些源文件中生成包含机器码和程序数据的目标文件。归档工具连接一组目标文件形成一个库。链接器把这些目标文件作为输入并生成一个可执行映像或是可被用于和其他目标文件链接的目标文件。链接器命令文件指示链接器怎样组合目标文件以及把二进制码和数据放在目标嵌入式系统的哪个位置。
 
链接器的主要功能是把多个目标文件组合成一个更大的可重定位的目标文件、一个共享目标文件或是一个最终的可执行映像。在一个典型的程序里,一个源文件中的一段代码可引用另一个源文件中定义的变量。一个函数在某个源文件中可调用另一个源文件中的函数。这些全局变量和非静态函数就是通常所说的全局符号。在源文件中,这些符号有不同的名称。在最终的可执行二进制映像中,一个符号对应一个内存中的地址。这个内存地址的内容是变量的数据或者是函数的可执行代码。
 
编译器创建一个包含符号名到地址的映射的符号表作为它生成的目标文件的一部分。当创建可重定位的输出文件时,编译器为每个符号生成一个与被编译文件相关的地址。因此,这些地址是按照0偏移量生成的。符号表包含定义在被编译文件中的全局符号以及在此文件中被引用的外部符号,这些外部符号要由链接器解析。由链接器执行的链接过程调用符号解析和符号重定位。
 
符号解析是这样一个过程:链接器进入每个目标文件并为该目标文件检查其外部符号在哪个或哪些其他目标文件中定义的。有时,当链接器试图解析所有的外部符号时,它必须多次处理这些目标文件。若外部符号定义在一个静态库中,链接器将从库中复制目标文件并写入最终的映像(静态链接)。
 
符号重定位是链接器把一个符号引用映射到它的定义的过程。链接器修改被链接目标文件的机器代码,以便对应于那些符号的代码反映出分配给这些符号的实际地址。对于很多符号,在多个目标文件被合并后,它的相对偏移量就变了。符号重定位要求代码修改,因为链接器调整引用这些符号机器的代码来反映它们最终的地址。重定位表告诉链接器在程序代码中哪里要求重定位。重定位表中的每个入口包含一个对符号表的引用。链接器可以使用这个引用检索符号的实际地址并把它用于程序中那个由重定位入口指定的位置。对于重定位表,同时包含符号地址和重定位入口信息是可以的,这种情况下就没有重定位表和符号表之间的引用了。
 
对于可执行映像,所有的外部符号必须被解析以便每个符号有一个绝对的内存地址,因为可执行映像是准备执行的。也有例外,那些符号如果被定义在共享库中将依然包含相对地址。这些符号将在运行时解析(动态链接)。

2.2 Overview of Linkers and the Linking Process

Figure 2.2 illustrates how different tools take various input files and generate appropriate output files to ultimately be used in building an executable image.

Click To expand
Figure 2.2: Creating an image file for the target system.

The developer writes the program in the C/C++ source files and header files. Some parts of the program can be written in assembly language and are produced in the corresponding assembly source files. The developer creates a makefile for the make utility to facilitate an environment that can easily track the file modifications and invoke the compiler and the assembler to rebuild the source files when necessary. From these source files, the compiler and the assembler produce object files that contain both machine binary code and program data. The archive utility concatenates a collection of object files to form a library. The linker takes these object files as input and produces either an executable image or an object file that can be used for additional linking with other object files. The linker command file instructs the linker on how to combine the object files and where to place the binary code and data in the target embedded system.

The main function of the linker is to combine multiple object files into a larger relocatable object file, a shared object file, or a final executable image. In a typical program, a section of code in one source file can reference variables defined in another source file. A function in one source file can call a function in another source file. The global variables and non-static functions are commonly referred to as global symbols. In source files, these symbols have various names, for example, a global variable called foo_bar or a global function called func_a. In the final executable binary image, a symbol refers to an address location in memory. The content of this memory location is either data for variables or executable code for functions.

The compiler creates a symbol table containing the symbol name to address mappings as part of the object file it produces. When creating relocatable output, the compiler generates the address that, for each symbol, is relative to the file being compiled. Consequently, these addresses are generated with respect to offset 0. The symbol table contains the global symbols defined in the file being compiled, as well as the external symbols referenced in the file that the linker needs to resolve. The linking process performed by the linker involves symbol resolution and symbol relocation.

Symbol resolution is the process in which the linker goes through each object file and determines, for the object file, in which (other) object file or files the external symbols are defined. Sometimes the linker must process the list of object files multiple times while trying to resolve all of the external symbols. When external symbols are defined in a static library, the linker copies the object files from the library and writes them into the final image.

Symbol relocation is the process in which the linker maps a symbol reference to its definition. The linker modifies the machine code of the linked object files so that code references to the symbols reflect the actual addresses assigned to these symbols. For many symbols, the relative offsets change after multiple object files are merged. Symbol relocation requires code modification because the linker adjusts the machine code referencing these symbols to reflect their finalized addresses. The relocation table tells the linker where in the program code to apply the relocation action. Each entry in the relocation table contains a reference to the symbol table. Using this reference, the linker can retrieve the actual address of the symbol and apply it to the program location as specified by the relocation entry. It is possible for the relocation table to contain both the address of the symbol and the information on the relocation entry. In this case, there is no reference between the relocation table and the symbol table.

Figure 2.3 illustrates these two concepts in a simplified view and serves as an example for the following discussions.

Click To expand
Figure 2.3: Relationship between the symbol table and the relocation table.

For an executable image, all external symbols must be resolved so that each symbol has an absolute memory address because an executable image is ready for execution. The exception to this rule is that those symbols defined in shared libraries may still contain relative addresses, which are resolved at runtime (dynamic linking).

A relocatable object file may contain unresolved external symbols. Similar to a library, a linker-reproduced relocatable object file is a concatenation of multiple object files with one main difference—the file is partially resolved and is used for further linking with other object files to create an executable image or a shared object file. A shared object file has dual purposes. It can be used to link with other shared object files or relocatable object modules, or it can be used as an executable image with dynamic linking.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值