Bump versions everywhere to 8.2.0
[dyninst.git] / patchAPI / src / PatchMgr.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 /* Public Interface */
31
32 #include "PatchMgr.h"
33 #include "PatchObject.h"
34 #include "PatchCFG.h"
35 #include "Point.h"
36 #include "PatchCallback.h"
37
38 using namespace Dyninst;
39 using namespace PatchAPI;
40
41 using Dyninst::ParseAPI::CodeSource;
42 using Dyninst::InstructionAPI::InstructionDecoder;
43 using Dyninst::InstructionAPI::Instruction;
44 using Dyninst::PatchAPI::PatchMgr;
45 using Dyninst::PatchAPI::PatchMgrPtr;
46 using Dyninst::PatchAPI::PointMaker;
47 using Dyninst::PatchAPI::InstancePtr;
48 using Dyninst::PatchAPI::Point;
49 using Dyninst::PatchAPI::PointSet;
50 using Dyninst::PatchAPI::PatchBlock;
51 using Dyninst::PatchAPI::PatchEdge;
52 using Dyninst::PatchAPI::PatchFunction;
53
54 static const int PatchAPI_major_version = 8;
55 static const int PatchAPI_minor_version = 2;
56 static const int PatchAPI_maintenance_version = 0;
57
58 void PatchMgr::version(int& major, int& minor, int& maintenance)
59 {
60     major = PatchAPI_major_version;
61     minor = PatchAPI_minor_version;
62     maintenance = PatchAPI_maintenance_version;
63 }
64
65 PatchMgr::PatchMgr(AddrSpace* as, Instrumenter* inst, PointMaker* pt)
66   : as_(as) {
67   if (!pt) {
68     patchapi_debug("Use default PointMaker");
69     point_maker_ = new PointMaker;
70   } else {
71     patchapi_debug("Use plugin PointMaker");
72     point_maker_ = pt;
73   }
74   if (!inst) {
75     patchapi_debug("Use default Instrumenter");
76     instor_ = Instrumenter::create(as);
77   } else {
78     patchapi_debug("Use plugin Instrumenter");
79     inst->setAs(as);
80     instor_ = inst;
81   }
82 }
83
84 PatchMgrPtr
85 PatchMgr::create(AddrSpace* as, Instrumenter* inst, PointMaker* pf) {
86   patchapi_debug("Create PatchMgr");
87   PatchMgrPtr ret = PatchMgrPtr(new PatchMgr(as, inst, pf));
88   if (!ret) return PatchMgrPtr();
89   ret->as_->mgr_ = ret;
90   ret->pointMaker()->setMgr(ret);
91   return ret;
92 }
93
94 /* Return false if no point is found */
95 bool
96 PatchMgr::removeSnippet(InstancePtr instance) {
97   if (instance == InstancePtr()) return false;
98   return instance->destroy();
99 }
100
101 Point *PatchMgr::findPoint(Location loc,
102                            Point::Type type,
103                            bool create) {
104    // Verify an untrusted Location
105    if (!loc.trusted) {
106       if (!verify(loc)) return NULL;
107    }
108
109    // Not sure if it's better to go by type
110    // or location first, so we're running
111    // with type...
112    switch (type) {
113       case Point::PreInsn:
114       case Point::PostInsn:
115       case Point::BlockEntry:
116       case Point::BlockExit:
117       case Point::BlockDuring:
118          if (loc.func) {
119             return loc.func->findPoint(loc, type, create);
120          }
121          else {
122             if (!loc.block) return NULL;
123             return loc.block->findPoint(loc, type, create);
124          }
125          break;
126       case Point::PreCall:
127       case Point::PostCall:
128       case Point::FuncExit:
129          if (!loc.func || !loc.block) return NULL;
130          return loc.func->findPoint(loc, type, create);
131          break;
132       case Point::FuncEntry:
133       case Point::FuncDuring:
134          if (!loc.func) {
135             return NULL;
136          }
137          return loc.func->findPoint(loc, type, create);
138          break;
139       case Point::EdgeDuring:
140          if (loc.func) {
141             return loc.func->findPoint(loc, type, create);
142          }
143          else {
144             // Not doing generic edges yet...
145             return NULL;
146          }
147          break;
148          // These are unimplemented
149       case Point::LoopStart:
150       case Point::LoopEnd:
151       case Point::LoopIterStart:
152       case Point::LoopIterEnd:
153       default:
154          return NULL;
155    }
156 }
157
158 PatchMgr::~PatchMgr() {
159   patchapi_debug("Destroy PatchMgr");
160   delete as_;
161   delete point_maker_;
162   delete instor_;
163   
164 }
165
166 bool PatchMgr::getCandidates(Scope &scope,
167                              Point::Type types,
168                              Candidates &ret) {
169    // We hand in pre-generated lists to reduce the requirement for iteration
170    if (wantFuncs(scope, types)) getFuncCandidates(scope, types, ret);
171    if (wantCallSites(scope, types)) getCallSiteCandidates(scope, types, ret);
172    if (wantExitSites(scope, types)) getExitSiteCandidates(scope, types, ret);
173
174    if (wantBlocks(scope, types)) getBlockCandidates(scope, types, ret);
175    if (wantEdges(scope, types)) getEdgeCandidates(scope, types, ret);
176    if (wantInsns(scope, types)) getInsnCandidates(scope, types, ret);
177
178    if (wantBlockInstances(scope, types)) getBlockInstanceCandidates(scope, types, ret);
179    //if (wantEdgeInstances(scope, types)) getEdgeInstanceCandidates(scope, types, ret);
180    if (wantInsnInstances(scope, types)) getInsnInstanceCandidates(scope, types, ret);
181
182    return true;
183 }
184
185 bool PatchMgr::wantFuncs(Scope &scope, Point::Type types) {
186   return (Point::TestType(types, Point::FuncDuring) ||
187           (Point::TestType(types, Point::FuncEntry) &&
188            (scope.func || scope.obj || scope.wholeProgram)));
189 }
190
191 bool PatchMgr::wantCallSites(Scope &scope, Point::Type types) {
192   return (Point::TestType(types, Point::CallTypes) &&
193          (scope.func || scope.obj || scope.wholeProgram));
194 }
195
196 bool PatchMgr::wantExitSites(Scope &scope, Point::Type types) {
197   return (Point::TestType(types, Point::FuncExit) &&
198          (scope.func || scope.obj || scope.wholeProgram));
199 }
200
201 bool PatchMgr::wantBlocks(Scope &scope, Point::Type types) {
202   return (scope.func == NULL && Point::TestType(types, Point::BlockTypes));
203 }
204
205 bool PatchMgr::wantBlockInstances(Scope &scope, Point::Type types) {
206   return (scope.func != NULL && Point::TestType(types, Point::BlockTypes));
207 }
208
209 bool PatchMgr::wantEdges(Scope &scope, Point::Type types) {
210   return (scope.func == NULL && Point::TestType(types, Point::EdgeTypes));
211 }
212
213 bool PatchMgr::wantInsns(Scope &scope, Point::Type types) {
214   return (scope.func == NULL && Point::TestType(types, Point::InsnTypes));
215 }
216
217 bool PatchMgr::wantInsnInstances(Scope &scope, Point::Type types) {
218   return (scope.func != NULL && Point::TestType(types, Point::InsnTypes));
219 }
220
221 void PatchMgr::getFuncCandidates(Scope &scope, Point::Type types, Candidates &ret) {
222    // We can either have a scope of PatchObject and be looking for all
223    // the functions it contains, a scope of a Function, or be looking
224    // for every single function we know about.
225    Functions funcs;
226    getFuncs(scope, funcs);
227
228    for (Functions::iterator iter = funcs.begin(); iter != funcs.end(); ++iter) {
229       if (types & Point::FuncDuring) ret.push_back(Candidate(Location::Function(*iter), Point::FuncDuring));
230       if (types & Point::FuncEntry) ret.push_back(Candidate(Location::EntrySite(*iter, (*iter)->entry(), true), Point::FuncEntry));
231    }
232 }
233
234
235 void PatchMgr::getCallSiteCandidates(Scope &scope, Point::Type types, Candidates &ret) {
236    CallSites sites;
237    getCallSites(scope, sites);
238    for (CallSites::iterator iter = sites.begin(); iter != sites.end(); ++iter) {
239       if (types & Point::PreCall) ret.push_back(Candidate(Location::CallSite(*iter), Point::PreCall));
240       if (types & Point::PostCall) ret.push_back(Candidate(Location::CallSite(*iter), Point::PostCall));
241    }
242 }
243
244 void PatchMgr::getExitSiteCandidates(Scope &scope, Point::Type, Candidates &ret) {
245    ExitSites sites;
246    getExitSites(scope, sites);
247    for (ExitSites::iterator iter = sites.begin(); iter != sites.end(); ++iter) {
248       ret.push_back(Candidate(Location::ExitSite(*iter), Point::FuncExit));
249    }
250 }
251
252 void PatchMgr::getBlockCandidates(Scope &scope, Point::Type types, Candidates &ret) {
253    Blocks blocks;
254    getBlocks(scope, blocks);
255    for (Blocks::iterator iter = blocks.begin(); iter != blocks.end(); ++iter) {
256       if (types & Point::BlockEntry) ret.push_back(Candidate(Location::Block(*iter), Point::BlockEntry));
257       if (types & Point::BlockDuring) ret.push_back(Candidate(Location::Block(*iter), Point::BlockDuring));
258       if (types & Point::BlockExit) ret.push_back(Candidate(Location::Block(*iter), Point::BlockExit));
259    }
260 }
261
262 void PatchMgr::getEdgeCandidates(Scope &scope, Point::Type, Candidates &ret) {
263    Edges edges;
264    getEdges(scope, edges);
265    for (Edges::iterator iter = edges.begin(); iter != edges.end(); ++iter) {
266       ret.push_back(Candidate(Location::Edge(*iter), Point::EdgeDuring));
267    }
268 }
269
270 void PatchMgr::getInsnCandidates(Scope &scope, Point::Type types, Candidates &ret) {
271    Insns insns;
272    getInsns(scope, insns);
273    for (Insns::iterator iter = insns.begin(); iter != insns.end(); ++iter) {
274       if (types & Point::PreInsn) ret.push_back(Candidate(Location::Instruction(*iter), Point::PreInsn));
275       if (types & Point::PostInsn) ret.push_back(Candidate(Location::Instruction(*iter), Point::PostInsn));
276    }
277 }
278
279 void PatchMgr::getBlockInstanceCandidates(Scope &scope, Point::Type types, Candidates &ret) {
280    BlockInstances blocks;
281    getBlockInstances(scope, blocks);
282    for (BlockInstances::iterator iter = blocks.begin(); iter != blocks.end(); ++iter) {
283       if (types & Point::BlockEntry) ret.push_back(Candidate(Location::BlockInstance(iter->first, iter->second, true), Point::BlockEntry));
284       if (types & Point::BlockDuring) ret.push_back(Candidate(Location::BlockInstance(iter->first, iter->second, true), Point::BlockDuring));
285       if (types & Point::BlockExit) ret.push_back(Candidate(Location::BlockInstance(iter->first, iter->second, true), Point::BlockExit));
286    }
287 }
288
289 void PatchMgr::getInsnInstanceCandidates(Scope &scope, Point::Type types, Candidates &ret) {
290    InsnInstances insns;
291    getInsnInstances(scope, insns);
292    for (InsnInstances::iterator iter = insns.begin(); iter != insns.end(); ++iter) {
293       if (types & Point::PreInsn) ret.push_back(Candidate(Location::InstructionInstance(iter->first, iter->second, true), Point::PreInsn));
294       if (types & Point::PostInsn) ret.push_back(Candidate(Location::InstructionInstance(iter->first, iter->second, true), Point::PostInsn));
295    }
296 }
297
298 void PatchMgr::getFuncs(Scope &scope, Functions &funcs) {
299    if (scope.wholeProgram) {
300       AddrSpace::ObjMap &objs = as()->objMap();
301       for (AddrSpace::ObjMap::iterator iter = objs.begin(); iter != objs.end(); ++iter) {
302          iter->second->funcs(std::back_inserter(funcs));
303       }
304    }
305    else if (scope.obj) {
306       scope.obj->funcs(std::back_inserter(funcs));
307    }
308    else if (scope.func) {
309       funcs.push_back(scope.func);
310    }
311 }
312
313 void PatchMgr::getCallSites(Scope &scope, CallSites &sites) {
314    // All sites in whatever functions we want
315    Functions funcs;
316    getFuncs(scope, funcs);
317    for (Functions::iterator iter = funcs.begin(); iter != funcs.end(); ++iter) {
318       const PatchFunction::Blockset &c = (*iter)->callBlocks();
319       for (PatchFunction::Blockset::const_iterator iter2 = c.begin(); iter2 != c.end(); ++iter2) {
320          if (!scope.block || (scope.block == *iter2))
321             sites.push_back(CallSite_t(*iter, *iter2));
322       }
323    }
324 }
325
326 void PatchMgr::getExitSites(Scope &scope, ExitSites &sites) {
327    // All sites in whatever functions we want
328    Functions funcs;
329    getFuncs(scope, funcs);
330    for (Functions::iterator iter = funcs.begin(); iter != funcs.end(); ++iter) {
331       const PatchFunction::Blockset &e = (*iter)->exitBlocks();
332       for (PatchFunction::Blockset::const_iterator iter2 = e.begin(); iter2 != e.end(); ++iter2) {
333          if (!scope.block || (scope.block == *iter2))
334             sites.push_back(ExitSite_t(*iter, *iter2));
335       }
336    }
337 }
338
339 void PatchMgr::getBlocks(Scope &scope, Blocks &blocks) {
340    if (scope.wholeProgram) {
341       const AddrSpace::ObjMap &objs = as()->objMap();
342       for (AddrSpace::ObjMap::const_iterator iter = objs.begin(); iter != objs.end(); ++iter) {
343          iter->second->blocks(std::back_inserter(blocks));
344       }
345    }
346    else if (scope.obj) {
347       scope.obj->blocks(std::back_inserter(blocks));
348    }
349    else if (scope.block) {
350       blocks.push_back(scope.block);
351    }
352 }
353
354 void PatchMgr::getEdges(Scope &scope, Edges &edges) {
355    if (scope.wholeProgram) {
356       const AddrSpace::ObjMap &objs = as()->objMap();
357       for (AddrSpace::ObjMap::const_iterator iter = objs.begin(); iter != objs.end(); ++iter) {
358          iter->second->edges(std::back_inserter(edges));
359       }
360    }
361    else if (scope.obj) {
362       scope.obj->edges(std::back_inserter(edges));
363    }
364 }
365
366 void PatchMgr::getInsns(Scope &scope, Insns &insns) {
367    Blocks blocks;
368    getBlocks(scope, blocks);
369
370    for (Blocks::iterator iter = blocks.begin(); iter != blocks.end(); ++iter) {
371       PatchBlock::Insns tmp;
372       (*iter)->getInsns(tmp);
373       for (PatchBlock::Insns::iterator t = tmp.begin(); t != tmp.end(); ++t) {
374          insns.push_back(InsnLoc_t(*iter, t->first, t->second));
375       }
376    }
377 }
378
379 void PatchMgr::getBlockInstances(Scope &scope, BlockInstances &blocks) {
380    Functions funcs;
381    getFuncs(scope, funcs);
382
383    for (Functions::iterator iter = funcs.begin(); iter != funcs.end(); ++iter) {
384       const PatchFunction::Blockset &b = (*iter)->blocks();
385       for (PatchFunction::Blockset::const_iterator iter2 = b.begin(); iter2 != b.end(); ++iter2) {
386          // TODO FIXME: make this more efficient to avoid iunnecessary iteration
387          if (scope.block && scope.block != *iter2) continue;
388          blocks.push_back(BlockInstance(*iter, *iter2));
389       }
390    }
391 }
392
393 void PatchMgr::getInsnInstances(Scope &scope, InsnInstances &insns) {
394    Functions funcs;
395    getFuncs(scope, funcs);
396
397    for (Functions::iterator iter = funcs.begin(); iter != funcs.end(); ++iter) {
398       const PatchFunction::Blockset &b = (*iter)->blocks();
399       for (PatchFunction::Blockset::const_iterator iter2 = b.begin(); iter2 != b.end(); ++iter2) {
400          // TODO FIXME: make this more efficient to avoid iunnecessary iteration
401          if (scope.block && scope.block != *iter2) continue;
402          PatchBlock::Insns i;
403          (*iter2)->getInsns(i);
404          for (PatchBlock::Insns::iterator iter3 = i.begin(); iter3 != i.end(); ++iter3) {
405             insns.push_back(InsnInstance(*iter, InsnLoc_t(*iter2, iter3->first, iter3->second)));
406          }
407       }
408    }
409 }
410
411
412 void PatchMgr::enumerateTypes(Point::Type types, EnumeratedTypes &out) {
413    for (unsigned i = 0; i <= 31; ++i) {
414       Point::Type tmp = (Point::Type) type_val(i);
415       if (types & tmp) out.push_back(tmp);
416    }
417 };
418
419
420 void PatchMgr::destroy(Point *p) {
421    p->obj()->cb()->destroy(p);
422 }
423
424 bool PatchMgr::verify(Location &loc) {
425    if (loc.trusted) return true;
426
427    switch (loc.type) {
428       case Location::Function_:
429          break;
430       case Location::Block_:
431          break;
432       case Location::BlockInstance_:
433          if (loc.func->blocks().find(loc.block) == loc.func->blocks().end()) return false;
434          break;
435       case Location::InstructionInstance_:
436          if (loc.func->blocks().find(loc.block) == loc.func->blocks().end()) return false;
437          // Fall through to Instruction_ case for detailed checking.
438       case Location::Instruction_:
439          if (loc.addr < loc.block->start()) return false;
440          if (loc.addr > loc.block->last()) return false;
441          loc.insn = loc.block->getInsn(loc.addr);
442          if (!loc.insn) return false;
443          break;
444       case Location::Edge_:
445          break;
446       case Location::EdgeInstance_:
447          if (loc.func->blocks().find(loc.edge->src()) == loc.func->blocks().end()) return false;
448          if (loc.func->blocks().find(loc.edge->trg()) == loc.func->blocks().end()) return false;
449          break;
450       case Location::Entry_:
451          if (loc.func->entry() != loc.block) return false;
452          break;
453       case Location::Call_:
454          // Check to see if the block is in the call blocks
455          if (loc.func->callBlocks().find(loc.block) == loc.func->callBlocks().end()) return false;
456          break;
457       case Location::Exit_:
458          if (loc.func->exitBlocks().find(loc.block) == loc.func->exitBlocks().end()) return false;
459          break;
460       default:
461          assert(0);
462          return true;
463    }
464    loc.trusted = true;
465    return true;
466
467 }
468
469 bool PatchMgr::consistency() const {
470    if (!point_maker_) return false;
471    if (!instor_) return false;
472    if (!as_) return false;
473    return (as_->consistency(this));
474 }
475