gcc attribute属性和section选项

转载: http://lihuize123123.blog.163.com/blog/static/878290522010420111428109
利用 GCC 的 __attribute__ 属性的 section 选项来控制数据区的基地址。 以下例子,主要涉及到两个知识点,一个是 GNU C 扩展中的 attribute section 属性,关于这个知识点的相关信息可以参考: http://www.groad.net/bbs/read.php?tid=1035


测试代码

#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 。
程序里要求变量 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 :
     0:       8d 4c 24 04                          lea       0x4(%esp),�x
     4:       83 e4 f0                                and       $0xfffffff0,%esp
     7:       ff 71 fc                                pushl   -0x4(�x)
     a:       55                                            push     �p
     b:       89 e5                                      mov       %esp,�p
     d:       51                                            push     �x
     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,�x
   2a:       8b 15 00 00 00 00              mov       0x0,�x
   30:       01 d0                                      add       �x,�x
  32:    a3 00 00 00 00           mov    �x,0x0
   37:       83 c4 04                                add       $0x4,%esp
   3a:       59                                            pop       �x
   3b:       5d                                            pop       �p
   3c:       8d 61 fc                                lea       -0x4(�x),%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 :
     0:       8d 4c 24 04                          lea       0x4(%esp),�x
     4:       83 e4 f0                                and       $0xfffffff0,%esp
     7:       ff 71 fc                                pushl   -0x4(�x)
     a:       55                                            push     �p
     b:       89 e5                                      mov       %esp,�p
     d:       51                                            push     �x
      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,�x
    28:    a1 04 00 1f 00           mov    0x1f0004,�x
   2d:       8d 04 02                                lea       (�x,�x,1),�x
  30:    a3 00 00 ff 00           mov    �x,0xff0000
   35:       b8 00 00 00 00                    mov       $0x0,�x
   3a:       59                                            pop       �x
   3b:       5d                                            pop       �p
   3c:       8d 61 fc                                lea       -0x4(�x),%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 地址开始。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值