Skip to content

Commit

Permalink
Add stackwalk/walker.h
Browse files Browse the repository at this point in the history
  • Loading branch information
hainest committed Apr 3, 2024
1 parent 4f7c7af commit fbb77c0
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 178 deletions.
1 change: 1 addition & 0 deletions docs/stackwalk/developer/API.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ Stackwalker
swk_errors.h
symtab-swk.h
x86-swk.h
walker.h
24 changes: 24 additions & 0 deletions docs/stackwalk/developer/walker.h.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.. _`sec-dev:walker.h`:

walker.h
########

.. cpp:namespace:: Dyninst::Stackwalker::dev

.. cpp:class:: WalkerSet

.. cpp:function:: static WalkerSet *newWalkerSet()
.. cpp:function:: ~WalkerSet()
.. cpp:type:: std::set<Walker *>::iterator iterator
.. cpp:type:: std::set<Walker *>::const_iterator const_iterator
.. cpp:function:: iterator begin()
.. cpp:function:: iterator end()
.. cpp:function:: iterator find(Walker *)
.. cpp:function:: const_iterator begin() const
.. cpp:function:: const_iterator end() const
.. cpp:function:: const_iterator find(Walker *) const
.. cpp:function:: std::pair<iterator, bool> insert(Walker *walker)
.. cpp:function:: void erase(iterator i)
.. cpp:function:: bool empty() const
.. cpp:function:: size_t size() const
.. cpp:function:: bool walkStacks(CallTree &tree, bool walk_initial_only = false) const
264 changes: 103 additions & 161 deletions docs/stackwalk/public/walker.h.rst
Original file line number Diff line number Diff line change
@@ -1,214 +1,156 @@
walker.h
========

.. cpp:namespace:: Dyninst::stackwalk

Class Walker
~~~~~~~~~~~~

**Defined in:** ``walker.h``

The ``Walker`` class returns a call stack as a vector of ``Frame``
objects. As described in Section `3.1.1 <#subsec:definitions>`__, each
Frame object represents a stack frame, and contains a return address
(RA), stack pointer (SP) and frame pointer (FP). For each of these
values, optionally, it stores the location where the values were found.
Each Frame object may also be augmented with symbol information giving a
function name (or a symbolic name, in the case of non-functions) for the
object that created the stack frame.

The ``Walker`` class allows users to walk call stacks and query basic
information about threads in a target process. The user should create a
``Walker`` object for each process from which they are walking call
stacks. Each ``Walker`` object is associated with one process, but may
walk call stacks on multiple threads within that process. The ``Walker``
class allows users to query for the threads available for walking, and
it allows you to specify a particular thread whose call stack should be
walked. Stackwalks are returned as a vector of Frame objects.

Each Walker object contains three objects:

- ProcessState
.. _`sec:walker.h`:

- StepperGroup

- SymbolLookup

These objects are part of the Callback Interface and can be used to
customize StackwalkerAPI. The ``ProcessState`` object tells ``Walker``
how to access data in the target process, and it determines whether this
``Walker`` collects first party or third party stackwalks. ``Walker``
will pick an appropriate default ``ProcessState`` object based on which
factory method the users calls. The ``StepperGroup`` object is used to
customize how the ``Walker`` steps through stack frames. The
``SymbolLookup`` object is used to customize how StackwalkerAPI looks up
symbolic names of the function or object that created a stack frame.

.. code-block:: cpp
static Walker *newWalker() static Walker *newWalker(Dyninst::PID pid)
static Walker *newWalker(Dyninst::PID pid, std::string executable)
static Walker *newWalker(Dyninst::ProcControlAPI::Process::ptr proc);
static Walker *newWalker(std::string executable, const
std::vector<std::string> &argv) static Walker *newWalker(ProcessState *proc, StepperGroup *steppergroup = NULL , SymbolLookup *lookup = NULL)
These factory methods return new Walker objects:

- The first takes no arguments and returns a first-party stackwalker.
walker.h
########

- The second takes a PID representing a running process and returns a
third-party stackwalker on that process.
.. cpp:namespace:: Dyninst::Stackwalker

- The third takes the name of the executing binary in addition to the
PID and also returns a third-party stackwalker on that process.
.. cpp:class:: Walker

- The fourth takes a ProcControlAPI process object and returns a
third-party stackwalker.
**Walks call stacks and queries basic information about threads in a target process**

Users should create a walker for each process from which they are walking call
stacks. Each walker is associated with one process, but may walk call stacks on
multiple threads within that process. This class allows users to query for the
threads available for walking, and it allows you to specify a particular thread
whose call stack should be walked.

- The fifth takes the name of an executable and its arguments, creates
the process, and returns a third-party stackwalker.
Every walker contains a :cpp:class:`ProcessState`, a :cpp:class:`StepperGroup`,
and a :cpp:class:`SymbolLookup`. These are part of the Callback Interface and can
be used to customize StackwalkerAPI. The ``ProcessState`` tells the walker how to
access data in the target process and determines whether this walker collects first
party or third party stackwalks. ``Walker`` will pick an appropriate default
``ProcessState`` based on which factory method the users calls. The ``StepperGroup``
is used to customize how the walker steps through stack frames. The ``SymbolLookup``
is used to customize how StackwalkerAPI looks up symbolic names of the function or
object that created a stack frame.

