Message ID | 20211111144010.23506-1-rzinsly@linux.ibm.com |
---|---|
State | New |
Headers | show |
Series | [v2] libgcc: fix backtrace fallback on PowerPC Big-endian. [PR103004] | expand |
Hi! On Thu, Nov 11, 2021 at 11:40:10AM -0300, Raphael Moreira Zinsly wrote: > Changes since v1: > - Removed -Wmissing-prototypes fix. > - Fixed formatting of Changelog and patch. > > --->8--- > > At the end of the backtrace stream _Unwind_Find_FDE() may not be able > to find the frame unwind info and will later call the backtrace fallback > instead of finishing. This occurs when using an old libc on ppc64 due to > dl_iterate_phdr() not being able to set the fde in the last trace. > When this occurs the cfa of the trace will be behind of context's cfa. > Also, libgo’s probestackmaps() calls the backtrace with a null pointer > and can get to the backchain fallback with the same problem, in this case > we are only interested in find a stack map, we don't need nor can do a > backchain. > _Unwind_ForcedUnwind_Phase2() can hit the same issue as it uses > uw_frame_state_for(), so we need to treat _URC_NORMAL_STOP. > > libgcc/ChangeLog: > > * config/rs6000/linux-unwind.h (ppc_backchain_fallback): Check if it's > called with a null argument or at the end of the backtrace and return. > * unwind.inc (_Unwind_ForcedUnwind_Phase2): Treat _URC_NORMAL_STOP. Committed, thanks! Please note the changelog formatting fixes I had to do, for later patches :-) Segher
diff --git a/libgcc/config/rs6000/linux-unwind.h b/libgcc/config/rs6000/linux-unwind.h index 8deccc1d650..ad1ab286a2f 100644 --- a/libgcc/config/rs6000/linux-unwind.h +++ b/libgcc/config/rs6000/linux-unwind.h @@ -401,8 +401,14 @@ void ppc_backchain_fallback (struct _Unwind_Context *context, void *a) struct trace_arg *arg = a; int count; - /* Get the last address computed and start with the next. */ + /* Get the last address computed. */ current = context->cfa; + + /* If the trace CFA is not the context CFA the backtrace is done. */ + if (arg == NULL || arg->cfa != current) + return; + + /* Start with next address. */ current = current->backchain; for (count = arg->count; current != NULL; current = current->backchain) diff --git a/libgcc/unwind.inc b/libgcc/unwind.inc index 456a5ee682f..dc2f9c13e97 100644 --- a/libgcc/unwind.inc +++ b/libgcc/unwind.inc @@ -160,12 +160,13 @@ _Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc, /* Set up fs to describe the FDE for the caller of cur_context. */ code = uw_frame_state_for (context, &fs); - if (code != _URC_NO_REASON && code != _URC_END_OF_STACK) + if (code != _URC_NO_REASON && code != _URC_END_OF_STACK + && code != _URC_NORMAL_STOP) return _URC_FATAL_PHASE2_ERROR; /* Unwind successful. */ action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE; - if (code == _URC_END_OF_STACK) + if (code == _URC_END_OF_STACK || code == _URC_NORMAL_STOP) action |= _UA_END_OF_STACK; stop_code = (*stop) (1, action, exc->exception_class, exc, context, stop_argument);