123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- 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
|