ARM程序集 - bl正在分支到错误的地址
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ARM程序集 - bl正在分支到错误的地址相关的知识,希望对你有一定的参考价值。
求助:一个动力循环修复它。必须是上部闪存块的电气问题导致HW执行单元从闪存中读取错误的值
我是集会踩踏,发生了一些奇怪的事情。
我有两个独立的闪存块,它们都包含代码。因为它们相隔很远,所以从一个块到另一个块的函数调用需要一个中间跳转,即veneer
,它是由链接器自动生成的。
这一直到现在为止,我做了一些事情 - 不知道是什么 - 打破它。
0x1001a9ca: 0x0cf0c5fe bl 0x10027758 <__atiupy_PutOutput2_veneer>
在执行之后,PC是0x100275ce
这是错误的。
如果我在反汇编窗口中滚动到0x10027758
,我会看到标签__atiupy_PutOutput2_veneer
。
为什么跳到错误的地址?
UPDATE
它从C代码跳转到C ++代码。是的,我在extern "C"
中有.h
,用于C代码中从C代码调用的函数。
C编译选项是:-x c -Wall -Werror -std=c99 -nostdlib -mthumb -mtune=cortex-m4 -mlittle-endian -Wdouble-promotion -DNDEBUG -fdata-sections -ffunction-sections -c -save-temps=obj -g3 -gdwarf-2
C ++编译选项是:-mthumb -mlittle-endian -x c++ -gdwarf-2 -g3 -fomit-frame-pointer -fnothrow-opt -ffreestanding -fverbose-asm -std=c++11 -c -fno-rtti -ffunction-sections -fdata-sections -fno-exceptions
根据要求,使用objdump -d
进行一些反汇编。
它将要跳到0x10027758
(但永远不会到达那里)
1001a9bc <mp_hal_stdout_tx_strn_cooked>:
1001a9bc: b580 push {r7, lr}
1001a9be: b082 sub sp, #8
1001a9c0: af00 add r7, sp, #0
1001a9c2: 6078 str r0, [r7, #4]
1001a9c4: 6039 str r1, [r7, #0]
1001a9c6: 6878 ldr r0, [r7, #4]
1001a9c8: 6839 ldr r1, [r7, #0]
1001a9ca: f00c fec5 bl 10027758 <__atiupy_PutOutput2_veneer>
1001a9ce: f107 0708 add.w r7, r7, #8
1001a9d2: 46bd mov sp, r7
1001a9d4: bd80 pop {r7, pc}
1001a9d6: bf00 nop
它应该跳到哪里
10027758 <__atiupy_PutOutput2_veneer>:
10027758: b401 push {r0}
1002775a: 4802 ldr r0, [pc, #8] ; (10027764 <__atiupy_PutOutput2_veneer+0xc>)
1002775c: 4684 mov ip, r0
1002775e: bc01 pop {r0}
10027760: 4760 bx ip
10027762: bf00 nop
10027764: 00035abd .word 0x00035abd
它实际上跳转到0x100275ce
,但我正在粘贴位于此处的整个功能
100275c8 <___ZN21CKinetisI2CController7DisableEv_veneer>:
100275c8: b401 push {r0}
100275ca: 4802 ldr r0, [pc, #8] ; (100275d4 <___ZN21CKinetisI2CController7DisableEv_veneer+0xc>)
100275cc: 4684 mov ip, r0
100275ce: bc01 pop {r0}
100275d0: 4760 bx ip
100275d2: bf00 nop
100275d4: 00029b2d .word 0x00029b2d
我在mp_hal_stdout_tx_strn_cooked
设置了一个断点,然后使用stepi
进行汇编步骤
p/x $pc
$2 = 0x1001a9c6
disass
Dump of assembler code for function mp_hal_stdout_tx_strn_cooked:
0x1001a9bc <+0>: push {r7, lr}
0x1001a9be <+2>: sub sp, #8
0x1001a9c0 <+4>: add r7, sp, #0
0x1001a9c2 <+6>: str r0, [r7, #4]
0x1001a9c4 <+8>: str r1, [r7, #0]
=> 0x1001a9c6 <+10>: ldr r0, [r7, #4]
0x1001a9c8 <+12>: ldr r1, [r7, #0]
0x1001a9ca <+14>: bl 0x10027758 <__atiupy_PutOutput2_veneer>
0x1001a9ce <+18>: add.w r7, r7, #8
0x1001a9d2 <+22>: mov sp, r7
0x1001a9d4 <+24>: pop {r7, pc}
End of assembler dump.
stepi
stepi
0x1001a9c8 23 atiupy_PutOutput2(str, len);
disass
Dump of assembler code for function mp_hal_stdout_tx_strn_cooked:
0x1001a9bc <+0>: push {r7, lr}
0x1001a9be <+2>: sub sp, #8
0x1001a9c0 <+4>: add r7, sp, #0
0x1001a9c2 <+6>: str r0, [r7, #4]
0x1001a9c4 <+8>: str r1, [r7, #0]
0x1001a9c6 <+10>: ldr r0, [r7, #4]
=> 0x1001a9c8 <+12>: ldr r1, [r7, #0]
0x1001a9ca <+14>: bl 0x10027758 <__atiupy_PutOutput2_veneer>
0x1001a9ce <+18>: add.w r7, r7, #8
0x1001a9d2 <+22>: mov sp, r7
0x1001a9d4 <+24>: pop {r7, pc}
End of assembler dump.
stepi
stepi
0x1001a9ca 23 atiupy_PutOutput2(str, len);
diasass
Undefined command: "diasass". Try "help".
disass
Dump of assembler code for function mp_hal_stdout_tx_strn_cooked:
0x1001a9bc <+0>: push {r7, lr}
0x1001a9be <+2>: sub sp, #8
0x1001a9c0 <+4>: add r7, sp, #0
0x1001a9c2 <+6>: str r0, [r7, #4]
0x1001a9c4 <+8>: str r1, [r7, #0]
0x1001a9c6 <+10>: ldr r0, [r7, #4]
0x1001a9c8 <+12>: ldr r1, [r7, #0]
=> 0x1001a9ca <+14>: bl 0x10027758 <__atiupy_PutOutput2_veneer>
0x1001a9ce <+18>: add.w r7, r7, #8
0x1001a9d2 <+22>: mov sp, r7
0x1001a9d4 <+24>: pop {r7, pc}
End of assembler dump.
stepi
stepi
0x100275ce in ___ZN21CKinetisI2CController7DisableEv_veneer ()
disass
Dump of assembler code for function ___ZN21CKinetisI2CController7DisableEv_veneer:
0x100275c8 <+0>: push {r0}
0x100275ca <+2>: ldr r0, [pc, #8] ; (0x100275d4 <___ZN21CKinetisI2CController7DisableEv_veneer+12>)
0x100275cc <+4>: mov r12, r0
=> 0x100275ce <+6>: pop {r0}
0x100275d0 <+8>: bx r12
0x100275d2 <+10>: nop
0x100275d4 <+12>: ldr r3, [sp, #180] ; 0xb4
0x100275d6 <+14>: movs r2, r0
End of assembler dump.
stepi
stepi
0x100275d0 in ___ZN21CKinetisI2CController7DisableEv_veneer ()
disass
Dump of assembler code for function ___ZN21CKinetisI2CController7DisableEv_veneer:
0x100275c8 <+0>: push {r0}
0x100275ca <+2>: ldr r0, [pc, #8] ; (0x100275d4 <___ZN21CKinetisI2CController7DisableEv_veneer+12>)
0x100275cc <+4>: mov r12, r0
0x100275ce <+6>: pop {r0}
=> 0x100275d0 <+8>: bx r12
0x100275d2 <+10>: nop
0x100275d4 <+12>: ldr r3, [sp, #180] ; 0xb4
0x100275d6 <+14>: movs r2, r0
End of assembler dump.
编译前的汇编文件
有人想要编译器的汇编文件输出,而不是objdump
的解释。此输出是编译选项-save-temps=obj
的结果
.LFE14:
.size mp_hal_stdout_tx_strn, .-mp_hal_stdout_tx_strn
.section .text.mp_hal_stdout_tx_strn_cooked,"ax",%progbits
.align 2
.global mp_hal_stdout_tx_strn_cooked
.thumb
.thumb_func
.type mp_hal_stdout_tx_strn_cooked, %function
mp_hal_stdout_tx_strn_cooked:
.LFB15:
.loc 1 22 0
.cfi_startproc
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
push {r7, lr}
.LCFI11:
.cfi_def_cfa_offset 8
.cfi_offset 7, -8
.cfi_offset 14, -4
sub sp, sp, #8
.LCFI12:
.cfi_def_cfa_offset 16
add r7, sp, #0
.LCFI13:
.cfi_def_cfa_register 7
str r0, [r7, #4]
str r1, [r7, #0]
.loc 1 23 0
ldr r0, [r7, #4]
ldr r1, [r7, #0]
bl atiupy_PutOutput2
.loc 1 25 0
add r7, r7, #8
mov sp, r7
pop {r7, pc}
.cfi_endproc
(悲伤)更新
我创建了最小的示例,但问题没有发生。因此,我认为这是我环境中的事情。我将开始恢复本地更改并将更新。我不会调用下面的代码完成,因为你需要链接器文件,但由于它不能重现问题,我没有看到提供所有内容的重点。
main.cpp中
#include "common.h"
int main()
{
test1();
}
int main_test()
{
int a = 5;
a = 23424 * a;
return a;
}
test.c的
#include "common.h"
void test1()
{
int a;
a = main_test();
a *= 2;
}
COMMON.H
#ifdef __cplusplus
extern "C" {
#endif //#ifdef __cplusplus
int main_test();
void test1();
#ifdef __cplusplus
}
#endif //#ifdef __cplusplus
main.obj位于“lower”闪存块中,而test.obj位于上部块中。当从上到下跳跃时,PC正确跳转到veneer
的正确地址。
求助:一个动力循环修复它。必须是上部闪存块的电气问题导致HW执行单元从闪存中读取错误的值。
以上是关于ARM程序集 - bl正在分支到错误的地址的主要内容,如果未能解决你的问题,请参考以下文章