我正在使用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()
答案 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同时使用exidx
和extab
部分来进行堆栈跟踪。
简而言之,exidx
是例程起始地址和extab
表索引的排序表。通过exidx
进行二进制搜索将找到相应的extab
条目。 extab
条目具有有关此例程中的堆栈的详细信息 Note1 。它提供了有关例程在堆栈中存储的内容的详细信息。
如果注释掉的部分(r变量赋值)未注释,则显示.ARM.exidx,否则不显示!现在可以解释了吗?
使用语句*r++ = (comp)tmp;
时,编译器无法将所有变量都保存在寄存器中,因此需要使用堆栈(或至少使用fp
)。这会导致它发出exidx
和extab
数据。
有一些解决方案。如果不需要堆栈跟踪或异步功能,则最好同时丢弃exidx
和extab
。可以使用-mapcs-frame
使用gnu工具/ gcc进行更简单的堆栈展开。那么fp
将始终用于存储先前的堆栈帧(存储其调用方fp
等)。实际的表不是很大,展开的例程非常简单。具有不会污染正常程序路径或使用诸如-mapcs-frame
之类的寄存器的表,可能会导致<3%的开销。在具有缓存和通常更多内存的Cortex-A cpus上理想。
参考:ATPCS Link and frame pointer explained
注意1::这是在序言调整堆栈之后。
注意2: ex
用于例外,但不仅限于C ++例外。