Chinaunix首页 | 论坛 | 博客
  • 博客访问: 491685
  • 博文数量: 52
  • 博客积分: 5017
  • 博客等级: 大校
  • 技术积分: 707
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-20 11:34
文章分类
文章存档

2011年(1)

2008年(51)

我的朋友

分类: LINUX

2008-06-28 19:20:53

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

阅读(5325) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~