Date: Wed, 01 May 2013 14:17:32 -0600 From: Ian Lepore <ian@FreeBSD.org> To: freebsd-arm <freebsd-arm@FreeBSD.org> Subject: A fix for the clang + eabi + kdb backtrace endless loop Message-ID: <1367439452.1180.92.camel@revolution.hippie.lan>
next in thread | raw e-mail | index | archive | help
--=-R74sECJmrSUq+3Vwtpin Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit The attached patch fixes the problem where a kdb backtrace loops endlessly on an eabi kernel. I'm no expert on this stuff, so while this fixes the problem for me, I'm not sure it's right, especially the STOP_UNWINDING in exception_exit (which handles a test case of breaking into the debugger with the keyboard and typing 'bt'). I'm not going to commit this until it's been reviewed by someone who actually knows what they're doing. :) -- Ian --=-R74sECJmrSUq+3Vwtpin Content-Disposition: inline; filename="eabi_unwind_fixes.diff" Content-Type: text/x-patch; name="eabi_unwind_fixes.diff"; charset="us-ascii" Content-Transfer-Encoding: 7bit Index: sys/arm/arm/db_trace.c =================================================================== --- sys/arm/arm/db_trace.c (revision 248960) +++ sys/arm/arm/db_trace.c (working copy) @@ -354,7 +354,7 @@ index = db_find_index(state->start_pc); if (index->insn == EXIDX_CANTUNWIND) { - db_printf("Unable to unwind\n"); + db_printf("Unable to unwind further\n"); break; } else if (index->insn & (1 << 31)) { /* The data is within the instruction */ @@ -412,6 +412,23 @@ } } db_printf("\n"); + + /* Stop if we've unwound back to the thread entry point. */ + if (state->registers[FP] == 0) { + break; + } + + /* + * Stop if the unwind function didn't change the PC, to avoid + * getting stuck in this loop forever. If this happens, it's an + * indication that the unwind information is incorrect somehow + * for the function named in the last frame printed before you + * see this message. + */ + if (state->start_pc == state->registers[PC]) { + db_printf("Unwind failure (PC didn't change)\n"); + break; + } } } #endif Index: sys/arm/arm/exception.S =================================================================== --- sys/arm/arm/exception.S (revision 248960) +++ sys/arm/arm/exception.S (working copy) @@ -196,15 +196,19 @@ * Interrupts are disabled at suitable points to avoid ASTs * being posted between testing and exit to user mode. * - * This function uses PULLFRAMEFROMSVCANDEXIT and - * DO_AST - * only be called if the exception handler used PUSHFRAMEINSVC + * This function uses PULLFRAMEFROMSVCANDEXIT and DO_AST and can + * only be called if the exception handler used PUSHFRAMEINSVC. * + * For EABI, don't try to unwind any further than this, because the unwind + * info generated here is a single INSN_FINISH instruction. Nothing gets + * unwound (no registers change) so the unwind would loop here forever. */ -exception_exit: +ASENTRY_NP(exception_exit) + STOP_UNWINDING DO_AST PULLFRAMEFROMSVCANDEXIT +END(exception_exit) /* * undefined_entry: --=-R74sECJmrSUq+3Vwtpin--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1367439452.1180.92.camel>