|  | /* dwarf2-backtrac.cc - backtrace implementation driven by the dwarf2 | 
|  | exception unwinder.  */ | 
|  |  | 
|  | /* Copyright (C) 2003  Free Software Foundation | 
|  |  | 
|  | This file is part of libgcj. | 
|  |  | 
|  | This software is copyrighted work licensed under the terms of the | 
|  | Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for | 
|  | details.  */ | 
|  |  | 
|  | /* Written by David Daney <ddaney@avtrex.com> */ | 
|  |  | 
|  | /* | 
|  | Although this in theory could be 'C' instead of C++, saying that it | 
|  | is C++ and including jvm.h makes it easier to insure that the proper | 
|  | compiler options are used.  There must be unwind tables for | 
|  | backtrace because it is on the stack when _Unwind_Backtrace is | 
|  | called.  Compiling as C++ insures this. | 
|  |  | 
|  | */ | 
|  |  | 
|  | #include <config.h> | 
|  |  | 
|  | #include <unwind.h> | 
|  |  | 
|  | #include <jvm.h> | 
|  |  | 
|  |  | 
|  | extern "C" | 
|  | { | 
|  | int backtrace (void **, int); | 
|  | } | 
|  |  | 
|  | struct backtrace_state | 
|  | { | 
|  | int skip_count; | 
|  | int current_level; | 
|  | int max_level; | 
|  | void **locations; | 
|  | }; | 
|  |  | 
|  | static _Unwind_Reason_Code | 
|  | my_trace_fn (struct _Unwind_Context *uc, void *arg) | 
|  | { | 
|  |  | 
|  | struct backtrace_state *bs = (struct backtrace_state *) arg; | 
|  |  | 
|  | if (bs->skip_count) | 
|  | { | 
|  | bs->skip_count--; | 
|  | return _URC_NO_REASON; | 
|  | } | 
|  |  | 
|  | _Unwind_Ptr loc = _Unwind_GetIP (uc); | 
|  |  | 
|  | if (bs->current_level < bs->max_level) | 
|  | bs->locations[bs->current_level++] = (void *) loc; | 
|  |  | 
|  | if (bs->current_level >= bs->max_level) | 
|  | return _URC_END_OF_STACK; | 
|  | else | 
|  | return _URC_NO_REASON; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * backtrace is defined in (some versions of) libc.  This definition | 
|  | * must match so that it can replace the libc version at link time. | 
|  | * | 
|  | * Fill the locations array with at most len back trace locations. | 
|  | * | 
|  | * Returns the number of locations actually filled in. | 
|  | * | 
|  | */ | 
|  | int | 
|  | backtrace (void **locations, int len) | 
|  | { | 
|  | struct backtrace_state bs; | 
|  | bs.skip_count = 1;		/* Don't log the call to backtrace itself. */ | 
|  | bs.current_level = 0; | 
|  | bs.max_level = len; | 
|  | bs.locations = locations; | 
|  |  | 
|  | _Unwind_Backtrace (my_trace_fn, &bs); | 
|  | return bs.current_level; | 
|  | } |