u-boot(四)-顶层目录链接脚本文件(u-boot.lds)介绍

一,IMX6ULL映像文件

1,格式概述

对于IMX6ULL,烧写在EMMC、SD/TF卡上的程序,并不能“自己复制自己”,是“别人把它复制到内存里”。一上电首先运行的是boot ROM上的程序,它从EMMC、SD/TF卡上把程序复制进内存里。

烧写在EMMC、SD卡或是TF卡上的,除了程序本身,还有位置信息、DCD 信息,这些内容合并成一个映像文件,如下图:

这4 部分内容合并成为一个映像文件,烧写在EMMC、SD 卡或TF 卡等启动设备的某个固定地址,boot ROM 程序去这个固定地址读出映像文件。启动设备不同, 固定地址不同,如下图:

 

2,格式详解

下面的讲解图中,列有C 语言格式的结构体,这些结构体来源于U-boot 的tools 目录下的imximage.h。

2.1 Image Vector Table(IVT)

IVT 会被放在固定的地址,IVT 中是一系列的地址,boot ROM 程序会根据这些地址来确定映像文件中其他部分在哪里。

IVT 格式如下:

要注意的是上图中这4项:

a) header:里面有3项:tag、length、version。length表示IVT的大小,它是32字节。要注意是的,它是大字节序的。

b) entry:用户程序运行时第1条指令的地址,就是程序的链接地址、程序被复制到内存哪里。

c) dcd:映像被复制到内存后,其中的DCD数据的地址。

d) boot data:映像被复制到内存后,其中的boot data的地址。

e) self:映像被复制到内存后,IVT自己所在的地址。

2.2 Boot data

映像被复制到内存后,整个映像文件(IVT之前还有几个扇区数据,比如分区表)所在的地址。

a) start:这是映像文件在内存中的地址,以SD/TF卡为例:

映像文件=(1K数据,内含分区表等信息)+IVT+BootData+DCD+用户数据(bin文件)

注意,IVT并不在映像文件的最前面,start也不是IVT在内存中的地址,而是整个映像文件在内存中的地址:

start = IVT在内存中的地址 - IVT offset

什么意思?假设IVT被保存在启动设备TF卡1024偏移地址处,IVT被复制到内存地址0x87000000,那么start=0x87000000-1024。

所以start表示的是启动设备开头的数据,被复制到内存哪里去。

从它的含义也可以推理出:boot ROM程序会把启动设备开头的数据,复制到内存;而不仅仅是从IVT开始复制。

b) length:保存在启动设备上的整个映像文件的长度,从0地址开始(不是从IVT开始)。

c) plugin:这是一个标记位,当它为1时表示这个映像文件是“plugin”,即插件。

boot ROM程序可以支持有限的启动设备,如果你想双持更多的启动设备比如网络启动、CDROM启动,就需要提供对应的驱动。这些驱动就是“plugin”,我们的教程不涉及,该标记位为0。

Boot data就是用来表示映像文件应该被复制到哪里去,以及它的大小。boot ROM程序就是根据它来把整个映像文件复制到内存去的。

2.3 DCD

“Device Configuration Data”,设备配置数据(DCD),这些DCD将会跟bin文件一起打包烧写在启动设备上。boot ROM程序会从启动设备上读出DCD数据,根据DCD来写对应的寄存器以便初始化芯片。DCD中列出的是对某些寄存器的读写操作,我们可以在DCD中设置DDR控制器的寄存器值,可以在DCD中使用更优的参数设置必需的硬件。这样boot ROM程序就会帮我们初始化DDR和其他硬件,然后才可以把bin程序读到DDR中并运行。

实际上DCD还可以更复杂,它支持多种命令:write data、check data、nop、unlock。我们可以通过write data命令写寄存器,通过check data命令等待寄存器就绪。

2.4 User code and data

就是用户程序或数据,原原本本地添加到映像文件里就可以。

3,实例

制作过程中各项值的计算方法如下图所示:

我们不需要手工去计算,一个mkimage命令就搞定了。上图中各步骤细说如下:

1)确定入口地址entry

我们的程序运行时要放在内存中哪一个位置,这是我们决定的。它被称为入口地址、链接地址。

2)确定映像文件在内存中的地址start

boot ROM程序启动时,会把“Initial Load Region”读出来,“Initial load  Region”里含有IVT、Boot data、DCD。boot ROM根据DCD初始化设备后,再把整个映像文件读到内存。

在启动设备上,“Initial Load Region”之后紧跟着我们的程序,反过来说就是我们程序的前面,放着“Initial Load Region”。假设“Initial Load Region”的大小为load_size,那么在内存中“Initial Load Region”的位置start = entry –  load_size。

注意:“Initial Load Region”位于启动设备0位置,它的头部并不是IVT,而是一些无用的数据(或是分区信息)。

在IMX6ULL中有一个表格,列出了不同启动设备对应的“Initial Load Region  Size”:

 

3)确定IVT在内存中的地址self:

我们知道IVT在启动设备上某个固定的位置,上或中的“Image Vector Table  Offset”:ivt_offset。那么在内存中它的位置可以如下计算:

self = start + ivt_offset = entry – load_size + ivt_offset

4)确定Boot data在内存中的地址boot_data

IVT的大小是32字节,IVT之后就是Boot data,而IVT中的boot_data值表示Boot  data在内存中的位置,计算如下:

boot_data = self + 32 = entry – load_size + ivt_offset + 32

5)确定DCD在内存中的地址dcd

Boot data的大小是12字节,Boot data之后就是DCD,而IVT中的dcd值表示DCD在内存中的位置,计算如下:

dcd = boot_data + 12 = entry – load_size + ivt_offset + 44

6)写入DCD的数据:

DCD是用初始化硬件的,特别是初始化DDR。而DDR的初始化非常的复杂、专业,我们一般是使用硬件厂家提供的代码。

我们是使用类似下面的指令来制作映象文件:

./tools/mkimage -n board/freescale/mx6ullevk/imximage.cfg.cfgtmp -T imximage -e 0x87800000 -d u-boot-dtb.bin u-boot-dtb.imx

上述命令中的imximage.cfg.cfgtmp就是厂家提供的,内部截取部分贴出来:

从上图也可以看到imximage.cfg.cfgtmp文件中基本是对寄存器的写操作。

mkimage程序来自u-boot,它会把imximage.cfg.cfgtmp中的内容转换为DCD数据。

7)写入用户程序

经过上述7个步骤,整个映像文件就构造出来了,可以把它烧入启动设备。

二,u-boot.lds链接脚本

1,u-boot.lds

链接脚本控制程序的链接过程,它规定如何把输入文件内的段放入输出文件, 并控制输出文件内的各部分在程序地址空间内的布局。

如果没有编译过 u-boot的话链接脚本为 arch/arm/cpu/u-boot.lds。但是这个不是最终使用的链接脚本,最终的链接脚本是在这个链接脚本的基础上生成的。编译一下 u-boot,编译完成以后就会在 uboot 根目录下生成 u-boot.lds

arm-buildroot-linux-gnueabihf-gcc -E -Wp,-MD,./.u-boot.lds.d -D__KERNEL__ -D__UBOOT__   -D__ARM__ -marm -mno-thumb-interwork  -mabi=aapcs-linux  -mword-relocations  -fno-pic  -mno-unaligned-access  -ffunction-sections -fdata-sections -fno-common
  -ffixed-r9  -msoft-float   -pipe  -march=armv7-a -D__LINUX_ARM_ARCH__=7   -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -I.  -nostdinc -isystem
  /home/zhuwg1/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/include -ansi -include ./include/u-boot/u-boot.lds.h -DCPUDIR=arch/arm/cpu/armv7  
  -D__ASSEMBLY__ -x assembler-with-cpp -P -o u-boot.lds arch/arm/cpu/u-boot.lds

u-boot.lds:

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
/*
*    首先定义了二进制程序的输出格式为"elf32-littlearm",
*    架构是"arm",程序入口为"_start"符号;
*/
ENTRY(_start)
SECTIONS
{
//定义了程序链接的基地址,默认是0,通过配置CONFIG_SYS_TEXT_BASE可修改这个默认值
. = 0x00000000;
//地址4字节对齐
. = ALIGN(4);
//代码段
.text :
{
/*
*    __image_copy_start和__image_copy_end用于定义需要重定向的段,
*    u-boot将启动初始化分为了两个部分,重定向前初始化board_f和
*    重定向后初始化board_r,在重定向之前完成一些必要初始化,
*    包括可能的ddr初始化,然后通过__image_copy_start和__image_copy_end
*    将u-boot搬运到ddr中,并在ddr中进行重定向后初始化。
  *(.__image_copy_start)
//vectors段, vectors 段保存中断向量表,从u-boot.lds文件我们知道了vectors.S的代码是存在vectors段中的;从地址映射文件中,vectors段的起始地址也是0X87800000,说明整个uboot的起始地址就是 0X87800000。
  *(.vectors)
//将 arch/arm/cpu/armv7/start.s 编译出来的代码放到中断向量表后面
  arch/arm/cpu/armv7/start.o (.text*)
// text段,其他的代码段就放到这里
  *(.text*)
}
. = ALIGN(4);
// .rodata只读数据段(一般存放常量)
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
//数据段 (一般存放已初始化的全局和静态变量)
.data : {
  *(.data*)
}
. = ALIGN(4);
. = .;
. = ALIGN(4);
/*
*     u_boot_list段定义了系统中当前支持的所有命令和设备驱动,此段把散落在各个文件中
*     通过U_BOOT_CMD的一系列拓展宏定义的命令和U_BOOT_DRIVER的拓展宏定义的设备驱动收集到一起,
*     并按照名字排序存放,以便后续在命令行快速检索到命令并执行和检测注册的设备和设备树匹配
*     probe设备驱动初始化;(设备驱动的probe只在定义了dm模块化驱动时有效)
*/
.u_boot_list : {
  KEEP(*(SORT(.u_boot_list*)));
}
. = ALIGN(4);
// 在定义了efi运行时相关支持时才会出现使用的段,一般不用关心
.__efi_runtime_start : {
  *(.__efi_runtime_start)
}
.efi_runtime : {
  *(efi_runtime_text)
  *(efi_runtime_data)
}
.__efi_runtime_stop : {
  *(.__efi_runtime_stop)
}
.efi_runtime_rel_start :
{
  *(.__efi_runtime_rel_start)
}
.efi_runtime_rel : {
  *(.relefi_runtime_text)
  *(.relefi_runtime_data)
}
.efi_runtime_rel_stop :
{
  *(.__efi_runtime_rel_stop)
}
. = ALIGN(8);
//.image_copy_end:uboot 拷贝的结束地址
.image_copy_end :
{
  *(.__image_copy_end)
}
/*
*     一般u-boot运行时是根据定义的基地址开始执行,如果加载地址和链接地址
*     不一致则会出现不能执行u-boot的问题。通过一个
*     配置CONFIG_POSITION_INDEPENDENT即可打开地址无关功能,
*     此选项会在链接u-boot时添加-PIE参数。此参数会在u-boot ELF文件中
*     生成rela*段,u-boot通过读取此段中表的相对地址值与实际运行时地址值
*     依次遍历进行修复当前所有需要重定向地址,使其可以实现地址无关运行;
*     即无论链接基地址如何定义,u-boot也可以在任意ram地址
*     运行(一般需要满足最低4K或者64K地址对齐);
*
*     注意此功能只能在sram上实现,因为此功能会在运行时修改文本段数据段中的地址,
*     如果此时运行在片上flash,则不能写flash,导致功能失效无法实现地址无关;
*/
.rel_dyn_start :
{
  *(.__rel_dyn_start)
}
.rel.dyn : {
  *(.rel*)
}
.rel_dyn_end :
{
  *(.__rel_dyn_end)
}
.end :
{
  *(.__end)
}
_image_binary_end = .;
. = ALIGN(4096);
.mmutable : {
  *(.mmutable)
}
//bbs段
.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));
}
.dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) }
.plt : { *(.plt*) }
.interp : { *(.interp*) }
.gnu.hash : { *(.gnu.hash) }
.gnu : { *(.gnu*) }
.ARM.exidx : { *(.ARM.exidx*) }
.gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
}