- The sixth takes a ProcessState pointer representing a running process
as well as user-defined StepperGroup and SymbolLookup pointers. It
can return both first-party and third-party Walkers, depending on the
ProcessState parameter.
.. cpp:function:: static Walker *newWalker(std::string exec_name = std::string(""))

Unless overriden with the sixth variant, the new Walker object uses the
default StepperGroup and SymbolLookup callbacks for the current
platform. First-party walkers use the ProcSelf callback for its
ProcessState object. Third-party walkers use ProcDebug instead. See
Section 3.5.1 for more information about defaults in the Callback
Interface.
Creates a walker by launching a process for the executable ``exec_name``.

This method returns NULL if it was unable to create a new Walker object.
The new Walker object was created with the new operator, and should be
deallocated with the delete operator when it is no longer needed.
If ``exec_name`` is omitted, the current process is used.

.. code-block:: cpp
.. cpp:function:: static Walker *newWalker(Dyninst::PID pid, std::string executable)

static bool newWalker(const std::vector<Dyninst::PID> &pids,
std::vector<Walker *> &walkers_out) static bool newWalker(const
std::vector<Dyninst::PID> &pids, std::vector<Walker *> &walkers_out,
std::string executable)
Creates a third-party walker attached to the process with id ``pid`` and gives it the name ``executable``.

This method attaches to a group of processes and returns a vector of
Walker objects that perform third-party stackwalks. As above, the first
variant takes a list of PIDs and attaches to those processes; the second
variant also specifies the executable binary.
.. danger:: The user is responsible for deallocating the returned value.

.. code-block:: cpp
.. cpp:function:: static Walker *newWalker(Dyninst::PID pid)
Creates a third-party walker attached to the process with id ``pid``.

.. danger:: The user is responsible for deallocating the returned value.

bool walkStack(std::vector<Frame> &stackwalk, Dyninst::THR_ID thread = NULL_THR_ID)
.. cpp:function:: static Walker *newWalker(Dyninst::ProcControlAPI::Process::ptr proc)

This method walks a call stack in the process associated with this
``Walker``. The call stack is returned as a vector of ``Frame`` objects
in stackwalk. The top of the stack is returned in index 0 of stackwalk,
and the bottom of the stack is returned in index ``stackwalk.size()-1``.
Creates a third-party walker attached to the process ``proc``.

A stackwalk can be taken on a specific thread by passing a value in the
thread parameter. If ``thread`` has the value ``NULL_THR_ID``, then a
default thread will be chosen. When doing a third party stackwalk, the
default thread will be the process’ initial thread. When doing a first
party stackwalk, the default thread will be the thread that called
``walkStack``. The default StepperGroup provided to a Walker will
support collecting call stacks from almost all types of functions,
including signal handlers and optimized, frameless functions.
.. danger:: The user is responsible for deallocating the returned value.

This method returns ``true`` on success and ``false`` on failure.
.. cpp:function:: static bool newWalker(const std::vector<Dyninst::PID> &pids, std::vector<Walker *> &walkers_out, std::string executable)

.. code-block:: cpp
For each id in ``pids``, returns in ``walkers_out`` a new third-party walker associated with that process and given the
name ``executable``.

Returns ``false`` on error.

.. danger:: The user is responsible for deallocating the returned values.

bool walkStackFromFrame(std::vector<Frame> &stackwalk, const Frame &frame)
.. cpp:function:: static bool newWalker(const std::vector<Dyninst::PID> &pids, std::vector<Walker *> &walkers_out)

This method walks a call stack starting from the given stack frame,
``frame``. The call stack will be output in the ``stackwalk`` vector,
with frame stored in index 0 of ``stackwalk`` and the bottom of the
stack stored in index ``stackwalk.size()-1``.
For each id in ``pids``, returns in ``walkers_out`` a new third-party walker associated with that process.

Returns ``false`` on error.

.. danger:: The user is responsible for deallocating the returned values.

This method returns ``true`` on success and ``false`` on failure.
.. cpp:function:: static Walker *newWalker(std::string exec_name, const std::vector<std::string> &argv)

.. code-block:: cpp
Creates a third-party walker by launching a process for the executable ``exec_name`` with arguments ``argv``.

bool walkSingleFrame(const Frame &in, Frame &out)
.. danger:: The user is responsible for deallocating the returned value.

This methods walks through single frame, ``in``. Parameter ``out`` will
be set to ``in``\ ’s caller frame.
.. cpp:function:: static Walker *newWalker(ProcessState *proc, StepperGroup *grp = NULL, SymbolLookup *lookup = NULL,\
bool default_steppers = true)

This method returns ``true`` on success and ``false`` on failure.
Creates a walker associated with a running process with state ``proc``, group ``grp``, and symbol lookup ``lookup``.

Return either a first-party and third-party walker, depending on the configuration of ``proc``.

