Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / BPatch_module.C
1 /*
2  * Copyright (c) 1996-2009 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 #include <stdio.h>
33 #include <ctype.h>
34 #include <string>
35
36 #define BPATCH_FILE
37
38 #include "process.h"
39 #include "debug.h"
40 #include "BPatch.h"
41 #include "BPatch_module.h"
42 #include "BPatch_libInfo.h"
43 #include "BPatch_function.h"
44 #include "BPatch_statement.h"
45 #include "BPatch_collections.h"
46 #include "symtabAPI/h/Type.h"    // For BPatch_type related stuff
47
48 #include "mapped_module.h"
49 #include "mapped_object.h"
50 #include "instPoint.h"
51
52 #if defined(arch_ia64)
53 #include "arch-ia64.h"
54 #endif
55
56 std::string current_func_name;
57 std::string current_mangled_func_name;
58 BPatch_function *current_func = NULL;
59
60 /*
61  * BPatch_module::getSourceObj()
62  *
63  * Return the contained source objects (e.g. functions).
64  *
65  */
66
67 bool BPatch_module::getSourceObj(BPatch_Vector<BPatch_sourceObj *> &vect)
68 {
69    if (!mod) return false;
70
71    BPatch_Vector<BPatch_function *> temp;
72    bool result = getProcedures(temp);
73    if (!result)
74       return false;
75
76    for (unsigned int i = 0; i < temp.size(); ++i) {
77       vect.push_back((BPatch_sourceObj*) temp[i]);
78    }
79    return true;
80 }
81
82 /*
83  * BPatch_function::getObjParent()
84  *
85  * Return the parent of the function (i.e. the image)
86  *
87  */
88 BPatch_sourceObj *BPatch_module::getObjParent()
89 {
90    return (BPatch_sourceObj *) img;
91 }
92
93 char *BPatch_module::getNameInt(char *buffer, int length)
94 {
95    if (!mod)
96       return NULL;
97
98    string str = mod->fileName();
99
100    strncpy(buffer, str.c_str(), length);
101
102    return buffer;
103 }
104
105 const char *BPatch_module::libraryNameInt()
106 {
107    if (!mod)
108       return NULL;
109
110    if (isSharedLib())      
111       return mod->fullName().c_str();
112
113    return NULL;
114 }
115
116 char *BPatch_module::getFullNameInt(char *buffer, int length)
117 {
118    if (!mod)
119       return NULL;
120    string str = mod->fullName();
121
122    strncpy(buffer, str.c_str(), length);
123
124    return buffer;
125 }
126
127
128 BPatch_module::BPatch_module(BPatch_addressSpace *_addSpace, 
129                              AddressSpace *as,
130                              mapped_module *_mod,
131                              BPatch_image *_img ) :
132    addSpace(_addSpace), 
133    lladdSpace(as),
134    mod(_mod),
135    img(_img), 
136    moduleTypes(NULL),
137    full_func_parse(false),
138    full_var_parse(false)
139 {
140    _srcType = BPatch_sourceModule;
141
142    switch(mod->language()) {
143       case lang_C:
144          setLanguage( BPatch_c );
145          break;
146
147       case lang_CPlusPlus:
148       case lang_GnuCPlusPlus:
149          setLanguage( BPatch_cPlusPlus );
150          break;
151
152       case lang_Fortran_with_pretty_debug:
153          setLanguage( BPatch_f90_demangled_stabstr );
154          break;
155
156       case lang_Fortran:
157       case lang_CMFortran:
158          setLanguage( BPatch_fortran );
159          break;
160
161       case lang_Assembly:
162          setLanguage( BPatch_assembly );
163          break;
164
165       case lang_Unknown: 
166       default:
167          setLanguage( BPatch_unknownLanguage );
168          break;
169    }; /* end language switch */
170
171 } /* end BPatch_module() */
172
173 // Public 'destructor' function...
174 void BPatch_module::handleUnload() 
175 {
176    // Hrm... what to do. For now, mark us as "deleted" so that
177    // any other calls return an error.
178
179    // Brainstorm: we can set mod to NULL (as it really is, 
180    // having been deleted...) and key off that. Saves a boolean.
181
182    mod = NULL;
183 }
184
185 bool BPatch_module::isValidInt() 
186 {
187    return mod != NULL;
188 }
189
190 BPatch_module::~BPatch_module()
191 {
192    if (moduleTypes) {
193       BPatch_typeCollection::freeTypeCollection(moduleTypes);
194    }
195
196    // XXX The odd while-loop structures allow the
197    //     destructors for map objects to remove themselves
198    //     from the maps; otherwise the iterators will
199    //     become invalidated
200
201    BPatch_funcMap::iterator fi = func_map.begin();
202    BPatch_funcMap::iterator tmp_f;
203    while(fi != func_map.end()) {
204       tmp_f = fi;
205       ++fi;
206       delete (*tmp_f).second;
207    }
208
209    BPatch_instpMap::iterator ii = instp_map.begin();
210    BPatch_instpMap::iterator tmp_i;
211    while(ii != instp_map.end()) {
212       tmp_i = ii;
213       ++ii; 
214       delete (*tmp_i).second;
215    }
216
217    BPatch_varMap::iterator vi = var_map.begin();
218    BPatch_varMap::iterator tmp_v;
219    while(vi != var_map.end()) {
220       tmp_v = vi;
221       ++vi;
222       delete (*tmp_v).second;
223    }
224
225    func_map.clear();
226    instp_map.clear();
227    var_map.clear();
228 }
229
230 bool BPatch_module::parseTypesIfNecessary() 
231 {
232         if ( moduleTypes != NULL ) 
233                 return false;
234
235         if (!isValid())
236                 return false;
237
238         bool is64 = (mod->pmod()->imExec()->getAddressWidth() == 8);
239
240         if (sizeof(void *) == 8 && !is64) 
241         {
242                 // Terrible Hack:
243                 //   If mutatee and mutator address width is different,
244                 //   we need to patch up certain standard types.
245                 BPatch_type *typePtr;
246
247                 typePtr = BPatch::bpatch->builtInTypes->findBuiltInType(-10);
248                 typePtr->getSymtabType()->setSize(4);
249
250                 typePtr = BPatch::bpatch->builtInTypes->findBuiltInType(-19);
251                 typePtr->getSymtabType()->setSize(4);
252         }
253
254         mod->pmod()->mod()->exec()->parseTypesNow();
255         moduleTypes = BPatch_typeCollection::getModTypeCollection(this);
256
257         vector<Type *> *modtypes = mod->pmod()->mod()->getAllTypes();
258
259         if (!modtypes)
260                 return false;
261
262         for (unsigned i=0; i<modtypes->size(); i++) 
263         {
264                 Type *typ = (*modtypes)[i];
265                 BPatch_type *type = new BPatch_type(typ);
266                 moduleTypes->addType(type);
267         }
268
269         vector<pair<string, Type *> > *globalVars = mod->pmod()->mod()->getAllGlobalVars();
270
271         if (!globalVars)
272                 return false;
273
274         for (unsigned i=0; i<globalVars->size(); i++)
275         {
276                 BPatch_type *var_type = NULL;
277                 extern AnnotationClass<BPatch_type> TypeUpPtrAnno;
278
279                 Type *ll_var_type = (*globalVars)[i].second;
280                 std::string &var_name = (*globalVars)[i].first;
281
282                 assert(ll_var_type);
283
284                 if (!ll_var_type->getAnnotation(var_type, TypeUpPtrAnno))
285                 {
286                         var_type = new BPatch_type((*globalVars)[i].second);
287                 }
288                 else
289                 {
290                         assert(var_type);
291                 }
292
293                 moduleTypes->addGlobalVariable(var_name.c_str(), var_type);
294 #if 0
295                 if (!(*globalVars)[i].second->getUpPtr())
296                 {
297                         new BPatch_type((*globalVars)[i].second);
298                 }
299
300                 moduleTypes->addGlobalVariable((*globalVars)[i].first.c_str(), 
301                                 (BPatch_type *)(*globalVars)[i].second->getUpPtr());
302 #endif
303         }
304         return true; 
305 }
306
307 BPatch_typeCollection *BPatch_module::getModuleTypesInt() 
308 {
309         parseTypesIfNecessary();
310         return moduleTypes;
311 }
312
313 /*
314  * BPatch_module::getProcedures
315  *
316  * Returns a list of all procedures in the module upon success, and NULL
317  * upon failure.
318  */
319 BPatch_Vector<BPatch_function *> *
320         BPatch_module::getProceduresInt(bool incUninstrumentable) {
321                 if (!isValid())
322                         return NULL;
323
324    BPatch_Vector<BPatch_function*> *funcs = new BPatch_Vector<BPatch_function*>();
325    bool result = getProceduresInt(*funcs, incUninstrumentable);
326    if (!result) {
327       delete funcs;
328       return NULL;
329    }
330
331    return funcs;
332 }
333
334 bool BPatch_module::getProceduresInt(BPatch_Vector<BPatch_function*> &funcs,
335                                      bool incUninstrumentable)
336 {
337    if (!isValid())
338       return false;
339
340    if (!full_func_parse) {
341       const pdvector<int_function*> &funcs = mod->getAllFunctions();
342       for (unsigned i=0; i<funcs.size(); i++) {
343          if (!func_map.count(funcs[i])) {
344             addSpace->findOrCreateBPFunc(funcs[i], this);
345          }
346       }
347       full_func_parse = true;
348    }      
349
350    BPatch_funcMap::iterator i = func_map.begin();
351    for (; i != func_map.end(); i++) {
352       if (incUninstrumentable || (*i).first->isInstrumentable())
353          funcs.push_back((*i).second);
354    }
355    return true;
356 }
357
358 /*
359  * BPatch_module::findFunction
360  *
361  * Returns a vector of BPatch_function* with the same name that is provided or
362  * NULL if no function with that name is in the module.  This function
363  * searches the BPatch_function vector of the module followed by
364  * the int_function of the module.  If a int_function is found
365  * a BPatch_function is created and added to the BPatch_function vector of
366  * the module.
367  * name The name of function to look up.
368  */
369
370    BPatch_Vector<BPatch_function *> *
371 BPatch_module::findFunctionInt(const char *name, 
372       BPatch_Vector<BPatch_function *> & funcs,
373       bool notify_on_failure, bool regex_case_sensitive,
374       bool incUninstrumentable, bool dont_use_regex)
375 {
376    if (!isValid())
377       return NULL;
378
379    unsigned size = funcs.size();
380
381    if (!name) {
382       char msg[512];
383       sprintf(msg, "%s[%d]:  Module %s: findFunction(NULL)...  failing",
384             __FILE__, __LINE__, mod->fileName().c_str());
385       BPatch_reportError(BPatchSerious, 100, msg);
386       return NULL;
387    }
388
389    // Do we want regex?
390    if (dont_use_regex 
391          ||  (NULL == strpbrk(name, REGEX_CHARSET))) {
392       pdvector<int_function *> int_funcs;
393       if (mod->findFuncVectorByPretty(name, int_funcs)) {
394          for (unsigned piter = 0; piter < int_funcs.size(); piter++) {
395             if (incUninstrumentable || int_funcs[piter]->isInstrumentable()) 
396             {
397                BPatch_function * bpfunc = addSpace->findOrCreateBPFunc(int_funcs[piter], this);
398                funcs.push_back(bpfunc);
399             }
400          }
401       }
402       else {
403          if (mod->findFuncVectorByMangled(name,
404                   int_funcs)) {
405             for (unsigned miter = 0; miter < int_funcs.size(); miter++) {
406                if (incUninstrumentable || int_funcs[miter]->isInstrumentable()) 
407                {
408                   BPatch_function * bpfunc = addSpace->findOrCreateBPFunc(int_funcs[miter], this);
409                   //                                            BPatch_function * bpfunc = proc->findOrCreateBPFunc(int_funcs[miter], this);
410                   funcs.push_back(bpfunc);
411                }
412             }
413          }
414       }
415       if (size != funcs.size())
416          return &funcs;
417    }
418    else {
419       // Regular expression search. As with BPatch_image, we handle it here
420
421 #if !defined(os_windows)
422       // REGEX falls through:
423       regex_t comp_pat;
424       int err, cflags = REG_NOSUB | REG_EXTENDED;
425
426       if ( !regex_case_sensitive )
427          cflags |= REG_ICASE;
428
429       //cerr << "compiling regex: " <<name<<endl;
430
431       if (0 != (err = regcomp( &comp_pat, name, cflags ))) {
432          char errbuf[80];
433          regerror( err, &comp_pat, errbuf, 80 );
434          if (notify_on_failure) {
435             cerr << __FILE__ << ":" << __LINE__ << ":  REGEXEC ERROR: "<< errbuf << endl;
436             std::string msg = std::string("Image: Unable to find function pattern: ") 
437                + std::string(name) + ": regex error --" + std::string(errbuf);
438             BPatch_reportError(BPatchSerious, 100, msg.c_str());
439          }
440          return NULL;
441       }
442
443       // Regular expression search. This used to be handled at the image
444       // class level, but was moved up here to simplify semantics. We
445       // have to iterate over every function known to the process at some
446       // point, so it might as well be top-level. This is also an
447       // excellent candidate for a "value-added" library.
448
449       const pdvector<int_function *> &int_funcs = mod->getAllFunctions();
450
451       for (unsigned ai = 0; ai < int_funcs.size(); ai++) {
452          int_function *func = int_funcs[ai];
453          // If it matches, push onto the vector
454          // Check all pretty names (and then all mangled names if there is no match)
455          bool found_match = false;
456          for (unsigned piter = 0; piter < func->prettyNameVector().size(); piter++) {
457             const string &pName = func->prettyNameVector()[piter];
458             int err;     
459             if (0 == (err = regexec(&comp_pat, pName.c_str(), 1, NULL, 0 ))){
460                if (func->isInstrumentable() || incUninstrumentable) {
461                   BPatch_function *foo = addSpace->findOrCreateBPFunc(func, NULL);
462                   //       BPatch_function *foo = proc->findOrCreateBPFunc(func, NULL);
463                   funcs.push_back(foo);
464                }
465                found_match = true;
466                break;
467             }
468          }
469          if (found_match) continue; // Don't check mangled names
470
471          for (unsigned miter = 0; miter < func->symTabNameVector().size(); miter++) {
472             const string &mName = func->symTabNameVector()[miter];
473             int err;
474
475             if (0 == (err = regexec(&comp_pat, mName.c_str(), 1, NULL, 0 ))){
476                if (func->isInstrumentable() || incUninstrumentable) {
477                   BPatch_function *foo = addSpace->findOrCreateBPFunc(func, NULL);
478                   //       BPatch_function *foo = proc->findOrCreateBPFunc(func, NULL);
479                   funcs.push_back(foo);
480                }
481                found_match = true;
482                break;
483             }
484          }
485       }
486
487       regfree(&comp_pat);
488
489       if (funcs.size() != size) {
490          return &funcs;
491       } 
492
493       if (notify_on_failure) {
494          std::string msg = std::string("Unable to find pattern: ") + std::string(name);
495          BPatch_reportError(BPatchSerious, 100, msg.c_str());
496       }
497 #endif
498    }
499
500    if (notify_on_failure) {
501       char msg[1024];
502       sprintf(msg, "%s[%d]:  Module %s: unable to find function %s",
503             __FILE__, __LINE__, mod->fileName().c_str(), name);
504       BPatch_reportError(BPatchSerious, 100, msg);
505
506    }
507    return &funcs;
508 }
509
510    BPatch_Vector<BPatch_function *> *
511 BPatch_module::findFunctionByAddressInt(void *addr, BPatch_Vector<BPatch_function *> &funcs,
512       bool notify_on_failure, 
513       bool incUninstrumentable)
514 {
515    if (!isValid()) return NULL;
516
517    int_function *pdfunc = NULL;
518    BPatch_function *bpfunc = NULL;
519
520    pdfunc = mod->findFuncByAddr((Address)addr);
521    if (!pdfunc) {
522       if (notify_on_failure) {
523          char msg[1024];
524          sprintf(msg, "%s[%d]:  Module %s: unable to find function %p",
525                __FILE__, __LINE__, mod->fileName().c_str(), addr);
526          BPatch_reportError(BPatchSerious, 100, msg);
527       }
528       return NULL;
529    }
530
531    if (incUninstrumentable || pdfunc->isInstrumentable()) {
532       bpfunc = addSpace->findOrCreateBPFunc(pdfunc, this);
533       //bpfunc = proc->findOrCreateBPFunc(pdfunc, this);
534       if (bpfunc) {
535          funcs.push_back(bpfunc);
536       }
537    }
538    return &funcs;
539 }
540
541 BPatch_function * BPatch_module::findFunctionByMangledInt(const char *mangled_name,
542       bool incUninstrumentable)
543 {
544    if (!isValid()) return NULL;
545
546    BPatch_function *bpfunc = NULL;
547
548    pdvector<int_function *> int_funcs;
549    std::string mangled_str(mangled_name);
550
551    if (!mod->findFuncVectorByMangled(mangled_str,
552             int_funcs))
553       return NULL;
554
555    if (int_funcs.size() > 1) {
556       fprintf(stderr, "%s[%d]: Warning: found multiple name matches for %s, returning first\n",
557             FILE__, __LINE__, mangled_name);
558    }
559
560    int_function *pdfunc = int_funcs[0];
561
562    if (incUninstrumentable || pdfunc->isInstrumentable()) {
563       bpfunc = addSpace->findOrCreateBPFunc(pdfunc, this);
564    }
565
566    return bpfunc;
567 }
568
569 bool BPatch_module::dumpMangledInt(char * prefix)
570 {
571    mod->dumpMangled(prefix);
572    return true;
573 }
574
575 void BPatch_module::parseTypes() 
576 {
577    mod->pmod()->mod()->exec()->parseTypesNow();
578 }
579 // This is done by analogy with BPatch_module::getVariables,
580 // not BPatch_image::findVariable.  This should result in consistent
581 // behavior at the module level.
582 BPatch_variableExpr* BPatch_module::findVariableInt(const char* name)
583 {
584    parseTypesIfNecessary();
585    const pdvector<int_variable *> &allVars = mod->getAllVariables();
586
587    for (unsigned i = 0; i < allVars.size(); i++) {
588      if(strcmp(allVars[i]->symTabName().c_str(), name) == 0)
589      {
590         return addSpace->findOrCreateVariable(allVars[i]);
591      }
592    }
593
594    return NULL;
595 }
596
597 bool BPatch_module::getVariablesInt(BPatch_Vector<BPatch_variableExpr *> &vars)
598 {
599    if (!isValid())
600       return false;
601    if (!full_var_parse) {
602       const pdvector<int_variable*> &vars = mod->getAllVariables();
603       for (unsigned i=0; i<vars.size(); i++) {
604          if (!var_map.count(vars[i])) {
605             addSpace->findOrCreateVariable(vars[i]);
606          }
607       }
608       full_var_parse = true;
609    }      
610
611    BPatch_varMap::iterator i = var_map.begin();
612    for (; i != var_map.end(); i++) {
613       vars.push_back((*i).second);
614    }
615
616    return true;
617 }
618
619 /* This function should be deprecated. */
620 bool BPatch_module::getLineToAddrInt( unsigned int lineNo, 
621       BPatch_Vector< unsigned long > & buffer, bool ) 
622 {
623    if (!isValid()) {
624       fprintf(stderr, "%s[%d]: module is not valid\n", FILE__, __LINE__);
625       return false;
626    }
627
628    std::vector< std::pair< Address, Address > > ranges;
629    if ( ! getAddressRangesInt( NULL, lineNo, ranges ) ) { 
630       return false; 
631    }
632
633    for ( unsigned int i = 0; i < ranges.size(); ++i ) {
634       buffer.push_back( ranges[i].first + mod->obj()->codeBase());
635    }
636
637    return true;
638 } /* end getLineToAddr() */
639
640 bool BPatch_module::getSourceLinesInt(unsigned long addr, 
641       BPatch_Vector< BPatch_statement> &lines) 
642 {
643    if (!isValid()) 
644    {
645       fprintf(stderr, "%s[%d]:  failed to getSourceLines: invalid\n", FILE__, __LINE__);
646       return false;
647    }
648
649    unsigned int originalSize = lines.size();
650    std::vector<Statement *> lines_ll;
651
652    Module *stmod = mod->pmod()->mod();
653    assert(stmod);
654
655    if (!stmod->getSourceLines(lines_ll, addr - mod->obj()->codeBase()))
656    {
657            return false;
658    }
659
660    for (unsigned int j = 0; j < lines_ll.size(); ++j)
661    {
662            Statement *t = lines_ll[j];
663            lines.push_back(BPatch_statement(this, t));
664    }
665
666    return (lines.size() != originalSize);
667 } /* end getSourceLines() */
668
669 bool BPatch_module::getStatementsInt(BPatch_Vector<BPatch_statement> &statements)
670 {
671         // Iterate over each address range in the line information
672         SymtabAPI::Module *stmod = mod->pmod()->mod();
673         assert(stmod);
674         std::vector<SymtabAPI::Statement *> statements_ll;
675
676         if (!stmod->getStatements(statements_ll))
677         {
678                 return false;
679         }
680
681         for (unsigned int i = 0; i < statements_ll.size(); ++i)
682         {
683                 // Form a BPatch_statement object for this entry
684                 // Note:  Line information stores offsets, so we need to adjust to
685                 //  addresses
686                 SymtabAPI::Statement *stm = statements_ll[i];
687                 BPatch_statement statement(this, stm);
688
689                 // Add this statement
690                 statements.push_back(statement);
691
692         }
693         return true;
694
695 }
696
697 bool BPatch_module::getAddressRangesInt( const char * fileName, 
698                 unsigned int lineNo, std::vector< std::pair< Address, Address > > & ranges ) 
699 {
700         unsigned int starting_size = ranges.size();
701
702    if (!isValid()) 
703    {
704       fprintf(stderr, "%s[%d]:  module is not valid\n", FILE__, __LINE__);
705       return false;
706    }
707
708    if ( fileName == NULL )
709    {
710            fileName = mod->fileName().c_str();
711    }
712
713    if (!mod->pmod()->mod()->getAddressRanges(ranges, std::string(fileName), lineNo))
714    {
715            return false;
716    }
717
718
719    //  Iterate over the returned offset ranges to turn them into addresses
720    for (unsigned int i = starting_size; i < ranges.size(); ++i)
721    {
722            ranges[i].first += mod->obj()->codeBase();
723            ranges[i].second += mod->obj()->codeBase();
724    }
725
726    return true;
727
728 } /* end getAddressRanges() */
729
730 bool BPatch_module::isSharedLibInt() 
731 {
732         return mod->obj()->isSharedLib();
733 }
734
735 /*
736  * BPatch_module::getBaseAddr
737  *
738  * Returns the starting address of the module.
739  */
740 void *BPatch_module::getBaseAddrInt()
741 {
742    return (void *)mod->obj()->codeAbs();
743 }
744
745 /*
746  * BPatch_module::getSize
747  *
748  * Returns the size of the module in bytes.
749  */
750 unsigned long BPatch_module::getSizeInt() 
751 {
752    if (!mod) return 0;
753    return (unsigned long) mod->obj()->imageSize();
754 }
755
756
757 bool BPatch_module::isNativeCompilerInt()
758 {
759    if (!mod) return false;
760    return mod->obj()->parse_img()->isNativeCompiler();
761 }
762
763 size_t BPatch_module::getAddressWidthInt()
764 {
765    if (!mod) return 0;
766    return mod->obj()->parse_img()->getObject()->getAddressWidth();
767 }
768
769 void BPatch_module::setDefaultNamespacePrefix(char * /*name*/) 
770
771 }
772
773 bool BPatch_module::isSystemLib() 
774 {
775    if (!mod) return false;
776    string str = mod->fileName();
777
778    // Solaris 2.8... we don't grab the initial func always,
779    // so fix up this code as well...
780 #if defined(os_solaris)
781    if (strstr(str.c_str(), "libthread"))
782       return true;
783 #endif
784 #if defined(os_linux)
785    if (strstr(str.c_str(), "libc.so"))
786       return true;
787    if (strstr(str.c_str(), "libpthread"))
788       return true;
789 #endif
790
791    if (strstr(str.c_str(), "libdyninstAPI_RT"))
792       return true;
793 #if defined(os_windows)
794    if (strstr(str.c_str(), "kernel32.dll"))
795       return true;
796    if (strstr(str.c_str(), "user32.dll"))
797       return true;
798    if (strstr(str.c_str(), "ntdll.dll"))
799       return true;
800 #endif
801
802    return false;
803 }
804
805 AddressSpace *BPatch_module::getAS()
806 {
807    return lladdSpace;
808 }
809
810 /* Build up a vector of control flow instructions with suspicious targets
811  * 1. Gather all instructions with static targets that leave the low-level
812  *    mapped_object's image and check to see if they jump into another
813  *    existing module
814  * 2. Add all dynamic call instructions to the vector
815  * 3. Add all dynamic jump instructions to the vector
816  */
817 BPatch_Vector<BPatch_point *> *BPatch_module::getUnresolvedControlFlowInt()
818 {
819     if (unresolvedCF.size()) {
820         unresolvedCF.clear();
821     }
822     std::set<image_instPoint*> ctrlTransfers 
823         = lowlevel_mod()->pmod()->getUnresolvedControlFlow();
824
825     std::set<image_instPoint*>::iterator cIter = ctrlTransfers.begin();
826     while (cIter != ctrlTransfers.end()) {
827         image_instPoint *curPoint = *cIter;
828         Address curAddr = curPoint->offset() 
829             + curPoint->func()->img()->desc().loadAddr();
830         // if this is a static CT skip if target leads to known code
831         if ( ! curPoint->isDynamic() && 
832              getAS()->findOrigByAddr(curPoint->callTarget())) {
833             continue;
834         }
835         // find or create BPatch_point from image_instPoint
836         BPatch_point *bpPoint = NULL;
837         BPatch_function *func = img->findFunctionInt
838             ((unsigned long)curAddr); // takes absolute address
839         if (func) {
840             // Create the vector of call points in the low-level func
841             if (curPoint->getPointType() == callSite) {
842                 func->lowlevel_func()->funcCalls();
843             }
844             // takes absolute address
845             instPoint *intPt = func->lowlevel_func()
846                 ->findInstPByAddr(curAddr);
847             if (!intPt) {// instPoint does not exist, create it
848                 intPt = instPoint::createParsePoint
849                     (func->lowlevel_func(), curPoint);
850             }
851             if (!intPt) {
852                 fprintf(stderr,"%s[%d] Did not find instPoint for "
853                         "unresolved control transfer at %lx\n",
854                         __FILE__,__LINE__, (long)curAddr);
855                 continue;
856             }
857             if (intPt->getPointType() == callSite) {
858                 bpPoint = addSpace->findOrCreateBPPoint
859                     (func, intPt, BPatch_locSubroutine);
860             } else {
861                 bpPoint = addSpace->findOrCreateBPPoint
862                     (func, intPt, BPatch_locLongJump);
863             }
864         } else {
865             fprintf(stderr,"%s[%d] Could not find function corresponding to "
866                     "unresolved control transfer at %lx\n",
867                     __FILE__,__LINE__, (long)curAddr);
868         } 
869         // add BPatch_point to vector of unresolved control transfers
870         if (bpPoint == NULL) {
871             fprintf(stderr,"%s[%d] Control transfer at %lx not instrumentable\n",
872                     __FILE__,__LINE__, (long)curAddr);
873         } else {
874             unresolvedCF.push_back(bpPoint);
875         }
876         cIter++;
877     }
878     return &unresolvedCF;
879 }
880
881 Address BPatch_module::getLoadAddrInt()
882 {
883    return mod->obj()->codeBase();
884 }
885
886 BPatchSnippetHandle* BPatch_module::insertInitCallbackInt(BPatch_snippet& what)
887 {
888     BPatch_Vector<BPatch_function*> init_funcs;
889     findFunction("_init", init_funcs);    
890     if(!init_funcs.empty())
891     {
892         assert(init_funcs[0]);
893         BPatch_Vector<BPatch_point*>* init_entry = init_funcs[0]->findPoint(BPatch_entry);
894         if(init_entry && !init_entry->empty() && (*init_entry)[0])
895         {
896             startup_printf("\tinserting init snippet at 0x%lx\n", (*init_entry)[0]->getAddress());
897             return addSpace->insertSnippet(what, *((*init_entry)[0]));
898         }
899     }
900     return NULL;
901 }
902
903 BPatchSnippetHandle* BPatch_module::insertFiniCallbackInt(BPatch_snippet& what)
904 {
905     BPatch_Vector<BPatch_function*> fini_funcs;
906     findFunction("_fini", fini_funcs);
907     if(!fini_funcs.empty())
908     {
909         assert(fini_funcs[0]);
910         BPatch_Vector<BPatch_point*>* fini_exit = fini_funcs[0]->findPoint(BPatch_exit);
911         if(fini_exit && !fini_exit->empty() && (*fini_exit)[0])
912         {
913             startup_printf("\tinserting fini snippet at 0x%lx\n", (*fini_exit)[0]->getAddress());
914             return addSpace->insertSnippet(what, *((*fini_exit)[0]));
915         }
916     }
917     return NULL;
918 }
919
920
921 #ifdef IBM_BPATCH_COMPAT
922
923 bool BPatch_module::getLineNumbersInt( unsigned int & startLine, unsigned int & endLine )
924 {
925    /* I don't think this function has ever returned nonzeroes.  Approximate a better 
926       result by with the line numbers for the first and last addresses in the module. */
927    if (!mod) return false;
928
929    void * startAddr, * endAddr;
930    if( ! getAddressRangeInt( startAddr, endAddr ) ) {
931       return false;
932    }
933
934    bool setAValue = false;
935    BPatch_Vector<BPatch_statement> lines;
936    getSourceLines( (Address)startAddr, lines );
937    if( lines.size() != 0 ) {
938       startLine = lines[0].lineNumber();
939       setAValue = true;
940    }
941
942    lines.clear();
943    getSourceLines( (Address)endAddr, lines );
944    if( lines.size() != 0 ) {
945       endLine = lines[0].lineNumber();
946       setAValue = true;
947    }
948
949    return setAValue;
950 }
951
952 bool BPatch_module::getAddressRangeInt(void * &start, void * &end)
953 {
954    // Code? Data? We'll do code for now...
955    if (!mod) return false;
956    start = (void *)(mod->obj()->codeAbs());
957    end = (void *)(mod->obj()->codeAbs() + mod->obj()->imageSize());
958    return true;
959 }
960 char *BPatch_module::getUniqueStringInt(char *buffer, int length)
961 {
962    // Use "<program_name>|<module_name>" as the unique name if this module is
963    // part of the executable and "<module_name>" if it is not.
964    if (!mod) return NULL;
965    if(isSharedLib())
966       snprintf(buffer, length, "%s", mod->fileName().c_str());
967    else {
968       char prog[1024];
969       addSpace->getImage()->getProgramFileName(prog, 1024);
970       snprintf(buffer, length, "%s|%s",
971             prog, mod->fileName().c_str());
972    }
973    // Return the unique name to the caller
974    return buffer;
975 }
976
977 int BPatch_module::getSharedLibTypeInt()        
978 {
979    return 0;
980 }
981
982 int BPatch_module::getBindingTypeInt()
983 {
984    return 0;
985 }
986
987 std::vector<struct BPatch_module::Statement> BPatch_module::getStatementsInt()
988 {
989    std::vector<struct BPatch_module::Statement> statements;
990    if (!mod) return statements;
991
992    Module *stmod = mod->pmod()->mod();
993    assert(stmod);
994    if (!stmod->getStatements(statements_ll))
995    {
996            return statements;
997    }
998
999    for (unsigned int i = 0; i < statements_ll.size(); ++i)
1000    {
1001            // Form a BPatch_statement object for this entry
1002            // Note:  Line information stores offsets, so we need to adjust to
1003            //  addresses
1004            SymtabAPI::Statement &stm = statements_ll[i];
1005            BPatch_statement statement(this, stm.file().c_str(), stm.line(),
1006                            stm.column(), (void *)(mod->obj()->codeBase() + stm.startAddr()),
1007                            (void *)(mod->obj()->codeBase() + stm.endAddr()));
1008
1009            // Add this statement
1010            statements.push_back(statement);
1011    }
1012
1013    // Return the statements to the caller
1014    return statements;
1015
1016 }
1017 #endif