您的位置:首页 > 其它

连接脚本(linker script)介绍

2010-12-15 22:41 197 查看
摘要:一些连接脚本示例。
关键字: 连接脚本   linker script    lds文件
连接脚本的详细介绍可以参考:http://sourceware.org/binutils/docs/ld/Scripts.html#Scripts,一个简单的lds文件如下所示:
1:  OUTPUT_FORMAT("elf32-i386", "elf32-i386","elf32-i386")


2:  OUTPUT_ARCH(i386)


3:  ENTRY(_start)


4:  SECTIONS


5:  {


6:      .text :


7:      {


8:          * (.text)


9:      }


10:


11:    .data :


12:      {


13:          * (.data)


14:      }


15:


16:      _bss_start = . ;


17:      .bss :


18:      {


19:          * (.bss)


20:      }


21:      _bss_end = . ;


22:  }


.codearea{ color:black; background-color:white; line-height:18px; border:1px solid #4f81bd; margin:0; width:auto !important; width:100%; overflow:auto; text-align:left; font-size:12px; font-family: "Courier New","Consolas","Fixedsys","BitStream Vera Sans Mono", courier,monospace,serif}
.codearea pre{ color:black; line-height:18px; padding:0 0 0 12px !important; margin:0em; background-color:#fff !important}
.linewrap pre{white-space:pre-wrap; white-space:-moz-pre-wrap; white-space:-pre-wrap; white-space:-o-pre-wrap; word-wrap:break-word; word-break:normal}
.codearea pre.alt{ background-color:#f7f7ff !important}
.codearea .lnum{color:#4f81bd;line-height:18px}

但是如果在PC平台,使用了标准库的话,这个lds还不够完整。

通常情况下,ld使用默认的连接脚本,这个脚本内嵌到ld文件中了。可以使用下面的命令查看:

ld –verbose
或者使用输出重定向,将其导出到一个lds文件中(当然需要稍作修改,把文件前面几句额外的说删除)。

ld –verbose > default.lds
可以使用下面的命令来使用这个default.lds

gcc –o hello hello.c –Wl,-Tdefault.lds
“-Wl,”后面不要有空格。当然也可以直接使用ld命令然后将-Tdefault.lds作为参数传入,但是那样比较麻烦,如果程序中使用了标准库,必须手动配置一些库文件,不然ld连接不成功,具体可以看这篇文章《gcc编译,ld连接》。如果仅仅是为了测试连接脚本的使用,还是上面的方式比较简单。

即使一个简单的hello.c程序,如果使用gcc直接编译,也会默认的增加一起初始化和标准库的代码,所以默认的default.lds相对来说并不简单,做测试的话,建议直接在上面增加自己的代码段。

PROVIDE (etext = .);


/* 对齐 */


. = ALIGN(4) ;


__m_section_init = .;


/* 测试下面一个语句会不会占用空间,测试结果是不占用空间,那这句话到底有什么作用呢? */


. = . ;




__m_section_start = . ;


.my_section :


{


*(.my_section)


*(.my_section1)


__m_section_mid = . ;


/* 测试通配符在段名中的使用 */


*(.my_section.a*)


}


__m_section_end = . ;




.rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }


.rodata1        : { *(.rodata1) }


.codearea{ color:black; background-color:white; line-height:18px; border:1px solid #4f81bd; margin:0; width:auto !important; width:100%; overflow:auto; text-align:left; font-size:12px; font-family: "Courier New","Consolas","Fixedsys","BitStream Vera Sans Mono", courier,monospace,serif}
.codearea pre{ color:black; line-height:18px; padding:0 0 0 12px !important; margin:0em; background-color:#fff !important}
.linewrap pre{white-space:pre-wrap; white-space:-moz-pre-wrap; white-space:-pre-wrap; white-space:-o-pre-wrap; word-wrap:break-word; word-break:normal}
.codearea pre.alt{ background-color:#f7f7ff !important}
.codearea .lnum{color:#4f81bd;line-height:18px}

测试结果是__m_section_start = . ;是不占用空间的;“.= . ;” 也不占用空间,但是为什么有的lds文件中会用这句话,有什么意义?

通配符是有效果的,所以在源程序中可以使用满足通配符的段。

上面代码是我自己测试时用的,主要是测试C语言调用连接脚本中的变量,测试代码如下(hello.c):

1:  #include <stdio.h>


2:


3:  extern char  __m_section_init[] ;


4:  extern char  __m_section_start ;


5:  extern char  __m_section_mid  ;


6:  extern char* __m_section_end ;


7:


8:  int var_standard = 0x1234 ;


9:


10:  #define DPRINT(x) printf( #x " is 0x%x/n", (unsigned int)x)


11:


12:  int var_a __attribute__((section(".my_section"))) = 1 ;


13:  int var_b __attribute__((section(".my_section1"))) = 2 ;


14:  int var_c __attribute__((section(".my_section.a_1"))) = 3 ;


15:


16:  int main(void)


17:  {


18:      DPRINT(&var_standard);


19:      DPRINT(__m_section_init);


20:      DPRINT(&__m_section_start);


21:      DPRINT(&var_a);


22:      DPRINT(&var_b);


23:      DPRINT(&__m_section_mid);


24:      DPRINT(&var_c);


25:


26:      DPRINT(&__m_section_end);


27:


28:      return 0;


29:  }


.codearea{ color:black; background-color:white; line-height:18px; border:1px solid #4f81bd; margin:0; width:auto !important; width:100%; overflow:auto; text-align:left; font-size:12px; font-family: "Courier New","Consolas","Fixedsys","BitStream Vera Sans Mono", courier,monospace,serif}
.codearea pre{ color:black; line-height:18px; padding:0 0 0 12px !important; margin:0em; background-color:#fff !important}
.linewrap pre{white-space:pre-wrap; white-space:-moz-pre-wrap; white-space:-pre-wrap; white-space:-o-pre-wrap; word-wrap:break-word; word-break:normal}
.codearea pre.alt{ background-color:#f7f7ff !important}
.codearea .lnum{color:#4f81bd;line-height:18px}

这段代码的运行结果是:

1:  &var_standard is 0x80495c4


2:  __m_section_init is 0x8048418


3:  &__m_section_start is 0x8048418


4:  &var_a is 0x8048418


5:  &var_b is 0x804841c


6:  &__m_section_mid is 0x8048420


7:  &var_c is 0x8048420


8:  &__m_section_end is 0x8048424


.codearea{ color:black; background-color:white; line-height:18px; border:1px solid #4f81bd; margin:0; width:auto !important; width:100%; overflow:auto; text-align:left; font-size:12px; font-family: "Courier New","Consolas","Fixedsys","BitStream Vera Sans Mono", courier,monospace,serif}
.codearea pre{ color:black; line-height:18px; padding:0 0 0 12px !important; margin:0em; background-color:#fff !important}
.linewrap pre{white-space:pre-wrap; white-space:-moz-pre-wrap; white-space:-pre-wrap; white-space:-o-pre-wrap; word-wrap:break-word; word-break:normal}
.codearea pre.alt{ background-color:#f7f7ff !important}
.codearea .lnum{color:#4f81bd;line-height:18px}

注意C语言中调用连接脚本的方法,特别是__m_section_end声明为了一个指针,但是实际上在这里相当于一个int类型而已,与数组名的意义并不一样,所以后面还是得使用&符号获取连接脚本里面的值。不过推荐的做法是声明为相关长度的数组,比如unsigned char或者unsigned int类型的数组。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: