NAME
uwx() — Unwind Express Library
SYNOPSIS
cc
[flag... ]
file...
-lunwind
[library] ...
#include <uwx.h>
#include <uwx_self.h>
DESCRIPTION
The Unwind Express Library is a lightweight library
for unwinding a process stack on Integrity systems.
It may be used for
"self-unwinding," where a thread traces back through its
own stack,
or for "cross-unwinding," where a debugger or other tool
can examine the stack of another target thread or process.
To use the Unwind Express Library, link your application
with the
-lunwind
option on the compiler or linker command line.
All source code should include the header file
<uwx.h>.
Source code that uses the library for self-unwinding
should also include the header file
<uwx_self.h>.
The Unwind Express Library maintains its entire state
within a single unwind environment structure.
To unwind a stack, the client application provides
an initial context to the unwind environment,
then unwinds the stack one frame at a time.
After reaching the bottom of the stack,
the unwind environment may be reused for a subsequent
unwind operation simply by providing a new initial context,
or it may be discarded, freeing the memory it was using.
A client application may create any
number of separate unwind environments, and each one will
operate independently of and completely unaffected by the
others.
The Unwind Express Library consists of a core unwind engine
that can be adapted to specific environments through the
use of callback routines.
For self-unwinding, a set of standard callback routines are
provided as part of the library.
For cross-unwinding, the client must supply callback routines
to interface the unwind engine to the target thread or process.
Self-Unwinding
To prepare for self-unwinding,
a client application must perform the following steps
to create and initialize a new unwind environment:
- 1.
Call
uwx_init()
to create a new unwind environment.
The return value is a pointer to the unwind environment.
- 2.
Call
uwx_self_init_info()
to initialize the standard callback environment.
The return value is a pointer to the callback info structure.
- 3.
Call
uwx_register_callbacks()
to register the standard callbacks:
uwx_self_copyin()
and
uwx_self_lookupip().
The steps above may be performed at any time in advance
of performing a stack unwind.
The resulting unwind environment can then be used repeatedly.
To perform a stack unwind from some point in the application,
the client must perform the following steps:
- 1.
Call
uwx_self_init_context()
to provide the current thread's context as a starting
point for unwinding.
The stack frame for the caller of this function becomes the
current frame.
- 2.
Call
uwx_step()
to step back one frame in the call stack.
After each step, the new frame becomes the current frame,
and the client may call
uwx_get_reg()
to obtain values from the reconstructed context for
the new frame.
This step can be repeated until the process reaches
the bottom of the stack or a signal context frame.
- 3.
When a signal context frame is reached, the client may call
uwx_self_do_context_frame()
to provide a new starting point for unwinding based on
the context at the point of interruption.
The stack frame for the function interrupted by the signal
becomes the current frame.
Subsequent calls to
uwx_step()
will proceed from there.
Cross-Unwinding
To prepare for cross-unwinding,
a client application must perform the following steps
to create and initialize a new unwind environment:
- 1.
Call
uwx_init()
to create a new unwind environment.
The return value is a pointer to the unwind environment.
- 2.
Call
uwx_set_remote()
to setup the unwind environment for cross unwinding.
This call also allows the client to specify the byte order
(little-endian or big-endian) of the target process.
- 3.
Call
uwx_register_callbacks()
to register the client-provided callback functions.
See
uwx_register_callbacks(3X)
for information on
writing callback routines.
The steps above may be performed at any time in advance
of performing a stack unwind.
The resulting unwind environment can then be used repeatedly.
To perform a stack unwind,
the client must perform the following steps:
- 1.
Call
uwx_init_context()
to provide the basic initial context as a starting
point for unwinding.
This initial context consists of the values of
ip
(instruction pointer),
sp
(stack pointer),
bsp
(backing store pointer),
and
cfm
(current frame marker).
The frame described by these values becomes the
current frame.
If the unwind engine needs values from additional registers
in the target thread's context, it will request them
as needed through the callback interface.
- 2.
Call
uwx_step()
to step back one frame in the call stack.
After each step, the new frame becomes the current frame,
and the client may call
uwx_get_reg()
to obtain values from the reconstructed context for
the new frame.
This step can be repeated until the process reaches
the bottom of the stack or a signal context frame.
- 3.
When a signal context frame is reached, the client may call
uwx_get_abi_context_code()
to obtain the
abi
and
context
parameters recorded in the unwind descriptors for the frame.
This routine returns the two values in a single int as
((abi
<< 8) |
context).
It should then call
uwx_init_context()
again to provide a new starting point for unwinding based on
the context at the point of interruption.
The stack frame for the function interrupted by the signal
becomes the current frame.
Subsequent calls to
uwx_step()
will proceed from there.
Obtaining Information From the Current Frame's Context
Registers from the current frame may be read using
uwx_get_reg()
and
uwx_get_nat().
The starting address of the current function may be obtained
by calling
uwx_get_funcstart().
Symbolic information may be obtained, if available,
for the current frame's IP by calling
uwx_get_module_info(),
uwx_get_sym_info(),
and
uwx_get_source_info().
ERRORS
For the APIs that return pointer values, a NULL
pointer
indicates a memory allocation error; otherwise a pointer
to an opaque object is returned.
For other APIs, an integer status code is returned.
These codes are listed here.
- UWX_OK
Request successfully completed.
- UWX_ABI_FRAME
uwx_step()
hit a signal context frame.
- UWX_BOTTOM
uwx_step()
hit bottom of stack.
- UWX_ERR_BADCACHE
The cached information returned by the lookup-ip callback was invalid.
- UWX_ERR_BADKEY
The "Lookup IP" callback returned an invalid key in the result vector.
- UWX_ERR_BADREGID
The register id is invalid.
- UWX_ERR_BADUDESC
The unwind information block contains an invalid descriptor.
- UWX_ERR_CANTUNWIND
The unwind engine is unable to unwind from the current frame
because of an unsupported descriptor.
- UWX_ERR_COPYIN_MSTK
There was an error reading a value from the memory stack.
- UWX_ERR_COPYIN_REG
There was an error reading a register from the initial context.
- UWX_ERR_COPYIN_RSTK
There was an error reading a value from the register stack backing store.
- UWX_ERR_COPYIN_UINFO
There was an error reading the unwind information block.
- UWX_ERR_COPYIN_UTBL
There was an error reading the unwind table.
- UWX_ERR_IPNOTFOUND
No module information was found for the current frame's IP.
- UWX_ERR_LOOKUPERR
The "Lookup IP" callback encountered an error.
- UWX_ERR_NOCALLBACKS
No callback routines have been registered.
- UWX_ERR_NOCONTEXT
No initial context has been supplied.
- UWX_ERR_NOENV
The
env
parameter is NULL.
- UWX_ERR_NOMEM
An attempt to allocate additional memory failed.
- UWX_ERR_NOSYM
No symbolic information was found.
- UWX_ERR_NOUDESC
An unwind information block was found, but it does not describe the
current frame's IP.
- UWX_ERR_NOUENTRY
No unwind information block was found for the current frame's IP.
- UWX_ERR_PROLOG_UF
The unwind information block is invalid -- the nesting of prologue
regions is not balanced.
- UWX_ERR_UCACCESS
An unidentified error was received from the
uc_access(3)
library.
- UWX_ERR_UNDEFLABEL
The unwind information block is invalid -- an undefined label is referenced.
EXAMPLES
The following code fragment performs a stack unwind
in the current thread:
int status;
struct uwx_env *env;
struct uwx_self_info *info;
uint64_t ip;
env = uwx_init();
info = uwx_self_init_info(env);
status = uwx_register_callbacks(env, (intptr_t)info,
uwx_self_copyin, uwx_self_lookupip);
status = uwx_self_init_context(env);
for (;;) {
status = uwx_step(env);
if (status != UWX_OK)
break;
status = uwx_get_reg(env, UWX_REG_IP, &ip);
printf("IP: %016llx\n", ip);
}
uwx_self_free_info(info);
uwx_free(env);
LIMITATIONS
The Unwind Express Library currently
does not recognize X-format unwind descriptors.
These are not currently used by HP compilers.
AUTHOR
The Unwind Express Library was developed by Hewlett-Packard.
SEE ALSO
uc_access(3),
uwx_add_to_bsp(3X),
uwx_find_source_info(3X),
uwx_find_symbol(3X),
uwx_free(3X),
uwx_get_abi_context_code(3X),
uwx_get_funcstart(3X),
uwx_get_module_info(3X),
uwx_get_nat(3X),
uwx_get_reg(3X),
uwx_get_source_info(3X),
uwx_get_sym_info(3X),
uwx_init(3X),
uwx_init_context(3X),
uwx_register_alloc_cb(3X),
uwx_register_callbacks(3X),
uwx_release_symbol_cache(3X),
uwx_self_do_context_frame(3X),
uwx_self_free_info(3X),
uwx_self_init_context(3X),
uwx_self_init_info(3X),
uwx_set_nofr(3X),
uwx_set_remote(3X),
uwx_step(3X),
uwx_step_inline(3X).