SlideShare una empresa de Scribd logo
1 de 77
Linux C++ 编程之链接与装载
              --提高篇
                五竹

            一淘搜索与算法
课程大纲页

• 链接与装载基础篇--复习

• 动态链接

• ELF 文件结构概述

• 参考资料
链接与装载基础篇--复习
 基本概念
 静态链接过程与符号解析
 静态链接时重定位
 常见链接错误
编译与链接的基本概念(1)

//hello.c
#include <stdio.h>
int main()
{
    printf("Hello Worldn");
    return 0;
}
编译:
gcc hello.c
编译与链接的基本概念(2)
编译与链接的基本概念(3)
• 链接(Linking):解决 一个程序被分割成多个模块后,
 模块间最后如何组合成一个单一程序的问题.

• 链接的主要内容是把各个模块之间相互引用的部
 分处理好,使各个模块之间能正确的衔接.
静态链接过程与符号解析—输入文件类型

• 重定位目标文件

• 归档库

• 共享库
静态链接过程
• 链接的主要内容是把各个模块之间相互引用的部
 分处理好,使各个模块之间能正确的衔接.

• 两步链接(Two-passing Linking)
   地址与空间分配(Address and Storage Allocation)

   符号解析(Symbol Resolution)和重定位(Relocation)

• 全局符号表:链接器会保存一个全局符号表,在任
 何输入文件中被引用或者定义的符号都会有一个
 表项
符号分类与符号解析

• 符号分类
• 符号解析(symbol resolution)概念
静态链接—符号处理示例
• libaba:
静态链接—符号处理示例
• Makefile
静态链接—符号解析示例
• aba_main.cpp:




• Case22:




• Case24:
静态链接—符号处理示例—case22
静态链接—符号处理示例—case24
静态链接时重定位
• 重定位概念
• 重定位表
• 符号解析与重定位的关系
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))
重定位类型表
名字                   值    计算
R_X86_64_32          1    S+A
R_X86_64_PC32        2    S+A-P
R_X86_64_GOT32       3    G+A
R_X86_64_PLT32       4    L+A- P
R_X86_64_COPY        5    none
R_X86_64_GLOB_DAT    6    S
R_X86_64_JUMP_SLOT   7    S
R_X86_64_RELATIVE    8    B+A
R_X86_64_GOTPCREL    9    S + A - GOT
静态链接时重定位示例
静态链接时重定位示例
常见链接错误
导致符号未定义的原因:
 1. 链接时缺少某个库, 目标文件的路径不正确, 符号
  的声明与定义不一样,父类声明的虚函数,父或子类
  都没有实现等.

 2. C与C++的库之间兼容问题

 3. 链接时库的顺序不正确
常见链接错误--库的顺序问总结

• 在链接静态库时, 如果目标文件(.o) 与静态库之间存在依赖关系,
 则有依赖关系的目标文件(.o)与静态库存在链接顺序问题。
• 在链接静态库时, 如果动态库 与静态库之间存在依赖关系,则有
 依赖关系的动态库与静态库存在链接顺序问题。
• 在链接静态库时,如果多个静态库之间存在依赖关系,则有依
 赖关系的静态库之间存在链接顺序问题。
• 静态库之间存在循环依赖的时候经常需要根据依赖关系,需将静
 态库列出多次.
• 最好遵守从左到右排序对象文件的惯例.
动态链接

  主要实现技术

  显式运行时加载(dlopen/dlsym/dlclose)

  动态链接过程

  符号的优先级与全局符号介入

  C++全局变量的构造与析构
动态链接的主要实现技术
• 方便程序开发,部属:         • 性能优化:
  方法:程序的各模块独立,       方法:延迟绑定(Lazy
  装载时才链接(符号查找,
                       Binding)
  重定位).
                      技术实现:函数链接表
• 节约内存:
                       (PLT)
  方法: 地址无关代码(PIC)
                     • 程序的可扩展性与兼容性:
  技术实现:全局偏移量表
                      方法: 显式运行时加载
  (GOT)
主要实现技术—相关数据结构

• .interp 节: 动态链接器 ld.so
• .dynamic 节: 保存了动态链接器所需的基本信息,
• 动态符号表:
    .dynsym: 只保存与动态链接相关的符号;
    .dynstr: 动态符号字符串表:
    .hash .gnu.hash: 输助的符号哈唏表
• 动态链接相关的重定位表:
    .rela.plt : 对数据引用的修正,它所修正的位置
     位于".got" 和数据段.
    .rela.dyn : 对函数引用的修正,它所修正的位
     置位于".got.plt"
