Skip to content

Commit

Permalink
Add patchAPI/PatchCallback.h
Browse files Browse the repository at this point in the history
  • Loading branch information
hainest committed Apr 3, 2024
1 parent 3834ee7 commit 5c8e720
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 104 deletions.
43 changes: 40 additions & 3 deletions docs/patchAPI/developer/ParseCallback.h.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,44 @@
.. _`sec:patchapi-ParseCallback.h.rst`:
.. _`sec-dev:ParseCallback.h`:

ParseCallback.h
===============
###############

.. cpp:namespace:: Dyninst::patchAPI
.. cpp:namespace:: Dyninst::PatchAPI

.. cpp:class:: PatchParseCallback : public ParseAPI::ParseCallback

**A wrapper around a ParseAPI::ParseCallback**

.. cpp:function:: PatchParseCallback(PatchObject *obj)

Creates a patch wrapper around the object ``obj``.

.. cpp:function:: protected virtual void split_block_cb(ParseAPI::Block*, ParseAPI::Block*)
.. cpp:function:: protected virtual void destroy_cb(ParseAPI::Block*)
.. cpp:function:: protected virtual void destroy_cb(ParseAPI::Edge*)
.. cpp:function:: protected virtual void destroy_cb(ParseAPI::Function*)
.. cpp:function:: protected virtual void modify_edge_cb(ParseAPI::Edge*, ParseAPI::Block*, edge_type_t)
.. cpp:function:: protected virtual void remove_edge_cb(ParseAPI::Block*, ParseAPI::Edge*, edge_type_t)
.. cpp:function:: protected virtual void add_edge_cb(ParseAPI::Block*, ParseAPI::Edge*, edge_type_t)
.. cpp:function:: protected virtual void remove_block_cb(ParseAPI::Function*, ParseAPI::Block*)
.. cpp:function:: protected virtual void add_block_cb(ParseAPI::Function*, ParseAPI::Block*)
.. cpp:function:: protected virtual bool absAddr(Address absolute, Address& loadAddr, ParseAPI::CodeObject*& containerObject)

Notes
=====

PatchAPI uses the ParseAPI CFG to construct its own CFG, which
means that we need to be notified of any changes in the underlying
CFG. These changes can come from a number of sources, including
the PatchAPI modification interface or a self-modifying binary.

The PatchAPI modification chain looks like the following:

1) User requests PatchAPI to modify the CFG;
2) PatchAPI makes the corresponding request to ParseAPI;
3) ParseAPI modifies its CFG, triggering "modified CFG" callbacks;
4) PatchAPI hooks these callbacks and updates its structures.

This is much easier than PatchAPI modifying them a priori, because
it allows for self-modifying code (which skips step 2) to work
with the exact same chain of events.
252 changes: 172 additions & 80 deletions docs/patchAPI/public/PatchCallback.h.rst
Original file line number Diff line number Diff line change
@@ -1,81 +1,173 @@
.. _`sec:PatchCallback.h`:

PatchCallback.h
===============

.. cpp:namespace:: Dyninst::patchAPI

PatchCallback
=============

**Declared in**: PatchCallback.h

The PatchAPI CFG layer may change at runtime due to program events
(e.g., a program loading additional code or overwriting its own code
with new code). The ``PatchCallback`` interface allows users to specify
callbacks they wish to occur whenever the PatchAPI CFG changes.

.. code-block:: cpp
virtual void destroy_cb(PatchBlock *); virtual void
destroy_cb(PatchEdge *); virtual void destroy_cb(PatchFunction *);
virtual void destroy_cb(PatchObject *);
Programmers implement the above virtual methods to handle the event of
destroying a PatchBlock, a PatchEdge, a PatchFunction, or a PatchObject
respectively. All the above methods will be called before corresponding
object destructors are called.

.. code-block:: cpp
virtual void create_cb(PatchBlock *); virtual void create_cb(PatchEdge
*); virtual void create_cb(PatchFunction *); virtual void
create_cb(PatchObject *);
Programmers implement the above virtual methods to handle the event of
creating a PatchBlock, a PatchEdge, a PatchFunction, or a PatchObject
respectively. All the above methods will be called after the objects are
created.

.. code-block:: cpp
virtual void split_block_cb(PatchBlock *first, PatchBlock *second);
Programmers implement the above virtual method to handle the event of
splitting a PatchBlock as a result of a new edge being discovered. The
above method will be called after the block is split.

.. code-block:: cpp
virtual void remove_edge_cb(PatchBlock *, PatchEdge *, edge_type_t);
virtual void add_edge_cb(PatchBlock *, PatchEdge *, edge_type_t);
Programmers implement the above virtual methods to handle the events of
removing or adding an PatchEdge respectively. The method remove_edge_cb
will be called before the event triggers, while the method add_edge_cb
will be called after the event triggers.

