免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 676 | 回复: 0
打印 上一主题 下一主题

AT91RM9200开发笔记(6):ELF文件生成bin文件的处理方法 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-02-21 14:49 |只看该作者 |倒序浏览

  
文章说明:calmarrow(lqm)原创
文章引自:
http://piaoxiang.cublog.cn

    在嵌入式系统中,固化到非易失性存储介质中的软件是binary格式。Linux下生成的可执行文件是ELF格式,不能直接固化,必须转化为bin文件。就处理方法而言,视链接方式不同,可以有两种不同的方法,下面分别举例说明。

    (一)以at91rm9200 boot官方程序为例,介绍方法一

    boot最终得到boot.bin,为bin文件,可以直接固化到NVM中。它有两个组成部分:boot.text和boot.data。处理方式如下:

all: boot.bin
boot.bin: boot.text boot.data
        cat $^ > $@
boot.text: boot
        $(OBJCOPY) -O binary -j .text $ $@
boot.data: boot
        $(OBJCOPY) -O binary -j .data $ $@
boot: $(OBJ)
        $(LD) $(LDFLAGS) $^ -o $@

    下面看一下链接器的设置。

[armlinux@lqm boot]$ cat ld.script
MEMORY {
        ram : ORIGIN = 0x20000000, LENGTH = 0xf000
        rom : ORIGIN = 0x00000000, LENGTH = 0xf000
}
SECTIONS {
        .text : {
                _stext = . ;
                *(.text)
                *(.rodata*)
                . = ALIGN(4);
                _etext = . ;
        } > rom
        .data : {
                _sdata = . ;
                *(.data)
                *(.glue_7*)
                . = ALIGN(4);
                _edata = . ;
        } > ram
        .bss : {
                _sbss = . ;
                *(.bss)
                . = ALIGN(4);
                _ebss = . ;
        } > ram
}

    可见,就内存空间的安排而言,.text段放在rom里,而.data放在ram里。具体分布如下:

    ---------------- 0x0000 0000
        .text
    ----------------
        ...
    ---------------- 0x2000 0000
        .data
    ---------------- (0x2000 0000 + sizeof(.data))
        .bss
    ----------------

    也就是说,.text和.data段的地址是不连续的,.data段和.bss则是连续的。而ELF具有可执行属性的段只有.text和.data。objcopy如果直接采用-O binary选项,实际上是解析ELF文件信息,然后复制.text段首地址到.data的段尾地址。很明显,像地址不连续的情况,就会出现空洞。如boot,空洞会相当大,根本不适合下载。下面根据Linux下工具进行具体分析。
   
[armlinux@lqm boot]$ arm-linux-readelf -a boot > elfinfo.txt

    这样可以得到生成的ELF文件的所有信息。主要信息如下:

Section Headers:
  [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
  [ 0] NULL 00000000 000000 000000 00 0 0 0
  [ 1] .text PROGBITS 00000000 000074 002744 00 AX 0 0 4
  [ 2] .data PROGBITS 20000000 0027b8 0001c4 00 WAX 0 0 4
  [ 3] .bss NOBITS 200001c4 00297c 00841c 00 WA 0 0 4
  [ 4] .comment PROGBITS 00000000 00297c 000098 00 0 0 1
  [ 5] .shstrtab STRTAB 00000000 002a14 000035 00 0 0 1
  [ 6] .symtab SYMTAB 00000000 002b8c 000710 10 7 53 4
  [ 7] .strtab STRTAB 00000000 00329c 0003e0 00 0 0 1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)
Program Headers:
  Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
  LOAD 0x000074 0x00000000 0x00000000 0x02744 0x02744 R E 0x4
  LOAD 0x0027b8 0x20000000 0x20000000 0x001c4 0x085e0 RWE 0x4
Section to Segment mapping:
  Segment Sections...
   00 .text
   01 .data .bss

    可以看出,.text从0x0000 0000开始,大小为0x2744Bytes,.data从0x2000 0000开始,大小为0x1c4.生成的bin文件应该为(0x2744+0x01c4)=0x2908=10504 Bytes。这个可以用ls -l来验证。

    不过,采用这种方式,需要在程序中进行处理,主要任务就是完成代码的搬移和bss的清0处理。这也就是crt0.S的作用。

[armlinux@lqm boot]$ cat crt0.S
@ r0 -> start of flash
@ r1 -> where to load data
@ r2 -> start of program
        .text
        .align
        .global main,_main
main:
_main:
        # copy .data section
        ldr r3, =_etext
        ldr r4, =_sdata
        ldr r5, =_edata
        subs r5, r5, r4
        bl copydata
        # clear .bss section
        ldr r4, =_sbss
        ldr r5, =_ebss
        subs r5, r5, r4
        mov r0, #0
        bl clearbss
        # and jump to the kernel
        b boot
copydata:
        subs r5, r5, #4
        ldr r6, [r3], #4
        str r6, [r4], #4
        bne copydata
        mov pc, lr
clearbss:
        subs r5, r5, #4
        str r0, [r3], #4
        bne clearbss
        mov pc, lr

    代码比较简单,不做分析。

    (二)以自修改的at91rm9200 loader为例,介绍方法二

all: loader.bin
loader.bin: $(OBJ)
        $(LD) $(LDFLAGS) $^ -o loader
        $(OBJCOPY) -O binary loader $@

    链接设置如下:

[armlinux@lqm loader]$ cat ld.script
MEMORY {
        ram : ORIGIN = 0x200000, LENGTH = 0x3000
}
SECTIONS {
        .text : {
                _stext = . ;
                *(.text)
                *(.rodata)
                . = ALIGN(4);
                _etext = . ;
        } > ram
        .data : {
                _sdata = . ;
                *(.data)
                *(.glue_7*)
                . = ALIGN(4);
                _edata = . ;
        } > ram
        .bss : {
                _sbss = . ;
                *(.bss)
                . = ALIGN(4);
                _ebss = . ;
        } > ram
}

    可见.text和.data的地址是连续的。这样,原来的loader代码中文件crt0.S是没有必要的。

    boot如果采用方法二的处理方法,生成的bin文件为0x2000 01c4,可以很容易验证。

    理解了这些,在自己设计boot loader时,就会综合考虑链接器设置的内存空间分配和bin生成方式选择。显然,方法一适合.text和.data地址不连续的情况,方法二适合.text和.data地址连续的情况。分析清楚了这些,也解决了原来在s3c2410设计实验程序时出现的生成bin文件过大的问题了。

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/21948/showart_481779.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP