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

news2024/12/28 2:09:38

一,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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

妙用OSGraph:发掘GitHub知识图谱上的开源故事

作者:范志东 1. 何为OSGraph? OSGraph (Open Source Graph) 是一个开源图谱关系洞察工具,基于GitHub开源数据全域图谱,实现开发者行为、项目社区生态的分析洞察。可以为开发者、项目Owner、开源布道师、社区运营等提供简洁直观的…

电脑自带录屏在哪?电脑录屏,4个详细方法

在现代社会中,越来越多的人需要在电脑上录制视频,比如录制游戏操作、制作教学视频、演示文稿等等。因此,电脑录屏成为了一项非常重要的功能。那么电脑自带录屏在哪?本文将带领大家看看可以使用哪些方法进行录屏。 录屏方法一&…

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

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

Python | Leetcode Python题解之第149题直线上最多的点数

题目&#xff1a; 题解&#xff1a; class Solution:def maxPoints(self, points: List[List[int]]) -> int:n len(points)if n < 2:return nres 2for i in range(n):x1, y1 points[i][0], points[i][1]has {}for j in range(i 1, n):x2, y2 points[j][0], points…

AI虚拟试穿技术:开启高保真、多场景、多样化服装组合的试穿应用

随着电子商务的快速发展,消费者对于在线购物体验的要求越来越高。特别是在服装领域,消费者渴望能够在购买前直观地了解服装的试穿效果。传统的虚拟试穿技术虽然已有一定的发展,但在不同场景下的高保真度和鲁棒性方面仍面临挑战。为此,我们研发了一种全新的AI虚拟试穿技术,…

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

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

探索AI视频生成技术的原理

探索AI视频生成技术的原理 随着人工智能技术的迅猛发展&#xff0c;AI在视频生成领域的应用已经引起了广泛关注。从娱乐、广告到教育和科学研究&#xff0c;AI视频生成技术正在彻底改变我们制作和消费视频内容的方式。本文将深入探讨AI视频生成技术的原理&#xff0c;解析其背…

解决CentOS的yum命令失效的问题

近日笔者对一台装有 CentOS 7.9 系统的服务器反复折腾&#xff0c;玩到最后发现 yum 命令用不了&#xff0c;总是报下面的错误信息&#xff1a; There was a problem importing one of the Python modules required to run yum. The error leading to this problem was:/usr/l…

通用大模型VS垂直大模型,你更青睐哪一方?

AI大模型之辩&#xff1a;通用与垂直&#xff0c;谁将引领未来&#xff1f; 在人工智能&#xff08;AI&#xff09;领域&#xff0c;大模型技术的崛起无疑为整个行业带来了革命性的变革。然而&#xff0c;随着技术的深入发展&#xff0c;AI大模型的战场似乎正在悄然分化&#…

9.常见集合

目录 一、三种常见集合二、Vector2.1 特性2.2 创建并更新Vector2.3 读取Vector中的元素2.4 遍历元素2.5 储存不同类型的值 三、字符串3.1 概念3.2 新建3.2 更新3.3 索引字符串3.4 字符串切片3.5 字符串遍历 四、哈希map4.1 基本概念4.2 新建哈希map4.3 访问哈希map中的值4.4 更…

使用adb通过wifi连接手机

1&#xff0c;手机打开开发者模式&#xff0c;打开无线调试 2&#xff0c;命令行使用adb命令配对&#xff1a; adb pair 192.168.0.102:40731 输入验证码&#xff1a;422859 3&#xff0c;连接设备&#xff1a; adb connect 192.168.0.102:36995 4&#xff0c;查看连接状态:…

【云岚到家】-day03-2-门户缓存实现实战

【云岚到家】-day03-2-门户缓存实现实战 5 缓存实现5.2 定时任务更新缓存5.2.1 分布式调度平台5.2.1.1 jdk提供的Timer定时器5.2.1.2 使用第三方Quartz方式5.2.1.3 使用分布式调度平台XXL-JOB 5.2.2 XXL-JOB5.2.2.1 介绍5.2.2.2 部署调度中心5.2.2.3 执行器 5.2.2 定义缓存更新…

二开版视频CMS完整运营源码/新版漂亮APP手机模板/集成员分销功能等

一个二开的影视CMS&#xff0c;直接上传源码至网站根目录&#xff0c;访问网站域名即可安装。 测试环境&#xff1a;Nginx 1.20.1—MySQL 5.6.50–PHP-7.2&#xff08;安装拓展/fileinfo&#xff09; 上传源码&#xff0c;访问域名直接安装 后台地址&#xff1a;域名/MDadmi…

4. 案例研究-接口程序

4. 案例研究-接口程序 本章通过一个案例研究, 来展示设计互相配合的函数的过程.4.1 turtle 模块 创建一个文件mypolygon.py, 并输入如下代码:import turtle bob turtle.Turtle() print(bob)# 这一句的作用是让画板停留, 等手动点击x关闭画板, 程序才结束. # 否则程序执行完毕…

Spring中的IOC

IOC&#xff08;Inversion of Control&#xff0c;控制反转&#xff09;是Spring框架核心概念之一。它是一种设计原则&#xff0c;用来实现对象的松耦合和依赖管理。在传统的编程中&#xff0c;对象负责创建或查找其依赖对象&#xff0c;而在IOC模式下&#xff0c;这些职责被移…

C++ | Leetcode C++题解之第150题逆波兰表达式求值

题目&#xff1a; 题解&#xff1a; class Solution { public:int evalRPN(vector<string>& tokens) {int n tokens.size();vector<int> stk((n 1) / 2);int index -1;for (int i 0; i < n; i) {string& token tokens[i];if (token.length() >…

24年大一尺取练习(东北林业大学)

前言&#xff1a; 今天下午才刚看到oj上发了这次练习&#xff0c;我已经错过了截止时间&#xff0c;刚好不是很想复习六级&#xff0c;就把这次练习补了吧。 正文&#xff1a; Problem:A 尺取Language&#xff1a; #include<bits/stdc.h> using namespace std; const i…

如何把路由器设备的LAN口地址为三大私网地址

要将路由器的LAN口地址配置为三大私有IP地址范围之一&#xff08;10.0.0.0/8、172.16.0.0/12 或 192.168.0.0/16&#xff09;&#xff0c;我们需要访问路由器的管理界面并进行相应的设置。 下面是步骤&#xff1a; 连接到路由器&#xff1a; 连接到路由器的管理界面&#xf…

C++设计模式——Bridge桥接模式

一&#xff0c;桥接模式简介 桥接模式是一种结构型设计模式&#xff0c;用于将抽象与实现分离&#xff0c;这里的"抽象"和"实现"都有可能是接口函数或者类。 桥接模式让抽象与实现之间解耦合&#xff0c;使得开发者可以更关注于实现部分&#xff0c;调用…

谷粒商城实战(036 k8s集群学习2-集群的安装)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第343p-第p345的内容 k8s 集群安装 kubectl --》命令行操作 要进入服务器 而且对一些不懂代码的产品经理和运维人员不太友好 所以我们使用可视化…