_start 在文件 arch/arm/lib/vectors.S 中有定义,表示代码执行入口,也就是第一条指令要放的位置。注意armv7的入口在vectors.S(armv8在start.s),中断向量表放在指令入口最开始的位置:可以看到_start后面就是中断向量表,从图中的“.section ".vectors", "ax”可以得到,此代码存放在.vectors 段里面。

打开u-boot.map如下图:因此代码段的排列顺序为:先放中断向量表,也就是vectors.s,然后再放start.s相关内容,最后放其他的.text段(一大堆built-in.o)。

 

注意这里为什么uboot.map中_start入口地址为什么是0x8780,0000。 链接脚本指定了程序的运行(链接)地址:

程序链接时会指定程序的运行(链接)地址:

  arm-buildroot-linux-gnueabihf-ld.bfd   -pie  --gc-sections -Bstatic -Ttext 0x87800000 -o u-boot -T u-boot.lds arch/arm/cpu/armv7/start.o --start-group  arch/arm/cpu/built-in.o  arch/arm/cpu/armv7/built-in.o  arch/arm/imx-common/built-in.o  
  arch/arm/lib/built-in.o  board/freescale/common/built-in.o  board/freescale/mx6ullevk/built-in.o  cmd/built-in.o  common/built-in.o  disk/built-in.o  drivers/built-in.o  drivers/dma/built-in.o  drivers/gpio/built-in.o  drivers/i2c/built-in.o  
  drivers/mmc/built-in.o  drivers/mtd/built-in.o  drivers/mtd/onenand/built-in.o  drivers/mtd/spi/built-in.o  drivers/net/built-in.o  drivers/net/phy/built-in.o  drivers/pci/built-in.o  drivers/power/built-in.o  drivers/power/battery/built-in.o  
  drivers/power/domain/built-in.o  drivers/power/fuel_gauge/built-in.o  drivers/power/mfd/built-in.o  drivers/power/pmic/built-in.o  drivers/power/regulator/built-in.o  drivers/serial/built-in.o  drivers/spi/built-in.o  drivers/usb/cdns3/built-in.o  
  drivers/usb/common/built-in.o  drivers/usb/dwc3/built-in.o  drivers/usb/emul/built-in.o  drivers/usb/eth/built-in.o  drivers/usb/gadget/built-in.o  drivers/usb/gadget/udc/built-in.o  drivers/usb/host/built-in.o  drivers/usb/musb-new/built-in.o  
  drivers/usb/musb/built-in.o  drivers/usb/phy/built-in.o  drivers/usb/ulpi/built-in.o  fs/built-in.o  lib/built-in.o  net/built-in.o  test/built-in.o  test/dm/built-in.o --end-group arch/arm/lib/eabi_compat.o  arch/arm/lib/lib.a -Map u-boot.map

运行地址0x87800000定义在:

include/configs/mx6_common.h:86:#define CONFIG_SYS_TEXT_BASE    0x87800000

2,System.map/u-boot.map

U-Boot编译之后会在其顶级目录中生成System.map和u-boot.map两个文件。

System.map用于存放符号表信息。 符号表是所有符号和其对应地址的一个列表,随着每次的编译,就会产生一个新的对应的System.map文件,当运行出错时, 通过System.map中的符号表解析,就可以查到一个地址值对应的变量名。按链接地址由小到大的顺序列出所有符号:

