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