The central data structure of the unwind API is the unwind cursor. This structure tracks the register contents. The unwind API defines a handful of well-known frame "registers": - ip: the instruction pointer (pc) - rp: the return pointer (rp, aka "return address" or "return link") - sp: the stack pointer (memory stack pointer, in the case of ia64) - fp: the frame pointer - first_ip: the starting address of the current "procedure" - handler: a pointer to an architecture & language-specific "personality" routine - lsda: a pointer to an architecture & language-specific data-area The API defines no well-known preserved registers. Each architecture can define additional registers as needed. Of course, a portable application may only rely on well-known registers. The names for preserved registers are defined in the architecture-specific header file <unwind-ARCH.h>. For example, to get the IA-64-specific register names, an application would do: #include <unwind-ia64.h> The API is designed to handle two primary cases: unwinding within the current (local) process and unwinding of another ("remote") process (e.g., through ptrace()). In the local case, the initial machine state is captured by an unwind context (currently the same as ucontext_t). In the remote case, the initial machine state is captured by an unwind accessor structure, which provides callback routines for reading/writing memory and registers and for obtaining unwind information. Once a cursor has been initialized, you can step through the call chain with the unw_step() routine. The frame registers and the preserved state can then be accessed with unw_get_reg() or modified with unw_set_reg(). For floating-point registers, there are separate unw_get_fpreg() and unw_set_fpreg() routines (on some arches, e.g., Alpha, these could be just aliases for unw_{g,s}et_reg()). The unw_resume() routine can be used to resume execution at an arbitrary point in the call-chain (as identified by an unwind cursor). This is intended for exception handling and, at least for now, the intention is to support this routine only for the local case. Kevin, if you feel gdb could benefit from such a routine, I'd be interested to hear about it. Note that it is perfectly legal to make copies of the unwind cursor. This makes it possible, e.g., to obtain an unwind context, modify the state in an earlier call frame, and then resume execution at the point at which the unwind context was captured. Here is a quick example of how to use the unwind API to do a simple stack trace: unw_cursor_t cursor; unw_word_t ip, sp; unw_context_t uc; unw_getcontext(&uc); unw_init_local(&cursor, &uc); do { unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); printf ("ip=%016lx sp=%016lx\n", ip, sp); } while (unw_step (&cursor) > 0); Note that this particular example should work on pretty much any architecture, as it doesn't rely on any arch-specific registers. * Multiarchitecture support If libunwind is configured for a target other than the local (native) host, the library is installed as libunwind-$ARCH, where $ARCH is the target architecture name (e.g., ia32, ia64, or alpha). Similarly, the header file is installed as libunwind-$ARCH. With this setup, an application should: - include <libunwind.h>, and - link against -lunwind if the application needs to use the unwinder of the host. An application wanting to use the unwinder for a different target (e.g., a cross-debugger) should: - include <libunwind-$ARCH.h>, and - link against -lunwind-$ARCH The global symbols exported by -lunwind-$ARCH are unique such that the same application can be linked against the separate unwind libraries of multiple targets. However, a single compilation unit can include the header file for only one target. For example, foo.c might include <libunwind-ia64.h> and bar.c might include <libunwind.h> and the entire application would have to be linked against both -lunwind and -lunwind-ia64. Note: the unwind header files of all targets have a common dependency on libunwind-common.h. To avoid version conflicts, it is necessary to ensure that the unwind libraries for all targets were derived from the same release of libunwind. That is, if the unwind library for one target is upgraded to a newer version, the libraries for all other targets also need to be upgraded. Note 2: The assumption is that a cross-unwinder can handle all interesting flavors of a target. For example, the unwinder for the ia64 target is expected to be able to handle both Linux and HP-UX. * IA-64 Specific Information Apart from the normal frame-registers, the IA-64 implementation of libunwind provides the means to access the current value of the register backing store pointer (bsp). One quirk with this frame-register is that it corresponds to the address that would be in register ar.bsp after flushing the current register stack to the backing store (i.e., as if a "flushrs" instruction had been executed). Of course, given this value and the contents of the current frame marker (CFM), it's easy to calculate the original value of ar.bsp: unw_word_t cfm, bsp, bsp_after_flushrs, sof; unw_get_reg (&cursor, UNW_IA64_BSP, &bsp_after_flushrs); unw_get_reg (&cursor, UNW_IA64_CFM, &cfm); bsp = ia64_rse_skip_regs (bsp_after_flushrs, -(cfm & 0x7f)); ** Dynamic Unwind Info