内存
目标文件
其他段
将一个二进制的文件,比如图片,MP3音乐作为目标文件中的一个段
objcopy -I binary -O elf32-i386 -B i386 image.jpg image.o
objdump -ht image.o
自定义段
将此相应的i变量放到对应的 name 段中
__attribute__((section(".FOO"))) int global = 42;
//格式
__attribute__((section("name"))) int global = 42;
ELF文件结构描述
ELF魔数:程序加载时,操作系统会判断魔数是否正确。
ELF可执行文件默认地址从0x08048000开始分配
ELF解析
强符号与弱符号
定义:
- 编译器默认函数和初始化的全局变量为强符号
- 未初始化的全局变量为弱符号
-
规则:
不允许去强符号被多次定义(即不同的目标文件中不能有同名的强符号)
- 如果一个符号存在强符号与弱符号,那么选择强符号
- 如果一个符号所在的目标文件都是弱符号,选择占用控件最大的一个,
Common 块
把所有的未初始化的全局变量不以COMMON块形式处理 当未初始化的全局变量不以COMMON块的形式处理,相当于是一个强符号,容易导致引起符号重定义
int global __attribute__((nocommon)); //
gcc -fno-common
最小ELF可执行文件
最小elf 可以缩减到45个字节
- ld 链接器默认生成.shstrtab .symtab .strtab 这三个段(符号表和字符串表是可选的,段名字符串表保存段名,不可缺少)
链接器脚本
链接器脚本6、可执行文件的装载与进程
6.4、页错误
当进程运行时,CPU读出程序的入口地址获取指令,即.text的起始地址,发现页面0x0804800~0x0804900是个空页面,于是产生页错误(Page Fault) ,CPU将控制权交给操作系统,操作系统将分配物理页面与虚拟页面进行映射,然后把控制权交给进程,进程从刚才的错误页面重新开始执行。
6.5、Linux内核装载ELF过程
8、共享库的组织
8.1 共享库的版本命名(xxx.so.x.y.z)
x:主版本号(重大升级)
y:次版本号(增量升级)
x:发布版本号(错误修正,性能改进)
8.2 符号版本机制实践
gcc -shared -fPIC lib.c -Xlinker --version-script lib.x.y.z -o lib.so
//lib.ver VERS_1.2 为版本标签,可随意
VERS_1.2{
global:
foo;
local:
*;
}
8.3 共享库查找路径
ld.so.conf 是一个文本配置文件,包含了so的路径
ldconfig 会将so-name 的信息,放到/etc/ld.so.cache中,建立缓存,方便动态链接器查找共享库。
LD_LIBRARY_PATH 动态库查找路径
LD_PRELOAD 预先装载的so,比LD_LIBRARY_PATH 优先级高
LD_DEBUG 打开动态链接器的调试功能 (LD_DEBUG=xx ./bin)
8.4 共享库的构造和析构函数
# number 为优先级
void __attribute__((constructor(number))) xxxx();
void __attribute__((destructor(number))) xxxx();
8.5 环境变量
LD_DEBUG
打印动态链接器的调试功能
- bindings 显示动态链接的符号绑定过程
- libs 显示共享库查找的过程
- versions 显示符号的版本依赖关系
- reloc 显示重定位过程
- symbols 显示符号查找过程
- statistics 显示动态链接过程中的各种统计信息
- all 显示以上所有信息
- help 显示上面各种选值的帮助信息
$LD_DEBUG=files ./xxx