consolidate 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     edges.push_back(object()->getEdge(iedge, this, NULL));
63     return;
64   }
65   std::vector<ParseAPI::Function *> ifuncs;
66   iblk->getFuncs(ifuncs);
67   for (unsigned i = 0; i < ifuncs.size(); ++i) {
68     PatchBlock *pblock = object()->getBlock(iblk);
69     assert(pblock);
70     PatchEdge *newEdge = NULL;
71     if (dir == forwards)
72       newEdge = object()->getEdge(iedge, this, pblock);
73     else
74       newEdge = object()->getEdge(iedge, pblock, this);
75
76     edges.push_back(newEdge);
77   }
78   return;
79 }
80
81
82 PatchBlock::edgelist &PatchBlock::getSources() {
83   if (srclist_.empty()) {
84      for (ParseAPI::Block::edgelist::iterator iter = block_->sources().begin();
85            iter != block_->sources().end(); ++iter) {
86          PatchEdge *newEdge = obj_->getEdge(*iter, NULL, this);
87          srclist_.push_back(newEdge);
88       }
89   }
90   return srclist_;
91 }
92
93 PatchBlock::edgelist &PatchBlock::getTargets() {
94   if (trglist_.empty()) {
95     for (ParseAPI::Block::edgelist::iterator iter = block_->targets().begin();
96          iter != block_->targets().end(); ++iter) {
97       PatchEdge *newEdge = obj_->getEdge(*iter, this, NULL);
98       trglist_.push_back(newEdge);
99     }
100   }
101   return trglist_;
102 }
103
104 void PatchBlock::removeSourceEdge(PatchEdge *e) {
105   // This is called as part of teardown
106   // of another Block to remove its edges from our
107   // vectors.
108   for (std::vector<PatchEdge *>::iterator iter = srclist_.begin();
109        iter != srclist_.end(); ++iter) {
110     if ((*iter) == e) {
111       srclist_.erase(iter);
112       return;
113     }
114   }
115 }
116
117 void PatchBlock::removeTargetEdge(PatchEdge *e) {
118   // This is called as part of teardown
119   // of another Block to remove its edges from our
120   // vectors.
121   for (std::vector<PatchEdge *>::iterator iter = trglist_.begin();
122        iter != trglist_.end(); ++iter) {
123     if ((*iter) == e) {
124       trglist_.erase(iter);
125       return;
126     }
127   }
128 }
129
130
131 bool PatchBlock::isShared() {
132   return containingFuncs() > 1;
133 }
134
135 PatchBlock::~PatchBlock() {
136 }
137
138 Address PatchBlock::start() const {
139   return object()->codeBase() + block_->start();
140 }
141
142 Address PatchBlock::end() const {
143   return object()->codeBase() + block_->end();
144 }
145
146 Address PatchBlock::last() const {
147   return object()->codeBase() + block_->lastInsnAddr();
148 }
149
150 Address PatchBlock::size() const {
151   return block_->size();
152 }
153
154 int PatchBlock::containingFuncs() const {
155   return block_->containingFuncs();
156 }
157
158 bool PatchBlock::containsCall() {
159   ParseAPI::Block::edgelist & out_edges = block_->targets();
160   ParseAPI::Block::edgelist::iterator eit = out_edges.begin();
161   for( ; eit != out_edges.end(); ++eit) {
162     if ( ParseAPI::CALL == (*eit)->type() ) {
163       return true;
164     }
165   }
166   return false;
167 }
168
169 bool PatchBlock::containsDynamicCall() {
170   ParseAPI::Block::edgelist & out_edges = block_->targets();
171   ParseAPI::Block::edgelist::iterator eit = out_edges.begin();
172    for( ; eit != out_edges.end(); ++eit) {
173      if ( ParseAPI::CALL == (*eit)->type() && ((*eit)->sinkEdge())) {
174          return true;
175       }
176    }
177    return false;
178 }
179
180 std::string PatchBlock::disassemble() const {
181     stringstream ret;
182     Insns instances;
183     getInsns(instances);
184     for (Insns::iterator iter = instances.begin();
185          iter != instances.end(); ++iter) {
186        ret << "\t" << hex << iter->first << ": " << iter->second->format() << dec << endl;
187     }
188     return ret.str();
189 }
190
191 InstructionAPI::Instruction::Ptr PatchBlock::getInsn(Address a) const {
192    Insns insns;
193    getInsns(insns);
194    return insns[a];
195 }
196
197 std::string PatchBlock::format() const {
198     stringstream ret;
199     ret << "BB["
200         << hex << start()
201         << ","
202         << end() << dec
203         << "]" << endl;
204     return ret.str();
205 }