87800000 T __image_copy_start
87800000 T _start
87800020 T _undefined_instruction
87800024 T _software_interrupt
87800028 T _prefetch_abort
8780002c T _data_abort
87800030 T _not_used
87800034 T _irq
87800038 T _fiq
87800040 T IRQ_STACK_START_IN
87800060 t undefined_instruction
878000c0 t software_interrupt
87800120 t prefetch_abort
87800180 t data_abort
878001e0 t not_used
87800240 t irq
878002a0 t fiq
878002e8 T reset
878002ec T save_boot_params_ret
87800328 T c_runtime_cpu_setup
87800338 W save_boot_params
8780033c T cpu_init_cp15
87800390 T cpu_init_crit
87800398 T __v7_flush_dcache_all
878003ac t start_flush_levels
878003b0 t flush_levels

由上面信息可知,_start 符号被链接在最前面的地址0x87800000,它是U-Boot的入口。SDRAM初始化完成后,需要将U-Boot加载到上述地址。

u-boot.map中包含了链接过程中涉及的目标文件和所依赖的库文件,然后所链接的目标文件的先后顺序并列出各目标文件中各符号所链接的地址。

Memory Configuration
Name             Origin             Length             Attributes
*default*        0x0000000000000000 0xffffffffffffffff
Linker script and memory map
Address of section .text set to 0x87800000
                0x0000000000000000                . = 0x0
                0x0000000000000000                . = ALIGN (0x4)
//代码段
.text           0x0000000087800000    0x499f0
*(.__image_copy_start)
.__image_copy_start
                0x0000000087800000        0x0 arch/arm/lib/built-in.o
                0x0000000087800000                __image_copy_start
*(.vectors)
//中断向量表
.vectors       0x0000000087800000      0x2e8 arch/arm/lib/built-in.o
                0x0000000087800000                _start
                0x0000000087800020                _undefined_instruction
                0x0000000087800024                _software_interrupt
                0x0000000087800028                _prefetch_abort
                0x000000008780002c                _data_abort
                0x0000000087800030                _not_used
                0x0000000087800034                _irq
                0x0000000087800038                _fiq
                0x0000000087800040                IRQ_STACK_START_IN
arch/arm/cpu/armv7/start.o(.text*)
//arch/arm/cpu/armv7/start.o
.text          0x00000000878002e8       0xb0 arch/arm/cpu/armv7/start.o
                0x00000000878002e8                reset
                0x00000000878002ec                save_boot_params_ret
                0x0000000087800328                c_runtime_cpu_setup
                0x0000000087800338                save_boot_params
                0x000000008780033c                cpu_init_cp15
                0x0000000087800390                cpu_init_crit
//其它代码段
*(.text*)
.text          0x0000000087800398      0x16c arch/arm/cpu/armv7/built-in.o
                0x0000000087800398                __v7_flush_dcache_all
                0x000000008780042c                v7_flush_dcache_all
                0x000000008780043c                __v7_invalidate_dcache_all
                0x00000000878004d0                v7_invalidate_dcache_all
                0x00000000878004e0                lowlevel_init
.text.invalidate_icache_all
                0x0000000087800504       0x18 arch/arm/cpu/armv7/built-in.o
                0x0000000087800504                invalidate_icache_all
... ...
.rodata         0x00000000878499f0    0x11d08
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
.rodata.efi_boot_services
                0x00000000878499f0       0xc8 lib/built-in.o
.rodata.lcd_pads
                0x0000000087849ab8       0xf0 board/freescale/mx6ullevk/built-in.o
.rodata.uart1_pads
                0x0000000087849ba8       0x10 board/freescale/mx6ullevk/built-in.o
.rodata        0x0000000087849bb8       0x80 arch/arm/lib/built-in.o
.rodata        0x0000000087849c38        0x8 drivers/mmc/built-in.o
.rodata.CSWTCH.11
                0x0000000087849c40       0xc8 arch/arm/imx-common/built-in.o
.rodata.CSWTCH.32
                0x0000000087849d08       0x20 common/built-in.o
.rodata.CSWTCH.38
                0x0000000087849d28       0x20 disk/built-in.o
