您的位置:首页 > 其它

GCC __attribute__ 和 link 脚本控制 section 基地址

2012-05-26 20:39 507 查看

GCC __attribute__ 和 link 脚本控制 section 基地址

网上看的一篇文章,感谢作者,另外加上自己的一点注释。

... ... ... ... .... .... .....

利用 GCC 的 __attribute__ 属性的 section 选项来控制数据区的基地址。

以下例子,主要涉及到两个知识点,一个是 GNU C 扩展中的 attribute section 属性,关于这个知识点的相关信息可以参考:http://www.groad.net/bbs/read.php?tid=1035

另外一个知识点是 ld 连接器所用到的 link 脚本相关知识。

测试代码

#include <stdio.h>

int
localmemory0 __attribute__((section("LOCALmem")))
= 0;

int
localmemory1 __attribute__((section("LOCALmem")))
= 0;

int
globalmemory __attribute__((section("GLOBALmem")))
= 0;

int
main (int
argc, char
*argv[])

{

localmemory0 =
0x456;

localmemory1 =
0x123;

globalmemory =
localmemory0 +
localmemory1;

}

在上面的代码中,定义了两个非传统的 section : LOCALmem 和 GLOBALmem 。

程序里要求变量 localmemory0 和 localmemory1 存放在 section LOCALmem 中,而 globalmemory 存放在 section GLOBALmem 中。

下面编译程序

beyes@linux-beyes:~/C/GNU_C_EXT> gcc -c -o elf_section.o elf_section.c

或者

beyes@linux-beyes:~/C/GNU_C_EXT> gcc -c -o elf_section2.o -fdata-sections elf_section.c

-fdata-sections 选项的目的是让编译器为每一个单独申明的数据 section 实际分配一个 section,而不是占用 .bss ,在某些系统上需要显式的使用这一参数。

使用 objdump 命令查看生成的 elf_section.o 文件

beyes@linux-beyes:~/C/GNU_C_EXT> objdump -S elf_section.o

elf_section.o: file format elf32-i386

Disassembly of section .text:

00000000 <main>:

0: 8d 4c 24 04 lea 0x4(%esp),%ecx

4: 83 e4 f0 and $0xfffffff0,%esp

7: ff 71 fc pushl -0x4(%ecx)

a: 55 push %ebp

b: 89 e5 mov %esp,%ebp

d: 51 push %ecx

e: 83 ec 04 sub $0x4,%esp

11: c7 05 00 00 00 00 56 movl $0x456,0x0

18: 04 00 00

1b: c7 05 00 00 00 00 23 movl $0x123,0x0

22: 01 00 00

25: a1 00 00 00 00 mov 0x0,%eax

2a: 8b 15 00 00 00 00 mov 0x0,%edx

30: 01 d0 add %edx,%eax

32: a3 00 00 00 00 mov %eax,0x0

37: 83 c4 04 add $0x4,%esp

3a: 59 pop %ecx

3b: 5d pop %ebp

3c: 8d 61 fc lea -0x4(%ecx),%esp

3f: c3 ret

上面的 objdump 使用了 -S 选项,这是查看目标文件反汇编代码的一个选项;对此,也可以使用 -d 选项,并建议使用 -d 选项。

上面加蓝色高亮的两条 movl 指令分别将数据存放到 localmemory0 和 localmemroy1 ;加粉红色高亮的 mov 指令将两个变量相加的结构存放到 globalmemory 中。

由于是目标文件,变量符号对应的地址没有经过解析和分配,所以指令变量中对应的地址都是 0x0 。

下面,使用一个 link 脚本来控制连接器 ld 输出 section 的己地址(像linux的内核源码树中的 arch/arm/vmlinux-armv.lds.in 文件也是这样的脚本文件<这里是ARM平台,编译内核后的文件)。

文件内容如下:

SECTIONS

{

.text : {

*(.text)

}

LOCALmem 0x1f0000 : {

*(LOCALmem)

}

GLOBALmem 0xff0000 : {

*(GLOBALmem)

}

}

用下面的命令观察生成的 elf 文件内容:

beyes@linux-beyes:~/C/GNU_C_EXT> objdump -S elf_section.elf

elf_section.elf: file format elf32-i386

Disassembly of section .text:

00000000 <main>:

0: 8d 4c 24 04 lea 0x4(%esp),%ecx

4: 83 e4 f0 and $0xfffffff0,%esp

7: ff 71 fc pushl -0x4(%ecx)

a: 55 push %ebp

b: 89 e5 mov %esp,%ebp

d: 51 push %ecx

e: c7 05 00 00 1f 00 56 movl $0x456,0x1f0000

15: 04 00 00

18: c7 05 04 00 1f 00 23 movl $0x123,0x1f0004

1f: 01 00 00

22: 8b 15 00 00 1f 00 mov 0x1f0000,%edx

28: a1 04 00 1f 00 mov 0x1f0004,%eax

2d: 8d 04 02 lea (%edx,%eax,1),%eax

30: a3 00 00 ff 00 mov %eax,0xff0000

35: b8 00 00 00 00 mov $0x0,%eax

3a: 59 pop %ecx

3b: 5d pop %ebp

3c: 8d 61 fc lea -0x4(%ecx),%esp

3f: c3 ret

说明

ld 命令的选项 -T ,等同于选项 -c ,这是告诉 ld 从 -c 后面的文件(commandfile) 中读取连接命令。这些命令彻底的覆盖 ld 的缺省连接格式 (不是添加);commandfile 必须详尽的描述目标格式的所有细节。

在两个加了蓝色高亮的语句中,可以看到,0x456 和 0x123 两数已经分别搬往 0x1f0000 与 0x1f0004 两个地址。

使用 objdump -s 来查看一下生成的 elf 文件:

beyes@linux-beyes:~/C/GNU_C_EXT> objdump -s elf_section.elf

elf_section.elf: file format elf32-i386

Contents of section .text:

0000 8d4c2404 83e4f0ff 71fc5589 e551c705 .L$.....q.U..Q..

0010 00001f00 56040000 c7050400 1f002301 ....V.........#.

0020 00008b15 00001f00 a104001f 008d0402 ................

0030 a30000ff 00b80000 0000595d 8d61fcc3 ..........Y].a..

Contents of section LOCALmem:

1f0000 00000000 00000000 ........

Contents of section GLOBALmem:

ff0000 00000000 ....

Contents of section .comment:

0000 00474343 3a202853 55534520 4c696e75 .GCC: (SUSE Linu

0010 78292034 2e332e32 205b6763 632d345f x) 4.3.2 [gcc-4_

0020 332d6272 616e6368 20726576 6973696f 3-branch revisio

0030 6e203134 31323931 5d00 n 141291].

Contents of section .comment.SUSE.OPTs:

0000 6f737077 6700 ospwg.

上面命令中, -s 选项表示显示任何一个 section 的所有内容。在默认情况下,所有非空 section 都要显示。

由上可见,section LOCALmem 从 0x1f0000 开始,而 section GLOBALmem 从 0xff0000 开始,程序正文段 .text 从 0x0 地址开始。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: