mostang.com!davidm | be72029 | 2002-02-23 20:27:03 +0000 | [diff] [blame] | 1 | The central data structure of the unwind API is the unwind cursor. |
| 2 | This structure tracks the frame registers and the preserved registers. |
| 3 | The distinction between frame registers and preserved registers is |
| 4 | important: the former represent the *current* value of a register (as |
| 5 | it existed at the current IP); the latter represent the *saved* value |
| 6 | of a register (i.e., the value that existed on entry to the current |
| 7 | procedure). The unwind API defines a handful of well-known frame |
| 8 | "registers": |
| 9 | |
| 10 | - ip: the instruction pointer (pc) |
| 11 | - rp: the return pointer (rp, aka "return address" or "return link") |
| 12 | - sp: the stack pointer (memory stack pointer, in the case of ia64) |
| 13 | - fp: the frame pointer |
| 14 | - first_ip: the starting address of the current "procedure" |
| 15 | - handler: a pointer to an architecture & language-specific |
| 16 | "personality" routine |
| 17 | - lsda: a pointer to an architecture & language-specific |
| 18 | data-area |
| 19 | |
| 20 | The API defines no well-known preserved registers. Each architecture |
| 21 | can define additional registers as needed. Of course, a portable |
| 22 | application may only rely on well-known registers. The names for |
| 23 | preserved registers are defined in the architecture-specific header |
| 24 | file <unwind-ARCH.h>. For example, to get the IA-64-specific register |
| 25 | names, an application would do: |
| 26 | |
| 27 | #include <unwind-ia64.h> |
| 28 | |
| 29 | The API is designed to handle two primary cases: unwinding within the |
| 30 | current (local) process and unwinding of another ("remote") process |
| 31 | (e.g., through ptrace()). In the local case, the initial machine |
| 32 | state is captured by an unwind context (currently the same as |
| 33 | ucontext_t). In the remote case, the initial machine state is |
| 34 | captured by an unwind accessor structure, which provides callback |
| 35 | routines for reading/writing memory and registers and for obtaining |
| 36 | unwind information. |
| 37 | |
| 38 | Once a cursor has been initialized, you can step through the call |
| 39 | chain with the unw_step() routine. The frame registers and the |
| 40 | preserved state can then be accessed with unw_get_reg() or modified |
| 41 | with unw_set_reg(). For floating-point registers, there are separate |
| 42 | unw_get_fpreg() and unw_set_fpreg() routines (on some arches, e.g., |
| 43 | Alpha, these could be just aliases for unw_{g,s}et_reg()). The |
| 44 | unw_resume() routine can be used to resume execution at an arbitrary |
| 45 | point in the call-chain (as identified by an unwind cursor). This is |
| 46 | intended for exception handling and, at least for now, the intention |
| 47 | is to support this routine only for the local case. Kevin, if you |
| 48 | feel gdb could benefit from such a routine, I'd be interested to hear |
| 49 | about it. |
| 50 | |
| 51 | Note that it is perfectly legal to make copies of the unwind cursor. |
| 52 | This makes it possible, e.g., to obtain an unwind context, modify the |
| 53 | state in an earlier call frame, and then resume execution at the point |
| 54 | at which the unwind context was captured. |
| 55 | |
| 56 | Here is a quick example of how to use the unwind API to do a simple |
| 57 | stack trace: |
| 58 | |
| 59 | unw_cursor_t cursor; |
| 60 | unw_word_t ip, sp; |
| 61 | ucontext_t uc; |
| 62 | |
| 63 | getcontext(&uc); |
| 64 | unw_init_local(&cursor, &uc); |
| 65 | do |
| 66 | { |
| 67 | unw_get_reg(&cursor, UNW_REG_IP, &ip); |
| 68 | unw_get_reg(&cursor, UNW_REG_SP, &sp); |
| 69 | printf ("ip=%016lx sp=%016lx\n", ip, sp); |
| 70 | } |
| 71 | while (unw_step (&cursor) > 0); |
| 72 | |
| 73 | Note that this particular example should work on pretty much any |
| 74 | architecture, as it doesn't rely on any arch-specific registers. |