.rodata.CSWTCH.57
                0x0000000087849d48       0x14 cmd/built-in.o
.rodata.asix_eth_id_table
                0x0000000087849d5c      0x138 drivers/usb/eth/built-in.o
.rodata.asix_eth_ops
... ...
.data           0x000000008785b710     0xec04
*(.data*)
.data.rel.ro   0x000000008785b710        0x0 arch/arm/cpu/armv7/start.o
.data.imx_ccm  0x000000008785b710        0x4 arch/arm/cpu/armv7/built-in.o
                0x000000008785b710                imx_ccm
.data.base     0x000000008785b714        0x4 arch/arm/imx-common/built-in.o
.data.reset_cause
                0x000000008785b718        0x4 arch/arm/imx-common/built-in.o
.data.display_count
                0x000000008785b71c        0x4 board/freescale/mx6ullevk/built-in.o
                0x000000008785b71c                display_count
.data.bootm_help_text
... ...
.u_boot_list    0x000000008786a320     0x1580
*(SORT_BY_NAME(.u_boot_list*))
.u_boot_list_2_blk_driver_1
                0x000000008786a320        0x0 drivers/built-in.o
.u_boot_list_2_blk_driver_2_mmc
                0x000000008786a320       0x18 drivers/mmc/built-in.o
                0x000000008786a320                _u_boot_list_2_blk_driver_2_mmc
.u_boot_list_2_blk_driver_2_usb
                0x000000008786a338       0x18 common/built-in.o
                0x000000008786a338                _u_boot_list_2_blk_driver_2_usb
.u_boot_list_2_blk_driver_3
                0x000000008786a350        0x0 drivers/built-in.o
.u_boot_list_2_cmd_1
                0x000000008786a350        0x0 cmd/built-in.o
.u_boot_list_2_cmd_1
                0x000000008786a350        0x0 common/built-in.o
.u_boot_list_2_cmd_2_base
                0x000000008786a350       0x1c cmd/built-in.o
                0x000000008786a350                _u_boot_list_2_cmd_2_base
.u_boot_list_2_cmd_2_bdinfo
                0x000000008786a36c       0x1c cmd/built-in.o
                0x000000008786a36c                _u_boot_list_2_cmd_2_bdinfo
... ...
.__efi_runtime_start
                0x000000008786b8a0        0x0
*(.__efi_runtime_start)
.__efi_runtime_start
                0x000000008786b8a0        0x0 arch/arm/lib/built-in.o
.efi_runtime    0x000000008786b8a0      0x100
*(efi_runtime_text)
efi_runtime_text
                0x000000008786b8a0       0x24 lib/built-in.o
                0x000000008786b8a0                efi_reset_system
                0x000000008786b8a4                efi_get_time
*(efi_runtime_data)
*fill*         0x000000008786b8c4        0x4
... ...
.image_copy_end
                0x000000008786ba30        0x0
*(.__image_copy_end)
.__image_copy_end
                0x000000008786ba30        0x0 arch/arm/lib/built-in.o
... ...
.rel_dyn_start  0x000000008786ba30        0x0
*(.__rel_dyn_start)
.__rel_dyn_start
                0x000000008786ba30        0x0 arch/arm/lib/built-in.o
.rel.dyn        0x000000008786ba30     0xa538
*(.rel*)
.rel.got       0x000000008786ba30        0x0 arch/arm/cpu/armv7/start.o
... ...
.rel_dyn_end    0x0000000087875f68        0x0
*(.__rel_dyn_end)
.__rel_dyn_end
                0x0000000087875f68        0x0 arch/arm/lib/built-in.o
.end            0x0000000087875f68        0x0
*(.__end)
.__end         0x0000000087875f68        0x0 arch/arm/lib/built-in.o
                0x0000000087875f68                _image_binary_end = .
                0x0000000087876000                . = ALIGN (0x1000)
... ...
.bss_start      0x000000008786ba30        0x0
*(.__bss_start)
.__bss_start   0x000000008786ba30        0x0 arch/arm/lib/built-in.o
                0x000000008786ba30                __bss_start
                0x000000008786ba30                __bss_base = .