.. code-block:: cpp
virtual void remove_block_cb(PatchFunction *, PatchBlock *); virtual
void add_block_cb(PatchFunction *, PatchBlock *);
Programmers implement the above virtual methods to handle the events of
removing or adding a PatchBlock respectively. The method remove_block_cb
will be called before the event triggers, while the method add_block_cb
will be called after the event triggers.

.. code-block:: cpp
virtual void create_cb(Point *pt); virtual void destroy_cb(Point *pt);
Programmers implement the create_cb method above, which will be called
after the Point *pt* is created. And, programmers implement the
destroy_cb method, which will be called before the point *pt* is
deleted.

.. code-block:: cpp
virtual void change_cb(Point *pt, PatchBlock *first, PatchBlock *second);
Programmers implement this method, which is to be invoked after a block
is split. The provided Point belonged to the first block and is being
moved to the second.
###############

.. cpp:namespace:: Dyninst::PatchAPI

.. cpp:class:: PatchCallback

**A callback invoked when the CFG changes**

The PatchAPI CFG layer may change at runtime due to program events
(e.g., a program loading additional code or overwriting its own code
with new code). The ``PatchCallback`` interface allows users to specify
callbacks they wish to occur whenever the PatchAPI CFG changes.

.. cpp:enum:: edge_type_t

.. cpp:enumerator:: source
.. cpp:enumerator:: target

.. important:: Users should only override the ``_cb`` member functions.

.. cpp:function:: protected virtual void destroy_cb(PatchBlock* b)

Invoked immediately before ``b``\ 's destructor is run.

.. cpp:function:: protected virtual void destroy_cb(PatchEdge* e, PatchObject* o)

Invoked immediately before ``e``\ 's destructor is run.

.. cpp:function:: protected virtual void destroy_cb(PatchFunction* f)

Invoked immediately before ``f``\ 's destructor is run.

.. cpp:function:: protected virtual void destroy_cb(PatchObject* o)

Invoked immediately before ``o``\ 's destructor is run.

.. cpp:function:: protected virtual void create_cb(PatchBlock* b)

Invoked immediately after ``b``\ 's constructor is run.

.. cpp:function:: protected virtual void create_cb(PatchEdge* e)

Invoked immediately after ``e``\ 's constructor is run.

.. cpp:function:: protected virtual void create_cb(PatchFunction* f)

Invoked immediately after ``f``\ 's constructor is run.

.. cpp:function:: protected virtual void create_cb(PatchObject* o)

Invoked immediately after ``o``\ 's constructor is run.

.. cpp:function:: protected virtual void split_block_cb(PatchBlock* first, PatchBlock* second)

Invoked after a block is split into ``first`` and ``second``.

.. cpp:function:: protected virtual void remove_edge_cb(PatchBlock* b, PatchEdge* e, edge_type_t t)

Invoked before the edge ``e`` of type ``t`` is removed from the block ``b``.

.. cpp:function:: protected virtual void add_edge_cb(PatchBlock* b, PatchEdge* e, edge_type_t t)

Invoked after the edge ``e`` of type ``t`` is added to the block ``b``.

.. cpp:function:: protected virtual void remove_block_cb(PatchFunction* f, PatchBlock* b)

Invoked after the block ``b`` is removed from function ``f``.

.. cpp:function:: protected virtual void add_block_cb(PatchFunction* f, PatchBlock* b)

Invoked before the block ``b`` is added to function ``f``.

.. cpp:function:: protected virtual void create_cb(Point* pt)

Invoked after the point ``pt`` is created.

.. cpp:function:: protected virtual void destroy_cb(Point* pt)

Invoked before the point ``pt`` is destroyed.

.. cpp:function:: protected virtual void change_cb(Point* pt, PatchBlock* first, PatchBlock* second)

Invoked after a block is split.

``pt`` belongs to the block ``first`` and is being moved to the block ``second``.

.. cpp:function:: void destroy(PatchBlock* b)

Invokes :cpp:func:`destroy_cb` and destroys the block ``b``.

.. cpp:function:: void destroy(PatchEdge* e, PatchObject* owner)

Invokes :cpp:func:`destroy_cb` and destroys the edge ``e`` owned by ``owner``.

.. cpp:function:: void destroy(PatchFunction* f)

Invokes :cpp:func:`destroy_cb` and destroys the function ``f``.

.. cpp:function:: void destroy(PatchObject* o)

Invokes :cpp:func:`destroy_cb` and destroys the object ``o``.

.. cpp:function:: void create(PatchBlock* b)

Invokes :cpp:func:`create_cb` for the block ``b``.

.. cpp:function:: void create(PatchEdge* e)

Invokes :cpp:func:`create_cb` for the edge ``e``.

.. cpp:function:: void create(PatchFunction* f)

Invokes :cpp:func:`create_cb` for the function ``f``.

.. cpp:function:: void create(PatchObject* o)

