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