.bss            0x000000008786ba30    0x37f00
*(.bss*)
.bss.modes     0x000000008786ba30        0x8 arch/arm/imx-common/built-in.o
.bss.params    0x000000008786ba38        0x4 arch/arm/lib/built-in.o
... ...
.bss_end        0x00000000878a3930        0x0
*(.__bss_end)
.__bss_end     0x00000000878a3930        0x0 arch/arm/lib/built-in.o
                0x00000000878a3930                __bss_end

 可以从u-boot.map获取下面符号的地址:

变量   

数值 

描述

*(.vectors)

0x87800000

中断向量表

arch/arm/cpu/armv7/start.o 

0x87800300 

start.c

__image_copy_start 

0x87800000

 u-boot拷贝的首地址

__image_copy_end

0x8785dd54

u-boot拷贝的结束地址

.rodata

0x878499f0

只读数据段

.data

0x8785b710 

数据段

__rel_dyn_start

 0x8785dd54

 .rel.dyn 段起始地址

__rel_dyn_end

 0x878668f4 

.rel.dyn 段结束地址

_image_binary_end

0x878668f4

镜像结束地址

__bss_start    

0x8785dd54

.bss 段起始地址

__bss_end

 0x878a8e74

 .bss 段结束地址

 

参考链接:

https://www.cnblogs.com/fuzidage/p/17901516.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/707347.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设

