Skip to content

Commit

Permalink
Add stackwalk/procstate.h
Browse files Browse the repository at this point in the history
  • Loading branch information
hainest committed Apr 3, 2024
1 parent f5055be commit 3f3d671
Show file tree
Hide file tree
Showing 5 changed files with 298 additions and 319 deletions.
1 change: 1 addition & 0 deletions docs/stackwalk/developer/API.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Stackwalker
libstate.h
linuxbsd-swk.h
linux-swk.h
procstate.h
sw.h
symtab-swk.h
x86-swk.h
119 changes: 119 additions & 0 deletions docs/stackwalk/developer/procstate.h.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
.. _`sec-dev:procstate.h`:

procstate.h
###########

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

.. note::

| TODO: isRunning(), isStopped()...
| TODO: Bug if trying to stop an already stopped process

.. cpp:class:: ProcessState

.. cpp:member:: protected Dyninst::PID pid
.. cpp:member:: protected std::string exec_path
.. cpp:member:: protected LibraryState *library_tracker
.. cpp:member:: protected Walker *walker
.. cpp:member:: protected static std::map<Dyninst::PID, ProcessState *> proc_map
.. cpp:member:: protected std::string executable_path

.. cpp:function:: protected ProcessState(Dyninst::PID pid_ = 0, std::string executable_path_ = std::string(""))
.. cpp:function:: protected void setPid(Dyninst::PID pid_)

.. cpp:function:: void setDefaultLibraryTracker()
.. cpp:function:: virtual LibraryState *getLibraryTracker()

.. cpp:function:: virtual bool preStackwalk(Dyninst::THR_ID tid)

Allow initialization

.. cpp:function:: virtual bool postStackwalk(Dyninst::THR_ID tid)

Allow uninitialization


.. cpp:class:: ProcDebug : public ProcessState

Access to StackwalkerAPI’s debugger is through the ``ProcDebug`` class,
which inherits from the ``ProcessState`` interface.

.. cpp:member:: protected Dyninst::ProcControlAPI::Process::ptr proc
.. cpp:member:: protected std::set<Dyninst::ProcControlAPI::Thread::ptr> needs_resume

.. cpp:function:: protected ProcDebug(Dyninst::ProcControlAPI::Process::ptr p)


.. cpp:class:: LibraryState

``LibraryState`` is a helper class for ``ProcessState`` that provides
information about the current DSOs (libraries and executables) that are
loaded into a process’ address space. FrameSteppers frequently use the
LibraryState to get the DSO through which they are attempting to stack
walk.

Each ``Library`` is represented using a ``LibAddrPair`` object, which is
defined as follows:

Class providing interfaces for library tracking. Only the public query
interfaces below are user-facing; the other public methods are callbacks
that allow StackwalkerAPI to update its internal state.

.. cpp:member:: protected ProcessState *procstate
.. cpp:member:: protected std::vector<std::pair<LibAddrPair, unsigned int> > arch_libs

.. cpp:function:: LibraryState(ProcessState *parent)

.. cpp:function:: virtual bool getLibraryAtAddr(Address addr, LibAddrPair &lib) = 0

Given an address ``addr`` in the target process, returns ``true`` and
sets ``lib`` to the name and base address of the library containing
addr. Given an address outside the target process, returns ``false``.

.. cpp:function:: virtual bool getLibraries(std::vector<LibAddrPair> &libs, bool allow_refresh = true) = 0

Fills ``libs`` with the libraries loaded in the target process. If
``allow_refresh`` is true, this method will attempt to ensure that this
list is freshly updated via inspection of the process; if it is false,
it will return a cached list.

.. cpp:function:: virtual void notifyOfUpdate() = 0

This method is called by the ``ProcessState`` when it detects a change
in the process’ list of loaded libraries. Implementations of
``LibraryStates`` should use this method to refresh their lists of
loaded libraries.

.. cpp:function:: virtual Address getLibTrapAddress() = 0

Some platforms that implement the System/V standard (Linux) use a trap
event to determine when a process loads a library. A trap instruction is
inserted into a certain address, and that trap will execute whenever the
list of loaded libraries change.

On System/V platforms this method should return the address where a trap
should be inserted to watch for libraries loading and unloading. The
ProcessState object will insert a trap at this address and then call
notifyOfUpdate when that trap triggers.

On non-System/V platforms this method should return 0.

.. cpp:function:: virtual bool getLibc(LibAddrPair &lc)

Convenience function to find the name and base address of the standard C
runtime, if present.

.. cpp:function:: virtual bool getLibthread(LibAddrPair &lt)

Convenience function to find the name and base address of the standard
thread library, if present (e.g. pthreads).

.. cpp:function:: virtual bool getAOut(LibAddrPair &ao) = 0

Convenience function to find the name and base address of the
executable.

.. cpp:function:: virtual bool updateLibsArch(std::vector<std::pair<LibAddrPair, unsigned int> > &alibs)
27 changes: 18 additions & 9 deletions docs/stackwalk/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,22 @@ Target Process
Host Process
The process in which StackwalkerAPI code is currently running.

.. _`topic:stackwalk-first-party`:

First Party Stackwalk
StackwalkerAPI collects first party stackwalk when it walks a call
stack in the same address space it is running in, i.e. the target
process is the same as the host process.

.. _`topic:stackwalk-third-party`:

Third Party Stackwalk
StackwalkerAPI collects third party stackwalk when it walks the call
stack in a different address space from the one it is running in,
i.e. the target process is different from the host process. A third
party stackwalk is usually done through a debugger interface.


Stackwalking Interface
----------------------

Expand Down Expand Up @@ -465,6 +470,10 @@ use the default implementations listed in Table `1 <#table:defaults>`__.
These implementations are described in Section
`4.2 <#sec:framesteppers>`__.

StackwalkerAPI provides two default types
of ``ProcessState`` objects: ``ProcSelf`` does a first party stackwalk,
and ``ProcDebug`` does a third party stackwalk.

.. container::
:name: table:defaults

Expand Down Expand Up @@ -515,13 +524,13 @@ thread.
:language: cpp
:linenos:

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:

.. code-block:: cpp
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). The easiest way to get at a :cpp:class:`ProcDebug` is to cast the return value of
:cpp:func:`Walker::getProcessState`.

auto *walker = sw::Walker::newWalker(pid);
..
rli:: https://raw.githubusercontent.com/dyninst/examples/master/stackwalker/determineWalkerParty.cpp
:language: cpp
:linenos:

0 comments on commit 3f3d671

Please sign in to comment.