Your SlideShare is downloading. ×
0
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509

9,715

Published on

Linux c++ 编程之链接与装载 -提高篇: …

Linux c++ 编程之链接与装载 -提高篇:
1).链接与装载基础篇--复习
2). 动态链接--主要实现技术,动态链接过程,全局符号介入问题分析,C++全局变量的构造与析构实现及相关问题分析
3). ELF 文件结构概述

Published in: Technology
1 Comment
15 Likes
Statistics
Notes
No Downloads
Views
Total Views
9,715
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
234
Comments
1
Likes
15
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Linux C++ 编程之链接与装载 --提高篇 五竹 一淘搜索与算法
  • 2. 课程大纲页• 链接与装载基础篇--复习• 动态链接• ELF 文件结构概述• 参考资料
  • 3. 链接与装载基础篇--复习 基本概念 静态链接过程与符号解析 静态链接时重定位 常见链接错误
  • 4. 编译与链接的基本概念(1)//hello.c#include <stdio.h>int main(){ printf("Hello Worldn"); return 0;}编译:gcc hello.c
  • 5. 编译与链接的基本概念(2)
  • 6. 编译与链接的基本概念(3)• 链接(Linking):解决 一个程序被分割成多个模块后, 模块间最后如何组合成一个单一程序的问题.• 链接的主要内容是把各个模块之间相互引用的部 分处理好,使各个模块之间能正确的衔接.
  • 7. 静态链接过程与符号解析—输入文件类型• 重定位目标文件• 归档库• 共享库
  • 8. 静态链接过程• 链接的主要内容是把各个模块之间相互引用的部 分处理好,使各个模块之间能正确的衔接.• 两步链接(Two-passing Linking)  地址与空间分配(Address and Storage Allocation)  符号解析(Symbol Resolution)和重定位(Relocation)• 全局符号表:链接器会保存一个全局符号表,在任 何输入文件中被引用或者定义的符号都会有一个 表项
  • 9. 符号分类与符号解析• 符号分类• 符号解析(symbol resolution)概念
  • 10. 静态链接—符号处理示例• libaba:
  • 11. 静态链接—符号处理示例• Makefile
  • 12. 静态链接—符号解析示例• aba_main.cpp:• Case22:• Case24:
  • 13. 静态链接—符号处理示例—case22
  • 14. 静态链接—符号处理示例—case24
  • 15. 静态链接时重定位• 重定位概念• 重定位表• 符号解析与重定位的关系
  • 16. Elf64_Rela// Relocation table entry with addend (in section of type SHT_RELA).typedef struct{ Elf64_Addr r_offset; /* Address of need relocation*/ Elf64_Xword r_info; /* Relocation type and symbol index */ Elf64_Sxword r_addend; /* Addend */} Elf64_Rela;#define ELF64_R_SYM(i) ((i) >> 32) // 符号表中的下标#define ELF64_R_TYPE(i) ((i) & 0xffffffff) // 重定位入口的类型#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type))
  • 17. 重定位类型表名字 值 计算R_X86_64_32 1 S+AR_X86_64_PC32 2 S+A-PR_X86_64_GOT32 3 G+AR_X86_64_PLT32 4 L+A- PR_X86_64_COPY 5 noneR_X86_64_GLOB_DAT 6 SR_X86_64_JUMP_SLOT 7 SR_X86_64_RELATIVE 8 B+AR_X86_64_GOTPCREL 9 S + A - GOT
  • 18. 静态链接时重定位示例
  • 19. 静态链接时重定位示例
  • 20. 常见链接错误导致符号未定义的原因: 1. 链接时缺少某个库, 目标文件的路径不正确, 符号 的声明与定义不一样,父类声明的虚函数,父或子类 都没有实现等. 2. C与C++的库之间兼容问题 3. 链接时库的顺序不正确
  • 21. 常见链接错误--库的顺序问总结• 在链接静态库时, 如果目标文件(.o) 与静态库之间存在依赖关系, 则有依赖关系的目标文件(.o)与静态库存在链接顺序问题。• 在链接静态库时, 如果动态库 与静态库之间存在依赖关系,则有 依赖关系的动态库与静态库存在链接顺序问题。• 在链接静态库时,如果多个静态库之间存在依赖关系,则有依 赖关系的静态库之间存在链接顺序问题。• 静态库之间存在循环依赖的时候经常需要根据依赖关系,需将静 态库列出多次.• 最好遵守从左到右排序对象文件的惯例.
  • 22. 动态链接 主要实现技术 显式运行时加载(dlopen/dlsym/dlclose) 动态链接过程 符号的优先级与全局符号介入 C++全局变量的构造与析构
  • 23. 动态链接的主要实现技术• 方便程序开发,部属: • 性能优化:  方法:程序的各模块独立, 方法:延迟绑定(Lazy 装载时才链接(符号查找, Binding) 重定位). 技术实现:函数链接表• 节约内存: (PLT)  方法: 地址无关代码(PIC) • 程序的可扩展性与兼容性:  技术实现:全局偏移量表 方法: 显式运行时加载 (GOT)
  • 24. 主要实现技术—相关数据结构• .interp 节: 动态链接器 ld.so• .dynamic 节: 保存了动态链接器所需的基本信息,• 动态符号表:  .dynsym: 只保存与动态链接相关的符号;  .dynstr: 动态符号字符串表:  .hash .gnu.hash: 输助的符号哈唏表• 动态链接相关的重定位表:  .rela.plt : 对数据引用的修正,它所修正的位置 位于".got" 和数据段.  .rela.dyn : 对函数引用的修正,它所修正的位 置位于".got.plt"
  • 25. 动态链接的实现--地址无关代码
  • 26. 动态链接的实现--地址无关代码 类型 2:模块内部的数据访问 类型 4:模块外部的数据访问 类型 1:模块内部的函数调用 类型 3:模块外部的函数调用
  • 27. The Procedure Linkage Table
  • 28. 模块外部的访问与延迟绑定
  • 29. 显式运行时加载#include <dlfcn.h>void *dlopen(const char *filename, int flag);功能:指定模式打开指定的动态连接库文件,并返回 一个句柄给调用进程. Flags 取值:  RTLD_LAZY: 延迟绑定,等有需要时再解出符号  RTLD_NOW: 立即绑定,返回前解除所有未决定的符号。  RTLD_LOCAL: 与RTLD_GLOBAL作用相反,动态库中定义 的符号不能被其后打开的其它库重定位。没有指定,则 缺省为RTLD_LOCAL。  RTLD_GLOBAL 动态库中定义的符号可被其后打开的其 它库重定位。  RTLD_DEEPBIND:符号查找优先在本共享库的符号表,找 不到才去全局符号表中查找
  • 30. 显式运行时加载void *dlsym(void *handle, const char *symbol);• 功能:返回指定符号的地址• handle 取值:  RTLD_DEFAULT: 直接在可执行程序的全局符号 表中查找 RTLD_NEXT: 在可执行程序的全局符号表中查找 第2次出现的符号。 dlopen 返回的 handle
  • 31. dlsym 之RTLD_NEXT应用 --Hook内存函数malloc#include <stdio.h>#include <stdlib.h>#include <dlfcn.h>void *malloc(size_t size) { size_t *(*_malloc)(size_t size) = NULL; _malloc = (size_t *(*)(size_t size)) dlsym(RTLD_NEXT, "malloc"); return NULL;}
  • 32. 动态链接过程 程序加载 动态链接器自举 处理环境变量 装载共享对象 重定位和初始化
  • 33. 动态链接过程—内存组织关系
  • 34. 动态链接过程—内存组织关系
  • 35. 动态链接过程—内存组织关系
  • 36. 符号的优先级与全局符号介入—示例1• tcmalloc 是怎么生效的?• 静态库: libtcmalloc.a ?• 动态库: libtcmalloc.so
  • 37. 符号的优先级与全局符号介入—示例2• cmclient_v1• cmclient_v2
  • 38. 符号的优先级与全局符号介入—示例2• dso
  • 39. 符号的优先级与全局符号介入—示例2• case01: symbol_priority_dlopen• case02: symbol_priority_dlopen_deepbind
  • 40. 符号的优先级与全局符号介入—示例2• case03: symbol_priority_link
  • 41. 符号的优先级与全局符号介入—示例2• case01: symbol_priority_dlopen• case02: symbol_priority_dlopen_deepbind • case03: symbol_priority_link
  • 42. C++全局变量的构造与析构—示例
  • 43. C++全局变量的构造与析构—示例
  • 44. C++全局变量的构造与析构—示例
  • 45. C++全局变量的构造与析构—示例
  • 46. C++全局变量的构造与析构—case01&case02Case01:Case02:
  • 47. C++全局变量的构造与析构—case03Case03:
  • 48. C++全局变量的构造与析构—依赖关系(1)
  • 49. C++全局变量的构造与析构—case01
  • 50. C++全局变量的构造与析构—case02
  • 51. C++全局变量的构造与析构—case03
  • 52. C++全局变量的构造与析构--.ctors 节的形成• g++ -o $@ $^ -L./ -Wl,-Bstatic -lclass_a -Wl,-Bdynamic -ldl --verbose /usr/libexec/gcc/x86_64-redhat-linux/4.1.2/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=gnu - dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main /usr/lib64/crt1.o /usr/lib64/crti.o /usr/lib/gcc/x86_64- redhat-linux/4.1.2/crtbegin.o -L./ -L/usr/lib/gcc/x86_64- redhat-linux/4.1.2 -L/usr/lib/gcc/x86_64-redhat- linux/4.1.2 -L/usr/lib64 -L/lib64 -L/usr//lib64 main.o - Bstatic -lclass_a -Bdynamic -ldl -lstdc++ -lm -lgcc_s -lgcc - lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat- linux/4.1.2/crtend.o /usr/lib64/crtn.o
  • 53. C++全局变量的构造与析构--.ctors 节的形成
  • 54. C++全局变量的构造与析构
  • 55. C++全局变量的构造与析构
  • 56. C++全局变量的构造与析构—case01
  • 57. C++全局变量的构造与析构—case02
  • 58. C++全局变量的构造与析构—示例
  • 59. C++全局变量的构造与析构—依赖关系(2)
  • 60. C++全局变量的构造与析构—case04&case05Case04:Case05:
  • 61. C++全局变量的构造与析构—case04
  • 62. C++全局变量的构造与析构—case05
  • 63. C++全局变量的构造与析构—case05
  • 64. C++全局变量的构造与析构—case06&case07Case06:Case07:
  • 65. C++全局变量的构造与析构—case06
  • 66. C++全局变量的构造与析构—case07
  • 67. ELF 文件结构概述
  • 68. ELF 文件结构概述int printf(const char * format,...);int global_init_var=84;int global_uninit_var;void func1(int i ){ printf("%dn",i);}int main(void){ static int static_var=85; static int static_var2; int a=1; int b; func1(static_var+static_var2+a+b); return a;}
  • 69. ELF 文件结构概述
  • 70. ELF 文件结构概述名称 说明文件头 位于目标文件最开始的位置,含有整个文件的一些基本信息.程序头表 一个可执行文件或共享目标文件的程序头表是一个数组,数组 中的每一个元素称为“程序头”.描述了一个 “段(segment)”或者一块用于准备执行程序的信息。节头表 是一个数组,每一项是一个 Elf32(64)_Shdr 结构,通过每一个表 项可以定位到对应的节。.strtab 表 字符串表包含有若干个以’null’结尾的字符序列,即字符串. 保存 符号的名字或者节的名字.symtab 表 符号表包含用来定位、重定位程序中符号定义和引用的信息。重定位表 含如何修改其节区内容的信息,从而允许可执行文件和共享目 标文件保存进程的程序映像的正确信息.静态链接:.rela.text 和 .rela.data); 动态链接:.rela.plt 和.rela.dyn
  • 71. ELF 文件结构概述名称 说明.dynstr 表 动态字符串表包含有若干个以’null’结尾的字符序列,即字符串. 保存动态符号的名字的名字.dynsym 表 动态符号表包含的信息用于动态重定位程序中的符号定义和引用.interp 节 动态链接器 , /lib64/ld-linux-x86-64.so.2.dynamic 节 保存动态链接器所需要的基本信息,如依赖的DSO, dynsym 表的位 置 ,动态链接重定位表的位置等.全局偏移表 全局偏移表在私有数据中包含绝对地址,从而使得地址可用,并(GOT) 且不会影响位置独立性和程序代码的可共享性。如果程序需要直 接访问某个符号的绝对地址,该符号就会具有一个全局偏移表项. 重定位项的类型 R_386_GLOB_DAT ,表示对全局偏移表的引用过程链接表 过程链接表(PLT)能够把位置独立的函数调用重定向到绝对位(PLT ) 置.哈希表(Hash 哈希表支持符号表访问Ta ble)
  • 72. ELF ‘Views’ – Split
  • 73. ELF Loading View• Much simpler view, divides executable into ‘Segments’• Only includes data to be loaded into memory at runtime• Segments have: – A simple type – Requested memory location at run time – Permissions (readable/writeable/executable)
  • 74. ELF ‘Views’ - Linking to Loading
  • 75. ELF 文件结构概述• 实际示例(understanding_elf.rar):• part_o.pdf• main_s.pdf
  • 76. 参考资料• <程序员的自我修养—链接、装载与库>• <连接器和加载器>• <ELF_Format.pdf>• http://blog.chinaunix.net/uid/725631/frmd/18945. html• Glibc 和 binutils 源码
  • 77. 谢 谢 !

×