From 6e2d66347b065fd5a6ee1aa223bcc05b08edf952 Mon Sep 17 00:00:00 2001 From: Key_Zhang Date: Mon, 24 Oct 2016 18:29:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A0=A1=E5=AF=B9=E6=84=8F?= =?UTF-8?q?=E8=A7=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Misc/linkers.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Misc/linkers.md b/Misc/linkers.md index 0378eca..9f4b0ae 100644 --- a/Misc/linkers.md +++ b/Misc/linkers.md @@ -3,26 +3,26 @@ During the writing of the [linux-insides](http://0xax.gitbooks.io/linux-insides/content/) book I have received many emails with questions related to the [linker](https://en.wikipedia.org/wiki/Linker_%28computing%29) script and linker-related subjects. So I've decided to write this to cover some aspects of the linker and the linking of object files. -在写[linux-insides](http://0xax.gitbooks.io/linux-insides/content/)一书的过程中,我收到了很多邮件询问关于[链接器](https://zh.wikipedia.org/wiki/%E9%93%BE%E6%8E%A5%E5%99%A8)和链接器脚本的问题。所以我决定写这篇文章来介绍链接器和目标文件的链接方面的知识。 +在写 [linux-insides](http://0xax.gitbooks.io/linux-insides/content/) 一书的过程中,我收到了很多邮件询问关于[链接器](https://zh.wikipedia.org/wiki/%E9%93%BE%E6%8E%A5%E5%99%A8)和链接器脚本的问题。所以我决定写这篇文章来介绍链接器和目标文件的链接方面的知识。 If we open the `Linker` page on Wikipedia, we will see following definition: -如果我们打开维基百科的 `链接器` 页,我们将会看到如下描述: +如果我们打开维基百科的 `链接器` 页,我们将会看到如下定义: >In computer science, a linker or link editor is a computer program that takes one or more object files generated by a compiler and combines them into a single executable file, library file, or another object file. ->在计算机科学中,链接器(英语:Linker),又译为链接器、连结器,是一个程序,将一个或多个由编译器或汇编器生成的目标文件链接为一个可执行文件、库或另一个目标文件。 +>在计算机科学中,链接器(英文:Linker),是一个计算机程序,它将一个或多个由编译器生成的目标文件链接为一个单独的可执行文件,库文件或者另外一个目标文件 If you've written at least one program on C in your life, you will have seen files with the `*.o` extension. These files are [object files](https://en.wikipedia.org/wiki/Object_file). Object files are blocks of machine code and data with placeholder addresses that reference data and functions in other object files or libraries, as well as a list of its own functions and data. The main purpose of the linker is collect/handle the code and data of each object file, turning it into the final executable file or library. In this post we will try to go through all aspects of this process. Let's start. -如果你曾经用 C 写过至少一个程序,那你就已经见过以 `*.o` 扩展名结尾的文件了。这些文件是[目标文件](https://en.wikipedia.org/wiki/Object_file)。目标文件是一块块的机器码和数据,其数据包含了引用其他目标文件或库的数据和函数的占位符地址,也包括其自身的函数和数据列表。链接器的主要目的就是收集/处理每一个目标文件的代码和数据,将它们转成最终的可执行文件或者库。在这篇文章里,我们会试着研究一遍这个流程的各个方面。开始吧。 +如果你曾经用 C 写过至少一个程序,那你就已经见过以 `*.o` 扩展名结尾的文件了。这些文件是[目标文件](https://en.wikipedia.org/wiki/Object_file)。目标文件是一块块的机器码和数据,其数据包含了引用其他目标文件或库的数据和函数的占位符地址,也包括其自身的函数和数据列表。链接器的主要目的就是收集/处理每一个目标文件的代码和数据,将它们转成最终的可执行文件或者库。在这篇文章里,我们会试着研究这个流程的各个方面。开始吧。 链接流程 --------------- Let's create a simple project with the following structure: -让我们按以下结构创建一个项目 +让我们按以下结构创建一个项目: ``` *-linkers @@ -231,7 +231,7 @@ Disassembly of section .init: Not that it starts at the `0x00000000004003a8` address relative to the `glibc` code. We can check it also in the [ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) output by running `readelf`: -注意其开始于相对 `glibc`代码偏移 `0x00000000004003a8` 的地址。我们也可以运行 `readelf` ,在 [ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 输出中检查: +注意其开始于相对 `glibc` 代码偏移 `0x00000000004003a8` 的地址。我们也可以运行 `readelf` ,在 [ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 输出中检查: ``` $ readelf -d factorial | grep \(INIT\) @@ -528,7 +528,7 @@ main.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped and after this we link object files of our program with the needed system object files and libraries. We just saw a simple example of how to compile and link a C program with the `gcc` compiler and `GNU ld` linker. In this example we have used a couple command line options of the `GNU linker`, but it supports much more command line options than `-o`, `-dynamic-linker`, etc... Moreover `GNU ld` has its own language that allows to control the linking process. In the next two paragraphs we will look into it. -在这之后,我们用所需的系统目标文件和库连链接我们的程序。我们刚看了一个简单的关于如何用 `gcc` 编译器和 `GNU ld` 链接器编译和链接一个 C 程序的样例。在这个样例中,我们使用了一些 `GNU linker` 的命令行选项,但是除了 `-o`、`-dynamic-linker` 等,它还支持其他很多选项。此外,`GNU ld` 还拥有其自己的语言来控制链接过程。我们会在接下来两段深入。 +在这之后,我们用所需的系统目标文件和库连链接我们的程序。我们刚看了一个简单的关于如何用 `gcc` 编译器和 `GNU ld` 链接器编译和链接一个 C 程序的样例。在这个样例中,我们使用了一些 `GNU linker` 的命令行选项,但是除了 `-o`、`-dynamic-linker` 等,它还支持其他很多选项。此外,`GNU ld` 还拥有其自己的语言来控制链接过程。在接下来的两个段落中我们深入讨论。。 实用的 GNU 链接器命令行选项 ---------------------------------------------- @@ -551,7 +551,7 @@ The next command line option is `-b` or `--format`. This command line option spe The next command line option is `--defsym`. Full format of this command line option is the `--defsym=symbol=expression`. It allows to create global symbol in the output file containing the absolute address given by expression. We can find following case where this command line option can be useful: in the Linux kernel source code and more precisely in the Makefile that is related to the kernel decompression for the ARM architecture - [arch/arm/boot/compressed/Makefile](https://github.com/torvalds/linux/blob/master/arch/arm/boot/compressed/Makefile), we can find following definition: -下一个命令行选项是 `--defsym` 。该选项的完整格式是 `--defsym=symbol=expression` 。它允许在输出文件创建包含了由表达式给出了绝对地址的全局符号。在下面的例子中,我们会发现这个命令行选项很实用:在 Linux 内核源码中关于 ARM 架构内核解压的 Makefile - [arch/arm/boot/compressed/Makefile](https://github.com/torvalds/linux/blob/master/arch/arm/boot/compressed/Makefile),我们可以找到如下定义: +下一个命令行选项是 `--defsym` 。该选项的完整格式是 `--defsym=symbol=expression` 。它允许在输出文件中创建包含了由表达式给出了绝对地址的全局符号。在下面的例子中,我们会发现这个命令行选项很实用:在 Linux 内核源码中关于 ARM 架构内核解压的 Makefile - [arch/arm/boot/compressed/Makefile](https://github.com/torvalds/linux/blob/master/arch/arm/boot/compressed/Makefile),我们可以找到如下定义: ``` LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ) @@ -559,7 +559,7 @@ LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ) As we already know, it defines the `_kernel_bss_size` symbol with the size of the `.bss` section in the output file. This symbol will be used in the first [assembly file](https://github.com/torvalds/linux/blob/master/arch/arm/boot/compressed/head.S) that will be executed during kernel decompressing: -我们已经知道,其在输出文件中用 `.bss` 段的大小定义了 `_kernel_bss_size` 符号。这个符号将会作为第一个 [汇编文件](https://github.com/torvalds/linux/blob/master/arch/arm/boot/compressed/head.S) 在内核解压阶段被执行: +正如我们所知,其在输出文件中用 `.bss` 段的大小定义了 `_kernel_bss_size` 符号。这个符号将会作为第一个 [汇编文件](https://github.com/torvalds/linux/blob/master/arch/arm/boot/compressed/head.S) 在内核解压阶段被执行: ```assembly ldr r5, =_kernel_bss_size @@ -567,7 +567,7 @@ ldr r5, =_kernel_bss_size The next command line options is the `-shared` that allows us to create shared library. The `-M` or `-map ` command line option prints the linking map with the information about symbols. In our case: -下一个选项是 `-shared` ,其允许我们创建共享库。`-M` 或者说 `-map ` 命令行选项可以打印带符号信息的链接映射内容。在这里是: +下一个选项是 `-shared` ,其允许我们创建共享库。`-M` 或者说 `-map ` 命令行选项会打印带符号信息的链接映射内容。在这里是: ``` $ ld -M @linker.ld @@ -648,7 +648,7 @@ $ ld -o hello hello.o Our program consists from two sections: `.text` contains code of the program and `.data` contains initialized variables. Let's write simple linker script and try to link our `hello.asm` assembly file with it. Our script is: -我们的程序包含了两个段: `.text` 包含了程序的代码, `.data` 段包含了被初始化的变量。让我们写一个简单的链接脚本然后尝试用它来链接我们的 `hello.asm` 汇编文件。我们的脚本是: +我们的程序包含了两个段: `.text` 包含了程序的代码, `.data` 段包含了被初始化的变量。让我们写一个简单的链接脚本,然后尝试用它来链接我们的 `hello.asm` 汇编文件。我们的脚本是: ``` /* @@ -778,7 +778,7 @@ That's all. This is the end of the post about linkers. We learned many things about linkers in this post, such as what is a linker and why it is needed, how to use it, etc.. -这是关于链接器文章的结尾。在这篇文章中,我们已经学习了很多关于链接器的知识,比如什么是链接器、为什么需要他、如何使用它等等... +这是关于链接器文章的结尾。在这篇文章中,我们已经学习了很多关于链接器的知识,比如什么是链接器、为什么需要它、如何使用它等等... If you have any questions or suggestions, write me an [email](kuleshovmail@gmail.com) or ping [me](https://twitter.com/0xAX) on twitter.