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

Like this? Share it with your network

Share

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

  • 10,122 views
Uploaded on

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

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

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
10,122
On Slideshare
5,376
From Embeds
4,746
Number of Embeds
10

Actions

Shares
Downloads
221
Comments
1
Likes
15

Embeds 4,746

http://www.searchtb.com 4,672
http://www-ig-opensocial.googleusercontent.com 52
http://localhost 9
http://192.168.6.52 6
http://codingcool.com 2
http://www.haowangkc.com 1
http://webcache.googleusercontent.com 1
http://www.zhuaxia.com 1
http://wse.baidu.com 1
http://www.yybean.com 1

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. 谢 谢 !