14

我正在使用 mbxxx 目标开发 Contiki 2.7。在构建我的代码时,链接器抱怨.ARM.exidx 和 .data 部分重叠。在修改了链接器脚本 contiki-2.7/cpu/stm32w108/gnu-stm32w108.ld 后,我通过替换解决了这个问题:

__exidx_start = .;
__exidx_end = .;

和:

.ARM.exidx : {
    __exidx_start = .;
    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    __exidx_end = .;
} >ROM_region

后来,当我尝试使用 objdump -h 查看其他一些示例应用程序的标题列表时,我没有找到这个特定的 .ARM.exidx 部分,而它存在于我的应用程序中。谷歌搜索 .ARM.exidx 让我发现它用于一些 c++ 异常处理。既然我的代码是纯 C 代码,为什么这部分会出现在我的代码中?.ARM.exidx 通常何时出现在代码中,它的用途是什么?

==================================================== =================================

不,我没有任何这样的编译器选项。我实际上正在使用 AxTLS api 并撕下证书处理代码并将其移植到 contiki。在进一步的挖掘中,我发现了 bigint 实现中的可疑行为。简而言之……这是 bigint.c 文件中的函数主体:

static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b)
{
   int j = 0, n = bia->size;
   bigint *biR = alloc(ctx, n + 1);
   comp carry = 5;
   comp *r = biR->comps;
   comp *a = bia->comps;

   check(bia);

   /* clear things to start with */
   memset(r, 0, ((n+1)*COMP_BYTE_SIZE));


   do
   {
       long_comp tmp = *r + (long_comp)a[j]*b + carry;
   //    *r++ = (comp)tmp;              /* downsize */
       carry = (comp)(tmp >> COMP_BIT_SIZE);
   } while (++j < n);

  // *r = carry;
  bi_free(ctx, bia);

  return trim(biR);
}

如果注释掉的部分(r 变量赋值)未注释,则 .ARM.exidx 会出现,否则不会出现!现在可以解释了吗???

==================================================== =================================

我没有发现在alloc(). 在代码的某个单独区域中使用了2 个引用alloca(),我将其替换为malloc()and free(),但这也没有解决问题。alloc()实现只调用malloc(),realloc()free()

4

3 回答 3

19

.ARM.exidx是包含展开堆栈信息的部分。如果您的 C 程序具有打印出堆栈回溯的函数,则这些函数可能取决于此部分是否存在。

也许在你的编译器选项中寻找一个-funwind-tables-fexceptions标志。

于 2014-02-03T12:45:43.197 回答
3

此功能在“C”中使用。ARM APCS 仅使用帧指针来恢复堆栈。较新的 AAPCS 有时会使用表格。堆栈展开、信号处理程序和其他异步“C”功能使用这些机制。对于裸机嵌入式设备,它可用于跟踪堆栈。例如,Linux 的unwind.c使用exidxextab部分来进行堆栈跟踪。

简而言之,exidx它是例程起始地址和extab表索引的排序表。通过二分搜索exidx将找到相应的extab条目。该条目包含有关此例程Note1extab中堆栈的详细信息。它提供了有关例程在堆栈中存储的内容的详细信息。

如果注释掉的部分(r 变量赋值)未注释,则 .ARM.exidx 会出现,否则不会出现!现在可以解释了吗???

当您有语句*r++ = (comp)tmp;时,编译器无法将所有变量保存在寄存器中,并且需要使用堆栈(或至少fp)。这导致它发出和exidxextab数据。


有一些解决方案。如果您不需要堆栈跟踪或异步功能exidx,则可以丢弃两者。extab可以使用 gnu 工具/gcc 来完成更简单的堆栈展开-mapcs-frame;thenfp将始终用于存储前一个堆栈帧(存储其调用者fp等)。实际的桌子并没有那么大,放松的例程也相当简单。拥有不会污染正常程序路径或使用类似-mapcs-frame. 在具有缓存和通常更多内存的 Cortex-A cpu 上是理想的。

参考:ATPCS 链接和帧指针解释
                  ARM extab 的结构

注意1:这是在序幕对堆栈进行调整之后。
注意 2:用于异常,ex但不仅仅用于 C++ 异常。

于 2019-08-12T14:53:07.010 回答
2

添加到 tangrs 的响应中,如果您使用 gcc -v,您可以转储编译期间使用的默认选项。

GCC 的所有选项(隐式和显式)选项都传递给 GCC 的 cc1 程序。

于 2015-01-27T09:48:28.057 回答