CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
86 lines
4.6 KiB
TeX
86 lines
4.6 KiB
TeX
\section{Introduction}
|
|
\label{sec:intro}
|
|
This document describes StackwalkerAPI, an API and library for walking a call
|
|
stack. The call stack (also known as the run-time stack) is a stack found in a
|
|
process that contains the currently active stack frames. Each stack frame is a
|
|
record of an executing function (or function-like object such as a signal
|
|
handler or system call). StackwalkerAPI provides an API that allows users to
|
|
collect a call stack (known as walking the call stack) and access information
|
|
about its stack frames. The current implementation supports Linux/x86,
|
|
Linux/x86-64, Linux/Power, Linux/Power-64, and Windows/x86.
|
|
|
|
StackwalkerAPI is designed to be both easy-to-use and easy-to-extend. Users can
|
|
easily use StackwalkerAPI to walk a call stack without needing to understand how
|
|
call stacks are laid out on their platform. Users can easily extend
|
|
StackwalkerAPI to work with new platforms and types of stack frames by
|
|
implementing a set of callbacks that can be plugged into StackwalkerAPI.
|
|
|
|
StackwalkerAPI's ease-of-use comes from it providing a platform independent
|
|
interface that allows users to access detailed information about the call stack.
|
|
For example, the following C++ code-snippet is all that is needed to walk and
|
|
print the call stack of the currently running thread.
|
|
|
|
\lstset{language=[GNU]C++,basicstyle=\ttfamily\selectfont\small}
|
|
\lstset{numbers=none}
|
|
\begin{lstlisting}
|
|
std::vector<Frame> stackwalk;
|
|
string s;
|
|
|
|
Walker *walker = Walker::newWalker();
|
|
walker->walkStack(stackwalk);
|
|
for (unsigned i=0; i<stackwalk.size(); i++) {
|
|
stackwalk[i].getName(s);
|
|
cout << "Found function " << s << endl;
|
|
}
|
|
\end{lstlisting}
|
|
|
|
StackwalkerAPI can walk a call stack in the same address space as where the
|
|
StackwalkerAPI library lives (known as a first party stackwalk), or it can walk
|
|
a call stack in another process (known as a third party stackwalk). To change
|
|
the above example to perform a third party stackwalk, we would only need to pass
|
|
a process identifier to newWalker, e.g:
|
|
\begin{lstlisting}
|
|
Walker *walker = Walker::newWalker(pid);
|
|
\end{lstlisting}
|
|
|
|
Our other design goal with StackwalkerAPI is to make it easy-to-extend. The
|
|
mechanics of how to walk through a stack frame can vary between different
|
|
platforms, and even between different types of stack frames on the same
|
|
platform. In addition, different platforms may have different mechanisms for
|
|
reading the data in a call stack or looking up symbolic names that go with a
|
|
stack frame. StackwalkerAPI provides a callback interface for plugging in
|
|
mechanisms for handling new systems and types of stack frames. The callback
|
|
interface can be used to port StackwalkerAPI to new platforms, extend
|
|
StackwalkerAPI support on existing systems, or more easily integrate
|
|
StackwalkerAPI into existing tools. There are callbacks for the following
|
|
StackwalkerAPI operations:
|
|
|
|
\begin{description}
|
|
\item[Walk through a stack frame] StackwalkerAPI will find different types
|
|
of stack frames on different platforms and even within the same
|
|
platform. For example, on Linux/x86 the stack frame generated by a
|
|
typical function looks different from the stack frame generated by a
|
|
signal handler. The callback interface can be used to register a handler
|
|
with StackwalkerAPI that knows how to walk through a new type of stack
|
|
frame. For example, the DyninstAPI tool registers an object with
|
|
StackwalkerAPI that describes how to walk through the stack frames
|
|
generated by its instrumentation.
|
|
|
|
\item[Access process data] To walk a call stack, StackwalkerAPI needs to be
|
|
able to read a process' memory and registers. When doing a first party
|
|
stackwalk, this is done by directly reading them from the current
|
|
address space. When doing a third party stackwalk, this is done by
|
|
reading them using a debugger interface. The callback interface can be
|
|
used to register new objects for accessing process data. This can be
|
|
used, for example, to port StackwalkerAPI to a new operating system or
|
|
make it work with a new debugger interface.
|
|
|
|
\item[Look up symbolic names] When StackwalkerAPI finds a stack frame, it
|
|
gets an address that points into the piece of code that created that
|
|
stack frame. This address is not necessarily meaningful to a user, so
|
|
StackwalkerAPI attempts to associate the address with a symbolic name.
|
|
The callback interface can be used to register an object with
|
|
StackwalkerAPI that performs an address to name mapping, allowing
|
|
StackwalkerAPI to associate names with stack frames.
|
|
\end{description}
|