Invokes :cpp:func:`create_cb` for the object ``o``.

.. cpp:function:: void split_block(PatchBlock* b1, PatchBlock* b2)

Invokes :cpp:func:`split_block_cb` when a block is split into ``b1`` and ``b1``.

.. cpp:function:: void remove_edge(PatchBlock* b, PatchEdge* e, edge_type_t t)

Invokes :cpp:func:`remove_edge_cb` when the edge ``e`` of type ``t`` is removed from ``b``.

.. cpp:function:: void add_edge(PatchBlock* b, PatchEdge* e, edge_type_t t)

Invokes :cpp:func:`add_edge_cb` when the edge ``e`` of type ``t`` is added to ``b``.

.. cpp:function:: void remove_block(PatchFunction* f, PatchBlock* b)

Invokes :cpp:func:`remove_block_cb` when the block ``b`` is removed from ``f``.

.. cpp:function:: void add_block(PatchFunction* f, PatchBlock* b)

Invokes :cpp:func:`add_block_cb` when the block ``b`` is added to ``f``.

.. cpp:function:: void destroy(Point* p)

Invokes :cpp:func:`destroy_cb` when ``p`` is destroyed.

.. cpp:function:: void create(Point* p)

Invokes :cpp:func:`destroy_cb` when ``p`` is created.

.. cpp:function:: void change(Point* p, PatchBlock* first, PatchBlock *second)

Invokes :cpp:func:`change_cb` when after a block is split.

``pt`` belongs to the block ``first`` and is being moved to the block ``second``.

.. cpp:function:: void batch_begin()

Starts batching.

.. cpp:function:: void batch_end()

Terminates batching.

Batching
========

Instead of invoking a callback for each event when it happens, the user can accumulate *all*
callback invocations and then request their invocation. This is referred to as ``batching``.
:cpp:func:`PatchCallback::batch_begin()` enables batching :cpp:func:`PatchCallback::batch_end()`
terminates batching and invokes all outstanding callbacks. Users can enable and disable batching
at any time. This can be useful for reducing overhead of creating many objects at once. However,
calling ``batch_end`` always invokes all outstanding callbacks. It is not possible to ignore
callback invocations.
7 changes: 2 additions & 5 deletions patchAPI/h/PatchCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ class PATCHAPI_EXPORT PatchCallback {
source,
target } edge_type_t;

// Users override these to provide their callbacks
protected:
virtual void destroy_cb(PatchBlock *) {}
virtual void destroy_cb(PatchEdge *, PatchObject * /*owner*/) {}
Expand All @@ -72,7 +71,6 @@ class PATCHAPI_EXPORT PatchCallback {
virtual void create_cb(PatchFunction *) {}
virtual void create_cb(PatchObject *) {}

// Some more abstract ones
virtual void split_block_cb(PatchBlock *, PatchBlock *) {}

virtual void remove_edge_cb(PatchBlock *, PatchEdge *, edge_type_t) {}
Expand All @@ -81,14 +79,13 @@ class PATCHAPI_EXPORT PatchCallback {
virtual void remove_block_cb(PatchFunction *, PatchBlock *) {}
virtual void add_block_cb(PatchFunction *, PatchBlock *) {}

// Points
virtual void destroy_cb(Point *) {}
virtual void create_cb(Point *) {}
// If we split a block, we may change the block a Point belongs to.

virtual void change_cb(Point *, PatchBlock *, PatchBlock *) {}

public:
// And these methods are used by PatchAPI and should not be overridden.

void batch_begin();
void batch_end();

Expand Down
16 changes: 0 additions & 16 deletions patchAPI/src/ParseCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,6 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* PatchAPI uses the ParseAPI CFG to construct its own CFG, which
means that we need to be notified of any changes in the underlying
CFG. These changes can come from a number of sources, including
the PatchAPI modification interface or a self-modifying binary.
The PatchAPI modification chain looks like the following:
1) User requests PatchAPI to modify the CFG;
2) PatchAPI makes the corresponding request to ParseAPI;
3) ParseAPI modifies its CFG, triggering "modified CFG" callbacks;
4) PatchAPI hooks these callbacks and updates its structures.
This is much easier than PatchAPI modifying them a priori, because
it allows for self-modifying code (which skips step 2) to work
with the exact same chain of events.
*/

#if !defined(_PATCHAPI_CALLBACK_H_)
#define _PATCHAPI_CALLBACK_H_
Expand All @@ -59,7 +44,6 @@ class PatchParseCallback : public ParseAPI::ParseCallback {
~PatchParseCallback() {}

protected:
// Callbacks we want to know about: CFG mangling
virtual void split_block_cb(ParseAPI::Block *, ParseAPI::Block *);
virtual void destroy_cb(ParseAPI::Block *);
virtual void destroy_cb(ParseAPI::Edge *);
Expand Down

0 comments on commit 5c8e720

Please sign in to comment.