动态链接的实现--地址无关代码
动态链接的实现--地址无关代码



     类型 2:模块内部的数据访问


     类型 4:模块外部的数据访问

     类型 1:模块内部的函数调用

     类型 3:模块外部的函数调用
The Procedure Linkage Table
模块外部的访问与延迟绑定
显式运行时加载
#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:符号查找优先在本共享库的符号表,找
    不到才去全局符号表中查找
显式运行时加载
void *dlsym(void *handle, const char *symbol);
• 功能:返回指定符号的地址
• handle 取值:
   RTLD_DEFAULT: 直接在可执行程序的全局符号
   表中查找
  RTLD_NEXT: 在可执行程序的全局符号表中查找
   第2次出现的符号。
  dlopen 返回的 handle
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;

}
动态链接过程
 程序加载

 动态链接器自举

 处理环境变量

 装载共享对象

 重定位和初始化
动态链接过程—内存组织关系
动态链接过程—内存组织关系
动态链接过程—内存组织关系
符号的优先级与全局符号介入—示例1

• tcmalloc 是怎么生效的?

• 静态库: libtcmalloc.a ?

• 动态库: libtcmalloc.so
符号的优先级与全局符号介入—示例2
• cmclient_v1




• cmclient_v2
符号的优先级与全局符号介入—示例2
• dso
符号的优先级与全局符号介入—示例2
• case01: symbol_priority_dlopen




• case02: symbol_priority_dlopen_deepbind
符号的优先级与全局符号介入—示例2
• case03: symbol_priority_link
符号的优先级与全局符号介入—示例2
• case01: symbol_priority_dlopen




• case02: symbol_priority_dlopen_deepbind




 • case03: symbol_priority_link
C++全局变量的构造与析构—示例
C++全局变量的构造与析构—示例
C++全局变量的构造与析构—示例
C++全局变量的构造与析构—示例
C++全局变量的构造与析构—case01&case02
Case01:




Case02:
C++全局变量的构造与析构—case03
Case03:
C++全局变量的构造与析构—依赖关系(1)
C++全局变量的构造与析构—case01
C++全局变量的构造与析构—case02
C++全局变量的构造与析构—case03
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
C++全局变量的构造与析构--.ctors 节的形成
C++全局变量的构造与析构
C++全局变量的构造与析构
C++全局变量的构造与析构—case01
C++全局变量的构造与析构—case02
C++全局变量的构造与析构—示例
C++全局变量的构造与析构—依赖关系(2)
C++全局变量的构造与析构—case04&case05
Case04:




Case05:
C++全局变量的构造与析构—case04
C++全局变量的构造与析构—case05
C++全局变量的构造与析构—case05
C++全局变量的构造与析构—case06&case07
Case06:




Case07:
C++全局变量的构造与析构—case06
C++全局变量的构造与析构—case07
ELF 文件结构概述
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;
}
ELF 文件结构概述
ELF 文件结构概述
名称          说明

文件头         位于目标文件最开始的位置,含有整个文件的一些基本信息.

程序头表        一个可执行文件或共享目标文件的程序头表是一个数组,数组
            中的每一个元素称为“程序头”.描述了一个
            “段(segment)”或者一块用于准备执行程序的信息。

节头表         是一个数组,每一项是一个 Elf32(64)_Shdr 结构,通过每一个表
            项可以定位到对应的节。
.strtab 表   字符串表包含有若干个以’null’结尾的字符序列,即字符串. 保存
            符号的名字或者节的名字
.symtab 表 符号表包含用来定位、重定位程序中符号定义和引用的信息。

重定位表        含如何修改其节区内容的信息,从而允许可执行文件和共享目
            标文件保存进程的程序映像的正确信息.静态链接:.rela.text
            和 .rela.data); 动态链接:.rela.plt 和.rela.dyn
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)
ELF ‘Views’ – Split
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)
ELF ‘Views’ - Linking to Loading
ELF 文件结构概述

• 实际示例(understanding_elf.rar):

• part_o.pdf

• main_s.pdf
参考资料

• <程序员的自我修养—链接、装载与库>

• <连接器和加载器>

• <ELF_Format.pdf>

• http://blog.chinaunix.net/uid/725631/frmd/18945.
  html

• Glibc 和 binutils 源码
谢 谢 !

Más contenido relacionado

La actualidad más candente

MySQL源码分析.01.代码结构与基本流程
MySQL源码分析.01.代码结构与基本流程MySQL源码分析.01.代码结构与基本流程
MySQL源码分析.01.代码结构与基本流程
Lixun Peng
 
Python 脚本入门基础
Python 脚本入门基础Python 脚本入门基础
Python 脚本入门基础
wklken
 
