arm处理器的u-boot.lds文件分析

1)u-boot的实现分为stage1与stage2两个阶段,其中依赖与CPU体系结构的代码通常都是放在stage1里,并且通常用汇编语言实现。stage2通常用C语言实现,可以实现更加复杂的功能,并且有更好的移植性与可读性。

2)U-Boot 的 Stage1 通常是在 start.S 文件中实现,并且都是用汇编语言编写。一个可执行性 image 文件必须有一个入口点, 并且只能有一个全局入口点, 通常这个入口点的地址放在 ROM(Flash)0x0 位置,因此必须使编译器知道这个入口地址,该过程通常修改连接器的 脚本文件来完成,这个靠u-boot.lds文件来实现。

3)下面来分析u-boot.lds文件(arch/arm/cpu/u-boot.lds)

/*指定输出可执行文件是elf格式,32位ARM指令,小端格式*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*指定输出可执行文件的平台为ARM*/
OUTPUT_ARCH(arm)
/*指定输出可执行文件的起始代码段为_start*/
ENTRY(_start)
SECTIONS
{
    /*
     * 指定可执行image文件的全局入口点,通常这个地址都放在ROM(flash)0x0位置。
     * 必须使编译器知道这个地址,通常都是修改此处来完成.
     */
    . = 0x00000000;
    /*代码以4字节对齐*/
    . = ALIGN(4);
    .text :
    {
             /*第一个代码部分存放*/
        __image_copy_start = .;
        CPUDIR/start.o (.text*)
        *(.text*)
    }

    . = ALIGN(4);
     /*指定只读数据段*/
    .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

    . = ALIGN(4);
    /*指定已经初始化的数据段*/
    .data : {
        *(.data*)
    }

    . = ALIGN(4);

    . = .;

    . = ALIGN(4);
    /*指定保存uboot命令段*/
    .u_boot_list : {
        KEEP(*(SORT(.u_boot_list*)));
    }

    . = ALIGN(4);

    __image_copy_end = .;
    /*relocaltion dynamic link info */
    .rel.dyn : {
        __rel_dyn_start = .;
        *(.rel*)
        __rel_dyn_end = .;
    }
    /* dynamic symbol table */
    .dynsym : {
        __dynsym_start = .;
        *(.dynsym)
    }

    _end = .;

    /*
     * Deprecated: this MMU section is used by pxa at present but
     * should not be used by new boards/CPUs.
     */
    . = ALIGN(4096);
    /*define mmutable */
    .mmutable : {
        *(.mmutable)
    }

/*
 * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
 * __bss_base and __bss_limit are for linker only (overlay ordering)
 */
    /*把__bss_start赋值为当前位置,即bss段的开始位置*/
    .bss_start __rel_dyn_start (OVERLAY) : {
        KEEP(*(.__bss_start));
        __bss_base = .;
    }

    .bss __bss_base (OVERLAY) : {
        *(.bss*)
         . = ALIGN(4);
         __bss_limit = .;
    }

    .bss_end __bss_limit (OVERLAY) : {
        KEEP(*(.__bss_end));
    }
    /* dynamic string table */
    /DISCARD/ : { *(.dynstr*) }
    /* dynamic linking information */
    /DISCARD/ : { *(.dynamic*) }
    /* Procedure linkage table */
    /DISCARD/ : { *(.plt*) }
    /* Pathname of program interpreter */
    /DISCARD/ : { *(.interp*) }
    /DISCARD/ : { *(.gnu*) }
}

下面是转其他博客的文章:

网上大部分u-boot.lds文件的分析大部分都是千遍一律,例如下面就是本人在网上找到的关于u-boot.lds的资料。

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

/*指定输出可执行文件是elf格式,32ARM指令,小端*/
OUTPUT_ARCH(arm)

/*指定输出可执行文件的平台为ARM*/
ENTRY(_start)

/*指定输出可执行文件的起始代码段为_start*/
SECTIONS
{

/*指定可执行image文件的全局入口点,通常这个地址都放在ROM(flash)0x0位置。必须使编译器知道这个地址,通常都是修改此处来完成*/
 . = 0x00000000;/*;0x0位置开始*/
 . = ALIGN(4);/*代码以4字节对齐*/
 .text :
 {
  cpu/arm920t/start.o (.text) 

    /*代码的第一个代码部分*/  
  *(.text)

/*下面依次为各个text段函数*/
 }
 . = ALIGN(4);

/*代码以4字节对齐*/
 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

 /*指定只读数据段*/
 . = ALIGN(4);

/*代码以4字节对齐*/
 .data : { *(.data) }
 . = ALIGN(4);

/*代码以4字节对齐*/
 .got : { *(.got) }

/*指定got, got段是uboot自定义的一个段非标准段*/
 . = .;
 __u_boot_cmd_start = .;

/*__u_boot_cmd_start赋值为当前位置即起始位置*/
 .u_boot_cmd : { *(.u_boot_cmd) }

 /*指定u_boot_cmd, uboot把所有的uboot命令放在该段.*/
 __u_boot_cmd_end = .;

 /*__u_boot_cmd_end赋值为当前位置,即结束位置*/
 . = ALIGN(4);

/*代码以4字节对齐*/
 __bss_start = .;

 /*__bss_start赋值为当前位置,bss段的开始位置*/
 .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }

