不同的 arm-none-eabi-gcc (cortex m0 / stm32f03) 上 ‘Address’ 属性的取值:

huangapple go评论48阅读模式
英文:

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&#39;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&#39;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&#39;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 =&gt; To_Address (SP_Calc + Stacked_Reg_Offset);
                   Old_PC_Content : constant Thumb_Instruction with
                     Import, Address =&gt; 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 (&quot;Hard Fault&quot;);
          -- fault handling to be done
       end Hardfault_Handler;

Output of objdump:

   

     08000754 &lt;m0__startup__hardfault_handler&gt;:
       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&#39;Address;
     800075a:       4e2a            ldr     r6, [pc, #168]  ; (8000804 &lt;m0__startup__hardfault_h
    andler+0xb0&gt;)
       end &quot;-&quot;;

Here the value for Hardfault_Handler&quot;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&#39;Address, NMI_Handler&#39;Address,
          Hardfault_Handler&#39;Address, MemManage_Handler&#39;Address,
          Bus_Fault_Handler&#39;Address, Usage_Fault_Handler&#39;Address, Reserved,
          Reserved, Reserved, Reserved, SVCall_Handler&#39;Address,
          Debug_Handler&#39;Address, Reserved, PendSV_Handler&#39;Address,    
          Systick_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address, Default_Handler&#39;Address,
          Default_Handler&#39;Address);
       --Default_Handler&#39;Address);
       pragma Linker_Section (Vector_Table, &quot;_vector_table&quot;);

    08000000 &lt;m0__startup__vector_table&gt;:
     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 &lt;Reset_Handler&gt;:
    
       -------------------
       -- Reset_Handler --
       -------------------
    
       procedure Reset_Handler is
     80005b0:       b570            push    {r4, r5, r6, lr}
          Data_L : Storage_Element with
            Volatile, Import, External_Name =&gt; &quot;__data_size&quot;;
    
          Data_Length : constant Storage_Offset := Addr2SO (Data_L&#39;Address);
    
          Data_Load_Array : Storage_Array (1 .. Data_Length) with
     80005b2:       4c16            ldr     r4, [pc, #88]   ; (800060c &lt;Reset_Handler+0x5c&gt;)
          Bss_L : Storage_Element with
            Volatile, Import, Convention =&gt; Asm, External_Name =&gt; &quot;__bss_size&quot;;

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>



huangapple
  • 本文由 发表于 2023年2月23日 21:46:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/75545679.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定