After tested under windows.
[dyninst.git] / dyninstAPI / src / function.C
1 /*
2  * Copyright (c) 1996-2011 Barton P. Miller
3  *
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  *
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  *
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  *
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: function.C,v 1.10 2005/03/02 19:44:45 bernat Exp
33
34 #include "function.h"
35 #include "process.h"
36 #include "instPoint.h"
37
38 #include "mapped_object.h"
39 #include "mapped_module.h"
40 #include "InstructionDecoder.h"
41 #include "MemoryEmulator/memEmulator.h"
42 #include "Relocation/Transformers/Movement-analysis.h"
43
44
45 #include "Parsing.h"
46
47 using namespace Dyninst;
48 using namespace Dyninst::ParseAPI;
49 using namespace Dyninst::Relocation;
50
51 int func_instance_count = 0;
52
53 func_instance::func_instance(parse_func *f,
54                              Address baseAddr,
55                              mapped_module *mod) :
56   PatchFunction(f, mod->obj()),
57   ptrAddr_(f->getPtrOffset() ? f->getPtrOffset() + baseAddr : 0),
58   mod_(mod),
59   entry_(NULL),
60   handlerFaultAddr_(0),
61   handlerFaultAddrAddr_(0)
62 #if defined(os_windows)
63   , callingConv(unknown_call)
64   , paramSize(0)
65 #endif
66    , wrapperSym_(NULL)
67 {
68   assert(f);
69 #if defined(ROUGH_MEMORY_PROFILE)
70   func_instance_count++;
71   if ((func_instance_count % 1000) == 0)
72     fprintf(stderr, "func_instance_count: %d (%d)\n",
73             func_instance_count, func_instance_count*sizeof(func_instance));
74 #endif
75
76   parsing_printf("%s: creating new proc-specific function at 0x%lx\n",
77                  symTabName().c_str(), addr_);
78
79 }
80
81 func_instance::func_instance(const func_instance *parFunc,
82                              mapped_module *childMod) :
83   PatchFunction(parFunc->ifunc(), childMod->obj()),
84   ptrAddr_(parFunc->ptrAddr_),
85   mod_(childMod),
86   entry_(NULL),
87   handlerFaultAddr_(0),
88   handlerFaultAddrAddr_(0)
89 #if defined(os_windows)
90   , callingConv(parFunc->callingConv)
91   , paramSize(parFunc->paramSize)
92 #endif
93    , wrapperSym_(NULL)
94 {
95    assert(ifunc());
96    // According to contract /w/ the mapped_object
97    // all blocks have already been constructed.
98    // Do we duplicate the parent or wait? I'm
99    // tempted to wait, just because of the common
100    // fork/exec case.
101 }
102
103 func_instance::~func_instance() {
104   // We don't delete blocks, since they're shared between functions
105   // We _do_ delete context instPoints, though
106   // Except that should get taken care of normally since the
107   // structures are static.
108   for (unsigned i = 0; i < parallelRegions_.size(); i++)
109     delete parallelRegions_[i];
110
111 }
112
113 void func_instance::setHandlerFaultAddr(Address fa) {
114     handlerFaultAddr_ = fa;
115 }
116
117 // Sets the address in the structure at which the fault instruction's
118 // address is stored if "set" is true.  Accesses the fault address and
119 // translates it back to an original address if it corresponds to
120 // relocated code in the Dyninst heap
121 void func_instance::setHandlerFaultAddrAddr(Address faa, bool set) {
122   if (set) {
123     // save the faultAddrAddr
124     handlerFaultAddrAddr_ = faa;
125   }
126
127   // get the faultAddr
128   assert(proc()->proc());
129   assert(sizeof(Address) == proc()->getAddressWidth());
130   Address faultAddr=0;
131   if (!proc()->readDataSpace
132       ((void*)faa, proc()->getAddressWidth(), (void*)&faultAddr, true))
133     {
134       assert(0);
135     }
136
137   // translate the faultAddr back to an original address, and if
138   // that translation was necessary, save it to the faultAddrAddr in the
139   // CONTEXT struct
140   if (proc()->proc()->isRuntimeHeapAddr(faultAddr)) {
141
142     Address origAddr = faultAddr;
143     vector<func_instance *> tmps;
144     baseTramp *bti = NULL;
145     bool success = proc()->getAddrInfo(faultAddr, origAddr, tmps, bti);
146     assert(success);
147     assert( proc()->writeDataSpace((void*)faa,
148                                    sizeof(Address),
149                                    (void*)&origAddr) );
150   }
151 }
152
153 // Set the handler return addr to the most recent instrumented or
154 // relocated address, similar to instPoint::instrSideEffect.
155 // Also, make sure that we update our mapped view of memory,
156 // we may have overwritten memory that was previously not code
157 void func_instance::fixHandlerReturnAddr(Address /*faultAddr*/) {
158     if ( !proc()->proc() || ! handlerFaultAddrAddr_ ) {
159         assert(0);
160         return;
161     }
162 #if 0 //KEVINTODO: this function doesn't work, I tried setting newPC to 0xdeadbeef and it had no impact on the program's behavior.  If the springboards work properly this code is unneeded
163     // Do a straightfoward forward map of faultAddr
164     // First, get the original address
165     func_instance *func;
166     block_instance *block; baseTrampInstance *ignored;
167     Address origAddr;
168     if (!proc()->getRelocInfo(faultAddr, origAddr, block, ignored)) {
169        func = dynamic_cast<process *>(proc())->findActiveFuncByAddr(faultAddr);
170        origAddr = faultAddr;
171     }
172     else {
173        func = block->func();
174     }
175     std::list<Address> relocAddrs;
176     proc()->getRelocAddrs(origAddr, func, relocAddrs, true);
177     Address newPC = (!relocAddrs.empty() ? relocAddrs.back() : origAddr);
178
179     if (newPC != faultAddr) {
180        if(!proc()->writeDataSpace((void*)handlerFaultAddrAddr_,
181                                   sizeof(Address),
182                                   (void*)&newPC)) {
183           assert(0);
184        }
185     }
186 #endif
187 }
188
189 // Remove funcs from:
190 //   mapped_object & mapped_module datastructures
191 //   addressSpace::textRanges codeRangeTree<func_instance*>
192 //   image-level & SymtabAPI datastructures
193 //   BPatch_addressSpace::BPatch_funcMap <func_instance -> BPatch_function>
194 void func_instance::removeFromAll()
195 {
196     mal_printf("purging blocks_ of size = %d from func at %lx\n",
197                blocks_.size(), addr());
198
199     // remove from mapped_object & mapped_module datastructures
200     obj()->removeFunction(this);
201     mod()->removeFunction(this);
202
203     delete(this);
204 }
205
206 #if 0
207
208 /* Find parse_blocks that are missing from these datastructures and add
209  * them.  The block_instance constructor does pretty much all of the work in
210  * a chain of side-effects extending all the way into the mapped_object class
211  *
212  * We have to take into account that additional parsing may cause basic block splitting,
213  * in which case it is necessary not only to add new int-level blocks, but to update
214  * block_instance and BPatch_basicBlock objects.
215  */
216 void func_instance::addMissingBlocks()
217 {
218    assert(0 && "TODO");
219     // A bit of a hack, but be sure that we've re-checked the blocks in the
220     // parse_func as well.
221     ifunc()->invalidateCache();
222
223    blocks();
224    // Add new blocks
225
226    const vector<parse_block*> & nblocks = obj()->parse_img()->getNewBlocks();
227    // add blocks by looking up new blocks, if it promises to be more
228    // efficient than looking through all of the llfunc's blocks
229    vector<parse_block*>::const_iterator nit = nblocks.begin();
230    for( ; nit != nblocks.end(); ++nit) {
231        if (ifunc()->contains(*nit)) {
232            addMissingBlock(*nit);
233        }
234    }
235
236    if (ifunc()->blocks().size() > blocks_.size()) { //not just the else case!
237        // we may have parsed into an existing function and added its blocks
238        // to ours, or this may just be a more efficient lookup method
239        Function::blocklist & iblks = ifunc()->blocks();
240        for (Function::blocklist::iterator bit = iblks.begin();
241             bit != iblks.end();
242             bit++)
243        {
244            if (!findBlock(*bit)) {
245                addMissingBlock(SCAST_PB(*bit));
246            }
247        }
248    }
249 }
250
251 void func_instance::getReachableBlocks(const set<block_instance*> &exceptBlocks,
252                                       const list<block_instance*> &seedBlocks,
253                                       set<block_instance*> &reachBlocks)//output
254 {
255     list<parse_block*> imgSeeds;
256     for (list<block_instance*>::const_iterator sit = seedBlocks.begin();
257          sit != seedBlocks.end();
258          sit++)
259     {
260         imgSeeds.push_back((*sit)->llb());
261     }
262     set<parse_block*> imgExcept;
263     for (set<block_instance*>::const_iterator eit = exceptBlocks.begin();
264          eit != exceptBlocks.end();
265          eit++)
266     {
267         imgExcept.insert((*eit)->llb());
268     }
269
270     // image-level function does the work
271     set<parse_block*> imgReach;
272     ifunc()->getReachableBlocks(imgExcept,imgSeeds,imgReach);
273
274     for (set<parse_block*>::iterator rit = imgReach.begin();
275          rit != imgReach.end();
276          rit++)
277     {
278         reachBlocks.insert( findBlock(*rit) );
279     }
280 }
281 #endif
282
283 void print_func_vector_by_pretty_name(std::string prefix,
284                                       pdvector<func_instance *>*funcs) {
285     unsigned int i;
286     func_instance *func;
287     for(i=0;i<funcs->size();i++) {
288       func = ((*funcs)[i]);
289       cerr << prefix << func->prettyName() << endl;
290     }
291 }
292
293 mapped_object *func_instance::obj() const { return mod()->obj(); }
294 AddressSpace *func_instance::proc() const { return obj()->proc(); }
295
296 const func_instance::BlockSet &func_instance::blocks() {
297   if (blocks_.empty()) {
298     for (PatchFunction::blocklist::const_iterator i = getAllBlocks().begin();
299          i != getAllBlocks().end(); i++) {
300       blocks_.insert(SCAST_BI(*i));
301     }
302   }
303   return blocks_;
304 }
305
306 const func_instance::BlockSet &func_instance::callBlocks() {
307   // Check the list...
308   if (callBlocks_.empty()) {
309     for (PatchFunction::blocklist::const_iterator i = getCallBlocks().begin();
310          i != getCallBlocks().end(); i++) {
311       callBlocks_.insert(SCAST_BI(*i));
312     }
313   }
314   return callBlocks_;
315 }
316
317 const func_instance::BlockSet &func_instance::exitBlocks() {
318   // Check the list...
319   if (exitBlocks_.empty()) {
320     for (PatchFunction::blocklist::const_iterator i = getExitBlocks().begin();
321          i != getExitBlocks().end(); i++) {
322       exitBlocks_.insert(SCAST_BI(*i));
323     }
324   }
325   return exitBlocks_;
326 }
327
328 const func_instance::BlockSet &func_instance::unresolvedCF() {
329    if (unresolvedCF_.empty()) {
330       // A block has unresolved control flow if it has an indirect
331       // out-edge.
332       blocks();
333       for (BlockSet::iterator iter = blocks_.begin(); iter != blocks_.end(); ++iter) {
334          if ((*iter)->llb()->unresolvedCF()) {
335             unresolvedCF_.insert(*iter);
336          }
337       }
338    }
339    return unresolvedCF_;
340 }
341
342 const func_instance::BlockSet &func_instance::abruptEnds() {
343    if (abruptEnds_.empty()) {
344       // A block has unresolved control flow if it has an indirect
345       // out-edge.
346       blocks();
347       for (BlockSet::iterator iter = blocks_.begin(); iter != blocks_.end(); ++iter) {
348          if ((*iter)->llb()->abruptEnd()) {
349             abruptEnds_.insert(*iter);
350          }
351       }
352    }
353    return abruptEnds_;
354 }
355
356 block_instance *func_instance::entryBlock() {
357   if (!entry_) {
358     entry_ = SCAST_BI(getEntryBlock());
359     if (!entry_) {
360       cerr << "ERROR: Couldn't find entry block for " << name() << endl;
361     }
362   }
363   return entry_;
364 }
365
366 unsigned func_instance::getNumDynamicCalls()
367 {
368    unsigned count=0;
369    for (BlockSet::const_iterator iter = callBlocks().begin(); iter != callBlocks().end(); ++iter) {
370       if ((*iter)->containsDynamicCall()) {
371          count++;
372       }
373    }
374
375    return count;
376 }
377
378
379 void func_instance::debugPrint() const {
380     fprintf(stderr, "Function debug dump (%p):\n", this);
381     fprintf(stderr, "  Symbol table names:\n");
382     for (unsigned i = 0; i < symTabNameVector().size(); i++) {
383         fprintf(stderr, "    %s\n", symTabNameVector()[i].c_str());
384     }
385     fprintf(stderr, "  Demangled names:\n");
386     for (unsigned j = 0; j < prettyNameVector().size(); j++) {
387         fprintf(stderr, "    %s\n", prettyNameVector()[j].c_str());
388     }
389     fprintf(stderr, "  Typed names:\n");
390     for (unsigned k = 0; k < typedNameVector().size(); k++) {
391         fprintf(stderr, "    %s\n", typedNameVector()[k].c_str());
392     }
393     fprintf(stderr, "  Address: 0x%lx\n", addr());
394     fprintf(stderr, "  Internal pointer: %p\n", ifunc());
395     fprintf(stderr, "  Object: %s (%p), module: %s (%p)\n",
396             obj()->fileName().c_str(),
397             obj(),
398             mod()->fileName().c_str(),
399             mod());
400     for (BlockSet::const_iterator
401              cb = blocks_.begin();
402          cb != blocks_.end();
403          cb++)
404     {
405         block_instance* orig = (*cb);
406         fprintf(stderr, "  Block start 0x%lx, end 0x%lx\n", orig->start(),
407                 orig->end());
408     }
409 }
410
411 // Add to internal
412 // Add to mapped_object if a "new" name (true return from internal)
413 void func_instance::addSymTabName(const std::string name, bool isPrimary) {
414     if (ifunc()->addSymTabName(name, isPrimary))
415         obj()->addFunctionName(this, name, mapped_object::mangledName);
416 }
417
418 void func_instance::addPrettyName(const std::string name, bool isPrimary) {
419     if (ifunc()->addPrettyName(name, isPrimary))
420         obj()->addFunctionName(this, name, mapped_object::prettyName);
421 }
422
423 // Dig down to the low-level block of b, find the low-level functions
424 // that share it, and map up to int-level functions and add them
425 // to the funcs list.
426 bool func_instance::getSharingFuncs(block_instance *b,
427                                    std::set<func_instance *> & funcs)
428 {
429     bool ret = false;
430
431     vector<Function *> lfuncs;
432     b->llb()->getFuncs(lfuncs);
433     vector<Function *>::iterator fit = lfuncs.begin();
434     for( ; fit != lfuncs.end(); ++fit) {
435       parse_func *ll_func = SCAST_PF(*fit);
436         func_instance *hl_func = obj()->findFunction(ll_func);
437         assert(hl_func);
438
439         if (hl_func == this) continue;
440
441         if (funcs.find(hl_func) == funcs.end()) ret = true;
442         funcs.insert(hl_func);
443     }
444
445     return ret;
446 }
447
448 // Find sharing functions via checking all basic blocks. We might be
449 // able to check only exit points; but we definitely need to check _all_
450 // exits so for now we're checking everything.
451
452 bool func_instance::getSharingFuncs(std::set<func_instance *> &funcs) {
453     bool ret = false;
454
455     // Create the block list.
456     blocks();
457
458     BlockSet::iterator bIter;
459     for (bIter = blocks_.begin();
460          bIter != blocks_.end();
461          bIter++) {
462        if (getSharingFuncs(*bIter,funcs))
463           ret = true;
464     }
465
466     return ret;
467 }
468
469 bool func_instance::getOverlappingFuncs(block_instance *block,
470                                        std::set<func_instance *> &funcs)
471 {
472         ParseAPI::Block *llB = block->llb();
473         std::set<ParseAPI::Block *> overlappingBlocks;
474         for (Address i = llB->start(); i < llB->end(); ++i) {
475                 llB->obj()->findBlocks(llB->region(), i, overlappingBlocks);
476         }
477         // We now have all of the overlapping ParseAPI blocks. Get the set of
478         // ParseAPI::Functions containing each and up-map to func_instances
479         for (std::set<ParseAPI::Block *>::iterator iter = overlappingBlocks.begin();
480                 iter != overlappingBlocks.end(); ++iter) {
481                 std::vector<ParseAPI::Function *> llFuncs;
482                 (*iter)->getFuncs(llFuncs);
483                 for (std::vector<ParseAPI::Function *>::iterator iter2 = llFuncs.begin();
484                      iter2 != llFuncs.end(); ++iter2)  {
485                    funcs.insert(obj()->findFunction(*iter2));
486                 }
487         }
488         return (funcs.size() > 1);
489 }
490
491 bool func_instance::getOverlappingFuncs(std::set<func_instance *> &funcs)
492 {
493     bool ret = false;
494
495     // Create the block list.
496     blocks();
497     BlockSet::iterator bIter;
498     for (bIter = blocks_.begin();
499          bIter != blocks_.end();
500          bIter++) {
501        if (getOverlappingFuncs(*bIter,funcs))
502           ret = true;
503     }
504
505     return ret;
506 }
507
508 std::string func_instance::get_name() const
509 {
510    return symTabName();
511 }
512
513 Offset func_instance::addrToOffset(const Address a) const {
514    return a - (addr() - ifunc()->getOffset());
515 }
516
517 const pdvector< int_parRegion* > &func_instance::parRegions()
518 {
519   if (parallelRegions_.size() > 0)
520     return parallelRegions_;
521
522   for (unsigned int i = 0; i < ifunc()->parRegions().size(); i++)
523     {
524       image_parRegion * imPR = ifunc()->parRegions()[i];
525       //int_parRegion * iPR = new int_parRegion(imPR, baseAddr, this);
526       int_parRegion * iPR = new int_parRegion(imPR, addr_, this);
527       parallelRegions_.push_back(iPR);
528     }
529   return parallelRegions_;
530 }
531
532 bool func_instance::consistency() const {
533    // 1) Check for 1:1 block relationship in
534    //    the block list and block map
535    // 2) Check that all instPoints are in the
536    //    correct block.
537
538    const ParseAPI::Function::blocklist &img_blocks = ifunc()->blocks();
539    assert(img_blocks.size() == blocks_.size());
540    for (ParseAPI::Function::blocklist::iterator iter = img_blocks.begin();
541         iter != img_blocks.end(); ++iter) {
542       parse_block *img_block = SCAST_PB(*iter);
543       block_instance *b_inst = obj()->findBlock(img_block);
544       assert(blocks_.find(b_inst) != blocks_.end());
545    }
546
547    return true;
548 }
549
550 Address func_instance::get_address() const { assert(0); return 0; }
551 unsigned func_instance::get_size() const { assert(0); return 0; }
552
553 bool func_instance::findInsnPoints(instPoint::Type type,
554                                    block_instance *b,
555                                    InsnInstpoints::const_iterator &begin,
556                                    InsnInstpoints::const_iterator &end) {
557    std::map<block_instance *, BlockInstpoints>::iterator iter = blockPoints_.find(b);
558    if (iter == blockPoints_.end()) return false;
559
560    switch(type) {
561       case instPoint::PreInsn:
562          begin = iter->second.preInsn.begin();
563          end = iter->second.preInsn.end();
564          return true;
565       case instPoint::PostInsn:
566          begin = iter->second.postInsn.begin();
567          end = iter->second.postInsn.end();
568          return true;
569       default:
570          return false;
571    }
572    return false;
573 }
574
575 bool func_instance::isInstrumentable() {
576    return ifunc()->isInstrumentable();
577
578    if (!ifunc()->isInstrumentable()) return false;
579
580    // Hack: avoid things that throw exceptions
581    // Make sure we parsed calls
582    callBlocks();
583    for (BlockSet::iterator iter = callBlocks_.begin(); iter != callBlocks_.end(); ++iter) {
584       if ((*iter)->calleeName().find("cxa_throw") != std::string::npos) {
585          cerr << "Func " << symTabName() << " found exception ret false" << endl;
586          return false;
587       }
588       func_instance *callee = (*iter)->callee();
589
590       cerr << "Func " << symTabName() << " @ " << hex
591            << (*iter)->start() << ", callee " << (*iter)->calleeName() << dec << endl;
592
593       if (!callee) {
594          cerr << "Warning: null callee" << endl;
595          continue;
596       }
597       cerr << "Checking callee named " << callee->symTabName() << endl;
598
599       if (callee->symTabName().find("cxa_throw") != std::string::npos) {
600          cerr << "Func " << symTabName() << " found exception ret false" << endl;
601          return false;
602       }
603
604       // TEMPORARY HACKAGE because we're not picking up names for
605       // PLT functions?
606       if (callee->symTabName().find("402700") != std::string::npos) {
607          cerr << "Func " << symTabName() << " found exception ret false" << endl;
608          return false;
609       }
610
611    }
612    return true;
613
614 }
615
616 block_instance *func_instance::getBlock(const Address addr) {
617         block_instance *block = obj()->findOneBlockByAddr(addr);
618         // Make sure it's one of ours
619         std::set<func_instance *> funcs;
620         block->getFuncs(std::inserter(funcs, funcs.end()));
621         if (funcs.find(this) != funcs.end()) {
622           //addBlock(block); // Update parent class's bookkeeping stuffs
623           return block;
624         }
625         return NULL;
626 }
627
628 using namespace SymtabAPI;
629
630 bool func_instance::callWrappedFunction(func_instance *target) {
631    // Not implemented for dynamic mode
632    if (proc()->proc()) return false;
633    // And not implemented for same-module
634    if (obj() == target->obj()) return false;
635    // Get the old symbol
636    Symbol *oldsym = target->getRelocSymbol();
637
638    // Get the new symbol
639    Symbol *wrapperSym = target->getWrapperSymbol();
640    if (!wrapperSym) {
641       return false;
642    }
643
644    // Now we split. If this is a static binary, we want to point all the relocations
645    // in this function at the new symbol. If it's a dynamic binary, we can just relocate
646    // the daylights out of it.
647    if (obj()->isStaticExec() || target->obj()->isStaticExec() ) {
648       if (!updateRelocationsToSym(oldsym, wrapperSym)) return false;
649    }
650    else {
651       // Not implemented yet
652       return false;
653    }
654
655    return true;
656 }
657
658 bool func_instance::updateRelocationsToSym(Symbol *oldsym, Symbol *newsym) {
659    for (BlockSet::const_iterator iter = blocks().begin();
660         iter != blocks().end(); ++iter) {
661       obj()->parse_img()->getObject()->updateRelocations((*iter)->start(), (*iter)->last(), oldsym, newsym);
662    }
663    return true;
664 }
665
666 Symbol *func_instance::getWrapperSymbol() {
667    // Is created during relocation, which should have
668    // already happened.
669    return wrapperSym_;
670 }
671
672 Symbol *func_instance::getRelocSymbol() {
673    // there should be only one...
674    // HIGHLANDER!
675
676    // find the Symbol corresponding to the func_instance
677    std::vector<Symbol *> syms;
678    ifunc()->func()->getSymbols(syms);
679
680    if (syms.size() == 0) {
681       char msg[256];
682       sprintf(msg, "%s[%d]:  internal error:  cannot find symbol %s"
683               , __FILE__, __LINE__, name().c_str());
684       showErrorCallback(80, msg);
685       assert(0);
686    }
687
688    // try to find a dynamic symbol
689    // (take first static symbol if none are found)
690    Symbol *referring = syms[0];
691    for (unsigned k=0; k<syms.size(); k++) {
692       if (syms[k]->isInDynSymtab()) {
693          referring = syms[k];
694          break;
695       }
696    }
697    return referring;
698 }
699
700 void func_instance::createWrapperSymbol(Address entry) {
701    if (wrapperSym_) {
702       // Just update the address
703       wrapperSym_->setOffset(entry);
704       return;
705    }
706    // Otherwise we need to create a new symbol
707    std::string wrapperName = name();
708    wrapperName += "_dyninst_wrapper";
709
710    wrapperSym_ = new Symbol(wrapperName,
711                             Symbol::ST_FUNCTION,
712                             Symbol::SL_GLOBAL,
713                             Symbol::SV_DEFAULT,
714                             entry,
715                             NULL, // This is module - I probably want this?
716                             NULL, // Region - again, find it?
717                             0, // size - zero okay?
718                             false, // Definitely not dynamic ("Static binaries don't have dynamic symbols - Dan")
719                             false); // Definitely not absolute
720    obj()->parse_img()->getObject()->addSymbol(wrapperSym_);
721
722 }
723
724 /* PatchAPI stuffs */
725
726 instPoint *func_instance::funcEntryPoint(bool create) {
727    assert(proc()->mgr());
728    // Lookup the cached points
729    if (points_.entry) return points_.entry;
730    if (!create) return NULL;
731    // Cache miss, resort to PatchAPI's findPoint
732    std::vector<Point*> pts;
733    proc()->mgr()->findPoints(this, Point::FuncEntry, back_inserter(pts));
734    assert(pts.size() == 1);
735    points_.entry = static_cast<instPoint*>(pts[0]);
736    return points_.entry;
737 }
738
739 instPoint *func_instance::funcExitPoint(block_instance* b, bool create) {
740   assert(proc()->mgr());
741
742   // Lookup the cached points
743   std::map<block_instance *, instPoint *>::iterator iter = points_.exits.find(b);
744   if (iter != points_.exits.end()) return iter->second;
745   if (!create) return NULL;
746   // Cache miss, resort to PatchAPI's findPoint
747   Points pts;
748   funcExitPoints(&pts);
749   assert(pts.size() > 0);
750   iter = points_.exits.find(b);
751   if (iter != points_.exits.end()) return iter->second;
752   assert(0);
753   return NULL;
754 }
755
756 void func_instance::funcExitPoints(Points* pts) {
757   assert(proc()->mgr());
758   // Lookup the cached points
759   if (points_.exits.size() > 0) {
760     for (std::map<block_instance*, instPoint*>::iterator pi = points_.exits.begin();
761          pi != points_.exits.end(); pi++) {
762       pts->push_back(pi->second);
763     }
764     return;
765   }
766   // Cache miss, resort to PatchAPI's findPoint
767   std::vector<Point*> points;
768   proc()->mgr()->findPoints(this, Point::FuncExit, back_inserter(points));
769   for (std::vector<Point*>::iterator pi = points.begin(); pi != points.end(); pi++) {
770     instPoint* p = static_cast<instPoint*>(*pi);
771     pts->push_back(p);
772     points_.exits[p->block()] = p;
773   }
774 }
775
776 instPoint *func_instance::preCallPoint(block_instance* b, bool create) {
777   std::map<block_instance *, BlockInstpoints>::iterator iter = blockPoints_.find(b);
778   if (iter != blockPoints_.end()) {
779     if (iter->second.preCall) return iter->second.preCall;
780   }
781   if (!create) return NULL;
782   Points pts;
783   callPoints(&pts);
784   iter = blockPoints_.find(b);
785   if (iter != blockPoints_.end()) {
786     if (iter->second.preCall) return iter->second.preCall;
787   }
788   return NULL;
789 }
790
791 instPoint *func_instance::postCallPoint(block_instance* b, bool create) {
792   std::map<block_instance *, BlockInstpoints>::iterator iter = blockPoints_.find(b);
793   if (iter != blockPoints_.end()) {
794     if (iter->second.postCall) return iter->second.postCall;
795   }
796   if (!create) return NULL;
797   Points pts;
798   callPoints(&pts);
799   iter = blockPoints_.find(b);
800   if (iter != blockPoints_.end()) {
801     if (iter->second.postCall) return iter->second.postCall;
802   }
803   return NULL;
804 }
805
806 void func_instance::callPoints(Points* pts) {
807   assert(proc()->mgr());
808   // Lookup the cached points
809   if (blockPoints_.size() > 0) {
810     bool done = true;
811     for (std::map<block_instance*, BlockInstpoints>::iterator pi = blockPoints_.begin();
812          pi != blockPoints_.end(); pi++) {
813       if (!pi->second.preCall) {
814         done = false;
815         break;
816       }
817       pts->push_back(pi->second.preCall);
818       pts->push_back(pi->second.postCall);
819     }
820     if (done) return;
821   }
822   // Cache miss, resort to PatchAPI's findPoint
823   std::vector<Point*> points;
824   proc()->mgr()->findPoints(this, Point::PreCall|Point::PostCall, back_inserter(points));
825   for (std::vector<Point*>::iterator pi = points.begin(); pi != points.end(); pi++) {
826     instPoint* p = static_cast<instPoint*>(*pi);
827     pts->push_back(p);
828     if (p->type() == Point::PreCall) blockPoints_[p->block()].preCall = p;
829     else blockPoints_[p->block()].postCall = p;
830   }
831 }
832
833 instPoint *func_instance::blockEntryPoint(block_instance* b, bool create) {
834   assert(proc()->mgr());
835   // Lookup the cached points
836   std::map<block_instance *, BlockInstpoints>::iterator iter = blockPoints_.find(b);
837   if (iter != blockPoints_.end()) {
838     if (iter->second.entry) return iter->second.entry;
839   }
840   if (!create) return NULL;
841   // Cache miss, resort to PatchAPI's findPoint
842   std::vector<Point*> pts;
843   proc()->mgr()->findPoints(b, Point::BlockEntry, back_inserter(pts));
844   assert(pts.size() == 1);
845   blockPoints_[b].entry = static_cast<instPoint*>(pts[0]);
846   return blockPoints_[b].entry;
847 }
848
849 instPoint *func_instance::blockExitPoint(block_instance* b, bool create) {
850   assert(proc()->mgr());
851   // Lookup the cached points
852   std::map<block_instance *, BlockInstpoints>::iterator iter = blockPoints_.find(b);
853   if (iter != blockPoints_.end()) {
854     if (iter->second.exit) return iter->second.exit;
855   }
856   if (!create) return NULL;
857   // Cache miss, resort to PatchAPI's findPoint
858   std::vector<Point*> pts;
859   proc()->mgr()->findPoints(b, Point::BlockExit, back_inserter(pts));
860   assert(pts.size() == 1);
861   blockPoints_[b].exit = static_cast<instPoint*>(pts[0]);
862   return blockPoints_[b].exit;
863 }
864
865 instPoint *func_instance::preInsnPoint(block_instance* b, Address a,
866                                        InstructionAPI::Instruction::Ptr ptr,
867                                        bool trusted, bool create) {
868   std::map<block_instance *, BlockInstpoints>::iterator iter = blockPoints_.find(b);
869   if (iter != blockPoints_.end()) {
870     std::map<Address, instPoint *>::iterator iter2 = iter->second.preInsn.find(a);
871     if (iter2 != iter->second.preInsn.end()) {
872       return iter2->second;
873     }
874   }
875   if (!create) return NULL;
876   if (!trusted || !ptr) {
877     ptr = b->getInsn(a);
878     if (!ptr) return NULL;
879   }
880   Points pts;
881   blockInsnPoints(b, &pts);
882   assert(pts.size() > 0);
883   iter = blockPoints_.find(b);
884   if (iter != blockPoints_.end()) {
885     std::map<Address, instPoint *>::iterator iter2 = iter->second.preInsn.find(a);
886     if (iter2 != iter->second.preInsn.end()) {
887       return iter2->second;
888     }
889   }
890   assert(0);
891   return NULL;
892 }
893
894 instPoint *func_instance::postInsnPoint(block_instance* b, Address a,
895                                         InstructionAPI::Instruction::Ptr ptr,
896                                         bool trusted, bool create) {
897
898   std::map<block_instance *, BlockInstpoints>::iterator iter = blockPoints_.find(b);
899   if (iter != blockPoints_.end()) {
900     std::map<Address, instPoint *>::iterator iter2 = iter->second.postInsn.find(a);
901     if (iter2 != iter->second.postInsn.end()) {
902       return iter2->second;
903     }
904   }
905   if (!create) return NULL;
906   if (!trusted || !ptr) {
907     ptr = b->getInsn(a);
908     if (!ptr) return NULL;
909   }
910   Points pts;
911   blockInsnPoints(b, &pts);
912   assert(pts.size() > 0);
913   iter = blockPoints_.find(b);
914   if (iter != blockPoints_.end()) {
915     std::map<Address, instPoint *>::iterator iter2 = iter->second.postInsn.find(a);
916     if (iter2 != iter->second.postInsn.end()) {
917       return iter2->second;
918     }
919   }
920   assert(0);
921   return NULL;
922 }
923
924 void func_instance::blockInsnPoints(block_instance* b, Points* pts) {
925   assert(proc()->mgr());
926   // Lookup the cache
927   std::map<block_instance *, BlockInstpoints>::iterator iter = blockPoints_.find(b);
928   if (iter != blockPoints_.end()) {
929     if (iter->second.preInsn.size() > 0 && iter->second.postInsn.size() > 0) {
930       for (std::map<Address, instPoint*>::iterator iter2 = iter->second.preInsn.begin();
931            iter2 != iter->second.preInsn.end(); iter2++) {
932         pts->push_back(iter2->second);
933       }
934       for (std::map<Address, instPoint*>::iterator iter2 = iter->second.postInsn.begin();
935            iter2 != iter->second.postInsn.end(); iter2++) {
936         pts->push_back(iter2->second);
937       }
938       return;
939     }
940   }
941   // Cache miss!
942   std::vector<Point*> points;
943   proc()->mgr()->findPoints(b, Point::PreInsn|Point::PostInsn, back_inserter(points));
944   assert(points.size() > 0);
945   for (std::vector<Point*>::iterator i = points.begin(); i != points.end(); i++) {
946     instPoint* pt = static_cast<instPoint*>(*i);
947     Address a = pt->address();
948     pts->push_back(pt);
949     if (pt->type() == Point::PreInsn) blockPoints_[b].preInsn[a] = pt;
950     else blockPoints_[b].postInsn[a] = pt;
951   }
952 }
953
954 instPoint* func_instance::edgePoint(edge_instance* e, bool create) {
955   std::map<edge_instance *, EdgeInstpoints>::iterator iter = edgePoints_.find(e);
956   if (iter != edgePoints_.end()) {
957     if (iter->second.point) return iter->second.point;
958   }
959   if (!create) return NULL;
960   Points pts;
961   edgePoints(&pts);
962   iter = edgePoints_.find(e);
963   if (iter != edgePoints_.end()) {
964     if (iter->second.point) return iter->second.point;
965   }
966   return NULL;
967 }
968
969 void func_instance::edgePoints(Points* pts) {
970   assert(proc()->mgr());
971   if (edgePoints_.size() > 0) {
972     for (std::map<edge_instance*, EdgeInstpoints>::iterator iter = edgePoints_.begin();
973          iter != edgePoints_.end(); iter++) {
974       pts->push_back(iter->second.point);
975     }
976     return;
977   }
978   std::vector<Point*> points;
979   proc()->mgr()->findPoints(this, Point::EdgeDuring, back_inserter(points));
980   for (std::vector<Point*>::iterator i = points.begin(); i != points.end(); i++) {
981     instPoint* pt = static_cast<instPoint*>(*i);
982     edge_instance* e = static_cast<edge_instance*>(pt->edge());
983     pts->push_back(pt);
984     edgePoints_[e].point = pt;
985   }
986 }
987
988 void func_instance::destroyBlock(block_instance *block) {
989    // Put things here that go away from the perspective of this function
990 }
991
992 void func_instance::destroy(func_instance *f) {
993    // Put things here that go away when we destroy this function
994    delete f;
995 }