Chinaunix首页 | 论坛 | 博客
  • 博客访问: 830428
  • 博文数量: 85
  • 博客积分: 10016
  • 博客等级: 上将
  • 技术积分: 952
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-19 22:52
文章分类

全部博文(85)

文章存档

2011年(1)

2008年(1)

2007年(60)

2006年(23)

我的朋友

分类: LINUX

2007-07-20 02:25:17

1. 目标文件格式与类型

GNU C compiler根据源文件的后缀名来对文件进行预处理、汇编或编译操作。在编译链接时,生成的目标文件都是ELF格式的(可执行链接格式,Executable and Linking Format)Object文件格式有三种类型:

(1)可重定位(relocatable)文件:用来和其他的object文件一起链接为一个可执行文件(executable)或一个共享文件(.so文件,shared object)

(2)可执行(executable)文件;

(3)共享目标文件(shared object file):用于被下面的两个链接器链接。一是链接编辑器(ld),可以和其他的relocatableshared object file来创建其他的目标文件,例如.so共享库(可用file命令查看其属性);二是动态链接器,联合一个可执行文件和其他的shared object file来创建一个进程映像。


2. 链接与链接脚本

链接器ldobject文件中的每个section都作为一个整体,为其分配运行的地址(memory layout),这个过程就是重定位(relocation);最后把所有目标文件合并为一个目标文件。


链接通过一个linker script来控制,这个脚本描述了输入文件的sections到输出文件的映射,以及输出文件的memory layout

因此,linker总会使用一个linker script,如果不特别指定,则使用默认的script;可以使用‘-T’命令行选项来指定一个linker script


*映像文件的输入段与输出段

linker把多个输入文件合并为一个输出文件。输出文件和输入文件都是目标文件(object file),输出文件通常被称为可执行文件(executable)

每个目标文件都有一系列section,输入文件的section称为input section,输出文件的section则称为output section

一个section可以是loadable的,即输出文件运行时需要将这样的section加载到memory(类似于RO&RW);也可以是allocatable的,这样的section没有任何内容,某些时候用0对相应的memory区域进行初始化(类似于ZI);如果一个section既非loadable也非allocatable,则它通常包含的是调试信息。

每个loadableallocatableoutput section都有两个地址,一是VMA(virtual memory address),是该section的运行时域地址;二是LMA(load memory address),是该section的加载时域地址。

可以通过objdump工具附加'-h'选项来查看目标文件中的sections


*简单的Linker script

(1) SECTIONS命令:

The SECTIONS command tells the linker how to map input sections into output sections, and how to place the output sections in memory.

命令格式如下:

SECTIONS

{

sections-command

sections-command

......

}

其中sections-command可以是ENTRY命令,符号赋值,输出段描述,也可以是overlay描述。

(2) 地址计数器‘.’(location counter)

该符号只能用于SECTIONS命令内部,初始值为‘0’,可以对该符号进行赋值,也可以使用该符号进行计算或赋值给其他符号。它会自动根据SECTIONS命令内部所描述的输出段的大小来计算当前的地址。

(3) 输出段描述(output section description)

前面提到在SECTIONS命令中可以作输出段描述,描述的格式如下:

section [address] [(type)] : [AT(lma)]

{

output-section-command

output-section-command

...

} [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp]

很多附加选项是用不到的。其中的output-section-command又可以是符号赋值,输入段描述,要直接包含的数据值,或者某一特定的输出段关键字。


linker script 实例

==============================

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS {

    . = 0xa3f00000;

    __boot_start = .;

    .start ALIGN(4) : {

        *(.text.start)

    }

    .setup ALIGN(4) : {

        setup_block = .;

        *(.setup)

        setup_block_end = .;

    }

    .text ALIGN(4) : {

        *(.text)

    }

    .rodata ALIGN(4) : {

        *(.rodata)

    }

    .data ALIGN(4) : {

        *(.data)

    }

    .got ALIGN(4) : {

        *(.got)

    }

    __boot_end = .;

    .bss ALIGN(16) : {

        bss_start = .;

        *(.bss)

        *(COMMON)

        bss_end = .;

    }

    .comment ALIGN(16) : {

        *(.comment)

    }

    stack_point = __boot_start + 0x00100000;

    loader_size = __boot_end - __boot_start;

    setup_size = setup_block_end - setup_block;

}

=============================  

SECTIONS命令中的类似于下面的描述结构就是输出段描述:

.start ALIGN(4) : {

    *(.text.start)

}

.startoutput section nameALIGN(4)返回一个基于location counter(.)4字节对齐的地址值。*(.text.start)是输入段描述,*为通配符,意思是把所有被链接的object文件中的.text.start段都链接进这个名为.start的输出段。

源文件中所标识的section及其属性实际上就是对输入段的描述,例如.text.start输入段在源文件start.S中的代码如下:

.section .text.start

.global _start

_start :

    b start


[推荐阅读]
1.ARM学习报告002--GNU tool开发ARM程序及生成映象文件机理
2.Using ld, the GNU Linker



阅读(2759) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~