程式設計師的自我修養 Chapter 8
程式設計師的自我修養 Chapter 8程式設計師的自我修養 Chapter 8
程式設計師的自我修養 Chapter 8
Shu-Yu Fu
 
Scala function-and-closures
Scala function-and-closuresScala function-and-closures
Scala function-and-closures
wang hongjiang
 
第06章 树和二叉树(java版)
第06章  树和二叉树(java版)第06章  树和二叉树(java版)
第06章 树和二叉树(java版)
Yan Li
 
深入剖析Concurrent hashmap中的同步机制(上)
深入剖析Concurrent hashmap中的同步机制(上)深入剖析Concurrent hashmap中的同步机制(上)
深入剖析Concurrent hashmap中的同步机制(上)
wang hongjiang
 
Hadoop学习总结
Hadoop学习总结Hadoop学习总结
Hadoop学习总结
ordinary2012
 

La actualidad más candente (19)

MySQL源码分析.01.代码结构与基本流程
MySQL源码分析.01.代码结构与基本流程MySQL源码分析.01.代码结构与基本流程
MySQL源码分析.01.代码结构与基本流程
 
Python 脚本入门基础
Python 脚本入门基础Python 脚本入门基础
Python 脚本入门基础
 
程式設計師的自我修養 Chapter 8
程式設計師的自我修養 Chapter 8程式設計師的自我修養 Chapter 8
程式設計師的自我修養 Chapter 8
 
Scala function-and-closures
Scala function-and-closuresScala function-and-closures
Scala function-and-closures
 
functional-scala
functional-scalafunctional-scala
functional-scala
 
C python 原始碼解析 投影片
C python 原始碼解析 投影片C python 原始碼解析 投影片
C python 原始碼解析 投影片
 
函数调用关系工具-2011-孙光福
函数调用关系工具-2011-孙光福函数调用关系工具-2011-孙光福
函数调用关系工具-2011-孙光福
 
系統程式 -- 第 5 章 連結與載入
系統程式 -- 第 5 章 連結與載入系統程式 -- 第 5 章 連結與載入
系統程式 -- 第 5 章 連結與載入
 
Google protocol buffers简析
Google protocol buffers简析Google protocol buffers简析
Google protocol buffers简析
 
Practical Data Analysis in R
Practical Data Analysis in RPractical Data Analysis in R
Practical Data Analysis in R
 
系統程式 -- 第 12 章
系統程式 -- 第 12 章系統程式 -- 第 12 章
系統程式 -- 第 12 章
 
系統程式 -- 第 2 章
系統程式 -- 第 2 章系統程式 -- 第 2 章
系統程式 -- 第 2 章
 
第06章 树和二叉树(java版)
第06章  树和二叉树(java版)第06章  树和二叉树(java版)
第06章 树和二叉树(java版)
 
第四章 串操作应用举例
第四章 串操作应用举例第四章 串操作应用举例
第四章 串操作应用举例
 
Oracle试题Exam Adminv1.1
Oracle试题Exam Adminv1.1Oracle试题Exam Adminv1.1
Oracle试题Exam Adminv1.1
 
深入剖析Concurrent hashmap中的同步机制(上)
深入剖析Concurrent hashmap中的同步机制(上)深入剖析Concurrent hashmap中的同步机制(上)
深入剖析Concurrent hashmap中的同步机制(上)
 
Hadoop学习总结
Hadoop学习总结Hadoop学习总结
Hadoop学习总结
 
Clojure简介与应用
Clojure简介与应用Clojure简介与应用
Clojure简介与应用
 
Coreseek/Sphinx 全文检索实践指南
Coreseek/Sphinx 全文检索实践指南Coreseek/Sphinx 全文检索实践指南
Coreseek/Sphinx 全文检索实践指南
 

Destacado

Destacado (7)

Redis 内存存储结构分析 -wuzhu--20110418
Redis 内存存储结构分析 -wuzhu--20110418Redis 内存存储结构分析 -wuzhu--20110418
Redis 内存存储结构分析 -wuzhu--20110418
 
ScyllaDB @ Apache BigData, may 2016
ScyllaDB @ Apache BigData, may 2016ScyllaDB @ Apache BigData, may 2016
ScyllaDB @ Apache BigData, may 2016
 
Back to the future with C++ and Seastar
Back to the future with C++ and SeastarBack to the future with C++ and Seastar
Back to the future with C++ and Seastar
 
Scylla Summit 2016: ScyllaDB, Present and Future
Scylla Summit 2016: ScyllaDB, Present and FutureScylla Summit 2016: ScyllaDB, Present and Future
Scylla Summit 2016: ScyllaDB, Present and Future
 
