【发布时间】:2021-11-11 21:28:40
【问题描述】:
我正在为 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 文件。做这样的事情的惯用方式是简单地创建一个结构来硬编码一些可以在文件中检测到的前导幻数序列吗?
【问题讨论】:
-
srecord 格式记录在维基百科中。使用 s3 记录完整地址在每一行中
-
对于一个 mcu,二进制文件中不应该定义 ram,这将是您构建中的一个非常严重的错误。任何非零 ram 初始化都将在闪存空间中,然后在引导程序中复制到 ram。写一个简单的asm程序,不到10行就可以了,然后看看它是怎么落到图像中的。
-
还可以查看链接描述文件的部分,答案就在那里
-
你也可以使用 readelf 查看二进制文件以了解链接的结果
-
哦,当然,我的思路已经走得太远了,以至于我忘了质疑我的基本假设。假设我有 elf 文件(没有反汇编 elf 文件并找到在 RAM 中设置相关地址的指令),有什么方法可以具体知道在 srec 文件中查找值的位置?
标签: linker arm gnu objcopy srecord