0

我正在为 ARM Cortex-M 微控制器开发一个独立的应用程序,在研究 S-Record 文件的结构时,我发现我对 S-Record 格式中地址的表示方式存在某种误解。

我在源代码中定义了一个变量,如下所示:

uint32_t g_ip_address = IP_ADDRESS(10, 1, 0, 56); // in LE: 0x3800010A

当我运行 objdump 时,我看到变量最终出现在地址 0x1ffe01c4 的 .data 部分中:

$ arm-none-eabi-objdump -t application.elf | grep g_ip_address
1ffe01c4 g     O .data  00000004 g_ip_address

这是有道理的,因为我的链接器脚本的内存部分看起来像这样并且 .data 将进入 RAM:

MEMORY
{
  FLASH (rx)         : ORIGIN = 0x00000000, LENGTH = 0x0200000  /*   2M */
  RAM (rwx)          : ORIGIN = 0x1FFE0000, LENGTH = 0x00A0000  /* 640K */   
}

但是,当我检查 srec 文件时,我发现记录的地址不是 0x1FFE0000。它是 0x0005F570,它似乎把它放在了 FLASH 部分(为清楚起见,添加了空格)。

S315 0005F570 00000000 3800010A 000010180000000014

是否在不同的记录条目中编码了隐式偏移量?objcopy 是如何得到这个新地址的呢?如果这个值以某种方式被编码到一个函数中(可能是一些变量的主前初始化)?

最终,我的目标是能够解析 srec 文件并修补 IP 地址值以创建新的 srec 文件。做这样的事情的惯用方式是否只是为了创建一个结构来硬编码一些可以在文件中检测到的前导幻数序列?

4

1 回答 1

1

闪存.s

.cpu cortex-m0
.thumb

.word 0x00002000
.word reset

.thumb_func
reset:
    b reset
    
.data
.word 0x11223344

.bss
.word 0x00000000
.word 0x00000000

闪存.ld

MEMORY
{
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
    .text   : { *(.text*)   } > rom
    .bss    : { *(.bss*)    } > ram AT > rom
    .data   : { *(.data*)   } > ram AT > rom
}

建造它

arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 flash.s -o flash.o
arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld flash.o -o so.elf
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy --srec-forceS3 so.elf -O srec so.srec
arm-none-eabi-objcopy -O binary so.elf so.bin

cat so.list

08000000 <reset-0x8>:
 8000000:   00002000    andeq   r2, r0, r0
 8000004:   08000009    stmdaeq r0, {r0, r3}

08000008 <reset>:
 8000008:   e7fe        b.n 8000008 <reset>

Disassembly of section .bss:

20000000 <.bss>:
    ...

Disassembly of section .data:

20000008 <.data>:
20000008:   11223344            ; <UNDEFINED> instruction: 0x11223344

cat so.srec

S00A0000736F2E7372656338
S30F080000000020000009000008FEE7D2
S3090800000A443322113A
S70508000000F2

arm-none-eabi-readelf -l so.elf

Elf file type is EXEC (Executable file)
Entry point 0x8000000
There are 3 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000094 0x08000000 0x08000000 0x0000a 0x0000a R E 0x2
  LOAD           0x000000 0x20000000 0x0800000a 0x00000 0x00008 RW  0x1
  LOAD           0x00009e 0x20000008 0x0800000a 0x00004 0x00004 RW  0x1

 Section to Segment mapping:
  Segment Sections...
   00     .text 
   01     .bss 
   02     .data 

hexdump -C so.bin

00000000  00 20 00 00 09 00 00 08  fe e7 44 33 22 11        |. ........D3".|
0000000e

bss 通常不会按原样公开,您使链接描述文件复杂化以添加起点和终点,以便您可以在引导程序中将该范围归零。对于 .data,您可以清楚地看到标准 binutils 工具发生了什么。

您没有提供足够的代码(和链接器脚本),也没有提供演示问题的最小示例,所以这已经是可以做到的了。

于 2021-09-17T02:47:54.413 回答