英文:
Different Values of Attribute 'Address on arm-none-eabi-gcc (cortex m0 / stm32f03)
问题
在 arm-none-eabi-gcc(cortex m0 / stm32f03)上,我看到Attribute'Address
的地址值似乎在编译时插入的地址和实际地址之间有差异。例如,我查看Hardfault_Handler
的地址。
这是我的代码:
procedure Hardfault_Handler is
SP : Address := Get_Stack_Pointer; -- 保存处理程序入口后的堆栈指针
PC : Address := Get_Program_Counter; -- 保存当前 PC
PC_Offset : Storage_Offset := PC - Hardfault_Handler'Address;
Num_Of_Pushed_Regs : Natural := 0;
SP_Calc : Integer_Address := To_Integer (SP);
package Thumb_Ins_Pnt is new System.Address_To_Access_Conversions
(Push_Instruction);
use Thumb_Ins_Pnt;
Temp_Ins : Object_Pointer;
begin
-- 遍历硬件错误处理程序开始处的程序代码
for I in 0 .. PC_Offset when (I mod 2 = 0) loop
Temp_Ins := To_Pointer (Hardfault_Handler'Address + I);
-- 这是一条推送指令吗?
if Temp_Ins.Mask = PUSH_Ins_Mask then
-- 是的,计算我们推送到堆栈上的寄存器数
for Bit of Temp_Ins.Regs when Bit = True loop
Num_Of_Pushed_Regs := Num_Of_Pushed_Regs + 1;
end loop;
-- 将 SP 回退到推送之前的位置(+ 表示堆栈向下增长)
SP_Calc := SP_Calc + 4 * Integer_Address (Num_Of_Pushed_Regs);
declare
Old_Regs : constant Stacked_Registers with
Import, Address => To_Address (SP_Calc + Stacked_Reg_Offset);
Old_PC_Content : constant Thumb_Instruction with
Import, Address => Old_Regs.PC;
begin
if Old_PC_Content = Break_Point_Instruction then
-- 由于未连接调试器而发生硬错误,
-- 只需返回
return;
end if;
end;
end if;
end loop;
Put_Line ("Hard Fault");
-- 处理错误
end Hardfault_Handler;
objdump的输出:
08000754 <m0__startup__hardfault_handler>:
procedure Hardfault_Handler is
8000754: b5f8 push {r3, r4, r5, r6, r7, lr}
function Get_Stack_Pointer return Address is
Result : Address;
begin
Asm
8000756: 46ec mov ip, sp
end Get_Stack_Pointer;
function Get_Program_Counter return Address is
Result : Address;
begin
Asm
8000758: 467d mov r5, pc
PC_Offset : Storage_Offset := PC - Hardfault_Handler'Address;
800075a: 4e2a ldr r6, [pc, #168] ; (8000804 <m0__startup__hardfault_handler+0xb0>)
end "-";
在这里,Hardfault_Handler"Address的值存储在8000804处
8000802: bdf8 pop {r3, r4, r5, r6, r7, pc}
8000804: 08000755 stmdaeq r0, {r0, r2, r4, r6, r8, r9, sl}
8000808: 08002a88 stmdaeq r0, {r3, r7, r9, fp, sp}
800080c: 7fffffff svcvc 0x00ffffff
8000810: 0000beab andeq fp, r0, fp, lsr #29
8000814: 08002a28 stmdaeq r0, {r3, r5, r9, fp, sp}
8000818: 08002ad8 stmdaeq r0, {r3, r4, r6, r7, r9, fp, sp}
在GDB中,它看起来像这样:
[![gdb][1]][1]
这是我的向量表,地址也不同。但复位处理程序被调用并正常运行:
Vector_Table : constant Address_Array :=
(Sram_Stack_Start, Reset_Handler'Address, NMI_Handler'Address,
Hardfault_Handler'Address, MemManage_Handler'Address,
Bus_Fault_Handler'Address, Usage_Fault_Handler'Address, Reserved,
Reserved, Reserved, Reserved, SVCall_Handler'Address,
Debug_Handler'Address, Reserved, PendSV_Handler'Address,
Systick_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address);
--Default_Handler'Address);
pragma Linker_Section (Vector_Table, "_vector_table");
向量表的输出:
08000000 <m0__startup__vector_table>:
8000000: 20001000 andcs r1, r0, r0
8000004: 080005b1 stmdaeq r0, {r0, r4, r5, r7, r8, sl}
8000008: 08000699 st
<details>
<summary>英文:</summary>
On arm-none-eabi-gcc (cortex m0 / stm32f03), I see address values from `Attribute'Address` that seem to differ between those inserted at compile time and those which should be real. As an example, I look at the address of `Hardfault_Handler`.
This is my code:
procedure Hardfault_Handler is
SP : Address := Get_Stack_Pointer; -- save sp after handler entry
PC : Address := Get_Program_Counter; -- save current pc
PC_Offset : Storage_Offset := PC - Hardfault_Handler'Address;
Num_Of_Pushed_Regs : Natural := 0;
SP_Calc : Integer_Address := To_Integer (SP);
package Thumb_Ins_Pnt is new System.Address_To_Access_Conversions
(Push_Instruction);
use Thumb_Ins_Pnt;
Temp_Ins : Object_Pointer;
begin
--loop over program code at start of hardfaulthandler
for I in 0 .. PC_Offset when (I mod 2 = 0) loop
Temp_Ins := To_Pointer (Hardfault_Handler'Address + I);
-- is this a push instruction?
if Temp_Ins.Mask = PUSH_Ins_Mask then
-- yes, count number of regs we pushed to stack
for Bit of Temp_Ins.Regs when Bit = True loop
Num_Of_Pushed_Regs := Num_Of_Pushed_Regs + 1;
end loop;
-- alter back SP to Point before push (+ because stack grows down)
SP_Calc := SP_Calc + 4 * Integer_Address (Num_Of_Pushed_Regs);
declare
Old_Regs : constant Stacked_Registers with
Import, Address => To_Address (SP_Calc + Stacked_Reg_Offset);
Old_PC_Content : constant Thumb_Instruction with
Import, Address => Old_Regs.PC;
begin
if Old_PC_Content = Break_Point_Instruction then
-- Hardfault happend because no Debugger is connected,
-- just return
return;
end if;
end;
end if;
end loop;
Put_Line ("Hard Fault");
-- fault handling to be done
end Hardfault_Handler;
Output of objdump:
08000754 <m0__startup__hardfault_handler>:
procedure Hardfault_Handler is
8000754: b5f8 push {r3, r4, r5, r6, r7, lr}
function Get_Stack_Pointer return Address is
Result : Address;
begin
Asm
8000756: 46ec mov ip, sp
end Get_Stack_Pointer;
function Get_Program_Counter return Address is
Result : Address;
begin
Asm
8000758: 467d mov r5, pc
PC_Offset : Storage_Offset := PC - Hardfault_Handler'Address;
800075a: 4e2a ldr r6, [pc, #168] ; (8000804 <m0__startup__hardfault_h
andler+0xb0>)
end "-";
Here the value for Hardfault_Handler"Address stored @8000804
8000802: bdf8 pop {r3, r4, r5, r6, r7, pc}
8000804: 08000755 stmdaeq r0, {r0, r2, r4, r6, r8, r9, sl}
8000808: 08002a88 stmdaeq r0, {r3, r7, r9, fp, sp}
800080c: 7fffffff svcvc 0x00ffffff
8000810: 0000beab andeq fp, r0, fp, lsr #29
8000814: 08002a28 stmdaeq r0, {r3, r5, r9, fp, sp}
8000818: 08002ad8 stmdaeq r0, {r3, r4, r6, r7, r9, fp, sp}
from inside gdb it looks like this:
[![gdb][1]][1]
[1]: https://i.stack.imgur.com/i22M0.png
also this is my vector table, the addresses are different too. But the reset handler, gets called and runs fine :
Vector_Table : constant Address_Array :=
(Sram_Stack_Start, Reset_Handler'Address, NMI_Handler'Address,
Hardfault_Handler'Address, MemManage_Handler'Address,
Bus_Fault_Handler'Address, Usage_Fault_Handler'Address, Reserved,
Reserved, Reserved, Reserved, SVCall_Handler'Address,
Debug_Handler'Address, Reserved, PendSV_Handler'Address,
Systick_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address, Default_Handler'Address,
Default_Handler'Address);
--Default_Handler'Address);
pragma Linker_Section (Vector_Table, "_vector_table");
08000000 <m0__startup__vector_table>:
8000000: 20001000 andcs r1, r0, r0
8000004: 080005b1 stmdaeq r0, {r0, r4, r5, r7, r8, sl}
8000008: 08000699 stmdaeq r0, {r0, r3, r4, r7, r9, sl}
800000c: 08000755 stmdaeq r0, {r0, r2, r4, r6, r8, r9, sl}
8000010: 080006b1 stmdaeq r0, {r0, r4, r5, r7, r9, sl}
8000014: 080006c9 stmdaeq r0, {r0, r3, r6, r7, r9, sl}
8000018: 080006e1 stmdaeq r0, {r0, r5, r6, r7, r9, sl}
...
080005b0 <Reset_Handler>:
-------------------
-- Reset_Handler --
-------------------
procedure Reset_Handler is
80005b0: b570 push {r4, r5, r6, lr}
Data_L : Storage_Element with
Volatile, Import, External_Name => "__data_size";
Data_Length : constant Storage_Offset := Addr2SO (Data_L'Address);
Data_Load_Array : Storage_Array (1 .. Data_Length) with
80005b2: 4c16 ldr r4, [pc, #88] ; (800060c <Reset_Handler+0x5c>)
Bss_L : Storage_Element with
Volatile, Import, Convention => Asm, External_Name => "__bss_size";
Can someone explain this behavior?
</details>
# 答案1
**得分**: 4
我假设你正在使用32位ARM平台。在这种情况下,函数和中断处理程序的地址必须是4字节对齐的(将位1和位0设置为0)。对于支持Thumb模式的处理器,地址的位0指示处理器在切换到该地址时必须使用的模式。有效地址始终将位1和位0设置为0。
<details>
<summary>英文:</summary>
I assume you are using a 32 bit ARM platform. In this case, functions and interrupt handlers address must be 4 byte aligned (bit 1 and bit 0 set to 0). For the processors that support Thumb mode, bit 0 of the address indicates which mode the processor must use when switching to this address. The effective address always have bit 1 and bit 0 set to 0.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论