October 26, 2017

操作系统学习1 ld 初步

说明

本文分析 toaruos 早期版本(cdff01) 的 linker script,学习相关 linker 知识。

代码

	 // 指定输出类型
     1	OUTPUT_FORMAT("binary")
	 // 指定入口函数
     2	ENTRY(start)
	 // 定义变量
     3	phys = 0x00100000;
	 // 以下表示输出定义
	 // 1. 输入到输出的映射关系
	 // 2. 控制输出的内存 layout
     4	SECTIONS
     5	{
     		// 输出 .text 包括所有输入文件的 .text 和 .rodata section
			// phs 为 VMA(虚拟地址)
			// AT(phs) 为 LMA(加载地址)
			// 两者是相同的,可以不用设置
     6		.text phys : AT(phys) {
     7			code = .;
     8			*(.text)
     9			*(.rodata)
		        // 接下来的 .data 段开始位置按 4096 对齐
    10			. = ALIGN(4096);
    11		}
    12		.data : AT(phys + (data - code))
    13		{
    14			data = .;
    15			*(.data)
    16			. = ALIGN(4096);
    17		}
    18		.bss : AT(phys + (bss - code))
    19		{
    20			bss = .;
    21			*(.bss)
    22			. = ALIGN(4096);
    23		}
    24		end = .;
    25	}

知识点

linker 的作用

linker 将多个输入的 object file 合并为一个输出文件,主要包括三个方面

  1. 将输入的多个 object file 映射到一个输出 object file
  2. 控制输出文件的内存分布

为什么需要 linker

将代码分成小的单元,分别进行编译。避免每次修改重新编译全部,而只需要局部编译。

链接将局部生成的小的 object file 合并生成一个大文件

object file

object file 中包含有多个 section 和 symbols table。

section 根据加载位置和内容不同可以分为三类:

  1. loadable: section 可以被加载到内存中
  2. allocatable: 如 rss 被动态申请到内存空间中,并不真正占用 object file 空间
  3. 其它:如包含 debug 信息等作用

地址

object file 中的 section 地址有二种:

  1. VMA:虚拟内存地址
  2. LMA:加载内存地址

语法

  1. SECTION 命令中可以指定每个输出 section 对应的输入,以及内存分布情况: 输出 : {输入*}
  2. .text: *(.text) 表示 .text 输出包含了所有文件(用 * 表示)中的 .text
  3. . 表示 location counter,即当前位置。可以被赋值