link_elf

学习使用的平台与工具
archlinux , nasm, ia16-gcc, make, cmake

ld

作为一个完整程序生成中间的一个重要工具,ld是将各个源程序编译成的.o 根据link.ld脚本中的结构将.o文件中的各个section 严格完整的排序合并,然后对程序中的各个符号进行解析并对各个子程序调用进行重定位。
所以我们最重要的是要了解linker script是如何严密的组织机器码在内存中的结构的。

linker script

vma lma

Every loadable or allocatable section has two address, the first is VAM or virtual memory address. This is the address the section will have when the output file is run.
详细来说vma可以用于处理标号在内存中运行时候的实际地址,程序内部的寻址,跳转,指针运算都要依赖vma构成的逻辑地址空间

the second is LVM, or load memory address.This is the address at which the section will be loaded
LVM则最终决定最后生成的bin文件中各个section最终会被安排进的实际位置

example

1
2
3
4
5
6
7
8
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}

通常一个简单的链接脚本只需要一个section 字段就行,一个section足以完成大部分的任务,并且多个section安排的内存空间通常一个section 也能完成。
假设我们的代码是由code, 初始化的数据以及未初始化的数据构成的,他们经过初步编译完后会被放在.text, .data, .bass section中。

上面的例子中.text section会被加载到0x10000开始的地址中,而.data与.bss数据段会被加载到0x8000000开始的地址中(这里的vma与lma是相同的)

在sections字段开始地址计数器会被至为0但是如果使用. = location 则会按照设定的地址进行计数
上面的例子中sectoin的subcommond .text .data .bss是output section

entry point

入口点分为硬件入口点以及软件入口点

硬件入口点的固定地址为0xFFFF0是不可动通常

1
ENTRY(symbol)  ;设置入口点其实就是为入口点设置一个标识符并且通常将这个标识符所在的代码放在.text的首位

Commands Dealing with Files

1
2
3
4
5
6
7
8
INPUT(finename[, finename[, filename]])   ;告诉链接器,除了命令行上提供的 .o 文件外,还必须链接这里指定的文件

GROUP(file1, file2, ...) ;用于静态库中解决循环链接的问题

AS_NEEDED(file1, file2, ...) ;只有当某个库确实存在之前代码中为解析到的符号的时候才会链接。

INCLUDE filename ;它会将另一个链接器脚本文件的内容,原封不动地“粘贴”到当前位置。

assign to a symbol

e.g.

1
2
3
4
5
6
7
8
9
symbol = expression ;
symbol += expression ;
symbol -= expression ;
symbol *= expression ;
symbol /= expression ;
symbol <<= expression ;
symbol >>= expression ;
symbol &= expression ;
symbol |= expression ;