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

关键词gcc elf section

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

样例代码 file: test.section.c

#include<stdio.h></stdio.h>
#include<stdlib.h></stdlib.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
要求变量 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 <main>:</main>
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 <main>:<br> 0: 55 push %ebp<br> 1: 89 e5 mov %esp,%ebp<br> 3: 83 ec 08 sub $0x8,%esp<br> 6: 83 e4 f0 and $0xfffffff0,%esp<br> 9: b8 00 00 00 00 mov $0x0,%eax<br> e: 29 c4 sub %eax,%esp<br> 10: c7 05 00 00 1f 00 56 movl $0x456,0x1f0000<br> 17: 04 00 00<br> 1a: c7 05 04 00 1f 00 23 movl $0x123,0x1f0004<br> 21: 01 00 00<br> 24: a1 04 00 1f 00 mov 0x1f0004,%eax<br> 29: 03 05 00 00 1f 00 add 0x1f0000,%eax<br> 2f: a3 00 00 ff 00 mov %eax,0xff0000<br> 34: c9 leave<br> 35: c3 ret</main>

使用 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开始

你可能感兴趣的:(attribute)