diff --git a/doc/NOTES b/doc/NOTES index e69de29b..a2a2f63d 100644 --- a/doc/NOTES +++ b/doc/NOTES @@ -0,0 +1,74 @@ +The central data structure of the unwind API is the unwind cursor. +This structure tracks the frame registers and the preserved registers. +The distinction between frame registers and preserved registers is +important: the former represent the *current* value of a register (as +it existed at the current IP); the latter represent the *saved* value +of a register (i.e., the value that existed on entry to the current +procedure). 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 . For example, to get the IA-64-specific register +names, an application would do: + + #include + +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; + ucontext_t uc; + + 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.