CSAPP:第7章 链接 今天药忘吃喽~ 2022-10-29 04:30 74阅读 0赞 ### CSAPP:第7章 链接 ### ### 文章目录 ### * * * CSAPP:第7章 链接 * * 7.1 编译器驱动程序 * 7.2 静态链接 * 7.3 目标文件 * 7.4 可重定位目标文件 * 7.5 符号和符号表 * 7.6 符号分析 * * 7.6.1 链接器如何解析多重定义的全局符号 * 7.6.2 与静态库链接 * 7.6.3 链接器如何使用静态库来解析引用 * 7.7 重定位 * * 7.7.1 重定位条目 * 7.7.2 重定位符号引用 * 7.8 可执行目标文件 * 7.9 加载可执行目标文件 * 7.10 动态链接共享库 * 7.11 从应用程序中加载和链接共享库 * 7.12 位置无关代码 * 7.13 库打桩机制 * * 7.13.1 编译时打桩 * 7.13.2 链接时打桩 * 7.13.3 运行时打桩 * 7.14 处理目标文件的工具 * 补充:elf文件内容 * 链接(linking)是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载(复制)到内存并执行。 * 可以帮助 * 构造大型程序 * 避免一些编程错误 * 理解语言的作用域是如何实现的 * 理解其他系统概念 * 利用共享库 #### 7.1 编译器驱动程序 #### * 下图展示了GCC中编译链接的过程 * ![image-20210207112325286][] linux> gcc -Og -o prog main.c sum.c # 调用gcc命令相当于调用如下: linux> cpp [otherarguments] main.c /tmp/main.i # 翻译成ASICC中间文件 linux> ccl /tmp/main.i -Og [other arguments] -o /tmp/main.s # 翻译成ASICC汇编语言文件 linux> as Mother arguments] -o /tmp/main.o /tmp/main.s # 可重定位目标文件(relo¬catable object file) linux> Id -o prog [system object files and args] /tmp/main.o /tmp/sum.o # 可执行目标文件(executable ob¬ject file)prog # 最后可以运行可执行文件,shell用到加栽器(loader),将代码和数据复制到内存,然后将控制转到程序入口 linux> ./prog #### 7.2 静态链接 #### * 链接器必须完成两个主要任务 * 符号解析(symbol resolution):目标文件定义和引用符号,每个符号对应于一个函数、一个全局变量或一个静态变量(即 C 语言中任何以 static 属性声明的变量)。符号解析的目的是将每个符号引用正好和一个符号定义关联起来。 * 重定位(relocation):编译器和汇编器生成从地址 0 开始的代码和数据节。链接器通过把每个符号定义与一个内存位置关联起来,从而重定位这些节,然后修改所有对这些符号的引用,使得它们指向这个内存位置。 #### 7.3 目标文件 #### * 可重定位目标文件。 * 包含二进制代码和数据,其形式可以在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件。 * 可执行目标文件。 * 包含二进制代码和数据,其形式可以被直接复制到内存并执行。 * 共享目标文件。 * 一种特殊类型的可重定位目标文件,可以在加载或者运行时被动态地加载进内存并链接。 #### 7.4 可重定位目标文件 #### * ![image-20210207115125628][] \- .text:已编译程序的机器代码。 - .rodata:只读数据。 - .data:已初始化的全局和静态 C 变量。 - .bss:未初始化的全局和静态 C 变量,以及所有被初始化为 0 的全局或静态变量。 - .symtab:一个符号表,它存放在程序中定义和引用的函数和全局变量的信息。 - .rel.text:一个 .text 节中位置的列表,当链接器把这个目标文件和其他文件组合时,需要修改这些位置。 - .rel.data:被模块引用或定义的所有全局变量的重定位信息。 - .debug:一个调试符号表,其条目是程序中定义的局部变量和类型定义,程序中定义和引用的全局变量,以及原始的 C 源文件。 - .line: 原始 C 源程序中的行号和 .text 节中机器指令之间的映射。 - .strtab:一个字符串表,其内容包括 .symtab 和.debug 节中的符号表,以及节头部中的节名字。 * 在描述下面内容之前,我编译了一下示例代码,并查看了elf文件(有两个,分别是main.o的代码,以及a.out的代码,可用下面的指令的到),暂时就以这个为例: //main.c int sum(int *a, int n); int array[2] = { 1,2}; int main(){ int val = sum(array,2); return val; } //sum.c int sum(int *a, int n){ int i,s = 0; for(i=0; i<n; i++){ s += a[i]; } return s; } * 具体elf信息将在末尾补充,下面是指令 # main.o (base) [root@VM_0_4_centos csapp]# gcc -Og -c main.c (base) [root@VM_0_4_centos csapp]# readelf -a -x .text -x .data main.o ------------------------------ # a.out (base) [root@VM_0_4_centos csapp]# gcc -Og main.c sum.c (base) [root@VM_0_4_centos csapp]# ls a.out main.c main.o main.s mstore.c mstore.o mstore.s sum.c (base) [root@VM_0_4_centos csapp]# readelf -a -x .text -x .data a.out #### 7.5 符号和符号表 #### * 例子中的符号表如下所示 # main.o的elf文件中.symtab部分 Symbol table '.symtab' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS main.c 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 3: 0000000000000000 0 SECTION LOCAL DEFAULT 3 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 5: 0000000000000000 0 SECTION LOCAL DEFAULT 6 6: 0000000000000000 0 SECTION LOCAL DEFAULT 7 7: 0000000000000000 0 SECTION LOCAL DEFAULT 5 8: 0000000000000000 24 FUNC GLOBAL DEFAULT 1 main 9: 0000000000000000 8 OBJECT GLOBAL DEFAULT 3 array 10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND sum * 下面是符号说明: * `Ndx`表示该符号所在的数据节的索引, * `main`函数就处在`.text`节(Ndx=1) * `array`数组就处在`.data`节(Ndx=3) * `ABS`表示不要重定位的符号 * `UND`(UNDEF)表示未定义的符号,也就是在当前可重定位目标文件中引用了,但是没有找到对应定义的符号,这也是链接器在符号解析中需要解决的符号 * `Name`就是符号。 #### 7.6 符号分析 #### * 对于局部引用,链接器需要保证其唯一性 * 对于全局符号引用,当编译器遇到一个不是在当前模块中定义的符号(变量或函数名)时,会假设该符号是在其他某个模块中定义的,生成一个链接器符号表条目,并把它交给链接器处理。如果链接器在它的任何输人模块中都找不到这个被引用符号的定义,就输出一条(通常很难阅读的)错误信息并终止。 ##### 7.6.1 链接器如何解析多重定义的全局符号 ##### * 根据强弱符号的定义(对于C/C++语言来说,编译器默认函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号),Linux链接器用如下规则定义多重定义的符号名: * 规则 1: 不允许有多个同名的强符号。 * 规则 2: 如果有一个强符号和多个弱符号同名,那么选择强符号。 * 规则 3: 如果有多个弱符号同名,那么从这些弱符号中任意选择一个。 ##### 7.6.2 与静态库链接 ##### * 所有的编译系统都提供一种机制,将所有相关的目标模块打包成为一个单独的文件,称为静态库(static library ), 它可以用做链接器的输人。当链接器构造一个输出的可执行文件时,它只复制静态库里被应用程序引用的目标模块。 * 如下所示:假如main2中调用了printf和addvec函数,则需要引入静态库(当然得\#include <stdio.h>,\#include “vector.h”) * ![image-20210207144135612][] ##### 7.6.3 链接器如何使用静态库来解析引用 ##### * 链接器维护 * 一个可重定位目标文件的集合E(这个集合中的文件将被合并起来成为可执行文件) * 一个未解析的符号(引用但未定义)集合U * 一个在前面输入文件中已定义的符号集合D * 初始时,EUD均为空 * 对于命令行上的每个输人文件f,链接器会判断f是一个目标文件还是一个存档文 件。如果f是一个目标文件,那么链接器把f添加到 E,修改 U 和 D 来反映f中 的符号定义和引用,并继续下一个输入文件。 * 如果f是一个存档文件,那么链接器就尝试匹配 U 中未解析的符号和由存档文件成员定义的符号, * 如果某个存档文件成员m,定义了一个符号来解析U中的一个引用,那么就将m添加到E中并且链接器修改E和D来反映 m 中的符号定义和引用。 * 对存档文件中所有的成员目标文件都依次进行这个过程,直到E和D都不再发生变化。此时,任何不包含在 E中的成员目标文件都简单地被丢弃,而链接器将继续处理下一个输入文件。 * 如果当链接器完成对命令行上输人文件的扫描后,U是非空的,那么链接器就会输出一个错误并终止。否则,它会合并和重定位 £中的目标文件,构建输出的可执行文件。 #### 7.7 重定位 #### * 完成符号解析【就把代码中的每个符号引用和正好一个符号定义(即它的一个输人目标模块中的一个符号表条目)关联起来。】之后,链接器就知道它的输人目标模块中的代码节和数据节的确切大小。然后就可以开始重定位了。 * 重定位分为以下两步: * 重定位节和符号定义 * 链接器将所有相同类型的节合并为同一类型的新的聚合节。 * 重定位节中的符号引用 * 链接器修改代码节和数据节中对每个符号的引用,使得它们指向正确的运行时地址。 ##### 7.7.1 重定位条目 ##### * ![image-20210207155051034][] \- offset 是需要被修改的引用的节偏移。 - symbol 标识被修改引用应该指向的符号。 - type 告知链接器如何修改新的引用。 - addend 是一个有符号常数,一些类型的重定位要使用它对被修改引用的值做偏移调整。 * 重定位类型(32种),其中最基本的两种(支持 X86-64 小型代码模型(small code model),其文件中的代码和数据的总体大小小于 2GB)是: * R\_X86\_64\_PC32:重定位一个使用 32 位 PC 相对地址(距程序计数器(PC)的当前运行时值的偏移量)的引用。 * R\_X86\_64\_32:重定位一个使用 32 位绝对地址的引用。通过绝对寻址,CPU 直接使用在指令编码中的32位值作为有效地址,不需要进一步修改。 ##### 7.7.2 重定位符号引用 ##### * 重定位PC相对引用 * ![image-20210207160328949][] * 参考上图代码中main调用sum * 重定位条目为: * ![image-20210207160823941][] * 假设:(addr=取地址) * ![image-20210207161348419][] * 则: * 我们已知程序起始地址和sum的起始地址:下面要算出call后面参数的地址,即引用的运行时地址 * ![image-20210207161543685][] * 根据r.append的值可知sum向前4字节为call,则可得参数的值(引用的值): * ![image-20210207161736191][] * 重定位绝对引用 * ![image-20210207161952892][] * 计算过程类似,只不过refptr算出的是绝对地址: * ![image-20210207162128677][] * ![image-20210207162305027][] * ![image-20210207162200560][] * ![image-20210207162225705][] #### 7.8 可执行目标文件 #### * elf的可执行目标文件格式: * ![image-20210207171349657][] * 关于elf头描述 * 多了入口地址 * ![image-20210207171545521][] * 段头部表: * ![image-20210207171857547][] * 段头部表是可执行文件必须包含的内容,主要用来说明如何将可执行目标文件映射到内存空间中。 * 可以注意到,它这里将可执行目标文件中不同的数据节根据不同读写执行的需要,分配成两个段:数据段和代码段,通过下图中02、03行可以知道每个段包含的数据节,其中第一行为代码段,第二行为数据段。而段头部表会以段为单位将其映射到内存空间中。我们需要注意这上图红框中两个LOAD,说明了数据段和代码段对应的内存映射(RE=只读=程序段,RW=读写=数据段)。 * ![image-20210207171959866][] #### 7.9 加载可执行目标文件 #### * `linux> ./prog` * 加载器运行它时,创建类似于下图所示的内存映像。 * ![image-20210208004126637][] * 1、在程序头部表的引导下,加载器将可执行文件的片(chunk)复制到代码段和数据段。 * 2、接下来,加载器跳转到程序的人口点,也就是\_start 函数的地址(这个函数是在系统目标文件 Ctrl.o 中定义的,对所\_有C程序都一样。\_start 函数调用系统启动函数\_\_libc\_start\_main, 该函数定义在 libc.so 中。它初始化执行环境,调用用户层的 main 函数,处理 main 函数的返回值,并且在需要的时候把控制返回给内核)。 #### 7.10 动态链接共享库 #### * 为什么选择动态链接共享库: * 静态库的缺点:需要定期维护与更新,而当程序员想用最新的版本的时候,必须了解这个库的更新情况。 * 常用的函数(每个进程都可能用到的那种)如果每个进程都复制一份,那么会造成极大内存浪费。 * 共享库(shared library)是致力于解决静态库缺陷的一个现代创新产物。 * 是一个目标模块,在运行或加载时,可以加载到任意的内存地址,并和一个在内存中的程序链接起来——动态链接(由动态链接器完成) * 在Linux中通常是.so的格式,在Win中则是.dll * 动态链接的过程如下: * ![image-20210208005543954][] * 首先,在任何给定的文件系统中,对于一个库只有一个 .so 文件。**所有引用该库的可执行目标文件共享这个 .so 文件中的代码和数据**,而不是像静态库的内容那样被复制和嵌入到引用它们的可执行的文件中。 * 其次,在内存中,一个共享库的 .text 节的一个副本可以被不同的正在运行的进程共享。 #### 7.11 从应用程序中加载和链接共享库 #### #include <dlfcn.h> void *dlopen(const char *filename, int flag);//返回 :若成功则为指向句柄的指针,若出错则为 NULL void *dlsym(void *hauidle, char symbol);//返回:若成功则为指向符号的指针,若出错则为 NULL int dlclose (void handle);//返回:若成功则为0,若出错则为-1 const char *dlerror(void);//返 回:如果前面对dlopen、dlsym或dlclose的调用失败,则为错误消息,如果前面的调用成功,则为NULL。 #### 7.12 位置无关代码 #### * 可以把它们加载到内存的任何位置而无需链接器修改。 * 可以加载而无需重定位的代码称为位置无关代码(Position-Ind印endent Code, PIC)。 * PIC 数据引用 * 编译器会创建GOT表(全局偏移量表) * 每个被这个目标模块引用的全局数据目标(过程或全局变量)都有一个 8 字节条目。 * 编译器还为 GOT 中每个条目生成一个重定位记录。 * 在加载时,动态链接器会重定位 GOT 中的每个条目,使得它包含目标的正确的绝对地址。每个引用全局目标的目标模块都有自己的 GOT。 * ![image-20210208143741072][] * PIC 函数调用 * GNU使用了延迟绑定(lazy binding),将过程地址的绑定推迟到第一次调用该过程时。 * 延迟绑定的实现 * 过程链接表(PLT)。 * PLT 是一个数组,其中每个条目是 16 字节代码。 * PLT\[0\]是一个特殊条目,它跳转到动态链接器中。每个被可执行程序调用的库函数都有它自己的 PLT 条目。 * 每个条目都负责调用一个具体的函数。 * 全局偏移量表(GOT)。 * 见上文 * 如下图所示GOT\[4\]+PLT\[2\]=addvec * ![image-20210208144312565][] * 延迟解析具体过程(图a): * 1、程序调用进入 PLT \[ 2 \],这是 addvec 的 PLT 条目。 * 2、第一条 PLT 指令通过 G0T \[ 4 \]进行间接跳转。 * 3、在 把 addvec 的 ID( Oxl)压人栈中之后,PLT \[ 2\]跳转到 PLT \[ 0\]。 * 4、PLT\[0\]通过 GOT \[ l \]间接地把动态链接器的一个参数压人栈中,然后通过GOT \[2\]间接跳转进动态链接器中。动态链接器使用两个栈条目来确定 addvec 的运行时位置,用这个地址重写 GOT \[ 4 \],再把控制传递给 addvec。 * 后续调用(图b): * 1、和前面一样,控制传递到 PLT \[ 2\]。 * 2、不过这次通过GOT \[ 4 \]的间接跳转会将控制直接转移到 addvec。 #### 7.13 库打桩机制 #### * 库打桩(library interpositioning),它允许你截获对共享库函数的调用,取而代之执行自己的代码。 ##### 7.13.1 编译时打桩 ##### * 根据我目前的理解,编译时打桩即:在编译的时候加上 -I参数,告诉编译器先检查当前目录是否存在库函数的头文件(自己写的),有的话优先调用。 * 附上附件中示例代码 // malloc.h #ifndef COMPILE_TIME #define malloc(size) mymalloc(size) #define free(ptr) myfree(ptr) #endif void * mymalloc(size_t size); void myfree(void *ptr); // mymalloc.cpp #ifdef COMPILE_TIME #include <stdio.h> #include <malloc.h> // malloc wrapper function void * mymalloc(size_t size) { void * ptr = ::malloc(size); printf("malloc %p size %u\n", ptr, size); return ptr; } // free wrapper function void myfree(void *ptr) { ::free(ptr); printf("free %p\n", ptr); } #endif ##### 7.13.2 链接时打桩 ##### * Linux 静态链接器支持用–wrap f 标志进行链接时打桩。这个标志告诉链接器,把对符号 f 的引用解析成\_\_wrap\_f(前缀是两个下划线),还要把对符号\_\_real\_f(前缀是两个下划线的引用解析f。 * 下面是一个demo #ifdef LINK_TIME #include <stdio.h> extern "C" { void * __real_malloc(size_t size); void __real_free(void * ptr); // malloc wrapper function void * __wrap_malloc(size_t size) { printf("%s enter %u\n", __FUNCTION__, size); void * ptr = __real_malloc(size); printf("malloc %p size %u\n", ptr, size); return ptr; } // free wrapper function void __wrap_free(void *ptr) { __real_free(ptr); printf("free %p\n", ptr); } } #endif gcc -DLINK_TIME -c mymalloc.cpp gcc -c main.cpp gcc -Wl,--wrap,malloc -Wl,--wrap,free -o intpos main.o mymalloc.o ##### 7.13.3 运行时打桩 ##### * 运行时打桩仅需要访问可执行目标文件即可,它的基本原理是基于动态链接器的LD\_PRELOAD环境变量。 * 如果LD\_PRELOAD环境变量被设置为一个共享库路径的列表(以空格或分号分隔),那么当你加载和执行一个程序,需要解析未定义的引用时,动态链接器会先搜做LD\_PRELOAD中给定的库,然后才搜索任何其他的库。有了这个机制,当你加载和执行任意可执行文件时,可以对任何共享库中任意函数打桩,包括libc.so中的malloc和free。 #ifdef RUNTIME #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> // malloc wrapper function void * malloc(size_t size) { printf("%s enter %u\n", __FUNCTION__, size); void *(* mallocp)(size_t size); char * error; // get address of libc malloc mallocp = dlsym(RTLD_NEXT, "malloc"); if ((error = dlerror()) != NULL) { fputs(error, stderr); exit(1); } void * ptr = mallocp(size); printf("malloc %p size %u\n", ptr, (int)size); return ptr; } // free wrapper function void free(void *ptr) { void (* freep)(void *ptr); char * error; // get address of libc free freep = dlsym(RTLD_NEXT, "free"); if ((error = dlerror()) != NULL) { fputs(error, stderr); exit(1); } freep(ptr); printf("free %p\n", ptr); } #endif gcc -DRUNTIME -shared -fpic -o mymalloc.so mymalloc.cpp -ldl -fpermissive LD_PRELOAD="./mymalloc.so" ./intr #### 7.14 处理目标文件的工具 #### * AR :创建静态库,插人、删除、列出和提取成员。 * STRINGS:列出一个目标文件中所有可打印的字符串。 * STRIP:从目标文件中删除符号表信息。 * NM:列出一个目标文件的符号表中定义的符号。 * SIZE: 列出目标文件中节的名字和大小。 * READELF:显示一个目标文件的完整结构,包括 ELF 头中编码的所有信息。包含SIZE 和 NM 的功能。 * OBJDUMP:所有二进制工具之母。能够显示一个目标文件中所有的信息。它最大的作用是反汇编 .text 节中的二进制指令。Linux 系统为操作共享库还提供了 LDD 程序: * LDD:列出一个可执行文件在运行时所需要的共享库。 #### 补充:elf文件内容 #### (base) [root@VM_0_4_centos csapp]# gcc -Og -c main.c (base) [root@VM_0_4_centos csapp]# readelf -a -x .text -x .data main.o ELF 头: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 类别: ELF64 数据: 2 补码,小端序 (little endian) 版本: 1 (current) OS/ABI: UNIX - System V ABI 版本: 0 类型: REL (可重定位文件) 系统架构: Advanced Micro Devices X86-64 版本: 0x1 入口点地址: 0x0 程序头起点: 0 (bytes into file) Start of section headers: 648 (bytes into file) 标志: 0x0 本头的大小: 64 (字节) 程序头大小: 0 (字节) Number of program headers: 0 节头大小: 64 (字节) 节头数量: 12 字符串表索引节头: 11 节头: [号] 名称 类型 地址 偏移量 大小 全体大小 旗标 链接 信息 对齐 [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .text PROGBITS 0000000000000000 00000040 0000000000000018 0000000000000000 AX 0 0 1 [ 2] .rela.text RELA 0000000000000000 000001e0 0000000000000030 0000000000000018 I 9 1 8 [ 3] .data PROGBITS 0000000000000000 00000058 0000000000000008 0000000000000000 WA 0 0 4 [ 4] .bss NOBITS 0000000000000000 00000060 0000000000000000 0000000000000000 WA 0 0 1 [ 5] .comment PROGBITS 0000000000000000 00000060 000000000000002e 0000000000000001 MS 0 0 1 [ 6] .note.GNU-stack PROGBITS 0000000000000000 0000008e 0000000000000000 0000000000000000 0 0 1 [ 7] .eh_frame PROGBITS 0000000000000000 00000090 0000000000000030 0000000000000000 A 0 0 8 [ 8] .rela.eh_frame RELA 0000000000000000 00000210 0000000000000018 0000000000000018 I 9 7 8 [ 9] .symtab SYMTAB 0000000000000000 000000c0 0000000000000108 0000000000000018 10 8 8 [10] .strtab STRTAB 0000000000000000 000001c8 0000000000000017 0000000000000000 0 0 1 [11] .shstrtab STRTAB 0000000000000000 00000228 0000000000000059 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific) There are no section groups in this file. 本文件中没有程序头。 重定位节 '.rela.text' 位于偏移量 0x1e0 含有 2 个条目: 偏移量 信息 类型 符号值 符号名称 + 加数 00000000000a 00090000000a R_X86_64_32 0000000000000000 array + 0 00000000000f 000a00000002 R_X86_64_PC32 0000000000000000 sum - 4 重定位节 '.rela.eh_frame' 位于偏移量 0x210 含有 1 个条目: 偏移量 信息 类型 符号值 符号名称 + 加数 000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. Symbol table '.symtab' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS main.c 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 3: 0000000000000000 0 SECTION LOCAL DEFAULT 3 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 5: 0000000000000000 0 SECTION LOCAL DEFAULT 6 6: 0000000000000000 0 SECTION LOCAL DEFAULT 7 7: 0000000000000000 0 SECTION LOCAL DEFAULT 5 8: 0000000000000000 24 FUNC GLOBAL DEFAULT 1 main 9: 0000000000000000 8 OBJECT GLOBAL DEFAULT 3 array 10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND sum No version information found in this file. “.text”节的十六进制输出: NOTE: This section has relocations against it, but these have NOT been applied to this dump. 0x00000000 4883ec08 be020000 00bf0000 0000e800 H............... 0x00000010 00000048 83c408c3 ...H.... “.data”节的十六进制输出: 0x00000000 01000000 02000000 ........ (base) [root@VM_0_4_centos csapp]# gcc -Og main.c sum.c (base) [root@VM_0_4_centos csapp]# ls a.out main.c main.o main.s mstore.c mstore.o mstore.s sum.c (base) [root@VM_0_4_centos csapp]# readelf -a -x .text -x .data a.out ELF 头: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 类别: ELF64 数据: 2 补码,小端序 (little endian) 版本: 1 (current) OS/ABI: UNIX - System V ABI 版本: 0 类型: EXEC (可执行文件) 系统架构: Advanced Micro Devices X86-64 版本: 0x1 入口点地址: 0x400400 程序头起点: 64 (bytes into file) Start of section headers: 6480 (bytes into file) 标志: 0x0 本头的大小: 64 (字节) 程序头大小: 56 (字节) Number of program headers: 9 节头大小: 64 (字节) 节头数量: 30 字符串表索引节头: 29 节头: [号] 名称 类型 地址 偏移量 大小 全体大小 旗标 链接 信息 对齐 [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 0000000000400238 00000238 000000000000001c 0000000000000000 A 0 0 1 [ 2] .note.ABI-tag NOTE 0000000000400254 00000254 0000000000000020 0000000000000000 A 0 0 4 [ 3] .note.gnu.build-i NOTE 0000000000400274 00000274 0000000000000024 0000000000000000 A 0 0 4 [ 4] .gnu.hash GNU_HASH 0000000000400298 00000298 000000000000001c 0000000000000000 A 5 0 8 [ 5] .dynsym DYNSYM 00000000004002b8 000002b8 0000000000000048 0000000000000018 A 6 1 8 [ 6] .dynstr STRTAB 0000000000400300 00000300 0000000000000038 0000000000000000 A 0 0 1 [ 7] .gnu.version VERSYM 0000000000400338 00000338 0000000000000006 0000000000000002 A 5 0 2 [ 8] .gnu.version_r VERNEED 0000000000400340 00000340 0000000000000020 0000000000000000 A 6 1 8 [ 9] .rela.dyn RELA 0000000000400360 00000360 0000000000000018 0000000000000018 A 5 0 8 [10] .rela.plt RELA 0000000000400378 00000378 0000000000000030 0000000000000018 AI 5 23 8 [11] .init PROGBITS 00000000004003a8 000003a8 000000000000001a 0000000000000000 AX 0 0 4 [12] .plt PROGBITS 00000000004003d0 000003d0 0000000000000030 0000000000000010 AX 0 0 16 [13] .text PROGBITS 0000000000400400 00000400 0000000000000192 0000000000000000 AX 0 0 16 [14] .fini PROGBITS 0000000000400594 00000594 0000000000000009 0000000000000000 AX 0 0 4 [15] .rodata PROGBITS 00000000004005a0 000005a0 0000000000000010 0000000000000000 A 0 0 8 [16] .eh_frame_hdr PROGBITS 00000000004005b0 000005b0 000000000000003c 0000000000000000 A 0 0 4 [17] .eh_frame PROGBITS 00000000004005f0 000005f0 0000000000000104 0000000000000000 A 0 0 8 [18] .init_array INIT_ARRAY 0000000000600e10 00000e10 0000000000000008 0000000000000008 WA 0 0 8 [19] .fini_array FINI_ARRAY 0000000000600e18 00000e18 0000000000000008 0000000000000008 WA 0 0 8 [20] .jcr PROGBITS 0000000000600e20 00000e20 0000000000000008 0000000000000000 WA 0 0 8 [21] .dynamic DYNAMIC 0000000000600e28 00000e28 00000000000001d0 0000000000000010 WA 6 0 8 [22] .got PROGBITS 0000000000600ff8 00000ff8 0000000000000008 0000000000000008 WA 0 0 8 [23] .got.plt PROGBITS 0000000000601000 00001000 0000000000000028 0000000000000008 WA 0 0 8 [24] .data PROGBITS 0000000000601028 00001028 000000000000000c 0000000000000000 WA 0 0 4 [25] .bss NOBITS 0000000000601034 00001034 0000000000000004 0000000000000000 WA 0 0 1 [26] .comment PROGBITS 0000000000000000 00001034 000000000000002d 0000000000000001 MS 0 0 1 [27] .symtab SYMTAB 0000000000000000 00001068 0000000000000618 0000000000000018 28 47 8 [28] .strtab STRTAB 0000000000000000 00001680 00000000000001c7 0000000000000000 0 0 1 [29] .shstrtab STRTAB 0000000000000000 00001847 0000000000000108 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific) There are no section groups in this file. 程序头: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 0x00000000000001f8 0x00000000000001f8 R E 8 INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 0x000000000000001c 0x000000000000001c R 1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000000006f4 0x00000000000006f4 R E 200000 LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 0x0000000000000224 0x0000000000000228 RW 200000 DYNAMIC 0x0000000000000e28 0x0000000000600e28 0x0000000000600e28 0x00000000000001d0 0x00000000000001d0 RW 8 NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254 0x0000000000000044 0x0000000000000044 R 4 GNU_EH_FRAME 0x00000000000005b0 0x00000000004005b0 0x00000000004005b0 0x000000000000003c 0x000000000000003c R 4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10 GNU_RELRO 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 0x00000000000001f0 0x00000000000001f0 R 1 Section to Segment mapping: 段节... 00 01 .interp 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr 07 08 .init_array .fini_array .jcr .dynamic .got Dynamic section at offset 0xe28 contains 24 entries: 标记 类型 名称/值 0x0000000000000001 (NEEDED) 共享库:[libc.so.6] 0x000000000000000c (INIT) 0x4003a8 0x000000000000000d (FINI) 0x400594 0x0000000000000019 (INIT_ARRAY) 0x600e10 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 0x000000000000001a (FINI_ARRAY) 0x600e18 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 0x000000006ffffef5 (GNU_HASH) 0x400298 0x0000000000000005 (STRTAB) 0x400300 0x0000000000000006 (SYMTAB) 0x4002b8 0x000000000000000a (STRSZ) 56 (bytes) 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000015 (DEBUG) 0x0 0x0000000000000003 (PLTGOT) 0x601000 0x0000000000000002 (PLTRELSZ) 48 (bytes) 0x0000000000000014 (PLTREL) RELA 0x0000000000000017 (JMPREL) 0x400378 0x0000000000000007 (RELA) 0x400360 0x0000000000000008 (RELASZ) 24 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes) 0x000000006ffffffe (VERNEED) 0x400340 0x000000006fffffff (VERNEEDNUM) 1 0x000000006ffffff0 (VERSYM) 0x400338 0x0000000000000000 (NULL) 0x0 重定位节 '.rela.dyn' 位于偏移量 0x360 含有 1 个条目: 偏移量 信息 类型 符号值 符号名称 + 加数 000000600ff8 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0 重定位节 '.rela.plt' 位于偏移量 0x378 含有 2 个条目: 偏移量 信息 类型 符号值 符号名称 + 加数 000000601018 000100000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0 000000601020 000200000007 R_X86_64_JUMP_SLO 0000000000000000 __gmon_start__ + 0 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. Symbol table '.dynsym' contains 3 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ Symbol table '.symtab' contains 65 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000400238 0 SECTION LOCAL DEFAULT 1 2: 0000000000400254 0 SECTION LOCAL DEFAULT 2 3: 0000000000400274 0 SECTION LOCAL DEFAULT 3 4: 0000000000400298 0 SECTION LOCAL DEFAULT 4 5: 00000000004002b8 0 SECTION LOCAL DEFAULT 5 6: 0000000000400300 0 SECTION LOCAL DEFAULT 6 7: 0000000000400338 0 SECTION LOCAL DEFAULT 7 8: 0000000000400340 0 SECTION LOCAL DEFAULT 8 9: 0000000000400360 0 SECTION LOCAL DEFAULT 9 10: 0000000000400378 0 SECTION LOCAL DEFAULT 10 11: 00000000004003a8 0 SECTION LOCAL DEFAULT 11 12: 00000000004003d0 0 SECTION LOCAL DEFAULT 12 13: 0000000000400400 0 SECTION LOCAL DEFAULT 13 14: 0000000000400594 0 SECTION LOCAL DEFAULT 14 15: 00000000004005a0 0 SECTION LOCAL DEFAULT 15 16: 00000000004005b0 0 SECTION LOCAL DEFAULT 16 17: 00000000004005f0 0 SECTION LOCAL DEFAULT 17 18: 0000000000600e10 0 SECTION LOCAL DEFAULT 18 19: 0000000000600e18 0 SECTION LOCAL DEFAULT 19 20: 0000000000600e20 0 SECTION LOCAL DEFAULT 20 21: 0000000000600e28 0 SECTION LOCAL DEFAULT 21 22: 0000000000600ff8 0 SECTION LOCAL DEFAULT 22 23: 0000000000601000 0 SECTION LOCAL DEFAULT 23 24: 0000000000601028 0 SECTION LOCAL DEFAULT 24 25: 0000000000601034 0 SECTION LOCAL DEFAULT 25 26: 0000000000000000 0 SECTION LOCAL DEFAULT 26 27: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 28: 0000000000600e20 0 OBJECT LOCAL DEFAULT 20 __JCR_LIST__ 29: 0000000000400430 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones 30: 0000000000400460 0 FUNC LOCAL DEFAULT 13 register_tm_clones 31: 00000000004004a0 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux 32: 0000000000601034 1 OBJECT LOCAL DEFAULT 25 completed.6355 33: 0000000000600e18 0 OBJECT LOCAL DEFAULT 19 __do_global_dtors_aux_fin 34: 00000000004004c0 0 FUNC LOCAL DEFAULT 13 frame_dummy 35: 0000000000600e10 0 OBJECT LOCAL DEFAULT 18 __frame_dummy_init_array_ 36: 0000000000000000 0 FILE LOCAL DEFAULT ABS main.c 37: 0000000000000000 0 FILE LOCAL DEFAULT ABS sum.c 38: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 39: 00000000004006f0 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__ 40: 0000000000600e20 0 OBJECT LOCAL DEFAULT 20 __JCR_END__ 41: 0000000000000000 0 FILE LOCAL DEFAULT ABS 42: 0000000000600e18 0 NOTYPE LOCAL DEFAULT 18 __init_array_end 43: 0000000000600e28 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC 44: 0000000000600e10 0 NOTYPE LOCAL DEFAULT 18 __init_array_start 45: 00000000004005b0 0 NOTYPE LOCAL DEFAULT 16 __GNU_EH_FRAME_HDR 46: 0000000000601000 0 OBJECT LOCAL DEFAULT 23 _GLOBAL_OFFSET_TABLE_ 47: 0000000000400590 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini 48: 0000000000601028 0 NOTYPE WEAK DEFAULT 24 data_start 49: 000000000060102c 8 OBJECT GLOBAL DEFAULT 24 array 50: 0000000000601034 0 NOTYPE GLOBAL DEFAULT 24 _edata 51: 0000000000400594 0 FUNC GLOBAL DEFAULT 14 _fini 52: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_ 53: 0000000000601028 0 NOTYPE GLOBAL DEFAULT 24 __data_start 54: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 55: 00000000004005a8 0 OBJECT GLOBAL HIDDEN 15 __dso_handle 56: 0000000000400505 27 FUNC GLOBAL DEFAULT 13 sum 57: 00000000004005a0 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used 58: 0000000000400520 101 FUNC GLOBAL DEFAULT 13 __libc_csu_init 59: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 25 _end 60: 0000000000400400 0 FUNC GLOBAL DEFAULT 13 _start 61: 0000000000601034 0 NOTYPE GLOBAL DEFAULT 25 __bss_start 62: 00000000004004ed 24 FUNC GLOBAL DEFAULT 13 main 63: 0000000000601038 0 OBJECT GLOBAL HIDDEN 24 __TMC_END__ 64: 00000000004003a8 0 FUNC GLOBAL DEFAULT 11 _init Version symbols section '.gnu.version' contains 3 entries: 地址:0000000000400338 Offset: 0x000338 Link: 5 (.dynsym) 000: 0 (*本地*) 2 (GLIBC_2.2.5) 0 (*本地*) Version needs section '.gnu.version_r' contains 1 entries: 地址:0x0000000000400340 Offset: 0x000340 Link: 6 (.dynstr) 000000: 版本: 1 文件:libc.so.6 计数:1 0x0010:名称:GLIBC_2.2.5 标志:无 版本:2 “.text”节的十六进制输出: 0x00400400 31ed4989 d15e4889 e24883e4 f0505449 1.I..^H..H...PTI 0x00400410 c7c09005 400048c7 c1200540 0048c7c7 ....@.H.. .@.H.. 0x00400420 ed044000 e8b7ffff fff4660f 1f440000 ..@.......f..D.. 0x00400430 b83f1060 0055482d 38106000 4883f80e .?.`.UH-8.`.H... 0x00400440 4889e577 025dc3b8 00000000 4885c074 H..w.]......H..t 0x00400450 f45dbf38 106000ff e00f1f80 00000000 .].8.`.......... 0x00400460 b8381060 0055482d 38106000 48c1f803 .8.`.UH-8.`.H... 0x00400470 4889e548 89c248c1 ea3f4801 d048d1f8 H..H..H..?H..H.. 0x00400480 75025dc3 ba000000 004885d2 74f45d48 u.]......H..t.]H 0x00400490 89c6bf38 106000ff e20f1f80 00000000 ...8.`.......... 0x004004a0 803d8d0b 20000075 11554889 e5e87eff .=.. ..u.UH...~. 0x004004b0 ffff5dc6 057a0b20 0001f3c3 0f1f4000 ..]..z. ......@. 0x004004c0 48833d58 09200000 741eb800 00000048 H.=X. ..t......H 0x004004d0 85c07414 55bf200e 60004889 e5ffd05d ..t.U. .`.H....] 0x004004e0 e97bffff ff0f1f00 e973ffff ff4883ec .{ .......s...H.. 0x004004f0 08be0200 0000bf2c 106000e8 05000000 .......,.`...... 0x00400500 4883c408 c3b80000 0000ba00 000000eb H............... 0x00400510 094863ca 03048f83 c20139f2 7cf3f3c3 .Hc.......9.|... 0x00400520 41574189 ff415649 89f64155 4989d541 AWA..AVI..AUI..A 0x00400530 544c8d25 d8082000 55488d2d d8082000 TL.%.. .UH.-.. . 0x00400540 534c29e5 31db48c1 fd034883 ec08e855 SL).1.H...H....U 0x00400550 feffff48 85ed741e 0f1f8400 00000000 ...H..t......... 0x00400560 4c89ea4c 89f64489 ff41ff14 dc4883c3 L..L..D..A...H.. 0x00400570 014839eb 75ea4883 c4085b5d 415c415d .H9.u.H...[]A\A] 0x00400580 415e415f c390662e 0f1f8400 00000000 A^A_..f......... 0x00400590 f3c3 .. “.data”节的十六进制输出: 0x00601028 00000000 01000000 02000000 ............ Displaying notes found at file offset 0x00000254 with length 0x00000020: 所有者 Data size Description GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag) OS: Linux, ABI: 2.6.32 Displaying notes found at file offset 0x00000274 with length 0x00000024: 所有者 Data size Description GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring) Build ID: d93b13aaa695f0cc69f00c3e9476d2edd48acb91 [image-20210207112325286]: /images/20221024/c34d949184394f7ebf8fe0bfe57ed488.png [image-20210207115125628]: /images/20221024/da92ab87fe3a4de085dfd6c0d5f2961c.png [image-20210207144135612]: /images/20221024/2960f25bbd2b411bbbff903f07cc4c62.png [image-20210207155051034]: [image-20210207160328949]: /images/20221024/06987d63de304268935dfdfd11cc7577.png [image-20210207160823941]: /images/20221024/0a8ed88917414b73935058dbb19e9bd9.png [image-20210207161348419]: /images/20221024/f3e1747053464115a083d33209607fdd.png [image-20210207161543685]: /images/20221024/c371b61f5d764d3982cf95afaf8ebb3b.png [image-20210207161736191]: /images/20221024/d30f27777dd642098bdcad60aab350c6.png [image-20210207161952892]: /images/20221024/cf8e760523b14e91b88ce0b6f6812c5f.png [image-20210207162128677]: /images/20221024/28cce45fe1f94cfbaebb3e42a792d563.png [image-20210207162305027]: /images/20221024/998bbd09690e4ead9b8f15ea62f7c6a9.png [image-20210207162200560]: /images/20221024/91f007206db4418588bf059eb9f2fecd.png [image-20210207162225705]: /images/20221024/6fb4c6ef7ddd4e31a446e2d644e749cc.png [image-20210207171349657]: /images/20221024/526c78a5268c46afbab2b10dcb45acc8.png [image-20210207171545521]: /images/20221024/1b5530fbdc1f492cac9a788265e04de3.png [image-20210207171857547]: /images/20221024/fc6ec4d8192245059760d75474e799ff.png [image-20210207171959866]: /images/20221024/3e5ef31ab55a4af28e6f6bd3c59f1f64.png [image-20210208004126637]: /images/20221024/f774152fe05b4dfdb6726b5dad35f790.png [image-20210208005543954]: /images/20221024/3380723f60d648a3b321b90514650f9f.png [image-20210208143741072]: /images/20221024/f9d49a43d6b642e5a31dc84b6aa7ed6a.png [image-20210208144312565]: /images/20221024/71f1354bd6a84546b2af14705b37bf4d.png
相关 CSAPP:第1章 计算机系统漫游 文章目录 1.1 information=bit+context 1.2 程序翻译 1 以你之姓@/ 2023年01月02日 03:24/ 0 赞/ 215 阅读
相关 CSAPP:第12章 并发编程 CSAPP:第12章 并发编程 文章目录 CSAPP:第12章 并发编程 12.1 基于进程的并发编程(Process 傷城~/ 2022年10月31日 01:47/ 0 赞/ 23 阅读
相关 CSAPP:第11章 网络编程 CSAPP:第11章 网络编程 文章目录 CSAPP:第11章 网络编程 11.1 客户端-服务器编程模型 待我称王封你为后i/ 2022年10月30日 05:24/ 0 赞/ 261 阅读
相关 CSAPP:第10章 系统级IO CSAPP:第10章 系统级IO 文章目录 CSAPP:第10章 系统级IO 10.1 Unix IO 水深无声/ 2022年10月29日 15:22/ 0 赞/ 231 阅读
相关 CSAPP:第9章 虚拟内存 CSAPP:第9章 虚拟内存 文章目录 CSAPP:第9章 虚拟内存 9.1 物理和虚拟寻址 谁践踏了优雅/ 2022年10月29日 11:27/ 0 赞/ 335 阅读
相关 CSAPP:第6章 存储器层次结构 CSAPP:第6章 存储器层次结构 文章目录 CSAPP:第6章 存储器层次结构 6.1 存储技术 Dear 丶/ 2022年10月28日 10:09/ 0 赞/ 244 阅读
相关 CSAPP:第4章 处理器体系结构 CSAPP:第4章 处理器体系结构 文章目录 CSAPP:第4章 处理器体系结构 Y86-84指令集体系结构 - 日理万妓/ 2022年10月24日 13:30/ 0 赞/ 355 阅读
相关 CSAPP学习笔记(二)链接问题 1. 链接器报告无法解析的引用是什么问题? > error LNK2019: 无法解析的外部符号是常见的链接问题,通常原因在于虽然包含了头文件,但是链接的时候无法找到相 向右看齐/ 2022年02月02日 16:13/ 0 赞/ 208 阅读
还没有评论,来说两句吧...