.. code-block:: cpp
.. danger:: The user is responsible for deallocating the returned value.

bool getInitialFrame(Frame &frame, Dyninst::THR_ID thread = NULL_THR_ID)
.. cpp:function:: virtual ~Walker()

This method returns the ``Frame`` object on the top of the stack in
parameter frame. Under ``walkStack``, ``frame`` would be the one
returned in index 0 of the ``stackwalk`` vector. A stack frame can be
found on a specific thread by passing a value in the thread parameter.
If ``thread`` has the value ``NULL_THR_ID``, then a default thread will
be chosen. When doing a third party stackwalk, the default thread will
be the process’ initial thread. When doing a first party stackwalk, the
default thread will be the thread that called ``getInitialFrame``.
.. cpp:function:: static SymbolReaderFactory *getSymbolReader()

This method returns ``true`` on success and ``false`` on failure.
Returns a factory for creating process-specific symbol readers.

.. code-block:: cpp
.. cpp:function:: static void setSymbolReader(SymbolReaderFactory *srf)

bool getAvailableThreads(std::vector<Dyninst::THR_ID> &threads)
Sets the symbol reader factory to ``srf``.

This method returns a vector of threads in the target process upon which
StackwalkerAPI can walk call stacks. The threads are returned in output
parameter ``threads``. Note that this method may return a subset of the
actual threads in the process. For example, when walking call stacks on
the current process, it is only legal to walk the call stack on the
currently running thread. In this case, ``getAvailableThreads`` returns
a vector containing only the current thread.
.. cpp:function:: bool walkStack(std::vector<Frame> &stackwalk, Dyninst::THR_ID thread = NULL_THR_ID)

This method returns ``true`` on success and ``false`` on failure.
Returns in ``stackwalk`` the call stack in either the associated process.

The top of the stack is the first element returned. The bottom of the stack is
the last element.

If ``thread`` is provided, then only the thread with that id is walked. If it is
omitted, then a default thread will be chosen. When doing a third-party stackwalk, the
default thread will be the process’ initial thread. When doing a first-party stackwalk,
the default thread will be the thread that called this function. The default
``StepperGroup`` provided to a Walker will support collecting call stacks from almost
all types of functions, including signal handlers and optimized, frameless functions.

.. code-block:: cpp
Returns ``false`` on failure.

ProcessState *getProcessState() const
.. cpp:function:: bool walkStackFromFrame(std::vector<Frame> &stackwalk, const Frame &frame)

This method returns the ``ProcessState`` object associated with this
``Walker``.
Returns in ``stackwalk`` the call stack starting from the stack frame, ``frame``.

.. code-block:: cpp
Returns ``false`` on failure.

StepperGroup *getStepperGroup() const
.. cpp:function:: bool walkSingleFrame(const Frame &in, Frame &out)

This method returns the ``StepperGroup`` object associated with this
``Walker``.
Walks the single frame ``in``. ``out`` is set to ``in``\ ’s caller frame.

.. code-block:: cpp
Returns ``false`` on failure.

SymbolLookup *getSymbolLookup() const
.. cpp:function:: bool getInitialFrame(Frame &frame, Dyninst::THR_ID thread = NULL_THR_ID)

This method returns the ``SymbolLookup`` object associated with this
``Walker``.
Returns in ``frame`` the top of the stack for thread ``thread``.

If ``thread`` is omitted, then a default thread is chosen. When doing a third-party walk,
the default thread is the process’ initial thread. For a first-party walk, the thread that
called this function is used.

.. code-block:: cpp
Returns ``false`` on error.

bool addStepper(FrameStepper *stepper)
.. cpp:function:: bool getAvailableThreads(std::vector<Dyninst::THR_ID> &threads) const

This method adds a provided FrameStepper to those used by the Walker.
Returns in ``threads`` the threads in the target process that can be walked.

The set of threads may be a subset of the actual threads in the process. For example,
when walking call stacks on the current process, it is only legal to walk the call stack on the
currently running thread. In this case, this function returns only the current thread.

.. code-block:: cpp
Returns ``false`` on error.

static SymbolReaderFactory *getSymbolReader()
.. cpp:function:: ProcessState *getProcessState() const

This method returns a factory for creating process-specific symbol
readers. Unlike the above methods it is global across all Walkers and is
thus defined static.
Returns the ProcessState associated with this walker.

.. code-block:: cpp
.. cpp:function:: SymbolLookup *getSymbolLookup() const

static void setSymbolReader(SymbolReaderFactory *);
Returns the SymbolLookup associated with this walker.

Set the symbol reader factory used when creating ``Walker`` objects.
.. cpp:function:: StepperGroup *getStepperGroup() const

.. code-block:: cpp
Returns the StepperGroup associated with this walker.

static void version(int &major, int &minor, int &maintenance)
.. cpp:function:: bool addStepper(FrameStepper *stepper)

This method returns version information (e.g., 8, 0, 0 for the 8.0
release).
Adds ``stepper`` to the stepper group for this walker.

0 comments on commit fbb77c0

Please sign in to comment.