/*指定bss,告诉加载器不要加载这个段*/
 __bss_end = .;

/*_end赋值为当前位置,bss段的结束位置*/
}

看完上面的解析思路本来应该是很清晰的,于是乎编译u-boot,查看一下System.map,

30100000 T _start

30100020 t _undefined_instruction

30100024 t _software_interrupt

30100028 t _prefetch_abort

3010002c t _data_abort

30100030 t _not_used

30100034 t _irq

30100038 t _fiq

发现 _start 的链接地址不是u-boot.lds中.text 的当前地址0x00000000,而是0x30100000,这就产生很多疑问了:

(1)     为什么u-boot.lds指定的 .text 的首地址不起作用?

(2)     0x30100000是什么地址,由谁指定.text的首地址是0x30100000的呢?

(3)     假如有其他动作改变了 .text 的首地址,那么该动作跟u-boot.lds的优先级又是怎么决定的呢?

其实这三个问题都在Makefile的LDFLAGS 变量和u-boot.lds 中找到答案。我们不妨试着修改一下u-boot.lds,把u-boot.lds修改成如下(红色字体部分为修改过部分):

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

/*指定输出可执行文件是elf格式,32ARM指令,小端*/
OUTPUT_ARCH(arm)

/*指定输出可执行文件的平台为ARM*/
ENTRY(_start)

/*指定输出可执行文件的起始代码段为_start*/
SECTIONS
{

/*指定可执行image文件的全局入口点,通常这个地址都放在ROM(flash)0x0位置。必须使编译器知道这个地址,通常都是修改此处来完成*/
 . = 0x30000000;/*;0x0位置开始*/
 . = ALIGN(4);/*代码以4字节对齐*/

.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
 . = ALIGN(4);

/*代码以4字节对齐*/

.text :
 {
  cpu/arm920t/start.o (.text) 

    /*代码的第一个代码部分*/  
  *(.text)

/*下面依次为各个text段函数*/
 }

 /*指定只读数据段*/
 . = ALIGN(4);

/*代码以4字节对齐*/
 .data : { *(.data) }
 . = ALIGN(4);

/*代码以4字节对齐*/
 .got : { *(.got) }

/*指定got, got段是uboot自定义的一个段非标准段*/
 . = .;
 __u_boot_cmd_start = .;

/*__u_boot_cmd_start赋值为当前位置即起始位置*/
 .u_boot_cmd : { *(.u_boot_cmd) }

 /*指定u_boot_cmd, uboot把所有的uboot命令放在该段.*/
 __u_boot_cmd_end = .;

 /*__u_boot_cmd_end赋值为当前位置,即结束位置*/
 . = ALIGN(4);

/*代码以4字节对齐*/
 __bss_start = .;

 /*__bss_start赋值为当前位置,bss段的开始位置*/
 .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }

/*指定bss,告诉加载器不要加载这个段*/
 __bss_end = .;

/*_end赋值为当前位置,bss段的结束位置*/
}

上面对u-boot.lds主要做了两点修改

(1)     把0x00000000 改成 0x30000000。

(2)     把 .text 和 .rodata 存放的地址调换了位置。

重新编译 u-boot, 查看System.map

30000000 R version_string

30000028 r C.27.2365

.

.

.

30100000 T _start

30100020 t _undefined_instruction

.

.

.

从上面的System.map部分内容可以看出:

(1)     u-boot.lds设定的地址(0x00000000或0x30000000)是有效的。

(2)     .text的地址仍然是30100000

跟着我们查看Makefile中的LDFLAGS变量,发现一条指令

LDFLAGS += -Ttext $(TEXT_BASE)  其中TEXT_BASE 是在u-boot根目录的board文件夹的对应的开发板名字的子目录下的config.mk文件中定义的

TEXT_BASE = 0x30100000

看到这里我们应该明白为什么_start,也就是.text的首地址总是等于0x30100000了,在连接的时候ld命令会把参数-Ttext指定的地址赋给.text,所以.text在u-boot.lds中的默认地址(当前地址)不起作用了。

时间: 2024-11-08 21:51:02

arm处理器的u-boot.lds文件分析的相关文章

U-boot.lds文件分析

1 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 2 OUTPUT_ARCH(arm) 3 ENTRY(_start) lds文件位于board/samsung/smdk6410/u-boot-nand.lds下. 指定elf32-littlearm 格式,即指定输出文件是elf格式,32位ARM指令,小端模式: 紧接着OUTPUT_ARCH(arm)

