[RFC][PATCH] Provide stack backtrace interface in libgcc
Ulrich Weigand
weigand@immd1.informatik.uni-erlangen.de
Mon Apr 7 19:23:00 GMT 2003
Hello,
we're trying to get rid of the requirement to maintain a stack
backchain at run-time on s390, while still allowing to generate
stack backtraces for debugging purposes.
To this purpose, we've set GCC to always generate DWARF-2
unwind data (CFI records) for every function. We've also
have a patch to gdb that makes use of this information.
However, there's still a couple of problems that prevent us
from actually making the switch to turn of the backchain:
- __builtin_return_address / __buitin_frame address
However, I can accept the argument that those simply are not
guaranteed to work with levels > 0, and callers should be
adapted to use something else if required.
- glibc's backtrace ()
Needs to be rewritten to use DWARF CFIs
- various third-party applications
There are various applications that need to generate backtraces
in error scenarios (e.g. from a SIGSEGV handler) in order to
allow to diagnose problems occurring at a customer site.
(All major applications like DB2, Oracle, SAP have this requirement.)
These applications currently contains code (on s390) that tracks
our backchain information manually. While this will obviously
stop working once the backchain is removed, the question is with
what to replace that code ... (glibc's backtrace () provides
only a subset of the information required, in particular no
data about stack contents and saved registers)
I had originally thought that both glibc (to implement backtrace ())
and also third-party applications could be rewritten to make use of
the libgcc _Unwind interfaces in order to generate backtraces via
DWARF-2 CFI data.
Unfortunately, this does not work, because while libgcc does contain
all necessary code, it is not exported. The only exported interfaces
(_Unwind_RaiseException and _Unwind_ForceUnwind) will not just scan
the stack, but actually call cleanup routines etc.
This is annoying, because to reimplement DWARF-2 backtraces outside
of libgcc would mean to duplicate the whole DWARF bytecode engine
(libgcc does export _Unwind_Find_FDE, but this in itself does not
help decoding the FDE). This is not a problem for gdb, but even
for glibc it would be awkward. For third-party applications this
is completely unacceptable.
(There is the libunwind project which could serve as alternative,
but as far as I can see this also does not have the DWARF-2 code,
and due to different licensing it would appear to be difficult to
reuse the libgcc code there ...)
However, within the context of the existing libgcc code, providing
a stack backtrace mechanism would be a matter of just a couple of
lines of code. Thus, I'd propose to extend the libgcc unwinder
interface by adding a third main entry point, _Unwind_Backtrace,
which would call back to a provided trace function for every
stack frame in the current call chain, passing an _Unwind_Context
pointer (which can then be used to retrieve the IP, CFA, and saved
registers of that frame via existing accessor routines).
This would not expose any implementation details of libgcc,
and simply add one additional function to the ABI.
Would something like this be considered acceptable or do you
have different suggestions to solve that problem?
Bye,
Ulrich
ChangeLog:
* unwind.inc (_Unwind_Backtrace): New function.
* unwind.h (_Unwind_Backtrace): Declare it.
* libgcc-std.ver (_Unwind_Backtrace): Export it.
Index: gcc/libgcc-std.ver
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc-std.ver,v
retrieving revision 1.19
diff -c -p -r1.19 libgcc-std.ver
*** gcc/libgcc-std.ver 3 Apr 2003 02:06:55 -0000 1.19
--- gcc/libgcc-std.ver 7 Apr 2003 15:27:34 -0000
*************** GCC_3.0 {
*** 180,185 ****
--- 180,186 ----
GCC_3.3 {
_Unwind_FindEnclosingFunction
_Unwind_GetCFA
+ _Unwind_Backtrace
}
%inherit GCC_3.4 GCC_3.3
Index: gcc/unwind.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind.h,v
retrieving revision 1.10
diff -c -p -r1.10 unwind.h
*** gcc/unwind.h 3 Apr 2003 02:06:55 -0000 1.10
--- gcc/unwind.h 7 Apr 2003 15:27:34 -0000
*************** extern void _Unwind_DeleteException (str
*** 127,132 ****
--- 127,138 ----
e.g. executing cleanup code, and not to implement rethrowing. */
extern void _Unwind_Resume (struct _Unwind_Exception *);
+ /* Use unwind data to perform a stack backtrace. */
+ typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)
+ (struct _Unwind_Context *, void *);
+
+ extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *);
+
/* These functions are used for communicating information about the unwind
context (i.e. the unwind descriptors and the user register state) between
the unwind library and the personality routine and landing pad. Only
Index: gcc/unwind.inc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind.inc,v
retrieving revision 1.7
diff -c -p -r1.7 unwind.inc
*** gcc/unwind.inc 15 Mar 2002 10:18:21 -0000 1.7
--- gcc/unwind.inc 7 Apr 2003 15:27:34 -0000
*************** _Unwind_DeleteException (struct _Unwind_
*** 239,241 ****
--- 239,277 ----
{
(*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
}
+
+
+ /* Perform stack backtrace through unwind data. */
+
+ _Unwind_Reason_Code
+ _Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
+ {
+ struct _Unwind_Context context;
+ _Unwind_Reason_Code code;
+
+ uw_init_context (&context);
+
+ while (1)
+ {
+ _Unwind_FrameState fs;
+
+ /* Set up fs to describe the FDE for the caller of context. */
+ code = uw_frame_state_for (&context, &fs);
+ if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ /* Call trace function. */
+ if ((*trace) (&context, trace_argument) != _URC_NO_REASON)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ /* We're done at end of stack. */
+ if (code == _URC_END_OF_STACK)
+ break;
+
+ /* Update context to describe the same frame as fs. */
+ uw_update_context (&context, &fs);
+ }
+
+ return code;
+ }
+
--
Dr. Ulrich Weigand
weigand@informatik.uni-erlangen.de
More information about the Gcc-patches
mailing list