NAME¶
libunwind -- a (mostly) platform-independent unwind API
SYNOPSIS¶
#include <libunwind.h>
int unw_getcontext(unw_context_t *);
int unw_init_local(unw_cursor_t *, unw_context_t *);
int unw_init_remote(unw_cursor_t *, unw_addr_space_t, void *);
int unw_step(unw_cursor_t *);
int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *);
int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t);
int unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t);
int unw_resume(unw_cursor_t *);
unw_addr_space_t unw_local_addr_space;
unw_addr_space_t unw_create_addr_space(unw_accessors_t, int);
void unw_destroy_addr_space(unw_addr_space_t);
unw_accessors_t unw_get_accessors(unw_addr_space_t);
void unw_flush_cache(unw_addr_space_t, unw_word_t, unw_word_t);
int unw_set_caching_policy(unw_addr_space_t, unw_caching_policy_t);
const char *unw_regname(unw_regnum_t);
int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *);
int unw_get_save_loc(unw_cursor_t *, int, unw_save_loc_t *);
int unw_is_fpreg(unw_regnum_t);
int unw_is_signal_frame(unw_cursor_t *);
int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *);
void _U_dyn_register(unw_dyn_info_t *);
void _U_dyn_cancel(unw_dyn_info_t *);
LOCAL UNWINDING¶
Libunwind is very easy to use when unwinding a stack from within a running
program. This is called
local unwinding. Say you want to unwind the
stack while executing in some function F(). In this function, you would call
unw_getcontext() to get a snapshot of the CPU registers (machine-state). Then
you initialize an
unwind cursor based on this snapshot. This is done
with a call to unw_init_local(). The cursor now points to the current frame,
that is, the stack frame that corresponds to the current activation of
function F(). The unwind cursor can then be moved ``up'' (towards earlier
stack frames) by calling unw_step(). By repeatedly calling this routine, you
can uncover the entire call-chain that led to the activation of function F().
A positive return value from unw_step() indicates that there are more frames
in the chain, zero indicates that the end of the chain has been reached, and
any negative value indicates that some sort of error has occurred.
While it is not possible to directly move the unwind cursor in the ``down''
direction (towards newer stack frames), this effect can be achieved by making
copies of an unwind cursor. For example, a program that sometimes has to move
``down'' by one stack frame could maintain two cursor variables: ``curr'' and
``prev''. The former would be used as the current cursor and prev would be
maintained as the ``previous frame'' cursor by copying the contents of curr to
prev right before calling unw_step(). With this approach, the program could
move one step ``down'' simply by copying back prev to curr whenever that is
necessary. In the most extreme case, a program could maintain a separate
cursor for each call frame and that way it could move up and down the
callframe-chain at will.
Given an unwind cursor, it is possible to read and write the CPU registers that
were preserved for the current stack frame (as identified by the cursor).
Libunwind provides several routines for this purpose: unw_get_reg() reads an
integer (general) register, unw_get_fpreg() reads a floating-point register,
unw_set_reg() writes an integer register, and unw_set_fpreg() writes a
floating-point register. Note that, by definition, only the
preserved
machine state can be accessed during an unwind operation. Normally, this state
consists of the
callee-saved (``preserved'') registers. However, in
some special circumstances (e.g., in a signal handler trampoline), even the
caller-saved (``scratch'') registers are preserved in the stack frame
and, in those cases, libunwind will grant access to them as well. The exact
set of registers that can be accessed via the cursor depends, of course, on
the platform. However, there are two registers that can be read on all
platforms: the instruction pointer (IP), sometimes also known as the ``program
counter'', and the stack pointer (SP). In libunwind, these registers are
identified by the macros UNW_REG_IP and UNW_REG_SP, respectively.
Besides just moving the unwind cursor and reading/writing saved registers,
libunwind also provides the ability to resume execution at an arbitrary stack
frame. As you might guess, this is useful for implementing non-local gotos and
the exception handling needed by some high-level languages such as Java.
Resuming execution with a particular stack frame simply requires calling
unw_resume() and passing the cursor identifying the target frame as the only
argument.
Normally, libunwind supports both local and remote unwinding (the latter will be
explained in the next section). However, if you tell libunwind that your
program only needs local unwinding, then a special implementation can be
selected which may run much faster than the generic implementation which
supports both kinds of unwinding. To select this optimized version, simply
define the macro UNW_LOCAL_ONLY before including the headerfile
<libunwind.h>. It is perfectly OK for a single program to employ both
local-only and generic unwinding. That is, whether or not UNW_LOCAL_ONLY is
defined is a choice that each source-file (compilation-unit) can make on its
own. Independent of the setting(s) of UNW_LOCAL_ONLY, you'll always link the
same library into the program (normally
-lunwind). Furthermore, the
portion of libunwind that manages unwind-info for dynamically generated code
is not affected by the setting of UNW_LOCAL_ONLY.
If we put all of the above together, here is how we could use libunwind to write
a function ``show_backtrace()'' which prints a classic stack trace:
#define UNW_LOCAL_ONLY
#include <libunwind.h>
void show_backtrace (void) {
unw_cursor_t cursor; unw_context_t uc;
unw_word_t ip, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
while (unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
printf ("ip = %lx, sp = %lx\n", (long) ip, (long) sp);
}
}
REMOTE UNWINDING¶
Libunwind can also be used to unwind a stack in a ``remote'' process. Here,
``remote'' may mean another process on the same machine or even a process on a
completely different machine from the one that is running libunwind. Remote
unwinding is typically used by debuggers and instruction-set simulators, for
example.
Before you can unwind a remote process, you need to create a new address-space
object for that process. This is achieved with the unw_create_addr_space()
routine. The routine takes two arguments: a pointer to a set of
accessor routines and an integer that specifies the byte-order of the
target process. The accessor routines provide libunwind with the means to
communicate with the remote process. In particular, there are callbacks to
read and write the process's memory, its registers, and to access unwind
information which may be needed by libunwind.
With the address space created, unwinding can be initiated by a call to
unw_init_remote(). This routine is very similar to unw_init_local(), except
that it takes an address-space object and an opaque pointer as arguments. The
routine uses these arguments to fetch the initial machine state. Libunwind
never uses the opaque pointer on its own, but instead just passes it on to the
accessor (callback) routines. Typically, this pointer is used to select, e.g.,
the thread within a process that is to be unwound.
Once a cursor has been initialized with unw_init_remote(), unwinding works
exactly like in the local case. That is, you can use unw_step() to move ``up''
in the call-chain, read and write registers, or resume execution at a
particular stack frame by calling unw_resume.
Libunwind has been designed to enable unwinding across platforms
(architectures). Indeed, a single program can use libunwind to unwind an
arbitrary number of target platforms, all at the same time!
We call the machine that is running libunwind the
host and the machine
that is running the process being unwound the
target. If the host and
the target platform are the same, we call it
native unwinding. If they
differ, we call it
cross-platform unwinding.
The principle behind supporting native, cross-platform, and multi-platform
unwinding is very simple: for native unwinding, a program includes
<libunwind.h> and uses the linker switch
-lunwind. For
cross-platform unwinding, a program includes <libunwind-PLAT.h> and uses
the linker switch
-lunwind-PLAT, where PLAT is the name of the target
platform (e.g., ia64 for IA-64, hppa-elf for ELF-based HP PA-RISC, or x86 for
80386). Multi-platform unwinding works exactly like cross-platform unwinding,
the only limitation is that a single source file (compilation unit) can
include at most one libunwind header file. In other words, the
platform-specific support for each supported target needs to be isolated in
separate source files---a limitation that shouldn't be an issue in practice.
Note that, by definition, local unwinding is possible only for the native case.
Attempting to call, e.g., unw_local_init() when targeting a cross-platform
will result in a link-time error (unresolved references).
THREAD- AND SIGNAL-SAFETY¶
All libunwind routines are thread-safe. What this means is that multiple threads
may use libunwind simulatenously. However, any given cursor may be accessed by
only one thread at any given time.
To ensure thread-safety, some libunwind routines may have to use locking. Such
routines
must not be called from signal handlers (directly or
indirectly) and are therefore
not signal-safe. The manual page for each
libunwind routine identifies whether or not it is signal-safe, but as a
general rule, any routine that may be needed for
local unwinding is
signal-safe (e.g., unw_step() for local unwinding is signal-safe). For
remote-unwinding,
none of the libunwind routines are guaranteed to be
signal-safe.
UNWINDING THROUGH DYNAMICALLY GENERATED CODE¶
Libunwind provides the routines _U_dyn_register() and _U_dyn_cancel() to
register/cancel the information required to unwind through code that has been
generated at runtime (e.g., by a just-in-time (JIT) compiler). It is important
to register the information for
all dynamically generated code because
otherwise, a debugger may not be able to function properly or high-level
language exception handling may not work as expected.
The interface for registering and canceling dynamic unwind info has been
designed for maximum efficiency, so as to minimize the performance impact on
JIT-compilers. In particular, both routines are guaranteed to execute in
``constant time'' (O(1)) and the data-structure encapsulating the dynamic
unwind info has been designed to facilitate sharing, such that similar
procedures can share much of the underlying information.
For more information on the libunwind support for dynamically generated code,
see
libunwind-dynamic(3).
CACHING OF UNWIND INFO¶
To speed up execution, libunwind may aggressively cache the information it needs
to perform unwinding. If a process changes during its lifetime, this creates a
risk of libunwind using stale data. For example, this would happen if
libunwind were to cache information about a shared library which later on gets
unloaded (e.g., via
dlclose(3)).
To prevent the risk of using stale data, libunwind provides two facilities:
first, it is possible to flush the cached information associated with a
specific address range in the target process (or the entire address space, if
desired). This functionality is provided by unw_flush_cache(). The second
facility is provided by unw_set_caching_policy(), which lets a program select
the exact caching policy in use for a given address-space object. In
particular, by selecting the policy UNW_CACHE_NONE, it is possible to turn off
caching completely, therefore eliminating the risk of stale data alltogether
(at the cost of slower execution). By default, caching is enabled for local
unwinding only.
FILES¶
- libunwind.h
-
Headerfile to include for native (same platform) unwinding.
- libunwind-PLAT.h
-
Headerfile to include when the unwind target runs on platform PLAT. For
example, to unwind an IA-64 program, the header file libunwind-ia64.h
should be included.
- -lunwind
-
Linker-switch to add when building a program that does native (same
platform) unwinding.
- -lunwind-PLAT
-
Linker-switch to add when building a program that unwinds a program on
platform PLAT. For example, to (cross-)unwind an IA-64 program, the linker
switch -lunwind-ia64 should be added. Note: multiple such switches may
need to be specified for programs that can unwind programs on multiple
platforms.
SEE ALSO¶
libunwind-dynamic(3),
libunwind-ia64(3),
libunwind-ptrace(3),
libunwind-setjmp(3),
unw_create_addr_space(3),
unw_destroy_addr_space(3),
unw_flush_cache(3),
unw_get_accessors(3),
unw_get_fpreg(3),
unw_get_proc_info(3),
unw_get_proc_name(3),
unw_get_reg(3),
unw_getcontext(3),
unw_init_local(3),
unw_init_remote(3),
unw_is_fpreg(3),
unw_is_signal_frame(3),
unw_regname(3),
unw_resume(3),
unw_set_caching_policy(3),
unw_set_fpreg(3),
unw_set_reg(3),
unw_step(3),
unw_strerror(3),
_U_dyn_register(3),
_U_dyn_cancel(3)
AUTHOR¶
David Mosberger-Tang
Email:
dmosberger@gmail.com
WWW:
http://www.nongnu.org/libunwind/.