zoukankan      html  css  js  c++  java
  • 代码重定位

    1 说明

    实验平台:     JZ2440

    CPU:     S3C2440

     

    2 S3C2440的启动过程

    图1 S3C2440A Memory Map after Reset

     

    S3C2440支持从多种存储设备启动:NOR/NAND Flash, EEPROM, 等等。芯片内部有4K SRAM用于启动设备使用。至于,设备最终以哪一种方式启动,通过配置芯片的OM引脚,由芯片内部实现。

     

    摘自《S3C2440A_UserManual_Rev13》:

                            图2 BANK0 BUS WIDTH

     

    举个例子,当选择以NOR Flash的方式启动时,芯片的0地址(4K地址空间)会直接映射到Nor Flash上,CPU直接从Nor Flash读取指令,并执行;当选择以Nand Flash启动时,S3C244会把Nand Flash的前4K数据,复制到芯片内部SRAM中,然后CPU从内部SRAM读取指令,并执行。(NOR Flash 是由内存控制器直接驱动的,而NAND Flash是由NAND Flash控制器驱动的,NAND Flash控制器则由内存控制器驱动,因此NOR Flash是CPU统一编址的,而NAND Flash不是,因此他们间的启动方式是有区别的)。

     

    3 分析可执行文件

    *.elf与*.bin文件的区别

    bin文件:二进制文件,只包含机器码;可在机器中直接运行。

    elf文件:除了机器码外,还包含其他额外的信息,例如:段的运行地址,加载地址,重定位表,符号表等等;只能运行于带操作系统的机器,经操作系统解析(提取出机器码)后执行;可用于调试。

    通过"arm-linux-ld -T target.lds *.o -o *.elf"链接得到*.elf文件;然后通过"arm-linux-objcopy -O binary -S *.elf *.bin"把*.elf转换成*.bin文件。

     

    4 链接脚本

    4.1 程序的组成

    程序由代码段、数据段、只读数据段、BSS段、注释段组成,其中BSS段、注释段不存放于bin文件或elf文件中。

    .text:    代码段;程序中的可执行部分。

    .data:    数据段;程序中的全局变量。

    .rodata:    只读数据段;程序中的const类型变量。

    .bss:    BSS段;程序中未初始化的或初始值为0的全局变量。

    .COMMON:    注释段。

    注意:局部变量是随着函数的调用,在栈中分配,并在函数退出时释放。

     

    4.2 链接脚本说明

    当不适用链接脚本指示链接器进行连接时,链接的顺序按照Makefile中,文件的放置顺序进行链接,注意把start.o防置在最前面,否则程序运行会出错。Makefile中使用链接脚本:[-T *.lds]。

     

    链接脚本的格式:

        SECTIONS{

            secname start Block(align) (NOLOAD) : AT(ldadr)

            {

    contents > region : phdr = fill

    }

    }

     

    示例:

    图3 链接脚本示例说明

     

    注意:链接脚本中,每个段的起始地址应当设置为4字节对齐,因为汇编指令会自动把需要操作的地址,自动进行4字节对齐,如果我们对一个非4字节对齐的地址进行操作,会出现意想不到的错误。

    例如:

        ldr r1, =0x32000000

        ldr r2, =0

        str r2, [r1]

    我们期望的结果是,[0x32000000] = 0;但是实际的结果是[0x30000000] = 0;这不是我们想要的。

     

    5 代码重定位

    5.1 代码重定位的意义

    从NOR Flash启动的角度分析:

    程序可以直接在NOR Flash上执行。NOR Flash可以通过地址直接读取,但是不能直接执行写操作,必须通过特定的操作,才能实现写操作,因此在NOR Flash上则行程序,其全局变量是无法更改的,因此,我们需要把烧写到NOR Flash上的程序重新重定位到SDRAM上。

     

    从NAND Flash启动的角度分析:

    程序不可以直接在NAND Flash上执行;通过配置OM引脚,当选择NAND Flash为启动方式时,芯片内部固件会把NAND Flash的前4K复制到内部SRAM,程序从SRAM的0地址开始执行,当程序超过4K时,为了保证程序能正常运行,一般前4K的代码实现把程序复制到SDRAM上,然后在SDRAM上执行程序。

     

    特别说明:在函数内部声明一个已初始化的数组,数组的元素是存放于代码段的;在调用这个函数时,会声明一个局部变量的指针(数组名),使该指针指向数组元素位于代码段的首地址,完成初始化动作,因此,未重定位之前,不能使用数组。

     

    5.2 重定位的方式

    5.2.1 lds文件中的变量

    通过对lds文件中的变量进行赋值,在C函数中,通过外部声明,可以获取对应段的地址信息。

                图4

     

    实际上,lds文件中的变量,并不会保存在程序中,编译程序时,有一个符号表(Symbol Table)保存lds中的变量,当程序需要使用lds中的变量时,通过声明外部变量的方法,通过取值,获取变量的值。例如:extern int name;target = &name;。

    图5 Symbol Table

     

    5.2.2 重定位的方式

    只重定位数据段:

    程序运行过程中,只有程序中的数据段和BSS段是可能被代码段修改的,因此在程序运行后,可以只把程序中的数据段以及BSS段重新定位到SDRAM中。

    在程序运行中,只需把存放于加载地址的数据段、BSS段,重新定位到运行时地址所指示的位置即可。

     

    重定位整个程序:

    在程序运行后,把整个程序重新定位到SDRAM中。

     

    5.2.3 位置无关码

    b/bl指令是相对跳转指令,跳转的目标地址只与当前PC值有关,与运行时地址无关,因此虽然烧写到NOR Flash上的程序的运行时地址指向SDRAM存储空间的起始地址(这里是0x30000000),由于b/bl是相对跳转的,因此,只要在完成重定位操作之前,不涉及全局变量、静态变量的操作,程序可以正常运行。通过操作相对地址指令实现的代码,也称为位置无关码。

    注意,重定位完成后,需要跳转到C函数去执行程序时,应该使用绝对跳转(直接修改PC值),而不能使用相对跳转,否则无法跳到SDRAM上去执行。

     

    附录1 程序源码

    Makefile

     

    target.lds

     

    Start.S

     

    Relocate.c

     

    附录2 参考文档

    《S3C2440用户手册》

    《The GNU linker》

  • 相关阅读:
    个人冲刺第七天6.15
    个人冲刺第六天6.14
    个人冲刺第五天6.11
    个人冲刺第四天6.10
    个人冲刺第三天6.9
    个人冲刺第二天6.8
    个人冲刺第一天6.7
    每日总结6.4
    oracle中CAST函数使用简介【转】
    rabbitmq安装
  • 原文地址:https://www.cnblogs.com/lilto/p/10856281.html
Copyright © 2011-2022 走看看