After tested under windows.
[dyninst.git] / patchAPI / src / Point.C
1 /* Public Interface */
2
3 #include "Point.h"
4 #include "PatchMgr.h"
5 #include "PatchObject.h"
6 #include "PatchCFG.h"
7
8 using Dyninst::PatchAPI::Instance;
9 using Dyninst::PatchAPI::InstancePtr;
10 using Dyninst::PatchAPI::Point;
11 using Dyninst::PatchAPI::PatchFunction;
12 using Dyninst::PatchAPI::PointMaker;
13 using Dyninst::ParseAPI::CodeObject;
14 using Dyninst::ParseAPI::CodeSource;
15 using Dyninst::ParseAPI::CodeRegion;
16 using Dyninst::InstructionAPI::InstructionDecoder;
17 using Dyninst::PatchAPI::SnippetPtr;
18 using Dyninst::PatchAPI::SnippetType;
19 using Dyninst::PatchAPI::PatchMgrPtr;
20 using Dyninst::PatchAPI::SnippetState;
21 using Dyninst::PatchAPI::PatchBlock;
22 using Dyninst::PatchAPI::PatchEdge;
23
24 InstancePtr
25 Instance::create(Point* point, SnippetPtr snippet,
26     SnippetType type, SnippetState state) {
27   InstancePtr ret = InstancePtr(new Instance(point, snippet));
28   if (!ret) return InstancePtr();
29   ret->state_ = state;
30   ret->type_ = type;
31   return ret;
32 }
33
34 bool
35 Instance::destroy() {
36   if (point_) {
37     bool ret = point_->remove(shared_from_this());
38     return ret;
39   }
40   return false;
41 }
42
43 /* If the Point is PreCall or PostCall */
44 PatchFunction*
45 Point::getCallee() {
46   if (type() != PreCall && type() != PostCall) return NULL;
47   PatchBlock* b = (*(inst_blks_.begin()));
48   PatchBlock::edgelist::iterator it = b->getTargets().begin();
49   for (; it != b->getTargets().end(); ++it) {
50     if ((*it)->type() == ParseAPI::CALL) {
51       PatchBlock* trg = (*it)->target();
52       return trg->function();
53     }
54   }
55   return NULL;
56 }
57
58 /* Associate this point with the block(s) and function(s)
59    that contain it */
60 void
61 Point::initCodeStructure() {
62   assert(mgr_);
63   // walk through all code objects
64   for (AddrSpace::ObjSet::iterator ci = mgr_->as()->objSet().begin();
65        ci != mgr_->as()->objSet().end(); ci++) {
66     PatchObject* obj = *ci;
67     CodeObject* co = obj->co();
68     CodeSource* cs = obj->cs();
69     Address relative_addr = addr_ - obj->codeBase();
70     vector<CodeRegion*> regions = cs->regions();
71     for (vector<CodeRegion*>::iterator ri = regions.begin(); ri != regions.end(); ri++) {
72       std::set<ParseAPI::Function*> parseapi_funcs;
73       co->findFuncs(*ri, relative_addr, parseapi_funcs);
74       std::set<ParseAPI::Block*> parseapi_blks;
75       co->findBlocks(*ri, relative_addr, parseapi_blks);
76
77       for (std::set<ParseAPI::Function*>::iterator fi = parseapi_funcs.begin();
78            fi != parseapi_funcs.end(); fi++) {
79         PatchFunction* func = obj->getFunc(*fi);
80         inst_funcs_.insert(func);
81       } // Function
82       for (std::set<ParseAPI::Block*>::iterator bi = parseapi_blks.begin();
83            bi != parseapi_blks.end(); bi++) {
84         PatchBlock* blk = obj->getBlock(*bi);
85         inst_blks_.insert(blk);
86       } // Block
87     } // Region
88     if (inst_blks_.size() > 0) {
89       co_ = co;
90       cs_ = cs;
91       obj_ = obj;
92       InstructionDecoder d(cs_->getPtrToInstruction(relative_addr),
93                           cs_->length(),
94                           cs_->getArch());
95       // Get the instruction that contain this point
96       insn_ = d.decode();
97       break;
98     }
99   }
100   if (!the_block_) the_block_ = *inst_blks_.begin();
101   if (!the_func_) the_func_ = *inst_funcs_.begin();
102 }
103
104 /* for single instruction */
105 Point::Point(Address addr, Point::Type type, PatchMgrPtr mgr, Address*)
106   :addr_(addr), type_(type), mgr_(mgr), the_block_(NULL), the_edge_(NULL), the_func_(NULL) {
107   initCodeStructure();
108 }
109
110 /* for a block */
111 Point::Point(Address addr, Type type, PatchMgrPtr mgr, PatchBlock* blk)
112   : addr_(addr), type_(type), mgr_(mgr), the_block_(blk), the_edge_(NULL), the_func_(NULL) {
113   initCodeStructure();
114 }
115
116 /* for an edge */
117 Point::Point(Address addr, Type type, PatchMgrPtr mgr, PatchEdge* edge)
118   : addr_(addr), type_(type), mgr_(mgr), the_block_(NULL), the_edge_(edge), the_func_(NULL) {
119   initCodeStructure();
120 }
121
122 /* for a function */
123 Point::Point(Address addr, Type type, PatchMgrPtr mgr,
124              PatchFunction* func) : addr_(addr), type_(type), mgr_(mgr),
125                                     the_block_(NULL), the_edge_(NULL), the_func_(func) {
126   initCodeStructure();
127 }
128
129 /* old_instance, old_instance, <---new_instance */
130 InstancePtr
131 Point::pushBack(SnippetPtr snippet) {
132   InstancePtr instance = Instance::create(this, snippet);
133   if (!instance) return instance;
134   instanceList_.push_back(instance);
135   instance->set_state(INSERTED);
136   return instance;
137 }
138
139 /* new_instance--->, old_instance, old_instance */
140 InstancePtr
141 Point::pushFront(SnippetPtr snippet) {
142   InstancePtr instance = Instance::create(this, snippet);
143   if (!instance) return instance;
144   instanceList_.push_front(instance);
145   instance->set_state(INSERTED);
146   return instance;
147 }
148
149 /* Test whether the type contains a specific type. */
150 bool
151 Point::TestType(Point::Type types, Point::Type trg) {
152   if (types & trg) return true;
153   return false;
154 }
155
156 /* Add a specific type to a set of types */
157 void
158 Point::AddType(Point::Type& types, Point::Type trg) {
159   int trg_int = static_cast<int>(trg);
160   int type_int = static_cast<int>(types);
161   type_int |= trg_int;
162   types = (Point::Type)type_int;
163 }
164
165 /* Remove a specific type from a set of types */
166 void
167 Point::RemoveType(Point::Type& types, Point::Type trg) {
168   int trg_int = static_cast<int>(trg);
169   int type_int = static_cast<int>(types);
170   type_int &= (~trg_int);
171   types = (Point::Type)type_int;
172 }
173
174 bool
175 Point::remove(InstancePtr instance) {
176   if (instance == InstancePtr()) return false;
177   InstanceList::iterator it = std::find(instanceList_.begin(),
178                                  instanceList_.end(), instance);
179   if (it != instanceList_.end()) {
180     instanceList_.erase(it);
181     instance->set_state(PENDING);
182     return true;
183   }
184   return false;
185 }
186
187 size_t
188 Point::size() {
189   return instanceList_.size();
190 }
191
192 void
193 Point::clear() {
194   while (size() > 0) {
195     InstancePtr i = instanceList_.back();
196     i->destroy();
197   }
198 }
199
200 /* 1, Clear all snippet instances
201    2, Detach from PatchMgr object */
202 bool
203 Point::destroy() {
204   clear();
205   PatchMgr::TypePtMap type_pt_map;
206   switch (type_) {
207     case PreInsn:
208     case PostInsn:
209     case InsnTaken:
210     case PreCall:
211     case PostCall:
212     {
213       type_pt_map = mgr_->addr_type_pt_map_[addr_];
214       break;
215     }
216     case BlockEntry:
217     case BlockExit:
218     case BlockDuring:
219     {
220       type_pt_map = mgr_->blk_type_pt_map_[the_block_];
221       break;
222     }
223     case FuncEntry:
224     case FuncExit:
225     case FuncDuring:
226     {
227       type_pt_map = mgr_->func_type_pt_map_[the_func_];
228       break;
229     }
230     case EdgeDuring:
231     {
232       type_pt_map = mgr_->edge_type_pt_map_[the_edge_];
233       break;
234     }
235     case LoopStart:
236     case LoopEnd:
237     case LoopIterStart:
238     case LoopIterEnd:
239     {
240       return false;
241     }
242     case InsnTypes:
243     case LoopTypes:
244     case BlockTypes:
245     case CallTypes:
246     case FuncTypes:
247     case OtherPoint:
248     case None:
249     {
250       return false;
251     }
252   }
253   PointSet& points = type_pt_map[type_];
254   points.erase(this);
255   return true;
256 }
257
258 Point::~Point() {
259   // Clear all instances associated with this point
260   clear();
261 }