尝试了解加载内存地址(LMA)和ARM二进制映像中的二进制文件偏移量 [英] Trying to understand the load memory address (LMA) and the binary file offset in an ARM binary image

查看:151
本文介绍了尝试了解加载内存地址(LMA)和ARM二进制映像中的二进制文件偏移量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 ARM Cortex M4 STM32F4xxxx ),并且正在尝试了解二进制文件( *。elf)的精确程度。 *。bin )已生成并刷新到内存中,特别是关于内存位置。具体来说,我不了解 LMA 是如何从实际二进制文件偏移量中翻译的。让我用一个例子来解释:

I'm working in an ARM Cortex M4 (STM32F4xxxx) and I'm trying to understand how exactly the binaries (*.elf and *.bin) are built and flashed in memory, specially with regards to the memory locations. Specifically, what I don't understand is how the LMA gets 'translated' from the actual binary file offset. Let me explain with an example:

我有一个 *。elf 文件,其(相关)部分如下一个:(从 objdump -h 获取)

I have an *.elf file whose (relevant) sections are the following ones:(obtained from objdump -h)

my_file.elf:     file format elf32-littlearm

Sections:
Idx Name              Size      VMA       LMA       File off  Algn
  0 .text             000001c4  08010000  08010000  00020000  2**0
                      CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .bootloader       00004000  08000000  08000000  00010000  2**0
                      CONTENTS, ALLOC, LOAD, DATA

根据该文件,VMA和LMA为 0x8000000 0x8010000 ,完美的选择是,因为它们是在链接描述文件中以这种方式定义的。此外,根据该报告,这些节的偏移量分别为 0x10000 0x20000 。接下来,我执行以下命令来转储与 .bootloader 相对应的内存:

According to that file, the VMA and LMA are 0x8000000 and 0x8010000, what is perfectly fine since they are defined that way in the linker script file. In addition, according to that report, the offsets of those sections are 0x10000 and 0x20000 respectively. Next, I execute the following command for dumping the memory corresponding to the .bootloader:

xxd -s 0x10000 -l 16 my_file.elf
00010000: b007 c0de b007 c0de b007 c0de b007 c0de  ................ 

现在,创建要闪存到内存中的二进制文件:

Now, create the binary file to be flashed into memory:

arm-none-eabi-objcopy -O binary --gap-fill 0xFF -S my_file.elf my_file.bin 

根据上面提供的信息,据我了解,生成的二进制文件应位于 .bootloader 部分在 0x8000000 。我知道这不是实际的工作方式,因为文件会变得非常大,因此 bootloader 放在文件的开头,因此地址 0x0 (检查两个内存块是否相同,即使它们位于不同的地址):

According to the information provided above, and as far as I understand, the generated binary file should have the .bootloader section located at 0x8000000. I understand that this is not how it actually works, inasmuch as the file would get extremely big, so the bootloader is placed at the beginning of the file, so the address 0x0 (check that both memory chunks are identical, even though the are at different addresses):

xxd -s 0x00000 -l 16 my_file.bin
00000000: b007 c0de b007 c0de b007 c0de b007 c0de  ................

据我了解,当提到的二进制文件被刷新到内存中时, bootloader 将位于地址 0x0 ,考虑到所讨论的MCU跳到地址 0x4 (从 0x0 获取SP之后),正如我在此处检查的那样(第26页): https://www.st.com/content/ccc/resource/technical/document/application_note/76/f9/c8/10/8a/33/4b/f0/DM00115714.pdf/ files / DM00115714.pdf / jcr:content / translations / en.DM00115714.pdf

As far as I understand, when the mentioned binary file is flashed into memory, the bootloader will be at address 0x0, what is perfectly fine taking into account that the MCU in question jumps to the address 0x4 (after getting the SP from 0x0) when it starts working, as I have checked here (page 26): https://www.st.com/content/ccc/resource/technical/document/application_note/76/f9/c8/10/8a/33/4b/f0/DM00115714.pdf/files/DM00115714.pdf/jcr:content/translations/en.DM00115714.pdf

最后,我的问题是:

引导加载程序是否实际放置在 0x0 上?如果是这样,在链接文件中定义存储扇区的目的是什么?

Will the bootloader actually be placed at 0x0? If so, what's the purpose of defining the memory sectors in the linker file?

这是因为 0x0 属于闪存,并且在MCU启动时,所有闪存均被复制到 RAM 地址为 0x8000000 ?如果是这样,引导程序是否将从闪存中执行,而其余所有代码是否从 RAM 中执行?

Is this because 0x0 belongs to flash memory, and when the MCU starts, all the flash is copied into RAM at address 0x8000000? If so, will the bootloader be executed from flash memory and all the rest of the code from RAM?

