consolidate function interface
[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->object()->getBlock(ib);
12 }
13
14 PatchBlock::PatchBlock(ParseAPI::Block *block,
15                        PatchFunction *func)
16    : block_(block),
17      function_(func),
18      srclist_(srcs_),
19      trglist_(trgs_),
20      obj_(func->object()) {
21 }
22
23 PatchBlock::PatchBlock(ParseAPI::Block *blk, PatchObject *obj)
24   : block_(blk),  srclist_(srcs_), trglist_(trgs_), obj_(obj) {
25
26   ParseAPI::CodeObject::funclist& all = obj->co()->funcs();
27   for (ParseAPI::CodeObject::funclist::iterator fit = all.begin();
28        fit != all.end(); ++fit) {
29     if ((*fit)->contains(blk)) {
30       function_ = obj->getFunc(*fit);
31       break;
32     }
33   }
34 }
35
36 PatchBlock::PatchBlock(const PatchBlock *parent, PatchObject *child)
37   : block_(parent->block_), srclist_(srcs_), trglist_(trgs_), obj_(child) {
38
39   ParseAPI::CodeObject::funclist& all = child->co()->funcs();
40   for (ParseAPI::CodeObject::funclist::iterator fit = all.begin();
41        fit != all.end(); ++fit) {
42     if ((*fit)->contains(block_)) {
43       function_ = child->getFunc(*fit);
44       break;
45     }
46   }
47 }
48
49 void PatchBlock::getInsns(Insns &insns) const {
50   // Pass through to ParseAPI. They don't have a native interface, so add one.
51   Offset off = block_->start();
52   const unsigned char *ptr =
53     (const unsigned char *)block_->region()->getPtrToInstruction(off);
54   if (ptr == NULL) return;
55   InstructionDecoder d(ptr, size(), block_->obj()->cs()->getArch());
56   while (off < block_->end()) {
57     Instruction::Ptr insn = d.decode();
58     insns[off + obj_->codeBase()] = insn;
59     off += insn->size();
60   }
61 }
62
63 void PatchBlock::createInterproceduralEdges(ParseAPI::Edge *iedge,
64                                             Direction dir,
65                                             std::vector<PatchEdge *> &edges) {
66   // Let pT be the target block in the parseAPI
67   // Let {f_1, ..., f_n} be the functions T is in
68   // We create blocks t_i for each function f_i
69   ParseAPI::Block *iblk = (dir == backwards) ? iedge->src() : iedge->trg();
70   if (!iblk) {
71     assert(dir == forwards); // Can't have sink in-edges
72
73     edges.push_back(PatchEdge::create(iedge, this, NULL));
74     return;
75   }
76   std::vector<ParseAPI::Function *> ifuncs;
77   iblk->getFuncs(ifuncs);
78   for (unsigned i = 0; i < ifuncs.size(); ++i) {
79     PatchFunction *pfunc = object()->getFunc(ifuncs[i]);
80     PatchBlock *pblock = object()->getBlock(iblk);
81     assert(pblock);
82     PatchEdge *newEdge = NULL;
83     if (dir == forwards)
84       newEdge = PatchEdge::create(iedge, this, pblock);
85     else
86       newEdge = PatchEdge::create(iedge, pblock, this);
87
88     edges.push_back(newEdge);
89   }
90   return;
91 }
92
93
94 PatchBlock::edgelist &PatchBlock::sources() {
95   if (srcs_.empty()) {
96     for (ParseAPI::Block::edgelist::iterator iter = block_->sources().begin();
97          iter != block_->sources().end(); ++iter) {
98       // We need to copy interprocedural edges to ensure that we de-overlap
99       // code in functions. We do this here.
100       // XXX
101       //if ((*iter)->interproc()) {
102       if ((*iter)->type() == ParseAPI::CALL) {
103         createInterproceduralEdges(*iter, backwards, srcs_);
104       }
105       else {
106         // Can lazily create the source block since it's in
107         // our function.
108         PatchEdge *newEdge = PatchEdge::create(*iter, NULL, this);
109         srcs_.push_back(newEdge);
110       }
111     }
112   }
113   return srclist_;
114 }
115
116 PatchBlock::edgelist &PatchBlock::targets() {
117   if (trgs_.empty()) {
118     for (ParseAPI::Block::edgelist::iterator iter = block_->targets().begin();
119          iter != block_->targets().end(); ++iter) {
120       // We need to copy interprocedural edges to ensure that we de-overlap
121       // code in functions. We do this here.
122       // XXX: this doesn't work!
123       //         if ((*iter)->interproc()) {
124       if ((*iter)->type() == ParseAPI::CALL) {
125         createInterproceduralEdges(*iter, forwards, trgs_);
126       }
127       else {
128         // Can lazily create the source block since it's in
129         // our function.
130         PatchEdge *newEdge = PatchEdge::create(*iter, this, NULL);
131         trgs_.push_back(newEdge);
132       }
133     }
134   }
135   return trglist_;
136 }
137
138 void PatchBlock::removeSourceEdge(PatchEdge *e) {
139   // This is called as part of teardown
140   // of another Block to remove its edges from our
141   // vectors.
142   for (std::vector<PatchEdge *>::iterator iter = srcs_.begin();
143        iter != srcs_.end(); ++iter) {
144     if ((*iter) == e) {
145       srcs_.erase(iter);
146       return;
147     }
148   }
149 }
150
151 void PatchBlock::removeTargetEdge(PatchEdge *e) {
152   // This is called as part of teardown
153   // of another Block to remove its edges from our
154   // vectors.
155   for (std::vector<PatchEdge *>::iterator iter = trgs_.begin();
156        iter != trgs_.end(); ++iter) {
157     if ((*iter) == e) {
158       trgs_.erase(iter);
159       return;
160     }
161   }
162 }
163
164
165 bool PatchBlock::isShared() {
166   return containingFuncs() > 1;
167 }
168
169 PatchBlock::~PatchBlock() {
170 }
171
172 Address PatchBlock::start() const {
173   return object()->codeBase() + block_->start();
174 }
175
176 Address PatchBlock::end() const {
177   return object()->codeBase() + block_->end();
178 }
179
180 Address PatchBlock::last() const {
181   return object()->codeBase() + block_->lastInsnAddr();
182 }
183
184 Address PatchBlock::size() const {
185   return block_->size();
186 }
187
188 int PatchBlock::containingFuncs() const {
189   return block_->containingFuncs();
190 }
191
192 bool PatchBlock::containsCall() {
193   ParseAPI::Block::edgelist & out_edges = block_->targets();
194   ParseAPI::Block::edgelist::iterator eit = out_edges.begin();
195   for( ; eit != out_edges.end(); ++eit) {
196     if ( ParseAPI::CALL == (*eit)->type() ) {
197       return true;
198     }
199   }
200   return false;
201 }
202
203 bool PatchBlock::containsDynamicCall() {
204   ParseAPI::Block::edgelist & out_edges = block_->targets();
205   ParseAPI::Block::edgelist::iterator eit = out_edges.begin();
206    for( ; eit != out_edges.end(); ++eit) {
207      if ( ParseAPI::CALL == (*eit)->type() && ((*eit)->sinkEdge())) {
208          return true;
209       }
210    }
211    return false;
212 }
213
214 std::string PatchBlock::disassemble() const {
215     stringstream ret;
216     Insns instances;
217     getInsns(instances);
218     for (Insns::iterator iter = instances.begin();
219          iter != instances.end(); ++iter) {
220        ret << "\t" << hex << iter->first << ": " << iter->second->format() << dec << endl;
221     }
222     return ret.str();
223 }
224
225 InstructionAPI::Instruction::Ptr PatchBlock::getInsn(Address a) const {
226    Insns insns;
227    getInsns(insns);
228    return insns[a];
229 }
230
231 std::string PatchBlock::format() const {
232     stringstream ret;
233     ret << "BB["
234         << hex << start()
235         << ","
236         << end() << dec
237         << "]" << endl;
238     return ret.str();
239 }