mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2025-01-22 16:20:29 +01:00
Partial draft.
(Logical change 1.139)
This commit is contained in:
parent
f18f14e2f5
commit
e91ef29727
1 changed files with 130 additions and 1 deletions
|
@ -1,5 +1,88 @@
|
|||
unw\_dyn\_region\_info\_t:
|
||||
\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
|
||||
|
||||
\section{Regions}
|
||||
|
||||
unw\_dyn\_region\_info\_t:
|
||||
- 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
|
||||
|
@ -7,3 +90,49 @@ unw\_dyn\_region\_info\_t:
|
|||
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.
|
||||
|
||||
\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}
|
||||
|
|
Loading…
Reference in a new issue