Clean up PatchAPI public interface code, in preparation for merging into master branch.
[dyninst.git] / patchAPI / src / PatchBlock.C
1 /* Public Interface */
2
3 #include "common.h"
4 #include "PatchCFG.h"
5
6 using namespace Dyninst;
7 using namespace PatchAPI;
8 using namespace InstructionAPI;
9
10 PatchBlock *PatchBlock::create(ParseAPI::Block *ib, PatchFunction *f) {
11   return f->getBlock(ib);
12 }
13
14 void PatchBlock::getInsns(InsnInstances &insns) {
15   // Pass through to ParseAPI. They don't have a native interface, so add one.
16   Offset off = block_->start();
17   const unsigned char *ptr =
18     (const unsigned char *)block_->region()->getPtrToInstruction(off);
19   if (ptr == NULL) return;
20   InstructionDecoder d(ptr, size(), block_->obj()->cs()->getArch());
21   while (off < block_->end()) {
22     insns.push_back(std::make_pair(off, d.decode()));
23     off += insns.back().second->size();
24   }
25 }
26
27 void PatchBlock::createInterproceduralEdges(ParseAPI::Edge *iedge,
28                                             Direction dir,
29                                             std::vector<PatchEdge *> &edges) {
30   // Let pT be the target block in the parseAPI
31   // Let {f_1, ..., f_n} be the functions T is in
32   // We create blocks t_i for each function f_i
33   ParseAPI::Block *iblk = (dir == backwards) ? iedge->src() : iedge->trg();
34   if (!iblk) {
35     assert(dir == forwards); // Can't have sink in-edges
36
37     edges.push_back(PatchEdge::create(iedge, this, NULL));
38     return;
39   }
40   std::vector<ParseAPI::Function *> ifuncs;
41   iblk->getFuncs(ifuncs);
42   for (unsigned i = 0; i < ifuncs.size(); ++i) {
43     PatchFunction *pfunc = object()->getFunction(ifuncs[i]);
44     assert(pfunc);
45     PatchBlock *pblock = pfunc->getBlock(iblk);
46     assert(pblock);
47     PatchEdge *newEdge = NULL;
48     if (dir == forwards)
49       newEdge = PatchEdge::create(iedge, this, pblock);
50     else
51       newEdge = PatchEdge::create(iedge, pblock, this);
52
53     edges.push_back(newEdge);
54   }
55   return;
56 }
57
58
59 const PatchBlock::edgelist &PatchBlock::sources() {
60   if (srcs_.empty()) {
61     for (ParseAPI::Block::edgelist::iterator iter = block_->sources().begin();
62          iter != block_->sources().end(); ++iter) {
63       // We need to copy interprocedural edges to ensure that we de-overlap
64       // code in functions. We do this here.
65       // XXX
66       //if ((*iter)->interproc()) {
67       if ((*iter)->type() == ParseAPI::CALL) {
68         createInterproceduralEdges(*iter, backwards, srcs_);
69       }
70       else {
71         // Can lazily create the source block since it's in
72         // our function.
73         PatchEdge *newEdge = PatchEdge::create(*iter, NULL, this);
74         srcs_.push_back(newEdge);
75       }
76     }
77   }
78   return srclist_;
79 }
80
81 const PatchBlock::edgelist &PatchBlock::targets() {
82   if (trgs_.empty()) {
83     for (ParseAPI::Block::edgelist::iterator iter = block_->targets().begin();
84          iter != block_->targets().end(); ++iter) {
85       // We need to copy interprocedural edges to ensure that we de-overlap
86       // code in functions. We do this here.
87       // XXX: this doesn't work!
88       //         if ((*iter)->interproc()) {
89       if ((*iter)->type() == ParseAPI::CALL) {
90         createInterproceduralEdges(*iter, forwards, trgs_);
91       }
92       else {
93         // Can lazily create the source block since it's in
94         // our function.
95         PatchEdge *newEdge = PatchEdge::create(*iter, this, NULL);
96         trgs_.push_back(newEdge);
97       }
98     }
99   }
100   return trglist_;
101 }
102
103 PatchObjectPtr PatchBlock::object() const {
104   assert(function_);
105   return function_->object();
106 }
107
108 PatchBlock::PatchBlock(ParseAPI::Block *block,
109                        PatchFunction *func)
110    : block_(block),
111      function_(func),
112      srclist_(srcs_),
113      trglist_(trgs_) {};
114
115 void PatchBlock::destroy(PatchBlock *b) {
116   // As a note, deleting edges that source and target this
117   // block is an exercise in delicacy. Make sure you know
118   // what you're doing. For this, we ensure that we always
119   // remove source edges first, and that we can't accidentally
120   // invalidate an iterator.
121   for (std::vector<PatchEdge *>::iterator iter = b->srcs_.begin();
122        iter != b->srcs_.end(); ++iter) {
123     if ((*iter)->src_) {
124       (*iter)->src_->removeTargetEdge(*iter);
125     }
126     PatchEdge::destroy(*iter);
127   }
128   b->srcs_.clear();
129   for (std::vector<PatchEdge *>::iterator iter = b->trgs_.begin();
130        iter != b->trgs_.end(); ++iter) {
131     if ((*iter)->trg_) {
132       (*iter)->trg_->removeSourceEdge(*iter);
133     }
134     PatchEdge::destroy(*iter);
135   }
136   b->trgs_.clear();
137   delete b;
138 }
139
140 void PatchBlock::removeSourceEdge(PatchEdge *e) {
141   // This is called as part of teardown
142   // of another Block to remove its edges from our
143   // vectors.
144   for (std::vector<PatchEdge *>::iterator iter = srcs_.begin();
145        iter != srcs_.end(); ++iter) {
146     if ((*iter) == e) {
147       srcs_.erase(iter);
148       return;
149     }
150   }
151 }
152
153 void PatchBlock::removeTargetEdge(PatchEdge *e) {
154   // This is called as part of teardown
155   // of another Block to remove its edges from our
156   // vectors.
157   for (std::vector<PatchEdge *>::iterator iter = trgs_.begin();
158        iter != trgs_.end(); ++iter) {
159     if ((*iter) == e) {
160       trgs_.erase(iter);
161       return;
162     }
163   }
164 }
165
166
167 bool PatchBlock::isShared() {
168   std::vector<ParseAPI::Function*> funcs;
169   block()->getFuncs(funcs);
170   if (funcs.size() > 1) return true;
171   return false;
172 }
173 PatchBlock::~PatchBlock() {
174   // We assume top-down teardown of data
175   //   assert(srcs_.empty());
176   //   assert(trgs_.empty());
177 }
178
179 PatchBlock* PatchBlock::convert(int_block* /*ib*/) {
180   return NULL;
181 }