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

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 地址开始。
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值