Finish Patch3_1.
[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*
11 PatchBlock::create(ParseAPI::Block *ib, PatchFunction *f) {
12   return f->object()->getBlock(ib);
13 }
14
15 PatchBlock::PatchBlock(ParseAPI::Block *blk, PatchObject *obj)
16   : block_(blk),   obj_(obj) {
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
40 PatchBlock::getInsns(Insns &insns) const {
41   // Pass through to ParseAPI. They don't have a native interface, so add one.
42   Offset off = block_->start();
43   const unsigned char *ptr =
44     (const unsigned char *)block_->region()->getPtrToInstruction(off);
45   if (ptr == NULL) return;
46   InstructionDecoder d(ptr, size(), block_->obj()->cs()->getArch());
47   while (off < block_->end()) {
48     Instruction::Ptr insn = d.decode();
49     insns[off + obj_->codeBase()] = insn;
50     off += insn->size();
51   }
52 }
53
54 PatchBlock::edgelist&
55 PatchBlock::getSources() {
56   if (srclist_.empty()) {
57     for (ParseAPI::Block::edgelist::iterator iter = block_->sources().begin();
58          iter != block_->sources().end(); ++iter) {
59       PatchEdge *newEdge = obj_->getEdge(*iter, NULL, this);
60       srclist_.push_back(newEdge);
61     }
62   }
63   return srclist_;
64 }
65
66 PatchBlock::edgelist&
67 PatchBlock::getTargets() {
68   if (trglist_.empty()) {
69     for (ParseAPI::Block::edgelist::iterator iter = block_->targets().begin();
70          iter != block_->targets().end(); ++iter) {
71       PatchEdge *newEdge = obj_->getEdge(*iter, this, NULL);
72       trglist_.push_back(newEdge);
73     }
74   }
75   return trglist_;
76 }
77
78 void
79 PatchBlock::removeSourceEdge(PatchEdge *e) {
80   std::vector<PatchEdge *>::iterator iter;
81   if ((iter = std::find(srclist_.begin(), srclist_.end(), e)) != srclist_.end()) {
82     srclist_.erase(iter);
83   }
84 }
85
86 void
87 PatchBlock::removeTargetEdge(PatchEdge *e) {
88   std::vector<PatchEdge *>::iterator iter;
89   if ((iter = std::find(trglist_.begin(), trglist_.end(), e)) != trglist_.end()) {
90     trglist_.erase(iter);
91   }
92 }
93
94
95 bool
96 PatchBlock::isShared() {
97   return containingFuncs() > 1;
98 }
99
100 PatchBlock::~PatchBlock() {
101   for (std::vector<PatchEdge *>::iterator iter = srclist_.begin();
102        iter != srclist_.end(); ++iter) {
103     PatchBlock* blk = (*iter)->source();
104     blk->removeTargetEdge(*iter);
105   }
106   for (std::vector<PatchEdge *>::iterator iter = trglist_.begin();
107        iter != trglist_.end(); ++iter) {
108     PatchBlock* blk = (*iter)->target();
109     blk->removeSourceEdge(*iter);
110   }
111 }
112
113 Address
114 PatchBlock::start() const {
115   return object()->codeBase() + block_->start();
116 }
117
118 Address
119 PatchBlock::end() const {
120   return object()->codeBase() + block_->end();
121 }
122
123 Address
124 PatchBlock::last() const {
125   return object()->codeBase() + block_->lastInsnAddr();
126 }
127
128 Address
129 PatchBlock::size() const {
130   return block_->size();
131 }
132
133 int
134 PatchBlock::containingFuncs() const {
135   return block_->containingFuncs();
136 }
137
138 bool
139 PatchBlock::containsCall() {
140   ParseAPI::Block::edgelist & out_edges = block_->targets();
141   ParseAPI::Block::edgelist::iterator eit = out_edges.begin();
142   for( ; eit != out_edges.end(); ++eit) {
143     if ( ParseAPI::CALL == (*eit)->type() ) {
144       return true;
145     }
146   }
147   return false;
148 }
149
150 bool
151 PatchBlock::containsDynamicCall() {
152   ParseAPI::Block::edgelist & out_edges = block_->targets();
153   ParseAPI::Block::edgelist::iterator eit = out_edges.begin();
154    for( ; eit != out_edges.end(); ++eit) {
155      if ( ParseAPI::CALL == (*eit)->type() && ((*eit)->sinkEdge())) {
156          return true;
157       }
158    }
159    return false;
160 }
161
162 std::string
163 PatchBlock::disassemble() const {
164   stringstream ret;
165   Insns instances;
166   getInsns(instances);
167   for (Insns::iterator iter = instances.begin();
168        iter != instances.end(); ++iter) {
169     ret << "\t" << hex << iter->first << ": " << iter->second->format() << dec << endl;
170   }
171   return ret.str();
172 }
173
174 InstructionAPI::Instruction::Ptr
175 PatchBlock::getInsn(Address a) const {
176    Insns insns;
177    getInsns(insns);
178    return insns[a];
179 }
180
181 std::string
182 PatchBlock::format() const {
183   stringstream ret;
184   ret << "BB["
185       << hex << start()
186       << ","
187       << end() << dec
188       << "]" << endl;
189   return ret.str();
190 }
191
192 PatchFunction*
193 PatchBlock::getFunction(ParseAPI::Function* f) {
194   return function()->object()->getFunc(f);
195 }
196
197 PatchFunction*
198 PatchBlock::function() const { return function_; }
199
200 ParseAPI::Block*
201 PatchBlock::block() const { return block_; }
202
203 PatchObject*
204 PatchBlock::object() const { return obj_; }
205
206 PatchFunction*
207 PatchBlock::getCallee() {
208   PatchBlock::edgelist::iterator it = getTargets().begin();
209   for (; it != getTargets().end(); ++it) {
210     if ((*it)->type() == ParseAPI::CALL) {
211       PatchBlock* trg = (*it)->target();
212       return trg->function();
213     }
214   }
215   return NULL;
216 }