mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-12-22 19:43:42 +01:00
Rename: NOTES -> doc/NOTES
(Logical change 1.7)
This commit is contained in:
parent
96e3133a62
commit
be72029dac
1 changed files with 74 additions and 0 deletions
74
doc/NOTES
74
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 <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;
|
||||
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.
|
Loading…
Reference in a new issue