通过读取 .hex 和 .map,我如何确定 BL 链接到正确的函数偏移量?
By reading .hex and .map, how can I be sure that a BL links to the right function offset?
我目前正在做一个 "hex compare" 的乐趣,以了解正在发生的事情。
我知道比较十六进制有时会产生太多变化,无法比较。
只需更改一个函数调用,我就可以在十六进制中进行一些小改动。
我的嵌入式代码包含 Foo(5);
,我将其替换为 Bar(5);
(其签名相同),然后替换为 Bla(5);
。
当我比较十六进制文件时,我有以下内容:
绿色部分为CRC。
借助hex文件和map文件,如何确定Foo确实被Bar或Bla取代,而不是被其他函数取代?
这是我在 ARMv7-M arch doc link 中发现的内容。但是即使知道了偏移量,我仍然不知道我是否可以从中找出一些东西......如何在机器代码中转录 .map 地址?
在.map中,各自的地址是:
我正在使用 IAR 编译器开发 STM32L4xx(皮质 M4)。
与往常一样,您需要该核心的 arm 架构参考手册(以及技术参考手册)。 cortex-m4 trm 会告诉您它是一个 armv7-m 架构,您为此获得了 arm。
BL 是两条独立的指令,尽管它通常显示为 32 条指令,但它们不必背靠背执行,但必须以正确的顺序执行(并且你不能在两者之间弄乱 lr) :
11110xxxxxxxxxxx
11111xxxxxxxxxxx
所以
0xF0E6
00011100110000000000000
0xFC03
00011100110000000000000
100000000110
00011100110100000000110
00011100110100000000110
000 1110 0110 1000 0000 0110
0x0E6806+4+PC
或者编写程序(不处理 H=10 上的符号扩展,因为您没有设置这些位):
#include <stdio.h>
void fun ( unsigned int a, unsigned int b )
{
unsigned int ra;
ra=a&0x7FF;
ra<<=12;
ra|=(b&0x7FF)<<1;
ra&=0xFFFFFFFE;
ra+=4;
printf("PC(inst)+0x%08X\n",ra);
}
int main ( void )
{
fun(0xF0E6,0xFC03);
fun(0xF008,0xFD03);
fun(0xF0C7,0xFC03);
return(1);
}
给出:
PC(inst)+0x000E680A
PC(inst)+0x00008A0A
PC(inst)+0x000C780A
有问题的 bl 指令的地址是什么?作为 Intel hex 文件,无法根据您提供的内容确定。 (我更喜欢 32 位地址的 srec)。
older/est ARM ARM,armv5 更适合查看这两条指令,但该文档中有一个 typo/bug thumb 版本,您不会去掉两个较低的位将是该指令的 arm 版本。
.thumb
bl here
nop
bl here
nop
nop
nop
here:
00000000 <here-0x10>:
0: f000 f806 bl 10 <here>
4: 46c0 nop ; (mov r8, r8)
6: f000 f803 bl 10 <here>
a: 46c0 nop ; (mov r8, r8)
c: 46c0 nop ; (mov r8, r8)
e: 46c0 nop ; (mov r8, r8)
PC(inst)+0x00000010
PC(inst)+0x0000000A
请注意,对于 GNU 汇编程序,您不能只使用 .word 或 .hword 技巧,您必须使用 .inst.n:
.thumb
bl here
nop
bl here
nop
nop
nop
here:
.inst.n 0xf000
.inst.n 0xf806
00000000 <here-0x10>:
0: f000 f806 bl 10 <here>
4: 46c0 nop ; (mov r8, r8)
6: f000 f803 bl 10 <here>
a: 46c0 nop ; (mov r8, r8)
c: 46c0 nop ; (mov r8, r8)
e: 46c0 nop ; (mov r8, r8)
00000010 <here>:
10: f000 f806 bl 20 <here+0x10>
与你的其中一位:
.thumb
.inst.n 0xF0E6
.inst.n 0xFC03
00000000 <.text>:
0: f0e6 fc03 bl e680a <.text+0xe680a>
我目前正在做一个 "hex compare" 的乐趣,以了解正在发生的事情。
我知道比较十六进制有时会产生太多变化,无法比较。
只需更改一个函数调用,我就可以在十六进制中进行一些小改动。
我的嵌入式代码包含 Foo(5);
,我将其替换为 Bar(5);
(其签名相同),然后替换为 Bla(5);
。
当我比较十六进制文件时,我有以下内容:
绿色部分为CRC。
借助hex文件和map文件,如何确定Foo确实被Bar或Bla取代,而不是被其他函数取代?
这是我在 ARMv7-M arch doc link 中发现的内容。但是即使知道了偏移量,我仍然不知道我是否可以从中找出一些东西......如何在机器代码中转录 .map 地址?
在.map中,各自的地址是:
我正在使用 IAR 编译器开发 STM32L4xx(皮质 M4)。
与往常一样,您需要该核心的 arm 架构参考手册(以及技术参考手册)。 cortex-m4 trm 会告诉您它是一个 armv7-m 架构,您为此获得了 arm。
BL 是两条独立的指令,尽管它通常显示为 32 条指令,但它们不必背靠背执行,但必须以正确的顺序执行(并且你不能在两者之间弄乱 lr) :
11110xxxxxxxxxxx
11111xxxxxxxxxxx
所以
0xF0E6
00011100110000000000000
0xFC03
00011100110000000000000
100000000110
00011100110100000000110
00011100110100000000110
000 1110 0110 1000 0000 0110
0x0E6806+4+PC
或者编写程序(不处理 H=10 上的符号扩展,因为您没有设置这些位):
#include <stdio.h>
void fun ( unsigned int a, unsigned int b )
{
unsigned int ra;
ra=a&0x7FF;
ra<<=12;
ra|=(b&0x7FF)<<1;
ra&=0xFFFFFFFE;
ra+=4;
printf("PC(inst)+0x%08X\n",ra);
}
int main ( void )
{
fun(0xF0E6,0xFC03);
fun(0xF008,0xFD03);
fun(0xF0C7,0xFC03);
return(1);
}
给出:
PC(inst)+0x000E680A
PC(inst)+0x00008A0A
PC(inst)+0x000C780A
有问题的 bl 指令的地址是什么?作为 Intel hex 文件,无法根据您提供的内容确定。 (我更喜欢 32 位地址的 srec)。
older/est ARM ARM,armv5 更适合查看这两条指令,但该文档中有一个 typo/bug thumb 版本,您不会去掉两个较低的位将是该指令的 arm 版本。
.thumb
bl here
nop
bl here
nop
nop
nop
here:
00000000 <here-0x10>:
0: f000 f806 bl 10 <here>
4: 46c0 nop ; (mov r8, r8)
6: f000 f803 bl 10 <here>
a: 46c0 nop ; (mov r8, r8)
c: 46c0 nop ; (mov r8, r8)
e: 46c0 nop ; (mov r8, r8)
PC(inst)+0x00000010
PC(inst)+0x0000000A
请注意,对于 GNU 汇编程序,您不能只使用 .word 或 .hword 技巧,您必须使用 .inst.n:
.thumb
bl here
nop
bl here
nop
nop
nop
here:
.inst.n 0xf000
.inst.n 0xf806
00000000 <here-0x10>:
0: f000 f806 bl 10 <here>
4: 46c0 nop ; (mov r8, r8)
6: f000 f803 bl 10 <here>
a: 46c0 nop ; (mov r8, r8)
c: 46c0 nop ; (mov r8, r8)
e: 46c0 nop ; (mov r8, r8)
00000010 <here>:
10: f000 f806 bl 20 <here+0x10>
与你的其中一位:
.thumb
.inst.n 0xF0E6
.inst.n 0xFC03
00000000 <.text>:
0: f0e6 fc03 bl e680a <.text+0xe680a>