When trying to terminate (SIGINT) our cross-compiled application running on a dual ARM Cortex-A9, we segfault on an illegal instruction in the stack unwinding.
In file ../libgcc/config/arm/unwind-arm.c:
/* ABI defined function to pop registers off the stack. */
_Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
_Unwind_VRS_RegClass regclass,
_uw discriminator,
_Unwind_VRS_DataRepresentation representation)
{
phase1_vrs *vrs = (phase1_vrs *) context;
switch (regclass)
{
case _UVRSC_CORE:
{
_uw *ptr;
_uw mask;
int i;
if (representation != _UVRSD_UINT32)
return _UVRSR_FAILED;
mask = discriminator & 0xffff;
ptr = (_uw *) vrs->core.r[R_SP];
/* Pop the requested registers. */
for (i = 0; i < 16; i++)
{
if (mask & (1 << i))
vrs->core.r[i] = *(ptr++);
}
(...)
}
A short excerpt from the disassembler for _Unwind_VRS_Pop
shows:
224 [1] switch (regclass)
0xb660202c 2d e9 f0 41 stmdb sp!, {r4, r5, r6, r7, r8, lr}
0xb6602030 <+ 4> 06 46 mov r6, r0
0xb6602032 <+ 6> c2 b0 sub sp, #264 ; 0x108
221 [1] {
0xb6602034 <+ 8> 14 46 mov r4, r2
0xb6602036 <+ 10> 1d 46 mov r5, r3
0xb6602038 <+ 12> 04 29 cmp r1, #4
0xb660203a <+ 14> 00 f2 b8 80 bhi.w 0xb66021ae <_Unwind_VRS_Pop+386>
0xb660203e <+ 18> df e8 01 f0 tbb [pc, r1]
0xb6602042 <+ 22> 03 20 b6 ae cdpge 0, 11, cr2, cr6, cr3, {0}
0xb6602046 <+ 26> db 00 00 2d stccs 0, cr0, [r0, #-876] ; 0xfffffc94
232 [1] if (representation != _UVRSD_UINT32)
0xb660204a <+ 30> 40 f0 b0 80 bne.w 0xb66021ae <_Unwind_VRS_Pop+386>
235 [1] mask = discriminator & 0xffff;
0xb660204e <+ 34> a1 b2 uxth r1, r4
236 [1] ptr = (_uw *) vrs->core.r[R_SP];
0xb6602050 <+ 36> 83 6b ldr r3, [r0, #56] ; 0x38
238 [1] for (i = 0; i < 16; i++)
0xb6602052 <+ 38> 2a 46 mov r2, r5
240 [1] if (mask & (1 << i))
0xb6602054 <+ 40> 01 20 movs r0, #1
241 [1] vrs->core.r[i] = *(ptr++);
0xb6602056 <+ 42> 37 1d adds r7, r6, #4
240 [1] if (mask & (1 << i))
0xb6602058 <+ 44> 00 fa 02 fc lsl.w r12, r0, r2
0xb660205c <+ 48> 1c ea 01 0f tst.w r12, r1
241 [1] vrs->core.r[i] = *(ptr++);
0xb6602060 <+ 52> 1c bf itt ne
0xb6602062 <+ 54> 53 f8 04 cb ldrne.w r12, [r3], #4
0xb6602066 <+ 58> 47 f8 22 c0 strne.w r12, [r7, r2, lsl #2]
238 [1] for (i = 0; i < 16; i++)
0xb660206a <+ 62> 01 32 adds r2, #1
0xb660206c <+ 64> 10 2a cmp r2, #16
0xb660206e <+ 66> f3 d1 bne.n 0xb6602058 <_Unwind_VRS_Pop+44>
244 [1] if ((mask & (1 << R_SP)) == 0)
0xb6602070 <+ 68> 14 f4 00 54 ands.w r4, r4, #8192 ; 0x2000
0xb6602074 <+ 72> 01 d1 bne.n 0xb660207a <_Unwind_VRS_Pop+78>
245 [1] vrs->core.r[R_SP] = (_uw) ptr;
0xb6602076 <+ 74> b3 63 str r3, [r6, #56] ; 0x38
408 [1] return _UVRSR_OK;
It stops on this line:
0xb6602062 <+ 54> 53 f8 04 cb ldrne.w r12, [r3], #4
The toolchain is using GCC 9; sysroot generated from Buildroot.
Could this be a mismatch in toolchain or with which instruction set is used? I assume STR/LDR instructions are pretty basic operations that shouldn't result in a SIGILL
?
I tried to compile with -march=armv7-a
without any change.