Function wrapping implementation and Symtab extensions for undefined symbols
[dyninst.git] / dyninstAPI / src / BPatch_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: BPatch_function.C,v 1.109 2008/11/03 15:19:24 jaw Exp $
33
34 #define BPATCH_FILE
35
36 #include <string.h>
37 #include <string>
38 #include "function.h"
39 #include "process.h"
40 #include "instPoint.h"
41 #include "ast.h"
42
43 #include "BPatch.h"
44 #include "BPatch_function.h"
45 #include "BPatch_point.h"
46 #include "BPatch_type.h"
47 #include "BPatch_collections.h"
48 #include "BPatch_Vector.h"
49 #include "BPatch_flowGraph.h"
50 #include "BPatch_libInfo.h"
51 #include "BPatch_memoryAccess_NP.h"
52 #include "BPatch_basicBlock.h"
53 #include "BPatch_statement.h"
54 #include "mapped_module.h"
55 #include "mapped_object.h"
56 #include "hybridAnalysis.h"
57
58 #include "common/h/Types.h"
59
60 #include "Point.h"
61 #include "PatchMgr.h"
62
63 using Dyninst::PatchAPI::PatchMgrPtr;
64 using Dyninst::PatchAPI::Point;
65
66
67
68 /**************************************************************************
69  * BPatch_function
70  *************************************************************************/
71 /*
72  * BPatch_function::BPatch_function
73  *
74  * Constructor that creates a BPatch_function.
75  *
76  */
77
78 int bpatch_function_count = 0;
79
80 BPatch_function::BPatch_function(BPatch_addressSpace *_addSpace, 
81                                  func_instance *_func,
82                                  BPatch_module *_mod) :
83         addSpace(_addSpace), 
84    lladdSpace(_func->proc()),
85    mod(_mod),
86    cfg(NULL), 
87    cfgCreated(false), 
88    liveInit(false),
89    func(_func), 
90         varsAndParamsValid(false)
91 {
92    _srcType = BPatch_sourceFunction;
93    
94    localVariables = new BPatch_localVarCollection;
95    funcParameters = new BPatch_localVarCollection;
96    retType = NULL;
97    
98    assert(mod && !mod->func_map.count(func));
99    mod->func_map[func] = this;
100 };
101
102 /*
103  * BPatch_function::BPatch_function
104  *
105  * Constructor that creates the BPatch_function with return type.
106  *
107  */
108 BPatch_function::BPatch_function(BPatch_addressSpace *_addSpace, func_instance *_func,
109                                  BPatch_type * _retType, BPatch_module *_mod) :
110         addSpace(_addSpace),
111    lladdSpace(_func->proc()),
112    mod(_mod),
113    cfg(NULL),
114    cfgCreated(false),
115    liveInit(false), 
116    func(_func),
117         varsAndParamsValid(false)
118 {
119   _srcType = BPatch_sourceFunction;
120
121   localVariables = new BPatch_localVarCollection;
122   funcParameters = new BPatch_localVarCollection;
123   retType = _retType;
124
125   assert(mod);
126   mod->func_map[func] = this;
127 };
128
129
130 BPatch_function::~BPatch_function()
131 {
132    if (localVariables) delete localVariables;
133    if (funcParameters) delete funcParameters;
134    
135    if (cfg) delete cfg;
136    
137    // Remove us from the proc map...
138    int num_erased = mod->func_map.erase(lowlevel_func());
139    assert(num_erased == 1);
140 }
141
142
143 //dynC internal:
144
145 bool BPatch_function::hasParamDebugInfo(){
146    std::vector<Dyninst::SymtabAPI::localVar *>SymTabParams;
147    return lowlevel_func()->ifunc()->getSymtabFunction()->getParams(SymTabParams);
148 }
149
150 /* 
151  * BPatch_function::getSourceObj()
152  *
153  * Return the contained source objects (e.g. statements).
154  *    This is not currently supported.
155  *
156  */
157 bool BPatch_function::getSourceObj(BPatch_Vector<BPatch_sourceObj *> &children)
158 {
159     // init and empty vector
160     BPatch_Vector<BPatch_sourceObj *> dummy;
161
162     children = dummy;
163     return false;
164 }
165
166
167 BPatch_process * BPatch_function::getProc() const
168 {
169   assert(addSpace->getType() == TRADITIONAL_PROCESS); 
170   return dynamic_cast<BPatch_process *>(addSpace); 
171 }
172
173
174 /*
175  * BPatch_function::getObjParent()
176  *
177  * Return the parent of the function (i.e. the module)
178  *
179  */
180 BPatch_sourceObj *BPatch_function::getObjParent()
181 {
182     return (BPatch_sourceObj *) mod;
183 }
184
185 std::string BPatch_function::getNameStr() {
186    return func->prettyName();
187 }
188
189
190 /*
191  * BPatch_function::getName
192  *
193  * Copies the name of the function into a buffer, up to a given maximum
194  * length.  Returns a pointer to the beginning of the buffer that was
195  * passed in.
196  *
197  * s            The buffer into which the name will be copied.
198  * len          The size of the buffer.
199  */
200 char *BPatch_function::getNameBuffer(char *s, int len)
201 {
202     assert(func);
203     string name = func->prettyName();
204     strncpy(s, name.c_str(), len);
205     return s;
206 }
207
208 #ifdef IBM_BPATCH_COMPAT
209 const char *BPatch_function::getNameDPCL()
210 {
211     assert(func);
212     return func->prettyName().c_str();
213 }
214 #endif
215
216 /*
217  * BPatch_function::getMangledName
218  *
219  * Copies the mangled name of the function into a buffer, up to a given maximum
220  * length.  Returns a pointer to the beginning of the buffer that was
221  * passed in.
222  *
223  * s            The buffer into which the name will be copied.
224  * len          The size of the buffer.
225  */
226 char *BPatch_function::getMangledNameInt(char *s, int len)
227 {
228   assert(func);
229   string mangledname = func->symTabName();
230   strncpy(s, mangledname.c_str(), len);
231   return s;
232 }
233
234 /*
235  * BPatch_function::getTypedName
236  *
237  * Copies the mangled name of the function into a buffer, up to a given maximum
238  * length.  Returns a pointer to the beginning of the buffer that was
239  * passed in.
240  *
241  * s            The buffer into which the name will be copied.
242  * len          The size of the buffer.
243  */
244 char *BPatch_function::getTypedNameInt(char *s, int len)
245 {
246   assert(func);
247   string typedname = func->typedName();
248   strncpy(s, typedname.c_str(), len);
249   return s;
250 }
251
252
253 /*
254  * BPatch_function::getNames
255  *
256  * Copies all names of the function into the provided BPatch_Vector.
257  * Names are represented as const char *s and are
258  * allocated/deallocated by Dyninst.
259  *
260  * names           BPatch_Vector reference
261  */
262
263 bool BPatch_function::getNamesInt(BPatch_Vector<const char *> &names)
264 {
265     assert(func);
266     unsigned pre_size = names.size();
267
268     for (unsigned i = 0; i < func->prettyNameVector().size(); i++) {
269         names.push_back(func->prettyNameVector()[i].c_str());
270     }
271
272     return names.size() > pre_size;
273 }
274
275 /*
276  * BPatch_function::getMangledNames
277  *
278  * Copies all mangled names of the function into the provided
279  * BPatch_Vector.  Names are represented as const char *s and are
280  * allocated/deallocated by Dyninst.
281  *
282  * names           BPatch_Vector reference
283  */
284
285 bool BPatch_function::getMangledNamesInt(BPatch_Vector<const char *> &names)
286 {
287     assert(func);
288     unsigned pre_size = names.size();
289
290     for (unsigned i = 0; i < func->symTabNameVector().size(); i++) {
291         names.push_back(func->symTabNameVector()[i].c_str());
292     }
293
294     return names.size() > pre_size;
295 }
296
297
298
299 /*
300  * BPatch_function::getBaseAddr
301  *
302  * Returns the starting address of the function.
303  */
304 void *BPatch_function::getBaseAddrInt()
305 {
306   return (void *)func->addr();
307 }
308
309 /*
310  * BPatch_function::getReturnType
311  *
312  * Returns the return type of the function.
313  */
314 BPatch_type *BPatch_function::getReturnTypeInt()
315 {
316     constructVarsAndParams();
317     return retType;
318 }
319
320 /* Update code bytes if necessary (defensive mode), 
321  * Parse new edge, 
322  * Correct missing elements in BPatch-level datastructures
323 */
324 bool BPatch_function::parseNewEdge(Dyninst::Address source, 
325                                    Dyninst::Address target)
326 {
327    assert(0 && "TODO");
328    return false;
329 #if 0
330     // mark code bytes as needing an update
331     if (BPatch_defensiveMode == func->obj()->hybridMode()) {
332         func->obj()->setCodeBytesUpdated(false);
333     }
334
335     // set up arguments to lower level parseNewEdges and call it
336     block_instance *sblock = func->findBlockByEntry(source);
337     assert(sblock);
338     vector<edgeStub> stubs;
339     stubs.push_back(edgeStub(sblock, target, ParseAPI::NOEDGE));
340     func->obj()->parseNewEdges(stubs);
341
342     // Correct missing elements in BPatch-level datastructures
343     // i.e., wipe out the BPatch_flowGraph CFG, we'll re-generate it
344     if ( cfg ) {
345         cfg->invalidate();
346     }
347
348     return true;
349 #endif
350 }
351
352 // Removes all instrumentation and relocation from the function and 
353 // restores the original version
354 // Also flushes the runtime library address cache, if present
355 bool BPatch_function::removeInstrumentation(bool useInsertionSet)
356 {
357     bool removedAll = true;
358     if (useInsertionSet) {
359         addSpace->beginInsertionSet();
360     }
361
362     // remove instrumentation, point by point
363     std::vector<BPatch_point*> points;
364     getAllPoints(points);
365     for (unsigned pidx=0; pidx < points.size(); pidx++) {
366         vector<BPatchSnippetHandle*> allSnippets = 
367             points[pidx]->getCurrentSnippetsInt();
368         for (unsigned all = 0; all < allSnippets.size(); all++) 
369         {
370             if (dynamic_cast<BPatch_process*>(addSpace)->getHybridAnalysis()->hybridOW()->
371                 hasLoopInstrumentation(true,*this))
372             {
373                 mal_printf("ERROR: Trying to remove active looop instrumentation\n");
374                 removedAll = false;
375                 assert(0);
376             }
377             else if ( ! addSpace->deleteSnippetInt(allSnippets[all]) ) {
378                 removedAll = false;
379             }
380         } 
381     }
382
383     if (useInsertionSet) {
384         bool dontcare=false;
385         if (!addSpace->finalizeInsertionSet(false,&dontcare)) {
386             removedAll = false;
387         }
388     }
389     mal_printf("removed instrumentation from func %lx\n", getBaseAddr());
390     return removedAll;
391 }
392
393 /* Gets unresolved instPoints from func_instance and converts them to
394    BPatch_points, puts them in unresolvedCF */
395 void BPatch_function::getUnresolvedControlTransfers
396 (BPatch_Vector<BPatch_point *> &unresolvedCF/*output*/)
397 {
398    const func_instance::BlockSet &blocks = func->unresolvedCF();
399    for (func_instance::BlockSet::const_iterator iter = blocks.begin(); iter != blocks.end(); ++iter) {
400       // We want to instrument before the last instruction, since we can pull out
401       // the target at that point. Technically, we want to instrument the sink edge;
402       // but we can't do that yet. 
403       instPoint *point = instPoint::preInsn(func, *iter, (*iter)->last());
404       BPatch_procedureLocation ptType = 
405          BPatch_point::convertInstPointType_t(point->type());
406       if (ptType == BPatch_locInstruction) {
407          // since this must be a control transfer, it's either an indirect
408          // jump or a direct jump
409          mal_printf("WARNING: ambiguous point type translation for "
410                     "insn at %lx, setting to locLongJump %s[%d]\n",
411                     point->nextExecutedAddr(), FILE__,__LINE__);
412          ptType = BPatch_locLongJump;
413       }
414       BPatch_point *curPoint = addSpace->findOrCreateBPPoint
415          (this, point, ptType);
416       unresolvedCF.push_back(curPoint);
417    }
418 }
419
420 /* Gets abrupt end instPoints from func_instance and converts them to
421    BPatch_points, puts them in abruptEnds */
422 void BPatch_function::getAbruptEndPoints
423 (BPatch_Vector<BPatch_point *> &abruptEnds/*output*/)
424 {
425   cerr << "getAbruptEndPoints\n";
426
427    const func_instance::BlockSet &blocks = func->abruptEnds();
428    for (func_instance::BlockSet::const_iterator iter = blocks.begin(); iter != blocks.end(); ++iter) {
429       // We just want to know if this code is executed, so use a "start of block" point.
430       instPoint *point = instPoint::blockEntry(func, *iter);
431       BPatch_point *curPoint = addSpace->findOrCreateBPPoint
432          (this, point, BPatch_locInstruction);
433       abruptEnds.push_back(curPoint);
434    }
435 }
436
437 // This one is interesting - get call points for everywhere that _calls_ us. 
438 // That we know about. 
439 void BPatch_function::getCallerPoints(std::vector<BPatch_point*>& callerPoints)
440 {
441   // TODO (wenbin) add PreCaller point and PostCaller point types
442    std::vector<block_instance *> callerBlocks;
443    func->getCallerBlocks(std::back_inserter(callerBlocks));
444    for (std::vector<block_instance *>::iterator iter = callerBlocks.begin(); 
445         iter != callerBlocks.end(); ++iter) {
446       instPoint *point = instPoint::preCall(func, *iter);
447       BPatch_point *curPoint = addSpace->findOrCreateBPPoint
448          (this, point, BPatch_locSubroutine);
449       callerPoints.push_back(curPoint);
450    }
451 }
452
453 void BPatch_function::getCallPoints(BPatch_Vector<BPatch_point *> &callPoints) {
454   /*
455   const func_instance::BlockSet &blocks = func->callBlocks();
456   for (func_instance::BlockSet::const_iterator iter = blocks.begin();
457        iter != blocks.end(); ++iter) {
458 */
459   const PatchFunction::blockset &blocks = func->getCallBlocks();
460   for (PatchFunction::blockset::const_iterator iter = blocks.begin();
461        iter != blocks.end(); ++iter) {
462     block_instance* iblk = SCAST_BI(*iter);
463     instPoint *point = instPoint::preCall(func, iblk);
464     BPatch_point *curPoint = addSpace->findOrCreateBPPoint(this, point,
465                                                            BPatch_locSubroutine);
466     callPoints.push_back(curPoint);
467   }
468 }
469
470 void BPatch_function::getEntryPoints(BPatch_Vector<BPatch_point *> &entryPoints/*output*/) {
471    BPatch_point *curPoint = addSpace->findOrCreateBPPoint(this,
472                                                           instPoint::funcEntry(func),
473                                                           BPatch_locEntry);
474    entryPoints.push_back(curPoint);
475 }
476
477 void BPatch_function::getExitPoints(BPatch_Vector<BPatch_point *> &exitPoints) {
478   func_instance::Points pts;
479   func->funcExitPoints(&pts);
480   for (func_instance::Points::iterator i = pts.begin(); i != pts.end(); i++) {
481     instPoint *point = *i;
482     BPatch_point *curPoint = addSpace->findOrCreateBPPoint(this, point, BPatch_locExit);
483     exitPoints.push_back(curPoint);
484   }
485 }
486
487
488 void BPatch_function::getAllPoints(std::vector<BPatch_point*>& bpPoints)
489 {
490    getEntryPoints(bpPoints);
491    getExitPoints(bpPoints);
492    getCallPoints(bpPoints);
493    getUnresolvedControlTransfers(bpPoints);
494    getAbruptEndPoints(bpPoints);
495    // Not running with arbitrary for now...
496 }
497
498 // Sets the address in the structure at which the fault instruction's
499 // address is stored if "set" is true.  Accesses the fault address and 
500 // translates it back to an original address if it corresponds to 
501 // relocated code in the Dyninst heap 
502 bool BPatch_function::setHandlerFaultAddrAddr
503         (Dyninst::Address addr, bool set)
504 {
505     if (lowlevel_func()->getHandlerFaultAddr()) {
506         lowlevel_func()->setHandlerFaultAddrAddr(addr,set);
507         return true;
508     }
509     return false;
510 }
511
512 void BPatch_function::fixHandlerReturnAddr(Dyninst::Address addr)
513 {
514     func->fixHandlerReturnAddr(addr);    
515 }
516
517
518 /*
519  * BPatch_function::getModule
520  *
521  * Returns the BPatch_module to which this function belongs.
522  */
523 BPatch_module *BPatch_function::getModuleInt()
524 {
525   return mod;
526 }
527
528 //  BPatch_function::getParams
529 //  Returns a vector of BPatch_localVar, representing this function's parameters
530
531 BPatch_Vector<BPatch_localVar *> * BPatch_function::getParamsInt()
532 {
533     if (!mod->isValid()) return NULL;
534     constructVarsAndParams();
535     return funcParameters->getAllVars();
536 }
537
538 /*
539  * BPatch_function::findPoint
540  *
541  * Returns a vector of the instrumentation points from a procedure that is
542  * identified by the parameters, or returns NULL upon failure.
543  * (Points are sorted by address in the vector returned.)
544  *
545  * loc          The points within the procedure to return.  The following
546  *              values are valid for this parameter:
547  *                BPatch_entry         The function's entry point.
548  *                BPatch_exit          The function's exit point(s).
549  *                BPatch_subroutine    The points at which the procedure calls
550  *                                     other procedures.
551  *                BPatch_longJump      The points at which the procedure make
552  *                                     long jump calls.
553  *                BPatch_allLocations  All of the points described above.
554  */
555 BPatch_Vector<BPatch_point*> *BPatch_function::findPointInt(
556         const BPatch_procedureLocation loc)
557 {
558     // function does not exist!
559     if (func == NULL) return NULL;
560
561     if (!mod->isValid()) return NULL;
562
563     // if the function is not instrumentable, we won't find the point
564     if (!isInstrumentable())
565        return NULL;
566
567     BPatch_Vector<BPatch_point*> *result = new BPatch_Vector<BPatch_point *>;
568     
569     switch(loc) {
570        case BPatch_entry:
571           getEntryPoints(*result);
572           break;
573        case BPatch_exit:
574           getExitPoints(*result);
575           break;
576        case BPatch_subroutine:
577           getCallPoints(*result);
578           break;
579        case BPatch_allLocations:
580           // Seems to be "entry, exit, call" rather than a true "all"
581           getEntryPoints(*result);
582           getExitPoints(*result);
583           getCallPoints(*result);
584           break;
585        default:
586           // Not implemented
587           delete result;
588           return NULL;
589     }
590
591     return result;
592 }
593
594 /*
595  * BPatch_function::findPoint (VG 09/05/01)
596  *
597  * Returns a vector of the instrumentation points from a procedure that is
598  * identified by the parameters, or returns NULL upon failure.
599  * (Points are sorted by address in the vector returned.)
600  *
601  * ops          The points within the procedure to return. A set of op codes
602  *              defined in BPatch_opCode (BPatch_point.h)
603  */
604
605 struct compareByEntryAddr
606 {
607     bool operator()(const BPatch_basicBlock* lhs, const BPatch_basicBlock* rhs)
608     {
609         return const_cast<BPatch_basicBlock*>(lhs)->getStartAddress() < 
610                         const_cast<BPatch_basicBlock*>(rhs)->getStartAddress();
611     }
612 };
613  
614 BPatch_Vector<BPatch_point*> *BPatch_function::findPointByOp(
615         const BPatch_Set<BPatch_opCode>& ops)
616 {
617    // function does not exist!
618    if (func == NULL) return NULL;
619    
620    if (!mod->isValid()) return NULL;
621    // function is generally uninstrumentable (with current technology)
622    if (!isInstrumentable()) return NULL;
623    
624    std::set<BPatch_basicBlock*, compareByEntryAddr> blocks;
625    std::set<BPatch_basicBlock*> unsorted_blocks;
626    getCFG()->getAllBasicBlocks(unsorted_blocks);
627    std::copy(unsorted_blocks.begin(), unsorted_blocks.end(), std::inserter(blocks, blocks.begin()));
628    BPatch_Vector<BPatch_point*>* ret = new BPatch_Vector<BPatch_point*>;
629    for(std::set<BPatch_basicBlock*, compareByEntryAddr>::iterator curBlk = blocks.begin();
630        curBlk != blocks.end();
631        curBlk++)
632    {
633       BPatch_Vector<BPatch_point*>* tmp = (*curBlk)->findPoint(ops);
634       for (unsigned int i = 0; i < tmp->size(); i++)
635       {
636          ret->push_back((*tmp)[i]);
637       } 
638       
639    }
640    return ret;
641 }
642
643 /*
644  * BPatch_function::addParam()
645  *
646  * This function adds a function parameter to the BPatch_function parameter
647  * vector.
648  */
649 void BPatch_function::addParam(Dyninst::SymtabAPI::localVar *lvar)
650 {
651   BPatch_localVar * param = new BPatch_localVar(lvar);
652   
653   // Add parameter to list of parameters
654   params.push_back(param);
655 }
656
657 #if 0
658 void BPatch_function::addParam(const char * _name, BPatch_type *_type,
659                                int _linenum, long _frameOffset, int _reg,
660                                BPatch_storageClass _sc)
661 {
662   BPatch_localVar * param = new BPatch_localVar(_name, _type, _linenum,
663                                                 _frameOffset, _reg, _sc);
664
665   // Add parameter to list of parameters
666   params.push_back(param);
667 }
668 #endif
669
670 /*
671  * BPatch_function::findLocalVarInt()
672  *
673  * This function searchs for a local variable in the BPatch_function's
674  * local variable collection.
675  */
676 BPatch_localVar * BPatch_function::findLocalVarInt(const char * name)
677 {
678     if (!mod->isValid()) 
679                 return NULL;
680     constructVarsAndParams();
681     BPatch_localVar * var = localVariables->findLocalVar(name);
682     return (var);
683 }
684
685 /*
686  * BPatch_function::findLocalParam()
687  *
688  * This function searchs for a function parameter in the BPatch_function's
689  * parameter collection.
690  */
691 BPatch_localVar * BPatch_function::findLocalParamInt(const char * name)
692 {
693     if (!mod->isValid()) return NULL;
694     constructVarsAndParams();
695     BPatch_localVar * var = funcParameters->findLocalVar(name);
696     return (var);
697 }
698
699 BPatch_flowGraph* BPatch_function::getCFGInt()
700 {
701     assert(mod);
702     if (!mod->isValid()) return NULL;
703     if (cfg && cfg->isValid() && 
704         ( ! mod->isExploratoryModeOn() || 
705           ! lowlevel_func()->obj()->parse_img()->hasNewBlocks()))
706         return cfg;
707     bool valid = false;
708     cfg = new BPatch_flowGraph(this, valid);
709     if (!valid) {
710         delete cfg;
711         cfg = NULL;
712         fprintf(stderr, "CFG is NULL for func %s at %lx %s[%d]\n", 
713                 lowlevel_func()->symTabName().c_str(),
714                 func->addr(),FILE__,__LINE__);
715         return NULL;
716     }
717     return cfg;
718 }
719
720 void BPatch_function::constructVarsAndParams()
721 {
722     if (varsAndParamsValid)
723        return;
724
725     if (mod) {
726         mod->parseTypesIfNecessary();
727     }
728
729     //Check flag to see if vars & params are already constructed
730     std::vector<SymtabAPI::localVar *>vars;
731
732     if (lowlevel_func()->ifunc()->getSymtabFunction()->getLocalVariables(vars)) 
733         {
734         for (unsigned i = 0; i< vars.size(); i++) 
735             {
736             if (mod) {
737                 vars[i]->fixupUnknown(mod->lowlevel_mod()->pmod()->mod());
738             }
739
740                 localVariables->addLocalVar(new BPatch_localVar(vars[i]));
741             }    
742     }
743
744     std::vector<SymtabAPI::localVar *>parameters;
745
746     if (lowlevel_func()->ifunc()->getSymtabFunction()->getParams(parameters)) 
747         {
748         for (unsigned i = 0; i< parameters.size(); i++) 
749                 {
750             if (mod) {
751                 parameters[i]->fixupUnknown(mod->lowlevel_mod()->pmod()->mod());
752             }
753
754                 BPatch_localVar *lparam = new BPatch_localVar(parameters[i]);
755             funcParameters->addLocalVar(lparam);
756                 params.push_back(lparam);
757         }    
758     }
759
760     if (!lowlevel_func()->ifunc()->getSymtabFunction()->getReturnType()) 
761         {
762         varsAndParamsValid = true;
763         return;
764     }
765         
766         SymtabAPI::Type *ret_type = lowlevel_func()->ifunc()->getSymtabFunction()->getReturnType();
767         assert(ret_type);
768
769         extern AnnotationClass<BPatch_type> TypeUpPtrAnno;
770
771         if (!ret_type->getAnnotation(retType, TypeUpPtrAnno))
772         {
773                 //  BPatch_type ctor adds the annotation to the lowlevel symtab type, so 
774                 //  no need to do it here.
775                 retType = new BPatch_type(ret_type);
776         }
777         else
778                 assert(retType);
779
780     varsAndParamsValid = true;
781 }
782
783 BPatch_Vector<BPatch_localVar *> *BPatch_function::getVarsInt() 
784 {
785     if (!mod->isValid()) return NULL;
786     constructVarsAndParams();
787     return localVariables->getAllVars(); 
788 }
789
790 bool BPatch_function::findVariableInt(const char *name, 
791                                       BPatch_Vector<BPatch_variableExpr *> &vars) 
792 {
793    if (!mod->isValid()) 
794            return false;
795
796    constructVarsAndParams();
797
798    BPatch_localVar *lv = findLocalVar(name);
799
800    if (!lv) 
801    {
802       // look for it in the parameter scope now
803       lv = findLocalParam(name);
804    }
805
806    if (lv) 
807    {
808       // create a local expr with the correct frame offset or absolute
809       //   address if that is what is needed
810       std::map<BPatch_localVar *, BPatch_variableExpr*>::iterator i;
811       i = local_vars.find(lv);
812
813       if (i != local_vars.end()) 
814           {
815          vars.push_back((*i).second);
816          return true;
817       }
818
819       BPatch_Vector<BPatch_point*> *points = findPoint(BPatch_entry);
820       assert(points->size() == 1);
821       BPatch_image *imgPtr = (BPatch_image *) mod->getObjParent();
822
823       BPatch_variableExpr *nv = new BPatch_variableExpr(imgPtr->getAddressSpace(),
824                                                         func->proc(),
825                                                         lv, lv->getType(), (*points)[0]);
826       vars.push_back(nv);
827       return true;
828    }
829
830    // finally check the global scope.
831    BPatch_image *imgPtr = (BPatch_image *) mod->getObjParent();
832    
833    if (!imgPtr) return false;
834    
835    BPatch_variableExpr *var = imgPtr->findVariable(name);
836    if (!var) return false;
837    
838    vars.push_back(var);
839    return true;   
840 }
841
842
843 BPatch_Vector<BPatch_variableExpr *> *BPatch_function::findVariableInt(const char *name)
844 {
845    BPatch_Vector<BPatch_variableExpr *> *vars = new BPatch_Vector<BPatch_variableExpr*>;
846    bool result = findVariableInt(name, *vars);
847    if (!result) {
848       delete vars;
849       return NULL;
850    }
851    return vars;
852 }
853
854 bool BPatch_function::getVariablesInt(BPatch_Vector<BPatch_variableExpr *> &/*vect*/)
855 {
856         return false;
857 }
858
859 char *BPatch_function::getModuleNameInt(char *name, int maxLen) {
860     return getModule()->getName(name, maxLen);
861 }
862
863 BPatch_variableExpr *BPatch_function::getFunctionRefInt() 
864 {
865   Address remoteAddress = (Address)getBaseAddrInt();
866   char *fname = const_cast<char *>(func->prettyName().c_str());
867
868   //  Need to figure out the type for this effective function pointer,
869   //  of the form <return type> (*)(<arg1 type>, ... , <argn type>)
870   
871   //  Note:  getParamsInt allocates the vector
872   assert(retType);
873   char typestr[1024];
874   sprintf(typestr, "%s (*)(", retType->getName());
875   
876   BPatch_Vector<BPatch_localVar *> *params = getParamsInt();
877   assert(params);
878   
879   for (unsigned int i = 0; i < params->size(); ++i) {
880      if (i >= (params->size() -1)) {
881         //  no comma after last parameter
882         sprintf(typestr, "%s %s", typestr, (*params)[i]->getName());
883      } else 
884         sprintf(typestr, "%s %s,", typestr, (*params)[i]->getName());
885   }
886   sprintf(typestr, "%s)", typestr);
887   
888   BPatch_type *type = addSpace->image->findType(typestr);
889   if (!type) {
890      fprintf(stderr, "%s[%d]:  cannot find type '%s'\n", FILE__, __LINE__, typestr);
891   }
892   assert(type);
893   
894   //  only the vector was newly allocated, not the parameters themselves
895   delete [] params;
896   
897   //  In truth it would make more sense for this to be a BPatch_constExpr,
898   //  But since we are adding this as part of the DPCL compatibility process
899   //  we use the IBM API, to eliminate one API difference.
900   
901   AstNodePtr ast(AstNode::operandNode(AstNode::Constant, (void *) remoteAddress));
902   
903   // the variableExpr owns the ast now.
904   return new BPatch_variableExpr(fname, addSpace, lladdSpace, ast, 
905                                  type, (void *) remoteAddress);
906   
907
908 } /* end getFunctionRef() */
909
910 bool BPatch_function::getAddressRangeInt(void * &start, void * &end) {
911    Address s, e;
912    bool ret = getAddressRange(s, e);
913    start = (void *)s;
914    end = (void *)e;
915    return ret;
916 }
917
918 bool BPatch_function::getAddressRangeInt(Dyninst::Address &start, Dyninst::Address &end) {
919    start = func->addr();
920    
921    // end is a little tougher
922    end = func->addr();
923    for (PatchFunction::blockset::const_iterator iter = func->getAllBlocks().begin();
924         iter != func->getAllBlocks().end(); ++iter) {
925       end = (end < (*iter)->end()) ? (*iter)->end() : end;
926    }
927
928    return true;
929 }
930
931 /*
932  * BPatch_function::isInstrumentable
933  *
934  * Returns true if the function is instrumentable, false otherwise.
935  */
936 bool BPatch_function::isInstrumentableInt()
937 {
938      return ((func_instance *)func)->isInstrumentable();
939 }
940
941 // Return TRUE if the function resides in a shared lib, FALSE otherwise
942
943 bool BPatch_function::isSharedLibInt(){
944   return mod->isSharedLib();
945
946
947 void BPatch_function::fixupUnknown(BPatch_module *module) {
948    if (retType != NULL && retType->getDataClass() == BPatch_dataUnknownType) 
949       retType = module->getModuleTypes()->findType(retType->getID());
950
951    for (unsigned int i = 0; i < params.size(); i++)
952       params[i]->fixupUnknown(module);
953    if (localVariables != NULL) {
954       BPatch_Vector<BPatch_localVar *> *vars = localVariables->getAllVars();
955       for (unsigned int i = 0; i < vars->size(); i++)
956          (*vars)[i]->fixupUnknown(module);
957       delete vars;
958    }
959 }
960
961 bool BPatch_function::containsSharedBlocks() {
962     return func->containsSharedBlocks();
963 }
964
965 // isPrimary: function will now use this name as a primary output name
966 // isMangled: this is the "mangled" name rather than demangled (pretty)
967 const char *BPatch_function::addNameInt(const char *name,
968                                         bool isPrimary, /* = true */
969                                         bool isMangled) { /* = false */
970     // Add to the internal function object
971     //    Add to the container mapped_object name mappings
972     //    Add to the proc-independent function object
973     //       Add to the container image class
974
975     if (isMangled) {
976         func->addSymTabName(std::string(name),
977                             isPrimary);
978     }
979     else {
980         func->addPrettyName(std::string(name),
981                               isPrimary);
982     }
983     return name;
984 }
985
986 bool BPatch_function::findOverlappingInt(BPatch_Vector<BPatch_function *> &funcs) {
987     assert(func);
988     assert(addSpace);
989
990     std::set<func_instance *> overlappingIntFuncs;
991     if (!func->getSharingFuncs(overlappingIntFuncs)) {
992         // No overlapping functions
993         return false;
994     }
995
996     // We now need to map from func_instances to BPatch_functions
997     for (std::set<func_instance *>::iterator iter = overlappingIntFuncs.begin();
998          iter != overlappingIntFuncs.end(); ++iter) {
999        funcs.push_back(addSpace->findOrCreateBPFunc(*iter,
1000                                                      mod));
1001     }
1002
1003     return true;
1004 }
1005
1006 ParseAPI::Function * BPatch_function::getParseAPIFuncInt() {
1007   assert(func);
1008  
1009   return func->ifunc();
1010 }
1011
1012 PatchAPI::PatchFunction * BPatch_function::getPatchAPIFuncInt() {
1013   assert(func);
1014  
1015   return func;
1016 }
1017
1018 void BPatch_function::relocateFunction()
1019 {
1020      lowlevel_func()->proc()->addModifiedFunction(lowlevel_func());
1021      if (getAddSpace()->pendingInsertions == NULL) {
1022         // Trigger it now
1023         bool tmp;
1024         getAddSpace()->finalizeInsertionSet(false, &tmp);
1025      }
1026 }
1027
1028 bool BPatch_function::getSharedFuncs(set<BPatch_function*> &sharedFuncs)
1029 {
1030    std::set<func_instance *> ishared;
1031    if (!func->getSharingFuncs(ishared)) return false;
1032    for (std::set<func_instance *>::iterator iter = ishared.begin();
1033         iter != ishared.end(); ++iter) {
1034       sharedFuncs.insert(getAddSpace()->findOrCreateBPFunc(*iter,
1035                                                            getModule()));
1036    }
1037    return true;
1038 }