考虑到上述问题,如果我什么都不懂, LMA 文件偏移量

Taking into account the above questions, if I have not understood anything, what's the relation/difference between the LMA and the File offset?

推荐答案

否,引导加载程序的定义位置为08000000

No, bootloader will be at 08000000, as defined in elf file.

图像将在该地址的闪存中刻录并直接从该地址执行(不在其他位置复制)。

Image will be burned in flash at that address and executed directly from there (not copied somewhere else or so).

有些未记录的行为,即在生成二进制图像时跳过实际数据之前的统一区域。作为BFDlib源代码中的注释( https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=bfd/binary.c;h=37f5f9f7363e7349612cdfc8bc579369bbabbc0c ; hb = HEAD#l238

There's somewhat undocumented behaviour, that unitialized area before actual data is skipped when producing binary image. As comment in BFDlib source states (https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=bfd/binary.c;h=37f5f9f7363e7349612cdfc8bc579369bbabbc0c;hb=HEAD#l238)

/* The lowest section LMA sets the virtual address of the start
   of the file.  We use this to set the file position of all the
   sections.  */

.elf中的最低节(.bootloader)LMA为08000000,因此二进制文件将启动

在确定图像中的地址时,应将此地址考虑在内并将其添加到文件偏移中。

Lowest section (.bootloader) LMA is 08000000 in your .elf, so binary file will start at this address.
You should take this address into account and add it to file offset when determining address in the image.

Sections:
Idx Name              Size      VMA       LMA       File off  Algn
  0 .text             000001c4  08010000  08010000  00020000  2**0
    /*                                    ^^^^^^^^              */
    /* this section will be at offset 10000 in image            */

                      CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .bootloader       00004000  08000000  08000000  00010000  2**0
    /*                                    ^^^^^^^^              */
    /* this is the lowest LMA in your case it will be used      */
    /* as a start of an image, and this section will be placed  */
    /* directly at start of the image                           */
                      CONTENTS, ALLOC, LOAD, DATA

Memory layout:     Bin. image layout:
000000000                    \ skipped
...       ________________   /
080000000 .bootloader         0
...       ________________
080004000   <gap>          4000
...       ________________
080010000 .text           10000
...       ________________
0800101C4                 101C4

该地址在ldscript中定义,因此二进制映像应从固定位置开始。但是,在处理ldscrips和二进制映像时,您应该意识到这种行为。

That address defined in ldscript, so binary image should start at fixed location. However you should be aware of this behaviour when dealing with ldscrips and binary images.

总结构建和刷新过程:


  1. 链接时,起始地址在ldscript中定义,而elf的第一部分位于此处。

  2. 转换为二进制文件时,起始地址由LMA和二进制映像从该地址开始。

  3. 刷新映像时,将相同的地址作为参数分配给flasher,因此映像放置在正确的位置(在ldscript中定义)。

更新:STM32F4xxx引导过程。

Update: STM32F4xxx booting process.

从地址0开始的地址区域对于这些MCU。可以将其配置为映射其他区域,例如闪存,SRAM或系统ROM。通过引脚 BOOTSELx 选择它们。
从CPU端看,似乎第二个闪存副本(SRAM或系统ROM)出现在地址0。

Address region starting at address 0 is special to those MCUs. It can be configured to map other regions, which are flash, SRAM, or system ROM. They're selected by pins BOOTSELx. From CPU side it looks like second copy of flash (SRAM or system ROM) appears at address 0.

CPU启动时,它首先从以下位置读取初始SP:地址0和地址4的初始PC。实际上,是从闪存中执行的。
如果链接了代码以从实际的闪存位置运行,则初始PC将指向该位置。在这种情况下,执行从实际的闪存地址开始。

When CPU starts, it first reads initial SP from adress 0 and initial PC from address 4. Actually, reads from the flash memory are performed. If the code is linked to run from actual flash location, then initial PC will point there. In this case execution starts at actual flash address.

----- Mapped area (mimics contents as flash) ---
       0:          (02001000)         ;
       4:          (0800ABCD) ----.   ; CPU reads PC here
....                              |   ; (it points to flash)
----- FLASH -----                 |
 8000000:           20001000      |   ; initial stack pointer
 8000004:           0800ABCD --.  |   ; address of _start in flash
....                           |  |   
 800ABCD: <_start:> movw ... <-'<-'   ; Code execution starts here

(注意:这不适用于十六进制图像(如intel十六进制或s-记录),这样的格式会明确定义加载地址,并按原样使用。)

(Note: this does not apply to hex images (like intel hex or s-record) as such formats define loading address explicitly and it is used as is there).

这篇关于尝试了解加载内存地址(LMA)和ARM二进制映像中的二进制文件偏移量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