什么时候使用.ARM.exidx

时间:2014-02-03 12:17:23

标签: arm stm32 linker-scripts contiki codesourcery

我正在使用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()的实现中使用的任何不寻常的东西。在代码的某个单独区域中使用了alloca()的2个引用,我将其替换为malloc()free(),但这也没有解决问题。 alloc()实施仅调用malloc()realloc()free()

3 个答案:

答案 0 :(得分:14)

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

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

答案 1 :(得分:2)

加入tangrs&#39;响应,如果你是gcc -v,你可以转储编译时使用的默认选项。

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

答案 2 :(得分:2)

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

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

  

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

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


有一些解决方案。如果不需要堆栈跟踪或异步功能,则最好同时丢弃exidxextab。可以使用-mapcs-frame使用gnu工具/ gcc进行更简单的堆栈展开。那么fp将始终用于存储先前的堆栈帧(存储其调用方fp等)。实际的表不是很大,展开的例程非常简单。具有不会污染正常程序路径或使用诸如-mapcs-frame之类的寄存器的表,可能会导致<3%的开销。在具有缓存和通常更多内存的Cortex-A cpus上理想。

参考:ATPCS Link and frame pointer explained

注意1::这是在序言调整堆栈之后。
注意2: ex用于例外,但不仅限于C ++例外。