uboot之uboot.lds文件分析

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") /*指定输出可执行文件是elf格式,32位ARM指令,小端*/OUTPUT_ARCH(arm) /*指定输出可执行文件的平台为ARM*/ENTRY(_start) /*指定输出可执行文件的起始代码段为_start*/SECTIONS{ /*指定可执行image文件的全局入口点,通常这个地址都放在ROM(fl

u-boot start.S启动文件分析

u-boot start.S启动文件分析 u-bootstart.SBL1 u-boot start.S启动文件分析 一.start.S来源 1.为何要分析start.S 2.start.S的来源 3.头文件包含 二.start.S分析 1.Start.S分析 16字节校验头 异常向量表 16字节内存对齐 设置CPU为SVC模式 L2 cache操作 Invalidate L1 I/D 关掉MMU 读取启动引脚信息 第一次设置栈 ./board/samsung/x210/lowlevel_ini

基于ARM处理器的反汇编器软件简单设计及实现

写在前面 2012年写的,仅供参考 反汇编的目的 缺乏某些必要的说明资料的情况下, 想获得某些软件系统的源代码.设计思想及理念, 以便复制, 改造.移植和发展: 从源码上对软件的可靠性和安全性进行验证,对那些直接与CPU 相关的目标代码进行安全性分析: 涉及的主要内容 分析ARM处理器指令的特点,以及编译以后可执行的二进制文件代码的特征: 将二进制机器代码经过指令和数据分开模块的加工处理: 分解标识出指令代码和数据代码: 然后将指令代码反汇编并加工成易于阅读的汇编指令形式的文件: 下面给出个示例

u-boot.lds文件简介

可执行文件由许多链接在一起的对象文件组成.对象文件有许多节,如文本.数据.init 数据.bss等.这些对象文件都是由一个称为 链接器脚本(*lds)的文件链接并装入的.这个链接器脚本的功能是将输入对象文件的各节映射到输出文件中:换句话说,它将所有输入对象文件都链接到单一的可执行文件中,将该可执行文件的各节装入到指定地址处. 因此在分析u-boot代码是,首先应关注的是u-boot.lds文件,它位于$(U-BOOT_SRC_ROOT)/board/$(BOARD_NAME)目录下. 1 /*

Android逆向-Android逆向基础10(so文件分析大合集)

0x00 前言 导航 博客导航戳这里练习资源戳这里 说明 在so文件的分析上,我们需要对一些ARM汇编的逻辑实现.在代码逻辑上,只对if,switch,还有循环进行一个demo分析和创建.可能会篇幅比较大. 内容 1.if逻辑NDK编程2.if逻辑ARM分析3.switch逻辑NDK编程4.switch逻辑ARM分析5.循环逻辑NDK编程6.循环逻辑ARM分析 0x01 if逻辑NDK编程 demo使用之前的demo,如果有兴趣,可以去看看博客导航戳这里 说明 demo主要实现一个输入,然后根据

从ARM处理器,看“贵云黔芯”国产自主安全解决方案

刚刚结束的2018数博会上,云宏与战略合作伙伴华芯通携手亮相,为观展嘉宾介绍了一套面向政府.机关和行业客户的国产自主安全云建设项目解决方案--"贵云黔芯".凭借云宏国内领先的云计算大数据关键技术及华芯通在ARM服务器芯片领域坚实的技术研发实力,双方共造基于高性能.低功耗ARM架构服务器搭建的应用云平台自主安全可控项目,旨在联合上下游资源,贯彻落实国家"自主.安全.可控"信息化战略部署实际行动. "贵云黔芯"云建设项目解决方案利用ARM 服务器芯片

/proc/cpuinfo 文件分析(查看CPU信息)

/proc/cpuinfo文件分析 根据以下内容,我们则可以很方便的知道当前系统关于CPU.CPU的核数.CPU是否启用超线程等信息. <1>查询系统具有多少个逻辑核:cat /proc/cpuinfo | grep "processor" | wc -l   //逻辑处理器的id(逻辑核数) <3>查询系统CPU的个数:cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l 

linux实践之ELF文件分析

linux实践之ELF文件分析 下面开始elf文件的分析. 我们首先编写一个简单的C代码. 编译链接生成可执行文件. 首先,查看scn15elf.o文件的详细信息. 以16进制形式查看scn15elf.o文件. 查看scn15elf.o中各个段和符号表的信息. 各个段的详细信息如下. 符号表的信息如下: 使用readelf命令查看各个段的详细信息: 段表信息如下: 符号表信息如下: 下面让我们开始分析文件头吧! 由于我的虚拟机是32位的,我下面就主要以32位的系统进行分析,就不比较32位机和64