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