gcc 链接器,如何在 HEAP 和 STACK 之间声明一个区域,在那里放置一个变量来检测溢出Cortex M3 上的硬故障问题?

问题描述

我正在开发 Silabs ARm Cortex M3 (EFM32PG12)

我想在堆和堆栈之间声明一个链接器部分 XXX,在那里放置一个变量,稍后查看(硬件故障主题)是否该变量变脏。

  .heap (copY):
  {
    __HeapBase = .;
    __end__ = .;
    end = __end__;
    _end = __end__;
    KEEP(*(.heaP*))
    __HeapLimit = .;
  } > RAM

  .xxx (NOLOAD): /* my DEBUG section */
  {
    . = ALIGN(4);
    __xxx_start__ = .;
    KEEP(*(.xxx*))
    __xxx_end__ = .;
  } > RAM

  /* .stack_dummy section doesn't contains any symbols. It is only
   * used for linker to calculate size of stack sections,and assign
   * values to stack symbols later */
  .stack_dummy (copY):
  {
    KEEP(*(.stack*))
  } > RAM

  /* Set stack top to end of RAM,and stack limit move down by
   * size of stack_dummy section */
  __StackTop = ORIGIN(RAM) + LENGTH(RAM);
  __StackLimit = __StackTop - SIZEOF(.stack_dummy);
  PROVIDE(__stack = __StackTop);

  /* Check if data + heap + stack exceeds RAM limit */
  ASSERT(__StackLimit >= __HeapLimit,"region RAM overflowed with stack")

  /* Check if FLASH usage exceeds FLASH size */
  ASSERT( LENGTH(FLASH) >= (__etext + SIZEOF(.data)),"FLASH memory overflowed !")

现在在我的代码中,我声明了这样的变量

__attribute__((section(".xxx"))) volatile uint32_t dirtyvar = 0x12345678;

但是地图文件显示的很奇怪,好像XXX区域还在HEAP之前

 *(COMMON)
 COMMON         0x20000c7c     0x6004 ./src/dbg_malloc.o
                0x20000c7c                dbgMallocData
 COMMON         0x20006c80        0x4 ./src/drv_uart.o
                0x20006c80                frames
 COMMON         0x20006c84        0x4 ./src/error.o
                0x20006c84                __stack_chk_guard
 COMMON         0x20006c88        0x4 c:/siliconlabs/simplicitystudio/v5/developer/toolchains/gnu_arm/7.2_2017q4/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m/fpv4-sp/softfp\libc_nano.a(lib_a-reent.o)
                0x20006c88                errno
                0x20006c8c                . = ALIGN (0x4)
                0x20006c8c                __bss_end__ = .

.heap           0x20006c90     0x2000
                0x20006c90                __HeapBase = .
                0x20006c90                __end__ = .
                0x20006c90                end = __end__
                0x20006c90                _end = __end__
 *(.heaP*)
 .heap          0x20006c90     0x2000 ./CMSIS/EFM32PG12B/startup_gcc_efm32pg12b.o
                0x20008c90                __HeapLimit = .

.xxx            0x20006c8c        0x4 load address 0x00009b88
                0x20006c8c                . = ALIGN (0x4)
                0x20006c8c                __xxx_start__ = .
 *(.xxx*)
 .xxx           0x20006c8c        0x4 ./src/error.o
                0x20006c8c                dirtyvar
                0x20006c90                __xxx_end__ = .

.stack_dummy    0x20006c90       0x80
 *(.stack*)
 .stack         0x20006c90       0x80 ./CMSIS/EFM32PG12B/startup_gcc_efm32pg12b.o
                0x20040000                __StackTop = (ORIGIN (RAM) + LENGTH (RAM))
                0x2003ff80                __StackLimit = (__StackTop - SIZEOF (.stack_dummy))
                0x20040000                PROVIDE (__stack,__StackTop)
                0x00000001                ASSERT ((__StackLimit >= __HeapLimit),region RAM overflowed with stack)
                0x00000001                ASSERT ((LENGTH (FLASH) >= (__etext + SIZEOF (.data))),FLASH memory overflowed !)
OUTPUT(5GNR_EFM32.axf elf32-littlearm)

如何正确声明这个区域,以便我可以在崩溃时看到 HEAP 是否损坏了我的堆栈?

我尽我所能:

  • 我为 malloc/free 编写了一个包装器,它按预期工作
  • 我用 -fstack-protector-all 编译,这里似乎一切正常
  • 我试图写一个像这样的 HARD FAULT 处理程序,但 CFSR 的内容完全无关

void debugHardfault(uint32_t *sp)
{
    uint32_t cfsr  = SCB->CFSR;
    uint32_t hfsr  = SCB->HFSR;
    uint32_t mmfar = SCB->MMFAR;
    uint32_t bfar  = SCB->BFAR;

    uint32_t r0  = sp[0];
    uint32_t r1  = sp[1];
    uint32_t r2  = sp[2];
    uint32_t r3  = sp[3];
    uint32_t r12 = sp[4];
    uint32_t lr  = sp[5];
    uint32_t pc  = sp[6];
    uint32_t psr = sp[7];

    printf("HardFault:\n");
    printf("SCB->CFSR   0x%08lx\n",cfsr);

    /*
     * HFSR
     * 0x1b4b09b3
     *
     *
     * 00011011 01001011 00001001 10110011
     *
     */

    printf("SCB->HFSR   0x%08lx\n",hfsr);
    printf("SCB->MMFAR  0x%08lx\n",mmfar);
    printf("SCB->BFAR   0x%08lx\n",bfar);
    printf("\n");

    printf("SP          0x%08lx\n",(uint32_t)sp);
    printf("R0          0x%08lx\n",r0);
    printf("R1          0x%08lx\n",r1);
    printf("R2          0x%08lx\n",r2);
    printf("R3          0x%08lx\n",r3);
    printf("R12         0x%08lx\n",r12);
    printf("LR          0x%08lx\n",lr);
    printf("PC          0x%08lx\n",pc);
    printf("PSR         0x%08lx\n",psr);

    while(1);
}

注意: 当我使用 -O3 编译时,这个错误会更频繁(仍然是随机的)。

我提到的另一个问题是 malloc() 永远不会像我有无限堆那样返回 NULL,所以这就是我怀疑堆栈溢出的原因。

先谢谢你,

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...