可执行程序产生流程;
源文件->预处理器->编译器->链接器->可执行目标文件
预处理器(preprocessor):执行以#开头的指令,预处理器可以删除注释,包含其他文件以及执行宏(宏macro是一段重复文字的简短描写)替代.
类似于编辑器,可以给程序添加内容,也可以进行修改.
编译器(compiler):将程序翻译成机器指令,即目标代码,但这样的程序还不可执行
链接器(linker):将编译器产生的目标代码和所需的其它附加代码整合在一起,最终产生可以执行的程序. 链接器(Linker)是一个程序,将一个或多个由汇编器或编译器生成的目标文件外加库链接成为一个可执行文件.
本文主要学习链接器.
链接:将各段代码和数据收集起来组合为单一文件.
链接器的主要工作:
1.符号解析.目标文件定义和引用的符号,将每个符号引用刚好和一个符号定义联系起来.
什么是符号?比如定义了一个函数,那么函数名就是一个符号.定义一个变量,那么变量名就是一个符号.
符号表就是记录符号名,以及符号定义所在地址位置信息的表.
和符号表对应的是重定位表,记录在某个位置引用某个符号.
CPU是不认识符号的,它只认识指令和地址,最终符合都会被地址所替代.
2.重定位. 编译器生成地址从零开始的代码和数据段.链接器将每个符号定义与一个存储器位置联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储器位置.从而重新定义这些段.
then ICF文件 . IAR用链接器ILINK, 参考文件EWARM_DevelopmentGuide.ENU . pdf
一个标准的ICF文件包括下面内容;
1.可编程存储空间(memory)
2.不同的存储器地址区域(region)
3.不同的地址块(block)
4.Section的初始化与否
4.Section在存储空间中的放置
下 面介绍了几条ICF文件中常见的指令,详细内容请参考ILINK相关说明文档(EWARM_DevelopmentGuide.pdf):
1. define [ exported ] symbol name = expr;
作用: 指定某个符号的值。
参数: exported 导出该symbol,使其对可执行镜像可用
name --符号名
expr --符号值
举例:
define symbol RAM_START_ADDRESS = 0x40000000;
define symbol RAM_END_ADDRESS = 0x4000FFFF;
2. define memory name with size = expr [, unit-size];
作用: 定义一个可编址的存储地址空间(memory)。
参数: name --memory的名称
expr --地址空间的大小
unit-size --expr的单位,可以是位(unitbitsize),缺省是字节(unitbytesize)
举例:
define memory MEM with size = 4G;
3. define region name = region-expr;
作用: 定义一个存储地址区域(region)。一个区域可由一个或多个范围组成,每个范围内地址必须连续,但几个范围之间不必是连续的。
参数: name region的名称
region-expr memory:[from expr { to expr | size expr}],可以定义起止范围,也可以定义起始地址和region的大小
举例:
define region ROM = MEM:[from 0x0 size 0x10000];
define region ROM = MEM:[from 0x0 to 0xFFFF];
4. define block name[ with param, param... ]
{
extended-selectors
};
作用: 定义一个地址块(block);它可以是个空块,比如栈、堆;也可以包含一系列sections。
参数: name block的名称
param 可以是: size = expr (块的大小)
maximum size = expr (块大小的上限)
alignment = expr (最小对齐字节数)
fixed order (按照固定顺序放置sections)
extended-selector [ first | last ] { section-selector | block name | overlay name }
first 最先存放
last 最后存放
section-selector [ section-attribute ][ section sectionname ][object filename ]
section-attribute [ readonly [ code | data ] | readwrite [ code | data ] | zeroinit ]
sectionname section的名称
filename 目标文件的名称
即可以按照section的属性,名称及其所在目标文件的名称这三个过滤条件中,任意选取一个条件,或选取多个条件进行组合,来圈定所要求的 sections。
name block或overlay的名称
举例:
define block HEAP with size = 0x1000, alignment = 4 { };
define block MYBLOCK1 = { section mysection1, section mysection2, readwrite };
define block MYBLOCK2 = { readonly object myfile2.o };
5. initialize { by copy | manually } [ with param, param... ]
{
section-selectors
};
作用: 初始化sections。
参数: by copy 在程序启动时自动执行初始化。
manually 在程序启动时不自动执行初始化。
param 可以是: packing = { none | compress1 | compress2 | auto }
copy routine = functionname
packing表示是否压缩数据,缺省是auto。
functionname表示是否使用自己的拷贝函数来取代缺省函数。
section-selector 同上
举例:
initialize by copy { rw };
6. do not initialize
{
section-selectors
};
作用: 规定在程序启动时不需要初始化的sections。一般用于__no_init声明的变量段(.noinit)。
参数: section-selector 同上
举例:
do not initialize { .noinit };
7. place at { address memory[: expr] | start of region_expr | end of region_expr }
{
extended-selectors
};
作用: 把一系列sections和blocks放置在某个具体的地址,或者一个region的开始或者结束处。
参数: memory memory的名称
expr 地址值,该地址必须在memory所定义的范围内
region_expr region的名称
extended-selector 同上
举例:
place at start of ROM { section .cstart }; place at end of ROM { section .checksum }; place at address MEM:0x0 { section .intvec };
8. place in region-expr
{
extended-selectors
};
作用: 把一系列sections和blocks放置在某个region中。sections和blocks将按任意顺序放置。
参数: region-expr region的名称
extended-selector 同上
举例:
place in ROM { readonly }; /* all readonly sections */
place in RAM { readwrite }; /* all readwrite sections */
place in RAM { block HEAP, block CSTACK, block IRQ_STACK };
place in ROM { section .text object myfile.o }; /* the .text section of myfile.o */
place in ROM { readonly object myfile.o }; /* all read-only sections of myfile.o */
place in ROM { readonly data object myfile.o }; /* all read-only data sections myfile.o */
FROM:http://blog.21ic.com/user1/5910/archives/2009/61982.html
下面是stm8s103 的ICF文件
/
// Example ILINK command file for
// STM8 IAR C/C++ Compiler and Assembler.
//
// Copyright 2010 IAR Systems AB.
//
// $Revision: 2384 $
//
/
define memory with size = 16M;
define region TinyData = [from 0x00 to 0xFF];
define region NearData = [from 0x0000 to 0x03FF];
define region Eeprom = [from 0x4000 to 0x427F];
define region NearFuncCode = [from 0x8000 to 0x9FFF];
define region FarFuncCode = [from 0x8000 to 0x9FFF];
define region HugeFuncCode = [from 0x8000 to 0x9FFF];
/
define block CSTACK with size = _CSTACK_SIZE {};
define block HEAP with size = _HEAP_SIZE {};
define block INTVEC with size = 0x80 { ro section .intvec };
// Initialization
initialize by copy { rw section .far.bss,
rw section .far.data,
rw section .far_func.textrw,
rw section .huge.bss,
rw section .huge.data,
rw section .huge_func.textrw,
rw section .iar.dynexit,
rw section .near.bss,
rw section .near.data,
rw section .near_func.textrw,
rw section .tiny.bss,
rw section .tiny.data,
ro section .tiny.rodata };
do not initialize { rw section .eeprom.noinit,
rw section .far.noinit,
rw section .huge.noinit,
rw section .near.noinit,
rw section .tiny.noinit,
rw section .vregs };
// Placement
place at start of TinyData { rw section .vregs };
place in TinyData { rw section .tiny.bss,
rw section .tiny.data,
rw section .tiny.noinit,
rw section .tiny.rodata };
place at end of NearData { block CSTACK };
place in NearData { block HEAP,
rw section .far.bss,
rw section .far.data,
rw section .far.noinit,
rw section .far_func.textrw,
rw section .huge.bss,
rw section .huge.data,
rw section .huge.noinit,
rw section .huge_func.textrw,
rw section .iar.dynexit,
rw section .near.bss,
rw section .near.data,
rw section .near.noinit,
rw section .near_func.textrw };
place at start of NearFuncCode { block INTVEC };
place in NearFuncCode { ro section .far.data_init,
ro section .far_func.textrw_init,
ro section .huge.data_init,
ro section .huge_func.textrw_init,
ro section .iar.init_table,
ro section .init_array,
ro section .near.data_init,
ro section .near.rodata,
ro section .near_func.text,
ro section .near_func.textrw_init,
ro section .tiny.data_init,
ro section .tiny.rodata_init };
place in FarFuncCode { ro section .far.rodata,
ro section .far_func.text };
place in HugeFuncCode { ro section .huge.rodata,
ro section .huge_func.text };
place in Eeprom { rw section .eeprom.noinit };
/