京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设 京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设 水库大坝监测系统主要包括渗流监测系统、流量监测系统、雨量监测系统、沉降监测系统组成。每一个监测系统由监测仪器及自动化数据采集装置(内置通信装…

AI引领项目管理新时代:效率与智能并驾齐驱

在数字化浪潮的推动下,项目管理领域正迎来一场由AI技术引领的革新。从自动化任务执行到智能决策支持,AI技术的应用正让项目管理变得更加高效、精准和智能化。本文将探讨项目管理人员及其实施团队如何运用AI技术,以及这些技术如何助力项目管理…

如何用Xinstall CPS结算系统打破传统营销桎梏,实现用户增长?

在互联网流量红利逐渐衰退的今天,App推广和运营面临着前所未有的挑战。如何快速搭建起满足用户需求的运营体系,成为了众多企业急待解决的问题。而在这个关键时刻,Xinstall CPS结算系统应运而生,以其独特的优势帮助企业解决了一系列…

iptables教程

1.iptables安装 1.1 iptables和iptables-service的关系 iptables 是基于内核的,和 iptables-services 没有关系,不用安装任何工具包就可以使用 iptable 命令添加的防火墙规则, 但是iptables添加的规则是临时的,基于内存的&…

SK海力士计划于2024年第四季度启动GDDR7大规模生产

SK海力士,作为HBM市场的领头羊,于6月13日宣布,公司目标于2024年第四季度开始其GDDR7芯片的大规模生产。 与此同时,美光科技在Computex展会上也宣布推出其GDDR7图形内存,目前正处于样品测试阶段。据AnandTech报道&#…

CRC计算单元

CRC计算单元 CRC是Cyclic Redundancy Check,循环冗余校验的缩写. 是一种检测数据错误的技术,主要用在数据通信和数据存储的方面. 但是这种技术只能检测到传输或存储的数据是否有误,没有将错误纠正的功能. 而CRC计算单元是一个独立的具备CRC计算功能的外设. AT32 MCU片上CRC计…

当JS遇上NLP:开启图片分析的奇幻之旅

前言 在当今科技飞速发展的时代,JavaScript(JS)作为广泛应用的编程语言,展现出了强大的活力与无限的可能性。与此同时,自然语言处理(NLP)领域也正在经历着深刻的变革与进步。 当这两者碰撞在一…

phpcms仿蚁乐购淘宝客网站模板

phpcms仿蚁乐购网站模板,淘宝客行业模板免费下载,该模板网站很容易吸引访客点击,提升ip流量和pv是非常有利的。本套模板采用现在非常流行的全屏自适应布局设计,且栏目列表以简洁,非常时尚大气。页面根据分辨率大小而自…

《现代通信原理与技术》--数字信号的最佳接收实验报告

《现代通信原理与技术》 数字信号的最佳接收实验报告 实 验:数字信号的最佳接收实验报告 目录 摘要......................................................................................................3 引言........................................…

Linux---系统的初步学习【 项目二 管理Linux文件和目录】

项目二 管理Linux文件和目录 2.1项目知识准备 ​ 文件是存储在计算机上的数据集合。在Windows系统中,我们理解的文件可以是文本文档、图片、程序、音乐、视频等。在Linux中,一切皆文件,也就是除了Windows中所理解的文件,目录、字…

如何申请小程序SSL证书

在互联网时代,数据安全和用户隐私保护变得尤为重要。SSL证书作为网站、应用或小程序与用户之间建立安全连接的关键工具,其重要性不言而喻。SSL证书能够加密数据传输,防止信息被窃取,提升用户信任度,对于小程序开发者来…

u-boot(六) - 详细启动流程

一,u-boot启动第一阶段 1,启动流程 ENTRY(_start) //arch/arm/lib/vectors.S ----b resets //arch/arm/cpu/armv7/start.S --------b save_boot_params ------------b save_boot_params_ret //将cpu的工作模式设置为SVC32模式(即管理模式&a…

【PHP开发工程师系统性教学】——thinkPHP的分页操作,不管有几页,用这个你想分几页就分几页

👨‍💻个人主页:开发者-曼亿点 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 曼亿点 原创 👨‍💻 收录于专栏&#xff1a…

力扣384. 打乱数组

Problem: 384. 打乱数组 文章目录 题目描述思路复杂度Code 题目描述 思路 打乱数组的主要算法: 从1 - n每次生成[i ~ n - i]的一个随机数字,再将原数组下标位置为i的元素和该随机数字位置的元素交换 复杂度 打乱数组的主要算法 时间复杂度: O ( n ) O(…

YOLOv8可视化界面,web网页端检测

YOLOv8可视化界面,web网页端检测。支持图片检测,视频检测,摄像头检测等,支持检测、分割等多种任务,实时显示检测画面。支持自定义数据集,计数,……

编译原理:语法分析

目录 引言上下文无关文法 CFG: Context-Free Grammar定义推导方法最左推导和最右推导 分析树分析树->抽象语法树常见的上下文无关文法文法设计二义性文法扩展巴科斯范式:EBNF extended Backus Normal Form 文法和语言分类相关术语直接推导推导*推导句型、句子、语…

酷开科技丨酷开系统智慧中心,解锁AI智能家居生活的无限可能

想象一下,未来的AI电视不再是冷冰冰的机器,而是家庭的智能伙伴。它学习你的喜好,预测你的需求,用声音和触感与你交流。它控制家中的灯光、温度,甚至帮你订购生活用品。 在探索智能家居的未来发展时,酷开系…

计算机图形学入门11:图形管线与着色器

1.什么是图形管线 把场景中的物体经过一系列的处理,最后一张图像的形式在屏幕上显示出来,这一系列过程就是图形管线(Graphics Pipeline),也叫实时渲染管线(Real-time Rendering Pipeline)。如下图所示,为整个渲染管线的过程。 渲染…

WPF学习(1)--类与类的继承

在面向对象编程中,继承是一种机制,允许一个类(称为子类或派生类)从另一个类(称为父类或基类)继承属性和方法。继承使我们能够创建一个通用类,然后根据需要扩展或修改它以创建更具体的类。以下是…

基于改进字典学习的旋转机械故障诊断方法(MATLAB)

在过去的二十年里,稀疏表示在各个领域引起了广泛的关注。它的核心思想是将信号描述为尽量少的字典原子,在计算机视觉、生物学、特征提取和机械故障诊断方面显示出强大而可靠的能力。SR通常分为两个步骤:构建字典和学习稀疏系数。对于稀疏系数…