Scylla Summit 2016: Scylla at Samsung SDS
Scylla Summit 2016: Scylla at Samsung SDSScylla Summit 2016: Scylla at Samsung SDS
Scylla Summit 2016: Scylla at Samsung SDS
 
Seastar / ScyllaDB, or how we implemented a 10-times faster Cassandra
Seastar / ScyllaDB,  or how we implemented a 10-times faster CassandraSeastar / ScyllaDB,  or how we implemented a 10-times faster Cassandra
Seastar / ScyllaDB, or how we implemented a 10-times faster Cassandra
 
Performance Monitoring: Understanding Your Scylla Cluster
Performance Monitoring: Understanding Your Scylla ClusterPerformance Monitoring: Understanding Your Scylla Cluster
Performance Monitoring: Understanding Your Scylla Cluster
 

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

3 hibernate映射元素和类型
3 hibernate映射元素和类型3 hibernate映射元素和类型
3 hibernate映射元素和类型
Zelin Wang
 
C++工程实践
C++工程实践C++工程实践
C++工程实践
Shuo Chen
 
第9章 Shell 編程
第9章 Shell 編程第9章 Shell 編程
第9章 Shell 編程
kidmany2001
 
主备备的两个备机转为双Master出现诡异的slave lag问题
主备备的两个备机转为双Master出现诡异的slave lag问题主备备的两个备机转为双Master出现诡异的slave lag问题
主备备的两个备机转为双Master出现诡异的slave lag问题
haojiewang
 
Cassandra简介.ppt
Cassandra简介.pptCassandra简介.ppt
Cassandra简介.ppt
james tong
 
第02章 线性表(java版)
第02章  线性表(java版)第02章  线性表(java版)
第02章 线性表(java版)
Yan Li
 

Similar a Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509 (20)

看似比較簡單的推坑教學 C語言從崩潰到崩潰Ex(二)
看似比較簡單的推坑教學 C語言從崩潰到崩潰Ex(二)看似比較簡單的推坑教學 C語言從崩潰到崩潰Ex(二)
看似比較簡單的推坑教學 C語言從崩潰到崩潰Ex(二)
 
3 hibernate映射元素和类型
3 hibernate映射元素和类型3 hibernate映射元素和类型
3 hibernate映射元素和类型
 
Introduction to C++ over CLI
Introduction to C++ over CLIIntroduction to C++ over CLI
Introduction to C++ over CLI
 
C++工程实践
C++工程实践C++工程实践
C++工程实践
 
Dev307
Dev307Dev307
Dev307
 
第9章 Shell 編程
第9章 Shell 編程第9章 Shell 編程
第9章 Shell 編程
 
Return to dlresolve
Return to dlresolveReturn to dlresolve
Return to dlresolve
 
getPDF.aspx
getPDF.aspxgetPDF.aspx
getPDF.aspx
 
getPDF.aspx
getPDF.aspxgetPDF.aspx
getPDF.aspx
 
Kid171 chap03 traditional Chinese Version
Kid171 chap03 traditional Chinese VersionKid171 chap03 traditional Chinese Version
Kid171 chap03 traditional Chinese Version
 
Linux binary Exploitation - Basic knowledge
Linux binary Exploitation - Basic knowledgeLinux binary Exploitation - Basic knowledge
Linux binary Exploitation - Basic knowledge
 
HW4_0711282.pdf
HW4_0711282.pdfHW4_0711282.pdf
HW4_0711282.pdf
 
Row Set初步学习V1.1
Row Set初步学习V1.1Row Set初步学习V1.1
Row Set初步学习V1.1
 
系統程式 -- 第 5 章
系統程式 -- 第 5 章系統程式 -- 第 5 章
系統程式 -- 第 5 章
 
软件工程
软件工程软件工程
软件工程
 
Hibernate教程
Hibernate教程Hibernate教程
Hibernate教程
 
主备备的两个备机转为双Master出现诡异的slave lag问题
主备备的两个备机转为双Master出现诡异的slave lag问题主备备的两个备机转为双Master出现诡异的slave lag问题
主备备的两个备机转为双Master出现诡异的slave lag问题
 
Cassandra简介.ppt
Cassandra简介.pptCassandra简介.ppt
Cassandra简介.ppt
 
第02章 线性表(java版)
第02章  线性表(java版)第02章  线性表(java版)
第02章 线性表(java版)
 
HITCON CTF 2014 BambooFox 解題心得分享
HITCON CTF 2014 BambooFox 解題心得分享HITCON CTF 2014 BambooFox 解題心得分享
HITCON CTF 2014 BambooFox 解題心得分享
 

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