Skip to content

Commit

Permalink
Add dyninstAPI/src/Relocation/Widgets/CFWidget.C
Browse files Browse the repository at this point in the history
  • Loading branch information
hainest committed Apr 3, 2024
1 parent 781d6c5 commit e702183
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 44 deletions.
59 changes: 55 additions & 4 deletions docs/dyninstAPI/developer/Relocation/Widgets/CFWidget.h.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,57 @@ CFWidget.h

.. cpp:class:: CFWidget : public Widget

.. cpp:member:: static const Address Fallthrough
.. cpp:member:: static const Address Taken
.. rubric::
Pick values that don't correspond to actual targets. Skip zero because it's
used all over the place as a null.

.. cpp:member:: static const Address Fallthrough = 1
.. cpp:member:: static const Address Taken = 2

......

.. cpp:type:: boost::shared_ptr<CFWidget> Ptr
.. cpp:type:: std::map<Address, TargetInt *> DestinationMap
.. cpp:function:: static Ptr create(Address addr)

Case 1: an empty trace ender for traces that do not end in a CF-category instruction

.. cpp:function:: static Ptr create(const Widget::Ptr info)

Case 2: wrap a CF-category instruction

.. cpp:function:: bool generate(const codeGen &templ, const RelocBlock *, CodeBuffer &buffer)

We need to create jumps to wherever our successors are
We can assume the addresses returned by our Targets
are valid, since we'll fixpoint until those stabilize.

There are the following cases:

**No explicit control flow/unconditional direct branch**

1. One target
2. Generate a branch unless it's unnecessary

**Conditional branch**

1. Two targets
2. Use stored instruction to generate correct condition
3. Generate a fallthrough "branch" if necessary

**Call**

1. Two targets (call and natural successor)
2. As above, except make sure call bit is flipped on

**Indirect branch**

1. Just go for it... we have no control, really

.. cpp:function:: virtual ~CFWidget()

Don't delete the Targets; they're taken care of when we nuke the overall CFG.

.. cpp:function:: void addDestination(Address index, TargetInt *dest)

Owns the provided dest parameter
Expand Down Expand Up @@ -63,9 +106,13 @@ CFWidget.h
.. cpp:function:: private bool generateBranch(CodeBuffer &gens, TargetInt *to, InstructionAPI::Instruction insn,\
const RelocBlock *trace, bool fallthrough)

These should move to a CodeGenerator class or something... But for now they can go here.
The Instruction input allows pulling out ancillary data (e.g., conditions, prediction, etc.)

We can put in an unconditional branch as an ender for a block that doesn't have a real branch. So if we don't have
an instruction generate a "generic" branch. We can see a problem where we want to branch to (effectively)
the next instruction. So if we ever see that (a branch of offset == size) back up the codeGen and shrink us down.

The Instruction input allows pulling out ancillary data (e.g., conditions, prediction, etc.
These should move to a CodeGenerator class or something... But for now they can go here.

.. cpp:function:: private bool generateCall(CodeBuffer &gens, TargetInt *to, const RelocBlock *trace,\
InstructionAPI::Instruction insn)
Expand All @@ -87,6 +134,10 @@ CFWidget.h
Address e = 0)

.. cpp:function:: private virtual bool apply(codeGen &gen, CodeBuffer *buf)

TODO: find smarter way of telling that we're doing CFG modification, in which
case we don't want to add padding in between blocks

.. cpp:function:: private virtual unsigned estimate(codeGen &templ)
.. cpp:function:: private virtual ~CFPatch()
.. cpp:member:: private Type type
Expand Down
40 changes: 0 additions & 40 deletions dyninstAPI/src/Relocation/Widgets/CFWidget.C
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,14 @@ using namespace Dyninst;
using namespace Relocation;
using namespace InstructionAPI;

///////////////////////

// Pick values that don't correspond to actual targets. I'm skipping
// 0 because it's used all over the place as a null.
const Address CFWidget::Fallthrough(1);
const Address CFWidget::Taken(2);

// Case 1: an empty trace ender for traces that do not
// end in a CF-category instruction
CFWidget::Ptr CFWidget::create(Address a) {
CFWidget::Ptr ptr = Ptr(new CFWidget(a));
return ptr;
}

// Case 2: wrap a CF-category instruction
CFWidget::Ptr CFWidget::create(Widget::Ptr atom) {
CFWidget::Ptr ptr = Ptr(new CFWidget(atom->insn(), atom->addr()));
return ptr;
Expand Down Expand Up @@ -117,24 +110,6 @@ bool CFWidget::generate(const codeGen &,
const RelocBlock *trace,
CodeBuffer &buffer)
{
// We need to create jumps to wherever our successors are
// We can assume the addresses returned by our Targets
// are valid, since we'll fixpoint until those stabilize.
//
// There are the following cases:
//
// No explicit control flow/unconditional direct branch:
// 1) One target
// 2) Generate a branch unless it's unnecessary
// Conditional branch:
// 1) Two targets
// 2) Use stored instruction to generate correct condition
// 3) Generate a fallthrough "branch" if necessary
// Call:
// 1) Two targets (call and natural successor)
// 2) As above, except make sure call bit is flipped on
// Indirect branch:
// 1) Just go for it... we have no control, really
relocation_cerr << "CFWidget generation for " << trace->id() << endl;
if (destMap_.empty() && !isIndirect_) {
// No successors at all? Well, it happens if
Expand Down Expand Up @@ -293,7 +268,6 @@ bool CFWidget::generate(const codeGen &,
}

CFWidget::~CFWidget() {
// Don't delete the Targets; they're taken care of when we nuke the overall CFG.
}

TrackerElement *CFWidget::tracker(const RelocBlock *trace) const {
Expand Down Expand Up @@ -362,14 +336,6 @@ bool CFWidget::generateBranch(CodeBuffer &buffer,
assert(to);
if (!to->necessary()) return true;

// We can put in an unconditional branch as an ender for
// a block that doesn't have a real branch. So if we don't have
// an instruction generate a "generic" branch

// We can see a problem where we want to branch to (effectively)
// the next instruction. So if we ever see that (a branch of offset
// == size) back up the codeGen and shrink us down.

CFPatch *newPatch = new CFPatch(CFPatch::Jump, insn, to, trace->func(), addr_);

if (fallthrough || trace->block() == NULL) {
Expand Down Expand Up @@ -439,10 +405,6 @@ std::string CFWidget::format() const {
return ret.str();
}

/////////////////////////
// Patching!
/////////////////////////

CFPatch::CFPatch(Type a,
Instruction b,
TargetInt *c,
Expand Down Expand Up @@ -479,8 +441,6 @@ PaddingPatch::PaddingPatch(unsigned size, bool registerDefensive, bool noop, blo


bool PaddingPatch::apply(codeGen &gen, CodeBuffer *) {
//TODO: find smarter way of telling that we're doing CFG modification,
// in which case we don't want to add padding in between blocks
if (BPatch_defensiveMode != block_->obj()->hybridMode()) {
bpwarn("WARNING: Disabling post-call block padding %s[%d]\n",FILE__,__LINE__);
return true;
Expand Down

0 comments on commit e702183

Please sign in to comment.