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