2003-12-10 08:14:38 +01:00
|
|
|
\documentclass{article}
|
|
|
|
\usepackage[fancyhdr,pdf]{latex2man}
|
|
|
|
|
|
|
|
\input{common.tex}
|
|
|
|
|
|
|
|
\begin{document}
|
|
|
|
|
|
|
|
\begin{Name}{3}{libunwind-dynamic}{David Mosberger-Tang}{Programming Library}{Introduction to dynamic unwind-info}libunwind-dynamic -- libunwind-support for runtime-generated code
|
|
|
|
\end{Name}
|
|
|
|
|
|
|
|
\section{Introduction}
|
|
|
|
|
|
|
|
For \Prog{libunwind} to do its work, it needs to be able to
|
|
|
|
reconstruct the \emph{frame state} of each frame in a call-chain. The
|
|
|
|
frame state consists of some frame registers (such as the
|
|
|
|
instruction-pointer and the stack-pointer) and the locations at which
|
|
|
|
the current values of every callee-saved (``preserved'') resides.
|
|
|
|
|
|
|
|
The purpose of the dynamic unwind-info is therefore to provide
|
|
|
|
\Prog{libunwind} the minimal information it needs about each
|
|
|
|
dynamically generated procedure such that it can reconstruct the
|
|
|
|
procedure's frame state.
|
|
|
|
|
|
|
|
For the purpose of the following discussion, a \emph{procedure} is any
|
|
|
|
contiguous piece of code. Normally, each procedure directly
|
|
|
|
corresponds to a function in the source-language but this is not
|
|
|
|
strictly required. For example, a runtime code-generator could
|
|
|
|
translate a given function into two separate (discontiguous)
|
|
|
|
procedures: one for frequently-executed (hot) code and one for
|
|
|
|
rarely-executed (cold) code. Similarly, simple source-language
|
|
|
|
functions (usually leaf functions) may get translated into code for
|
|
|
|
which the default unwind-conventions apply and for such code, no
|
|
|
|
dynamic unwind info needs to be registered.
|
|
|
|
|
|
|
|
Within a procedure, the code can be thought of as being divided into a
|
|
|
|
sequence of \emph{regions}. Each region logically consists of an
|
|
|
|
optional \emph{prologue}, a \emph{body}, and an optional
|
|
|
|
\emph{epilogue}. If present, the prologue sets up the frame state for
|
|
|
|
the body, which does the actual work of the procedure. For example,
|
|
|
|
the prologue may need to allocate a stack-frame and save some
|
|
|
|
callee-saved registers before the body can start executing.
|
|
|
|
Correspondingly, the epilogue, if present, restores the previous frame
|
|
|
|
state and thereby undoes the effect of the prologue. Regions are
|
|
|
|
nested in the sense that the frame state at the end of a region serves
|
|
|
|
as the entry-state of the next region. At the end of several nested
|
|
|
|
regions, there may be a single epilogue which undoes the effect of all
|
|
|
|
the prologues in the nested regions.
|
|
|
|
|
|
|
|
Even though logically we think of the prologue, body, and epilogue as
|
|
|
|
separate entities, optimizing code-generators will generally
|
|
|
|
interleave instructions from all three entities to achieve higher
|
|
|
|
performance. In fact, as far as the dynamic unwind-info is concerned,
|
|
|
|
there is no distinction at all between prologue and body. Similarly,
|
|
|
|
the exact set of instructions that make up an epilogue is also
|
|
|
|
irrelevant. The only point in the epilogue that needs to be described
|
|
|
|
explicitly is the point at which the stack-pointer gets restored. The
|
|
|
|
reason this point needs to be described is that once the stack-pointer
|
|
|
|
is restored, all values saved in the deallocated portion of the stack
|
|
|
|
become invalid. All other locations that store the values of
|
|
|
|
callee-saved register are assumed to remain valid throughout the end
|
|
|
|
of the region.
|
|
|
|
|
|
|
|
Within a region, each instruction that affects the frame state in some
|
|
|
|
fashion needs to be described with an operation descriptor. For this
|
|
|
|
purpose, each instruction in the region is assigned a unique index.
|
|
|
|
Exactly how this index is derived depends on the architecture. For
|
|
|
|
example, on RISC and EPIC-style architecture, instructions have a
|
|
|
|
fixed size so it's possible to simply number the instructions. In
|
|
|
|
contrast, most CISC use variable-length instruction encodings, so it
|
|
|
|
is usually necessary to use a byte-offset as the index. Given the
|
|
|
|
instruction index, the operation descriptor specifies the effect of
|
|
|
|
the instruction in an abstract manner. For example, it might express
|
|
|
|
that the instruction stores calle-saved register \Var{r1} at offset 16
|
|
|
|
in the stack frame.
|
|
|
|
|
|
|
|
\section{Procedures}
|
|
|
|
|
|
|
|
unw\_dyn\_info\_t
|
|
|
|
unw\_dyn\_proc\_info\_t
|
|
|
|
unw\_dyn\_table\_info\_t
|
|
|
|
unw\_dyn\_remote\_table\_info\_t
|
2003-02-22 09:19:43 +01:00
|
|
|
|
2003-12-10 08:14:38 +01:00
|
|
|
\section{Regions}
|
|
|
|
|
|
|
|
unw\_dyn\_region\_info\_t:
|
2003-02-22 09:19:43 +01:00
|
|
|
- insn_count can be negative to indicate that the region is
|
|
|
|
at the end of the procedure; in such a case, the negated
|
|
|
|
insn_count value specifies the length of the final region
|
|
|
|
in number of instructions. There must be at most one region
|
|
|
|
with a negative insn_count and only the last region in a
|
|
|
|
procedure's region list may be negative. Furthermore, both
|
|
|
|
di->start\_ip and di->end\_ip must be valid.
|
2003-12-10 08:14:38 +01:00
|
|
|
|
|
|
|
\section{Operations}
|
|
|
|
|
|
|
|
unw\_dyn\_operation\_t
|
|
|
|
unw\_dyn\_op\_t
|
|
|
|
\_U\_QP\_TRUE
|
|
|
|
|
|
|
|
unw\_dyn\_info\_format\_t
|
|
|
|
|
|
|
|
- instructions don't have to be sorted in increasing order of ``when''
|
|
|
|
values: In general, if you can generate the sorted order easily
|
|
|
|
(e.g., without an explicit sorting step), I'd recommend doing so
|
|
|
|
because in that case, should some version of libunwind ever require
|
|
|
|
sorted order, libunwind can verify in O(N) that the list is sorted
|
|
|
|
already. In the particular case of the ia64-version of libunwind, a
|
|
|
|
sorted order won't help, since it always scans the instructions up
|
|
|
|
to UNW_DYN_STOP.
|
|
|
|
|
|
|
|
\_U\_dyn\_region\_info\_size(opcount);
|
|
|
|
\_U\_dyn\_op\_save\_reg();
|
|
|
|
\_U\_dyn\_op\_spill\_fp\_rel();
|
|
|
|
\_U\_dyn\_op\_spill\_sp\_rel();
|
|
|
|
\_U\_dyn\_op\_add();
|
|
|
|
\_U\_dyn\_op\_pop\_frames();
|
|
|
|
\_U\_dyn\_op\_label\_state();
|
|
|
|
\_U\_dyn\_op\_copy\_state();
|
|
|
|
\_U\_dyn\_op\_alias();
|
|
|
|
\_U\_dyn\_op\_stop();
|
|
|
|
|
|
|
|
\section{See Also}
|
|
|
|
|
|
|
|
\SeeAlso{libunwind(3)},
|
|
|
|
\SeeAlso{\_U\_dyn\_register(3)},
|
|
|
|
\SeeAlso{\_U\_dyn\_cancel(3)}
|
|
|
|
|
|
|
|
\section{Author}
|
|
|
|
|
|
|
|
\noindent
|
|
|
|
David Mosberger-Tang\\
|
|
|
|
Hewlett-Packard Labs\\
|
|
|
|
Palo-Alto, CA 94304\\
|
|
|
|
Email: \Email{davidm@hpl.hp.com}\\
|
|
|
|
WWW: \URL{http://www.hpl.hp.com/research/linux/libunwind/}.
|
|
|
|
\LatexManEnd
|
|
|
|
|
|
|
|
\end{document}
|