Linux 第七章学习笔记
2016-04-07 18:28
274 查看
1:链接概述
链接(linking)是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或被拷贝)到存储并执行。
编译系统提供的调用预处理器、编译器、汇编器和链接器来构造目标文件的。
2.静态链接
为了构造可执行文件,链接器的两个主要任务
符号解析:目标文件定义和引用符号。符号解析的目的是将每个符号引用刚好和一个符号定义联系起来。重定位:编译器和汇编器生成从地址0开始的代码和数据节。链接器通过把每个符号定义与一个存储器位置联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储器位置,从而重定位这些节。
3.目标文件
三种形式可重定位目标文件:包含二进制代码和数据,其形式可以在编译时与其他可重定位目标文件合并起来,创建一个可执行目标件。
可执行目标文件:包含二进制代码和数据,其形式可以被直接拷贝到存储器并执行。
共享目标文件:一种特殊类型的可重定位目标文件,可以在加载或者运行地被动态地加载到存储器并链接。
4.可重定位目标文件
一个典型的ELF可重定位目标文件的格式:ELF文件已经是适应到某一种CPU体系结构的二进制兼容文件了。
默认的ELF头加载地址是0x8048000,头部大概要到0x48100处或者0x483000处,也就是可执行文件加载到内存之后
5.符号和符号表
每个可重定位目标模块m都有一个符号表,它包含m所定义和引用的符号的信息。
链接器上下文中的三种不同符号
由m定义并能被其他模块引用的全局符号。
由其他模块定义并被模块m引用的全局符号。
只被模块m定义和引用的本地符号。
符号表
intname;//字符串表中的字节偏移,指向符号的以NULL结尾的名字
intvalue;//符号的地址,对于可重定位的模块是距定义目标的节起始位置的偏移。
intsize;//目标大小(单位:字节)
chartype:4,//数据或函数
binding:4;//本地LOCAL/全局GLOBAL
charreserved;
charsection;//到节头部表的索引
}Elf_Symbol;
每个符号都和目标的某个节相关联,由section字段表示。
ABS:不该被重定位的符号。
UNDEF:未定义的符号,在本目标模块中引用,但在其他地方定义。
COMMON:未被分配位置的未初始化数据目标。
6.符号解析
与静态库链接
所有的编译系统都提供一种机制,将所有相关的目标模块打包成为一个单独的文件,称为静态库(Linux下是存档文件,Windows下是lib),只拷贝静态库里被应用程序引用的目标模块。链接时加上-static参数告诉编译器驱动程序,链接器应该构建一个完全链接的可执行目标文件,它可以加载到存储器并执行,在加载时无需更进一步的链接。
7.重定位
(1)重定位两步
(2)重定位条目
ELF定义了11种不同的重定位类型。两种最基本的重定位类型:*R_386_PC32重定位一个使用32位PC相对地址的引用。
*R_386_32重定位一个使用32位绝对地址的引用。
(3)重定位符号引用
链接器修改代码节和数据节中对每个符号的引用,使得他们指向正确的运行时地址。重定位PC相对引用 重定位绝对引用
8.可执行目标文件及加载
(1)可执行目标文件
C程序开始时是一组ASCII文本文件,已经被转化为一个二进制文件,且这个二进制文件包含加载程序到存储器并运行它所需的所有信息。段头部表:可执行文件的连续片被映射到连续的存储器段,段头部表描述了这种关系。
在32位Linux系统中,代码段总是从地址0x08048000处开始。
(2)加载可执行目标文件
加载器将可执行目标文件中的执行代码和数据从磁盘拷贝到存储器中,然后通过跳转到程序的第一条指令或入口点来运行该程序。这个将程序拷贝到存储器并运行的过程叫做加载。
要运行可执行目标文件p,可以在Unix外壳的命令行中输入它的名字:unix>./p
将程序拷贝到存储器并运行的过程叫做加载。
用户栈总是最大的合法用户地址开始,向下增长的(向低存储器地址方向增长)。从栈的上部开始的段是为操作系统驻留存储器
的部分(内核)的代码和数据保留的。
9.动态连接共享库
动态链接器通过执行下面的重定位完成链接任务:重定位libc.so的文本和数据到某个存储器段
重定位libvector.so的文本和数据到另一个存储器段
重定位p2中所有对libc.so和libvector.so定义的符号的引用
最后动态链接器将控制传递给应用程序,此时共享库的位置已固定,并且在程序执行的过程中不会改变
(1)静态库的缺点
首先,静态库在更新时,使用该库的程序需要与更新的库进行重新链接。其次,由于使用静态库的程序在链接时都会拷贝静态库里被应用程序引用的目标模块,像printf和scanf这样的函数的代码在运行时都会被复制到每个运行进程的文本段中,这造成了冗余,浪费了稀缺的存储器资源。
(2)共享库
共享库是一个目标模块,在运行时,可以加载到任意的存储器地址,并和一个在存储器中的程序链接起来。这个过程称为动态链接,是由一个叫做动态链接器的程序来执行的。
共享库也称为共享目标,在Unix系统中通常用.so后缀来表示。微软的操作系统大量地利用了共享库,它们称为DLL(动态链接库)。
共享库是以两种不同的方式来“共享”的(在Windows中分别称为“隐式链接”和“显示链接”)。
而不是像静态库的内容那样被拷贝和嵌入引用它们的可执行的文件中。
2:在存储器中,一个共享库的.text节一个副本可以被不同的正在运行的进程共享。
10.从应用程序中加载和链接共享库
void*dlsym(void*restricthandle,constchar*restrictname);//回一个指向被请求入口点的指针
char*dlerror();//返回NULL或者一个指向描述最近错误的ASCII字符串的指针
char*dlclose(void*handle);//关闭句柄并且取消共享目标文件的映射
11.处理目标文件的工具
相关文章推荐
- Linux单向pint通
- linux常用命令大全
- java开发常用的linux命令
- red hat linux下安装mysql
- VMware安装centos6.7后开机,提示kernel panic - not syncing : attempted to kill init 完整解决方案
- linux安装AWStats业务数据分析工具
- vim 常用命令
- Linux下Qt4与qt5的程序使用输入法(ibus与fcitx)不冲突
- linux本地yum源配置
- Linux下同时运行不同版本的qt程序
- linux下的C语言带参数的main函数
- 在linux中install命令和cp命令的区别
- linux 第七周 总结及实验
- Linux命令全称及目录结果
- Linux 第七周实验 及总结
- Linux下添加FTP账号和服务器、增加密码和用户,更改FTP目录(转)
- CentOS x64 安装Matlab R2015b
- LINUX 学习篇
- Linux如何配置ftp服务器、给ftp服务器添加访问用户
- linux下查看某一软件是否安装