看视频学习
Binary Format
- 执行档的格式的格式会根据 OS 不同,而有所不同
- 执行档:可执行文件在计算机科学上,指一种内容可被电脑解释为程序的电脑文件。通常可执行文件内,含有以二进制编码的微处理器指令,也因此可执行文件有时称为二进制档。
- OS:一般指操作系统
- Linux - ELF
- Windows - PE
- 在 Binary 的开头会有个 magic number 栏位,方便让 OS 辨认是属于什么类型的档案
- 在 Linux 下可以使用 file 来 检视(检视:检验查看)
Segment
段是指占用数据文件空间的通称,或数据库对象使用的空间的集合;段可以有表段、索引段、回滚段、临时段和高速缓存段等;
- 在程序执行时期才有的概念,基本上会根据读写执行权限及特性来分为数个 segment
- 一般来说可分为 rodata、data、code、stack、heap 等 segment
- data : rw-
- code : r-x
- stack : rw-
- heap : rw-
- r – 可读
- w – 可写
- x – 可执行
Execution Flow (执行流程)
- What happened when we execute an elf file?
- #./hello
- 在一般情况下程式会在 disk 中,而 kernel 会通过一连串的过程将程序式 mapping(映射) 到记忆体中去执行
- 我们在 shell 执行一个 elf 时
- 会先去fork 一个 process
- child 再去使用 execve 执行
- sys_execve()
- 检查参数 ex: argv , envp
- do_execve()
- 搜寻执行档位置
- 读取执行档前 128 byte 获取执行档的资讯
- e.g. magic number
- search_binary_handler()
- 利用前面所获取的资讯来呼叫相对应的handler
- e.g. load_script()、load_elf_binary()
- load_elf_binary()
- 检查及获取 program header 资讯
- 如果是 dynamic linking(动态链路) 则利用 .interp 这个 section 来确定 loader 路径
- 将 program header 记录的位置 mapping 到 memory 中,e.g. code segment 位置
- 将 sys_execve 的 return address 改为 loader (ld.so) 的 entry point
- static linking 下则会时 elf 的 entry point
- How program maps to virtual memory
- 在 program header 中
- 记录着那些 segment 应该 mapping 到什么位置,以及该 segment 的读写执行权限
- 记录那些 section 属于那些 segment
- 当 program mapping 记忆体时会根据权限的不同分为好几个 segment
- 一个 segment 可以包含0个到多个 section
- 在 program header 中
- How program maps to virtual memory
- readelf -l binary
- 查看 program header
- readelf -S binary
- 查看 section header
- readelf -d binary
- 查看 dynamic section 内容
- readelf -l binary
- ld.so
- 载入 elf 所需的 shared library
- 这部分会记录在 elf 中的 DT_NEED中
- 初始化 GOT
- 其他相关初始化的动作
- ex:将 symbol table 合并到 global symbo table 等等
- 在 ld.so 执行完后会跳到 _start 开始执行主要程式
- 载入 elf 所需的 shared library
- _start
- 将下列项目传给 libc_start_main
- 环境变数起始位置
- main 的位置(通常在第一个参数)
- .init
- 呼叫 main 之前的初始化工作
- .fini
- 程序结束前的收尾工作
- 将下列项目传给 libc_start_main
- _libc_start_main
- 执行 .init
- 执行 main
- 主程式部分
- 执行 .fini
- 执行 exit 结束程式