全部博文(254)
分类:
2012-12-26 09:59:21
利用 GCC 的 __attribute__ 属性的section选项来控制数据区的基地址
样例代码 file: test.section.c
#include
#include
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
要求变量 localmemroy0和变量localmemory0 存放在section LOCALmem
而变量 globalmemory 存放在section GLOBALmem
首先使用命令行
gcc -c -o test.section.o test.section.c
或者
gcc -c -o test.section.o -fdata-sections test.section.c
获得目标代码 test.section.o
-fdata-sections选项的目的是让编译器为每一个单独申明的数据section实际分配一个section,而不是占用.bss,在某些系统上需要显式的使用这一参数
再使用objdump查看代码
objdump -S test.secton.o
获得如下结果
test.section.o: file format elf32-i386
Disassembly of section .text:
00000000
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: 83 e4 f0 and $0xfffffff0,%esp
9: b8 00 00 00 00 mov $0x0,%eax
e: 29 c4 sub %eax,%esp
10: c7 05 00 00 00 00 56 movl $0x456,0x0
17: 04 00 00
1a: c7 05 00 00 00 00 23 movl $0x123,0x0
21: 01 00 00
24: a1 00 00 00 00 mov 0x0,%eax
29: 03 05 00 00 00 00 add 0x0,%eax
2f: a3 00 00 00 00 mov %eax,0x0
34: c9 leave
35: c3 ret
注意到两条movl指令分别将数据存放到localmemory0和localmemory1,在leave指令之前的mov将加法结果存放到globalmemory中
由于是目标文件,变量符号对于的地址没有经过解析和分配,指令中变量对应的地址都是0x0。
使用一个link脚本script来控制链接器ld输出section的基地址。
file: sections.script
SECTIONS
{
.text :
{
*(.text)
}
LOCALmem 0x1f0000 :
{
*(LOCALmem)
}
GLOBALmem 0xff0000 :
{
*(GLOBALmem)
}
}
使用命令行:
ld -o test.section.elf -T section.script test.section.o
获得elf可执行文件链接结果 test.section.elf
这时使用 objdump 观看链接结构
命令行:
objdump -S test.section.elf
可以得到:
test.section.elf: file format elf32-i386
Disassembly of section .text:
00000000
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: 83 e4 f0 and $0xfffffff0,%esp
9: b8 00 00 00 00 mov $0x0,%eax
e: 29 c4 sub %eax,%esp
10: c7 05 00 00 1f 00 56 movl $0x456,0x1f0000
17: 04 00 00
1a: c7 05 04 00 1f 00 23 movl $0x123,0x1f0004
21: 01 00 00
24: a1 04 00 1f 00 mov 0x1f0004,%eax
29: 03 05 00 00 1f 00 add 0x1f0000,%eax
2f: a3 00 00 ff 00 mov %eax,0xff0000
34: c9 leave
35: c3 ret
使用 objdump -s test.section.elf 观察elf文件中所有内容可以看到:
test.section.elf: file format elf32-i386
Contents of section .text:
0000 5589e583 ec0883e4 f0b80000 000029c4 U.............).
0010 c7050000 1f005604 0000c705 04001f00 ......V.........
0020 23010000 a104001f 00030500 001f00a3 #...............
0030 0000ff00 c9c3 ......
Contents of section LOCALmem:
1f0000 00000000 00000000 ........
Contents of section GLOBALmem:
ff0000 00000000 ....
Contents of section .data:
Contents of section .comment:
0000 00474343 3a202847 4e552920 332e322e .GCC: (GNU) 3.2.
0010 32203230 30333032 32322028 52656420 2 20030222 (Red
0020 48617420 4c696e75 7820332e 322e322d Hat Linux 3.2.2-
0030 352900 5).
Section LOCALmem从0x1f0000开始, 而Section GLOBALmem从0xff0000开始
程序正文段.text从0地址开始
如果将section.script中对于.text部分的内容去掉,那么ld产生的elf文件中.text部分
将紧接在GLOBALmem部分之后,从0xff0004开始