内存

虚拟地址与物理地址
分段 、分页

目标文件

其他段

将一个二进制的文件,比如图片,MP3音乐作为目标文件中的一个段

  1. objcopy -I binary -O elf32-i386 -B i386 image.jpg image.o
  2. objdump -ht image.o

自定义段

将此相应的i变量放到对应的 name 段中

__attribute__((section(".FOO"))) int global = 42;
//格式
__attribute__((section("name"))) int global = 42;

ELF文件结构描述

ELF魔数:程序加载时,操作系统会判断魔数是否正确。
ELF可执行文件默认地址从0x08048000开始分配
ELF解析

强符号与弱符号

定义:

  • 编译器默认函数和初始化的全局变量为强符号
  • 未初始化的全局变量为弱符号
  • attribute((weak)) 定义弱符号

    规则:

  • 不允许去强符号被多次定义(即不同的目标文件中不能有同名的强符号)

  • 如果一个符号存在强符号与弱符号,那么选择强符号
  • 如果一个符号所在的目标文件都是弱符号,选择占用控件最大的一个,

    Common 块

    把所有的未初始化的全局变量不以COMMON块形式处理 当未初始化的全局变量不以COMMON块的形式处理,相当于是一个强符号,容易导致引起符号重定义

int global __attribute__((nocommon)); // 
gcc -fno-common

GNU C/C++的符号机制

最小ELF可执行文件

最小elf 可以缩减到45个字节

  • ld 链接器默认生成.shstrtab .symtab .strtab 这三个段(符号表和字符串表是可选的,段名字符串表保存段名,不可缺少)

    链接器脚本

    链接器脚本

    6、可执行文件的装载与进程

    6.4、页错误

    当进程运行时,CPU读出程序的入口地址获取指令,即.text的起始地址,发现页面0x0804800~0x0804900是个空页面,于是产生页错误(Page Fault) ,CPU将控制权交给操作系统,操作系统将分配物理页面与虚拟页面进行映射,然后把控制权交给进程,进程从刚才的错误页面重新开始执行。
    image.pngimage.png

6.5、Linux内核装载ELF过程

image.png

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
    
    image.png