- New file to extract type info from executables in Coff format
[dyninst.git] / dyninstAPI / src / symtab.C
1 /*
2  * Copyright (c) 1996 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: symtab.C,v 1.105 2000/01/11 21:55:36 altinel Exp $
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <assert.h>
47
48 // TODO - machine independent instruction functions
49 #include "dyninstAPI/src/symtab.h"
50 #include "dyninstAPI/src/arch.h"
51 #include "dyninstAPI/src/instPoint.h"
52 #include "util/h/Object.h"
53 #include <fstream.h>
54 #include "dyninstAPI/src/util.h"
55 #include "dyninstAPI/src/dyninstP.h"
56 #include "util/h/String.h"
57 #include "dyninstAPI/src/inst.h"
58 #include "util/h/Timer.h"
59 #include "dyninstAPI/src/showerror.h"
60 #include "util/h/debugOstream.h"
61 #include "util/h/pathName.h"          // extract_pathname_tail()
62 #include "dyninstAPI/src/process.h"   // process::getBaseAddress()
63
64 #ifndef BPATCH_LIBRARY
65 #include "paradynd/src/mdld.h"
66 #include "paradynd/src/main.h"
67 #include "paradynd/src/init.h"
68 #include "util/h/Dictionary.h"
69 #else
70 extern vector<sym_data> syms_to_find;
71 #endif
72
73 // All debug_ostream vrbles are defined in process.C (for no particular reason)
74 extern debug_ostream sharedobj_cerr;
75
76 vector<image*> image::allImages;
77
78 #if defined(i386_unknown_nt4_0)
79 extern char *cplus_demangle(char *, int);
80 #else
81 extern "C" char *cplus_demangle(char *, int);
82 #endif
83
84
85 /*
86   Debuggering info for function_base....
87  */
88 ostream & function_base::operator<<(ostream &s) const {
89     s << "symTabName_ = " << symTabName_ << " prettyName_ = "
90       << prettyName_
91       << " line_ = " << line_ << " addr_ = "<< addr_ << " size_ = " << size_
92       << " tag_ = " << tag_ << endl;
93     return s;
94 }
95
96 ostream &operator<<(ostream &os, function_base &f) {
97     return f.operator<<(os);
98 }
99
100 /* imported from platform specific library list.  This is lists all
101    library functions we are interested in instrumenting. */
102
103 pdmodule *image::newModule(const string &name, const Address addr)
104 {
105     pdmodule *ret;
106     // modules can be defined several times in C++ due to templates and
107     //   in-line member functions.
108     if ((ret = findModule(name, TRUE)))
109       return(ret);
110
111     string fullNm, fileNm;
112     char *out = P_strdup(name.string_of());
113     char *sl = P_strrchr(out, '/');
114     if (sl) {
115       *sl = (char)0;
116       fullNm = out;
117       fileNm = sl+1;
118     } else {
119       fullNm = string("/default/") + out;
120       fileNm = out;
121     }
122     free(out);
123
124     ret = new pdmodule(lang_Unknown, addr, fullNm, fileNm, this);
125
126 #ifndef BPATCH_LIBRARY
127     // if module was excluded,stuff it into excludedMods (and dont
128     //  index it in modeByFileName && modsByFullName.
129     if (module_is_excluded(ret)) {
130         excludedMods += ret;
131     } else {
132 #endif /* BPATCH_LIBRARY */
133         modsByFileName[ret->fileName()] = ret;
134         modsByFullName[ret->fullName()] = ret;
135         includedMods += ret;
136 #ifndef BPATCH_LIBRARY
137     }
138 #endif /* BPATCH_LIBRARY */
139
140     return(ret);
141 }
142
143
144 // TODO -- is this g++ specific
145 bool buildDemangledName(const string &mangled, string &use)
146 {
147  /* The C++ demangling function demangles MPI__Allgather (and other MPI__
148   * functions with start with A) into the MPI constructor.  In order to
149   * prevent this a hack needed to be made, and this seemed the cleanest
150   * approach.
151   */
152   if(!mangled.prefixed_by("MPI__")) {
153     char *tempName = P_strdup(mangled.string_of());
154     char *demangled = cplus_demangle(tempName, 0);
155     
156     if (demangled) {
157       use = demangled;
158       free(tempName);
159       free(demangled);
160       return true;
161     } else {
162       free(tempName);
163       return false;
164     }
165   }
166   return(false);
167 }
168
169 // err is true if the function can't be defined
170 // COMMENTS????
171 // looks like this function attempts to do several things:
172 //  1) Check if can find the function (WHERE DOES IT LOOK????).
173 //  2) strip out something from function name which looks like
174 //    possible scoping info (everything up to?? ":")??
175 //  3) try to demangle this (descoped??) name.
176 //  4) make new pd_Function under origional name and demangled name.
177 //  5) Insert into (data members) funcsByAdd && mods->funcs.
178 //  n) insert into (data member) funcsByPretty (indexed under 
179 //    demangled name).
180 bool image::newFunc(pdmodule *mod, const string &name, const Address addr, 
181                     const unsigned size, const unsigned tag, 
182                     pd_Function *&retFunc) {
183   pd_Function *func;
184
185   retFunc = NULL;
186   // KLUDGE
187   if ((func = findFunction(addr, TRUE))){
188     //string temp = name;
189     //temp += string(" findFunction succeeded\n");
190     //logLine(P_strdup(temp.string_of()));
191     return false;
192   }
193
194   if (!mod) {
195     logLine("Error function without module\n");
196     showErrorCallback(34, "Error function without module");
197     return false;
198   }
199   
200   string mangled_name = name;
201   const char *p = P_strchr(name.string_of(), ':');
202   if (p) {
203      unsigned nchars = p - name.string_of();
204      mangled_name = string(name.string_of(), nchars);
205   }
206      
207   string demangled;
208   if (!buildDemangledName(mangled_name, demangled)) 
209     demangled = mangled_name;
210
211   bool err=false;
212   
213   func = new pd_Function(name, demangled, mod, addr, size, tag, this, err);
214   assert(func);
215   //cout << name << " pretty: " << demangled << " addr :" << addr <<endl;
216   retFunc = func;
217   // if there was an error in determining the instrumentation info for
218   //  function, add it to notInstruFunction.
219   if (err) {
220     //delete func;
221     retFunc = NULL;
222     addNotInstruFunc(func);
223     return false;
224   }
225  
226   addInstruFunction(func, mod, addr,
227 #ifdef BPATCH_LIBRARY
228                     false);
229 #else
230                     function_is_excluded(func, mod->fileName()));
231 #endif
232   return true;
233 }
234
235 void image::addInstruFunction(pd_Function *func, pdmodule *mod,
236                               const Address addr, bool excluded) {
237     vector<pd_Function*> *funcsByPrettyEntry = NULL;
238     vector<pd_Function*> *funcsByMangledEntry = NULL;
239
240     // any functions whose instrumentation info could be determined 
241     //  get added to instrumentableFunctions, and mod->funcs.
242     instrumentableFunctions += func;
243     mod->funcs += func;
244
245     if (excluded) {
246         excludedFunctions[func->prettyName()] = func;
247     } else {
248         includedFunctions += func;
249         funcsByAddr[addr] = func;
250         if (!funcsByPretty.find(func->prettyName(), funcsByPrettyEntry)) {
251             funcsByPrettyEntry = new vector<pd_Function*>;
252             funcsByPretty[func->prettyName()] = funcsByPrettyEntry;
253         }
254         // several functions may have the same demangled name, and each one
255         // will appear in a different module
256         assert(funcsByPrettyEntry);
257         (*funcsByPrettyEntry) += func;
258
259         if (!funcsByMangled.find(func->symTabName(), funcsByMangledEntry)) {
260             funcsByMangledEntry = new vector<pd_Function*>;
261             funcsByMangled[func->symTabName()] = funcsByMangledEntry;
262         }
263         // several functions may have the same demangled name, and each one
264         // will appear in a different module
265         assert(funcsByMangledEntry);
266         (*funcsByMangledEntry) += func;
267     }
268 }
269
270 void image::addNotInstruFunc(pd_Function *func) {
271     notInstruFunctions[func->prettyName()] = func;
272 }
273
274 #ifdef DEBUG_TIME
275 static timer loadTimer;
276 static FILE *timeOut=0;
277 #endif /* DEBUG_TIME */
278
279 /*
280  * load an executable:
281  *   1.) parse symbol table and identify rotuines.
282  *   2.) scan executable to identify inst points.
283  *
284  *  offset is normally zero except on CM-5 where we have two images in one
285  *    file.  The offset passed to parseImage is the logical offset (0/1), not
286  *    the physical point in the file.  This makes it faster to "parse" multiple
287  *    copies of the same image since we don't have to stat and read to find the
288  *    physical offset. 
289  */
290 image *image::parseImage(const string file)
291 {
292   /*
293    * Check to see if we have parsed this image at this offeset before.
294    */
295   // TODO -- better method to detect same image/offset --> offset only for CM5
296
297   unsigned numImages = allImages.size();
298
299   for (unsigned u=0; u<numImages; u++)
300     if (file == allImages[u]->file())
301       return allImages[u];
302
303   /*
304    * load the symbol table. (This is the a.out format specific routine).
305    */
306
307   statusLine("Process executable file");
308   bool err=false;
309
310   // TODO -- kill process here
311   image *ret = new image(file, err);
312   if (err || !ret) {
313     if (ret)
314       delete ret;
315     return NULL;
316   }
317
318   // Add to master image list.
319   image::allImages += ret;
320
321   // define all modules.
322 #ifndef BPATCH_LIBRARY
323   tp->resourceBatchMode(true);
324 #endif
325
326   statusLine("defining modules");
327   ret->defineModules();
328
329 //  statusLine("ready"); // this shouldn't be here, right? (cuz we're not done, right?)
330
331 #ifndef BPATCH_LIBRARY
332   tp->resourceBatchMode(false);
333 #endif
334
335   return(ret);
336 }
337
338 /*
339  * load a shared object:
340  *   1.) parse symbol table and identify rotuines.
341  *   2.) scan executable to identify inst points.
342  *
343  */
344 image *image::parseImage(const string file, Address baseAddr)
345 {
346   /*
347    * Check to see if we have parsed this image at this offeset before.
348    */
349   // TODO -- better method to detect same image/offset --> offset only for CM5
350
351   unsigned theSize = allImages.size();
352
353   for (unsigned u=0; u<theSize; u++)
354     if (file == allImages[u]->file())
355       return allImages[u];
356
357   /*
358    * load the symbol table. (This is the a.out format specific routine).
359    */
360
361   if(!baseAddr) statusLine("Processing an executable file");
362   else  statusLine("Processing a shared object file");
363   bool err=false;
364
365   // TODO -- kill process here
366   image *ret = new image(file, baseAddr, err);
367   if (err || !ret) {
368     if (ret)
369       delete ret;
370     //logLine("error after new image in parseImage\n");
371     return NULL;
372   }
373
374   // Add to master image list.
375   image::allImages += ret;
376
377   // define all modules.
378   ret->defineModules();
379   return(ret);
380 }
381
382 // COMMENTS??  COMMENTS??
383 // check symbol whose name is in <str>.  If it is prefixed by
384 // "_DYNINST" or "_TRACELIB", then assume that that it is an
385 // "internal" symbol, and add it to (private data member) 
386 // iSymsMap.
387 bool image::addInternalSymbol(const string &str, const Address symValue) {
388   // Internal symbols are prefixed by { DYNINST, TRACELIB }
389   // don't ignore the underscore
390   static string dyn = "_DYNINST"; 
391   static string tlib = "_TRACELIB";
392
393
394   // normalize all symbols -- remove the leading "_"
395   if (str.prefixed_by(dyn)) {
396     const char *s = str.string_of(); s++;
397     if (!iSymsMap.defines(s)){
398       iSymsMap[s] = new internalSym(symValue, s);
399     }
400     return true;
401   } else if (str.prefixed_by(tlib)) {
402     const char *s = str.string_of(); s++;
403     if (!iSymsMap.defines(s))
404       iSymsMap[s] = new internalSym(symValue, s);
405     return true;
406   } else {
407     if (!iSymsMap.defines(str))
408       iSymsMap[str] = new internalSym(symValue, str);
409     return true;
410   }
411   return false;
412 }
413
414 #ifndef BPATCH_LIBRARY
415 /*
416  * will search for symbol NAME or _NAME
417  * returns false on failure 
418  */
419 bool image::findInternalSymbol(const string &name, 
420                                const bool warn, 
421                                internalSym &ret_sym)
422 {
423    Symbol lookUp;
424
425    if(linkedFile.get_symbol(name,lookUp)){
426       ret_sym = internalSym(lookUp.addr(),name); 
427       return true;
428    }
429    else {
430        string new_sym;
431        new_sym = string("_") + name;
432        if(linkedFile.get_symbol(new_sym,lookUp)){
433           ret_sym = internalSym(lookUp.addr(),name); 
434           return true;
435        }
436    } 
437    if(warn){
438       string msg;
439       msg = string("Unable to find symbol: ") + name;
440       statusLine(msg.string_of());
441       showErrorCallback(28, msg);
442    }
443    return false;
444 }
445
446 Address image::findInternalAddress(const string &name, 
447                                    const bool warn, 
448                                    bool &err)
449 {
450   err = false;
451
452   internalSym *theSym; // filled in by find()
453   if (!iSymsMap.find(name, theSym)) {
454     // not found!
455     if (warn) {
456       string msg = string("Unable to find symbol: ") + name;
457       statusLine(msg.string_of());
458       showErrorCallback(28, msg);
459     }
460     err = true;
461     return 0;
462   } 
463   else
464     return (theSym->getAddr());
465 }
466
467 #endif
468
469 pdmodule *image::findModule(const string &name, bool find_if_excluded)
470 {
471   unsigned i;
472
473   //cerr << "image::findModule " << name << " , " << find_if_excluded
474   //     << " called" << endl;
475
476   if (modsByFileName.defines(name)) {
477     //cerr << " (image::findModule) found module in modsByFileName" << endl;
478     return (modsByFileName[name]);
479   }
480   else if (modsByFullName.defines(name)) {
481     //cerr << " (image::findModule) found module in modsByFuleName" << endl;
482     return (modsByFullName[name]);
483   }
484   
485   // if also looking for excluded functions, check through 
486   //  excludedFunction list to see if any match function by FullName
487   //  or FileName....
488   if (find_if_excluded) {
489       for(i=0;i<excludedMods.size();i++) {
490         if ((excludedMods[i]->fileName() == name) ||
491                   (excludedMods[i]->fullName() == name)) {
492           //cerr << " (image::findModule) found module in excludedMods" << endl;
493           return excludedMods[i];
494         }
495       }
496   }
497
498   //cerr << " (image::findModule) did not find module, returning NULL" << endl;
499   return NULL;
500 }
501
502 // TODO -- this is only being used in cases where only one function
503 // should exist -- should I assert that the vector size <= 1 ?
504 // mcheyney - should return NULL when function being searched for 
505 //  is excluded!!!!
506 // Checks for function in pretty name hash first, then in
507 //  mangled name hash to better handle many (mangled name) to one 
508 //  (pretty name) mapping in C++ function names....
509 pd_Function *image::findOneFunction(const string &name)
510 {
511   vector<pd_Function*> *a;
512
513   //cerr << "image::findOneFunction " << name << " called" << endl;
514   if (funcsByPretty.defines(name)) {
515     a = funcsByPretty[name];
516   } else if (funcsByMangled.defines(name)) {
517     a = funcsByMangled[name];
518   } else {
519     //cerr << " returning NULL" << endl;
520     return NULL;
521   }
522   assert(a);
523   if (!a->size()) {
524     //cerr << " returning NULL" << endl;
525     return NULL;
526   }
527   //cerr << " returning a pd_Function : " << endl;
528   //cerr << "  prettyName : " << ((*a)[0])->prettyName() << endl;
529   //cerr << "  symTabName : " << ((*a)[0])->symTabName() << endl;
530   return ((*a)[0]);
531 }
532
533 // This function supposely is only used to find function that
534 // is not instrumentable which may not be totally defined.
535 // Use with caution.  
536 // NEW - also can be used to find an excluded function....
537 pd_Function *image::findOneFunctionFromAll(const string &name) {
538     pd_Function *ret;
539     if ((ret = findOneFunction(name))) 
540         return ret;
541
542     //cerr << "image::findOneFunctionFromAll " << name <<
543     //" called, unable to find function in hash table" << endl; 
544
545     if (notInstruFunctions.defines(name)) {
546       //cerr << "  (image::findOneFunctionFromAll) found in notInstruFunctions"
547       //<< endl;
548         return notInstruFunctions[name];
549     }
550
551     if (excludedFunctions.defines(name)) {
552       //cerr << "  (image::findOneFunctionFromAll) found in excludedFunctions"
553       //<< endl;
554         return excludedFunctions[name];
555     }
556     return NULL;
557 }
558
559 // Only looks for function by pretty name.
560 //  Should it also look by mangled name??
561 bool image::findFunction(const string &name, vector<pd_Function*> &retList,
562         bool find_if_excluded) {
563
564     bool found = FALSE;
565     if (funcsByPretty.defines(name)) {
566         retList = *funcsByPretty[name];
567         found = TRUE;
568     } 
569
570     if (find_if_excluded) {
571         // should APPEND to retList!!!!
572         if (find_excluded_function(name, retList)) {
573             found = TRUE;
574         }
575     }    
576     return found;
577 }
578
579 pd_Function *image::findFunction(const Address &addr, bool find_if_excluded) 
580 {
581   pd_Function *result; // filled in by find()
582   if (funcsByAddr.find(addr, result))
583      return result;
584   if (find_if_excluded) {
585      return find_excluded_function(addr);
586   }
587   return NULL;
588 }
589
590 // find (excluded only) function byt address.... 
591 pd_Function *image::find_excluded_function(const Address &addr) 
592 {
593     pd_Function *this_func = NULL;
594     string str;
595     dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
596     while(ex.next(str, this_func)) {
597         // ALERT ALERT - assumes that code in image is NOT
598         //  relocated!!!!
599         if (addr == this_func->getAddress(0)) {
600             return this_func;
601         }
602     }
603     return NULL;
604 }
605
606 //  Question??  Currently only finding 1 excluded function reference by
607 //  name (e.g. findOneFunctionFromAll.  Want to keep multiple copies
608 // of same excluded function (as referenced by name)??
609 bool image::find_excluded_function(const string &name,
610         vector<pd_Function*> &retList) {
611     bool found = FALSE;
612
613     found = excludedFunctions.defines(name);
614     if (found) {
615         retList += excludedFunctions[name];
616     }
617     return found;
618 }
619
620 pd_Function *image::findFunctionInInstAndUnInst(const Address &addr,const process *p) const 
621 {
622   pd_Function *pdf;
623   vector <pd_Function *> values;
624   unsigned i;
625
626   if (funcsByAddr.find(addr, pdf))
627      return pdf;
628   
629   // If not found, we are going to search them in the 
630   // uninstrumentable function
631   values = notInstruFunctions.values();
632   for (i = 0; i < values.size(); i++) {
633       pdf = values[i];
634       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size())))
635           return pdf;
636   }
637
638   // and in excludedFunctions....
639   values = excludedFunctions.values();
640   for (i = 0; i < values.size(); i++) {
641       pdf = values[i];
642       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size())))
643           return pdf;
644   }
645
646   return NULL; 
647 }
648
649 //This function is identical to FindFunctionIn(), only it
650 //determines the relocated address of functions that have
651 //been relocated, rather than their prelocation address.
652 pd_Function *image::findPossiblyRelocatedFunctionIn(const Address &addr,const process *p) const 
653 {
654   pd_Function *pdf;
655
656   // first, look in funcsByAddr - should contain instrumentable non-
657   //  excluded functions....
658   dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
659   Address adr;
660   while (mi.next(adr, pdf)) {
661     if ((addr>=pdf->getEffectiveAddress(p))&&(addr<(pdf->getEffectiveAddress(p)+pdf->size())))
662       return pdf;
663   }
664
665   // next, look in excludedFunctions...
666   dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
667   string str;
668   while (ex.next(str, pdf)) {
669     if ((addr>=pdf->getEffectiveAddress(p))&&(addr<(pdf->getEffectiveAddress(p)+pdf->size()))) 
670       return pdf;
671   }
672   
673   dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
674   while (ni.next(str, pdf)) {
675     if ((addr>=pdf->getEffectiveAddress(p))&&(addr<(pdf->getEffectiveAddress(p)+pdf->size()))) 
676       return pdf;
677   }
678   
679   return NULL; 
680 }
681  
682
683 pd_Function *image::findFunctionIn(const Address &addr,const process *p) const 
684 {
685   pd_Function *pdf;
686
687   // first, look in funcsByAddr - should contain instrumentable non-
688   //  excluded functions....
689   dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
690   Address adr;
691   while (mi.next(adr, pdf)) {
692     if ((addr>=pdf->getAddress(p))&&(addr<(pdf->getAddress(p)+pdf->size()))){
693       return pdf;
694     }
695   }
696   
697   // next, look in excludedFunctions...
698   dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
699   string str;
700   while (ex.next(str, pdf)) {
701     if ((addr>=pdf->getAddress(p))&&(addr<(pdf->getAddress(p)+pdf->size()))) 
702       return pdf;
703   }
704
705   dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
706   while (ni.next(str, pdf)) {
707     if ((addr>=pdf->getAddress(p))&&(addr<(pdf->getAddress(p)+pdf->size()))) 
708       return pdf;
709   }
710
711   return NULL; 
712 }
713
714
715 #ifndef BPATCH_LIBRARY
716 void image::changeLibFlag(resource *res, const bool setSuppress)
717 {
718   image *ret;
719   pdmodule *mod;
720
721   unsigned numImages = image::allImages.size();
722   for (unsigned u=0; u<numImages; u++) {
723     ret = image::allImages[u];
724     // assume should work even if module excluded....
725     mod = ret->findModule(res->part_name(), TRUE);
726     if (mod) {
727       // suppress all procedures.
728       mod->changeLibFlag(setSuppress);
729     } else {
730       // more than one function may have this name --> templates, statics
731       vector<pd_Function*> pdfA;
732       if (ret->findFunction(res->part_name(), pdfA)) {
733         for (unsigned i=0; i<pdfA.size(); ++i) {
734           if (setSuppress) 
735             pdfA[i]->tagAsLib();
736           else
737             pdfA[i]->untagAsLib();
738         }
739       }
740     }
741   }
742 }
743 #endif
744
745
746 /* 
747  * return 0 if symbol <symname> exists in image, non-zero if it does not
748  */
749 bool image::symbolExists(const string &symname)
750 {
751   pd_Function *dummy = findOneFunction(symname);
752   return (dummy != NULL);
753 }
754
755 #ifndef BPATCH_LIBRARY
756 void image::postProcess(const string pifname)
757 {
758   FILE *Fil;
759   string fname, errorstr;
760   char key[5000];
761   char tmp1[5000], abstraction[500];
762   resource *parent;
763
764   return;
765
766   /* What file to open? */
767   if (!(pifname == (char*)NULL)) {
768     fname = pifname;
769   } else {
770     fname = file_ + ".pif";
771   }
772
773   /* Open the file */
774   Fil = P_fopen(fname.string_of(), "r");
775
776   if (Fil == NULL) {
777     errorstr = string("Tried to open PIF file ") + fname;
778     errorstr += string(", but could not (continuing)\n");
779     logLine(P_strdup(errorstr.string_of()));
780     showErrorCallback(35, errorstr); 
781     return;
782   }
783
784   /* Process the file */
785   while (!feof(Fil)) {
786     fscanf(Fil, "%s", key);
787     switch (key[0]) {
788     case 'M':
789       /* Ignore mapping information for right now */
790       fgets(tmp1, 5000, Fil);
791       break;
792     case 'R':
793 #ifndef BPATCH_LIBRARY
794       /* Create a new resource */
795       fscanf(Fil, "%s {", abstraction);
796       parent = rootResource;
797       do {
798         fscanf(Fil, "%s", tmp1);
799         if (tmp1[0] != '}') {
800           parent = resource::newResource(parent, NULL,
801                                          abstraction,
802                                          tmp1, 0.0,
803                                          nullString, // uniqifier
804                                          MDL_T_STRING,
805                                          true);
806         } else {
807           parent = NULL;
808         }
809       } while (parent != NULL);
810 #endif
811       break;
812     default:
813       errorstr = string("Ignoring bad line key (") + fname;
814       errorstr += string(") in file %s\n");
815       logLine(P_strdup(errorstr.string_of()));
816       fgets(tmp1, 5000, Fil);
817       break;
818     }
819   }
820   return;
821 }
822 #endif
823
824 void image::defineModules() {
825   unsigned i;
826
827   string pds; pdmodule *mod;
828   dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
829
830   while (mi.next(pds, mod)){
831     mod->define();
832   }
833
834   for(i=0;i<excludedMods.size();i++) {
835     mod = excludedMods[i];
836     mod->define();
837   }
838
839 #ifdef DEBUG_MDL
840   char buffer[100];
841   ostrstream osb(buffer, 100, ios::out);
842   osb << "IMAGE_" << name() << "__" << getpid() << ends;
843   ofstream of(buffer, ios::app);
844
845   of << "INCLUDED FUNCTIONS\n";
846   for (unsigned ni=0; ni<includedFunctions.size(); ni++) {
847     of << includedFunctions[ni]->prettyName() << "\t\t" 
848        << includedFunctions[ni]->addr() << "\t\t" << endl;
849   }
850   
851 #endif
852 }
853
854 #ifndef BPATCH_LIBRARY
855 void image::FillInCallGraphStatic(process *proc)
856 {
857   unsigned i;
858   string pds;
859   pdmodule *mod;
860   dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
861   string buffer;
862
863   // define call graph relations for all non-excluded modules.
864   while (mi.next(pds, mod)){
865     buffer = "building call graph module: " +
866       mod->fileName();
867     statusLine(buffer.string_of());
868     mod->FillInCallGraphStatic(proc);
869   }
870   // also define call graph relations for all excluded modules.
871   //  Call graph gets information about both included and excluded 
872   //  modules and functions, and allows the DM and PC to decide whether
873   //  to look at a given function based on whether the function is 
874   //  included or excluded....
875   for(i=0;i<excludedMods.size();i++) {
876     mod = excludedMods[i];
877     buffer = "building call graph module: " +
878       mod->fileName();
879     statusLine(buffer.string_of());
880     mod->FillInCallGraphStatic(proc);
881   }
882 }
883 #endif
884
885 //  Comments on what this does would be nice....
886 //  Appears to run over a pdmodule, after all code in it has been processed
887 //   and parsed into functions, and define a resource for the module + a 
888 //   resource for every function found in the module (apparently includes 
889 //   excluded functions, but not uninstrumentable ones)....
890 //  Can't directly register call graph relationships here as resources
891 //   are being defined, because need all resources defined to 
892 //   do that....
893
894
895 void pdmodule::define() {
896 #ifndef BPATCH_LIBRARY
897   resource *modResource = NULL;
898 #endif
899 #ifdef DEBUG_MODS
900   char buffer[100];
901   ostrstream osb(buffer, 100, ios::out);
902   osb << "MODS_" << exec->name() << "__" << getpid() << ends;
903   ofstream of(buffer, ios::app);
904 #endif
905
906   unsigned f_size = funcs.size();
907
908   for (unsigned f=0; f<f_size; f++) {
909 #ifndef BPATCH_LIBRARY
910     pd_Function *pdf = funcs[f];
911 #ifdef DEBUG_MODS
912     of << fileName << ":  " << pdf->prettyName() <<  "  "
913         << pdf->addr() << endl;
914 #endif
915     // ignore line numbers for now 
916
917     //if (!(pdf->isLibTag())) {
918     if (1) {
919       // see if we have created module yet.
920       if (!modResource) {
921         modResource = resource::newResource(moduleRoot, this,
922                                             nullString, // abstraction
923                                             fileName(), // name
924                                             0.0, // creation time
925                                             string(), // unique-ifier
926                                             MDL_T_MODULE,
927                                             false);
928       }
929
930       pdf->SetFuncResource(resource::newResource(modResource, pdf,
931                                                  nullString, // abstraction
932                                                  pdf->prettyName(), 0.0,
933                                                  nullString, // uniquifier
934                                                  MDL_T_PROCEDURE,
935                                                  false));                  
936       
937     }
938 #endif
939   }
940
941 #ifndef BPATCH_LIBRARY
942   resource::send_now();
943 #endif
944 }
945
946 #ifndef BPATCH_LIBRARY
947 // send message to data manager to specify the entry function for the
948 //  call graph corresponding to a given image.  r should hold the 
949 //  FULL resourcename of the entry function (e.g. "/Code/module.c/main")
950 void CallGraphSetEntryFuncCallback(string exe_name, string r)
951 {
952     tp->CallGraphSetEntryFuncCallback(exe_name, r);
953 }
954
955 void CallGraphAddProgramCallback(string name){
956   tp->CallGraphAddProgramCallback(name);
957 }
958
959 //send message to the data manager, notifying it that all of the statically
960 //determinable functions have been registered with the call graph. The
961 //data manager will then be able to create the call graph.
962 void CallGraphFillDone(string exe_name)
963 {
964   tp->CallGraphFillDone(exe_name);
965 }
966
967 //send message to the data manager in order to register a function 
968 //in the call graph.
969 void AddCallGraphNodeCallback(string exe_name, string r)
970 {
971     tp->AddCallGraphNodeCallback(exe_name, r);
972 }
973
974 //send a message to the data manager in order register a the function
975 //calls made by a function (whose name is stored in r).
976 void AddCallGraphStaticChildrenCallback(string exe_name, string r,
977                                         const vector<string> children) 
978 {
979     tp->AddCallGraphStaticChildrenCallback(exe_name, r, children);
980 }
981
982 // Called across all modules (in a given image) to define the call
983 //  graph relationship between functions.
984 // Must be called AFTER all functions in all modules (in image) are
985 //  registered as resource (e.g. w/ pdmodule::define())....
986 void pdmodule::FillInCallGraphStatic(process *proc) {
987   pd_Function *pdf, *callee;
988   vector <pd_Function *>callees;
989   resource *r , *callee_as_resource;
990   string callee_full_name;
991   vector <string>callees_as_strings;
992   vector <instPoint*> callPoints; 
993   unsigned f, g,i, f_size = funcs.size();
994   
995   string resource_full_name;
996   
997   // for each INSTRUMENTABLE function in the module (including excluded 
998   //  functions, but NOT uninstrumentable ones)....
999   
1000   for (f=0;f<f_size;f++) {
1001     pdf = funcs[f];
1002     
1003     callees_as_strings.resize(0);
1004     
1005     // Translate from function name to resource *.
1006     // Note that this probably is NOT the correct translation, as 
1007     //  function names are not necessarily unique, but the paradyn
1008     //  code assumes that they are in several places (e.g. 
1009     //  resource::findResource)....
1010     resource_full_name = pdf->ResourceFullName();
1011     r = resource::findResource(resource_full_name);
1012     // functions registered under pretty name....
1013     assert(r != NULL);
1014     
1015     // get list of statically determined call destinations from pdf,
1016     //  using the process info to help fill in calls througb PLT
1017     //  entries....
1018     pdf->getStaticCallees(proc, callees); 
1019     
1020     // and convert them into a list of resources....
1021     for (g=0;g<callees.size();g++) {
1022       callee = callees[g];
1023       assert(callee);
1024       
1025       //if the funcResource is not set, then the function must be
1026       //uninstrumentable, so we don't want to notify the front end
1027       //of its existence
1028       if(callee->FuncResourceSet()){
1029         callee_full_name = callee->ResourceFullName();
1030         
1031         // if callee->funcResource has been set, then it should have 
1032         //  been registered as a resource.... 
1033         callee_as_resource = resource::findResource(callee_full_name);
1034         assert(callee_as_resource);
1035         callees_as_strings += callee_full_name;
1036         }
1037       
1038     }//end for
1039     
1040     // register that callee_resources holds list of resource*s 
1041     //  describing children of resource r....
1042     string exe_name = proc->getImage()->file();
1043     AddCallGraphNodeCallback(exe_name, resource_full_name);
1044     AddCallGraphStaticChildrenCallback(exe_name, resource_full_name,
1045                                        callees_as_strings);
1046
1047     //Locate the dynamic call sites within the function, and notify 
1048     //the front end as to their existence
1049     callPoints = pdf->funcCalls(proc);
1050     for(i = 0; i < callPoints.size(); i++){
1051       if(proc->isDynamicCallSite(callPoints[i])){
1052         tp->CallGraphAddDynamicCallSiteCallback(exe_name, resource_full_name);
1053         break;
1054       }
1055     }
1056   }
1057 }
1058 #endif // ndef BPATCH_LIBRARY
1059
1060 // get all functions in module which are not "excluded" (e.g.
1061 //  with mdl "exclude" command.  
1062 // Assed to provide support for mdl "exclude" on functions in
1063 //  statically linked objects.
1064 //  mcheyney 970727
1065 vector<function_base *> *pdmodule::getIncludedFunctions() {
1066     // laxy construction of some_funcs, as per sharedobject class....
1067     // cerr << "pdmodule " << fileName() << " :: getIncludedFunctions called "
1068     //      << endl;
1069     if (some_funcs_inited == TRUE) {
1070         //cerr << "  about to return : " << endl;
1071         //print_func_vector_by_pretty_name(string("  "), (vector<function_base *>*)&some_funcs);
1072         return (vector<function_base *>*)&some_funcs;
1073     }
1074 #ifdef BPATCH_LIBRARY  //BPatch Library doesn't know about excluded funcs 
1075     some_funcs = funcs;
1076 #else
1077     some_funcs.resize(0);
1078     
1079     if (filter_excluded_functions(funcs, some_funcs, fileName()) == FALSE) {
1080         //cerr << "  about to return NULL";
1081         return NULL;
1082     }
1083 #endif
1084     some_funcs_inited = TRUE;
1085     
1086     //cerr << "  about to return : " << endl;
1087     //print_func_vector_by_pretty_name(string("  "),(vector<function_base *>*) &some_funcs);
1088     return (vector<function_base *>*)&some_funcs;
1089 }
1090
1091
1092 const vector<pd_Function*> &image::getAllFunctions() {
1093     //cerr << "pdmodule::getAllFunctions() called, about to return instrumentableFunctions = " << endl;
1094     //print_func_vector_by_pretty_name(string("  "),
1095     //        (vector<function_base*>*)&instrumentableFunctions);
1096     return instrumentableFunctions;
1097 }
1098
1099 const vector <pdmodule*> &image::getAllModules() {
1100     // reinit all modules to empty vector....
1101     allMods.resize(0);
1102
1103     // and add includedModules && excludedModules to it....
1104     allMods += includedMods;
1105     allMods += excludedMods;
1106
1107     //cerr << "image::getAllModules called" << endl;
1108     //cerr << " about to return sum of includedMods and excludedMods" << endl;
1109     //cerr << " includedMods : " << endl;
1110     //print_module_vector_by_short_name(string("  "), &includedMods);
1111     //cerr << " excludedMods : " << endl;
1112     //print_module_vector_by_short_name(string("  "), &excludedMods);
1113     
1114     return allMods;
1115 }
1116
1117
1118 #ifndef BPATCH_LIBRARY
1119 const vector <pdmodule*> &image::getIncludedModules() {
1120     //cerr << "image::getIncludedModules called" << endl;
1121     //cerr << " about to return includedMods = " << endl;
1122     //print_module_vector_by_short_name(string("  "), &includedMods);
1123
1124     return includedMods;
1125 }
1126 #endif
1127
1128 void print_module_vector_by_short_name(string prefix ,
1129                                        vector<pdmodule*> *mods) {
1130     unsigned int i;
1131     pdmodule *mod;
1132     for(i=0;i<mods->size();i++) {
1133         mod = ((*mods)[i]);
1134         cerr << prefix << mod->fileName() << endl;
1135     }
1136 }
1137
1138 void print_func_vector_by_pretty_name(string prefix,
1139                                       vector<function_base *>*funcs) {
1140     unsigned int i;
1141     function_base *func;
1142     for(i=0;i<funcs->size();i++) {
1143       func = ((*funcs)[i]);
1144       cerr << prefix << func->prettyName() << endl;
1145     }
1146 }
1147
1148 // rip module name out of constraint....
1149 // Assumes that constraint is of form module/function, or
1150 // module.... 
1151 string getModuleName(string constraint) {
1152     string ret;
1153
1154     const char *data = constraint.string_of();
1155     const char *first_slash = P_strchr(data, RH_SEPERATOR);
1156     
1157     // no "/", assume string holds module name....
1158     if (first_slash == NULL) {
1159         return constraint;
1160     }    
1161     // has "/", assume everything up to "/" is module name....
1162     return string(data, first_slash - data);
1163 }
1164
1165 // rip function name out of constraint....
1166 // Assumes that constraint is of form module/function, or
1167 // module.... 
1168 string getFunctionName(string constraint) {
1169     string ret;
1170
1171     const char *data = constraint.string_of();
1172     const char *first_slash = P_strchr(data, RH_SEPERATOR);
1173     
1174     // no "/", assume constraint is module only....
1175     if (first_slash == NULL) {
1176         return string("");
1177     }    
1178     // has "/", assume everything after "/" is function....
1179     return string(first_slash+1);
1180 }
1181
1182
1183 #ifndef BPATCH_LIBRARY
1184
1185 // mcheyney, Oct. 6, 1997
1186 static dictionary_hash<string, string> func_constraint_hash(string::hash);
1187 static bool cache_func_constraint_hash() {
1188     static bool func_constraint_hash_loaded = FALSE;
1189
1190     // strings holding exclude constraints....
1191     vector<string> func_constraints;
1192     // if unble to get list of excluded functions, assume all functions
1193     //  are NOT excluded!!!!
1194     if(mdl_get_lib_constraints(func_constraints) == FALSE) {
1195         return FALSE;
1196     }
1197     func_constraint_hash_loaded = TRUE;
1198
1199     unsigned i;
1200     for(i=0;i<func_constraints.size();i++) {
1201         func_constraint_hash[func_constraints[i]] = func_constraints[i];
1202     }
1203     return TRUE;
1204 }
1205
1206 // mcheyney, Oct. 3, 1997
1207 // Return boolean value indicating whether function is found to
1208 //  be excluded via "exclude module_name/function_name" (but NOT
1209 //  via "exclude module_name").
1210 bool function_is_excluded(pd_Function *func, string module_name) {
1211     static bool func_constraint_hash_loaded = FALSE;
1212
1213     string function_name = func->prettyName();
1214     string full_name = module_name + string("/") + function_name;
1215
1216     if (func_constraint_hash_loaded == FALSE) {
1217         if (!cache_func_constraint_hash()) {
1218             return FALSE;
1219         }
1220     }
1221
1222     if (func_constraint_hash.defines(full_name)) {
1223         return TRUE;
1224     }
1225     return FALSE;
1226 }
1227
1228 bool module_is_excluded(pdmodule *module) {
1229     static bool func_constraint_hash_loaded = FALSE;
1230
1231     string full_name = module->fileName();
1232
1233     if (func_constraint_hash_loaded == FALSE) {
1234         if (!cache_func_constraint_hash()) {
1235             return FALSE;
1236         }
1237     }
1238
1239     if (func_constraint_hash.defines(full_name)) {
1240         return TRUE;
1241     }
1242     return FALSE;
1243 }
1244
1245 //
1246 // mcheyney, Sep 28, 1997
1247 // Take a list of functions (in vector <all_funcs>.  Copy all
1248 //  of those functions which are not excluded (via "exclude" 
1249 //  {module==module_name}/{function==function_name) into
1250 //  <some_functions>.  DONT filter out those excluded via
1251 //  exclude module==module_name...., eh????
1252 // Returns status of mdl_get_lib_constraints() call.
1253 //  If this status == FALSE< some_funcs is not modified....
1254 // We assume that all_funcs is generally longer than the list
1255 //  of constrained functions.  As such, internally proc. copies
1256 //  all funcs into some funcs, then runs over excluded funcs
1257 //  removing any matches, as opposed to doing to checking 
1258 //  while adding to some_funcs....
1259
1260 bool filter_excluded_functions(vector<pd_Function*> all_funcs,
1261     vector<pd_Function*>& some_funcs, string module_name) {
1262     unsigned i;
1263
1264     string full_name;
1265     static bool func_constraint_hash_loaded = FALSE;
1266
1267     if (func_constraint_hash_loaded == FALSE) {
1268         if (!cache_func_constraint_hash()) {
1269             return FALSE;
1270         }
1271     }
1272
1273     // run over all_funcs, check if module/function is caught
1274     //  by an exclude....
1275     for(i=0;i<all_funcs.size();i++) {
1276         full_name = module_name + string("/") + all_funcs[i]->prettyName();
1277         if (!(func_constraint_hash.defines(full_name))) {
1278             some_funcs += all_funcs[i];
1279         }
1280     }
1281     
1282     //cerr << " looks successful : about to return TRUE" << endl;
1283     //cerr << " some_funcs (by pretty name) " << endl;
1284     //for (i=0;i<some_funcs.size();i++) {
1285     //    cerr << "  " << some_funcs[i]->prettyName() << endl;
1286     //}
1287     
1288     return TRUE;
1289 }
1290
1291 #endif /* BPATCH_LIBRARY */
1292
1293 // identify module name from symbol address (binary search)
1294 // based on module tags found in file format (ELF/COFF)
1295 static void findModByAddr (const Symbol &lookUp, vector<Symbol> &mods,
1296                            string &modName, Address &modAddr, 
1297                            const string &defName)
1298 {
1299   if (mods.size() == 0) {
1300     modAddr = 0;
1301     modName = defName;
1302     return;
1303   }
1304
1305   Address symAddr = lookUp.addr();
1306   int index;
1307   int start = 0;
1308   int end = mods.size() - 1;
1309   int last = end;
1310   bool found = false;
1311   while ((start <= end) && !found) {
1312     index = (start+end)/2;
1313     if ((index == last) ||
1314         ((mods[index].addr() <= symAddr) && 
1315          (mods[index+1].addr() > symAddr))) {
1316       modName = mods[index].name();
1317       modAddr = mods[index].addr();      
1318       found = true;
1319     } else if (symAddr < mods[index].addr()) {
1320       end = index - 1;
1321     } else {
1322       start = index + 1;
1323     }
1324   }
1325   if (!found) { 
1326     // must be (start > end)
1327     modAddr = 0;
1328     modName = defName;
1329     //modName = mods[0].name();
1330     //modAddr = mods[0].addr();
1331   }
1332 }
1333
1334 // addOneFunction(): find name of enclosing module and define function symbol
1335 //
1336 // module information comes from one of three sources:
1337 //   #1 - debug format (stabs, DWARF, etc.)
1338 //   #2 - file format (ELF, COFF)
1339 //   #3 - file name (a.out, libXXX.so)
1340 // (in order of decreasing reliability)
1341 bool image::addOneFunction(vector<Symbol> &mods,
1342                            pdmodule *lib,
1343                            pdmodule * /*dyn*/,
1344                            const Symbol &lookUp, pd_Function *&retFunc) 
1345 {
1346   // find module name
1347   Address modAddr = 0;
1348   string modName = lookUp.module();
1349   if (modName == "") {
1350     modName = name_ + "_module";
1351   } else if (modName == "DEFAULT_MODULE") {
1352       string modName_3 = modName;
1353       findModByAddr(lookUp, mods, modName, modAddr, modName_3);
1354   }
1355
1356   // add symbol definition
1357   return (defineFunction(lib, lookUp, modName, modAddr, retFunc));
1358 }
1359
1360 bool inLibrary(Address addr, Address boundary_start, Address boundary_end,
1361                       Address startAddr, bool startB,
1362                       Address endAddr, bool endB) {
1363   if ((addr >= boundary_start) && (addr <= boundary_end))
1364     return true;
1365   else if (startB) {
1366     if (addr <= startAddr)
1367       return true;
1368     else if (endB) {
1369       if (addr >= endAddr)
1370         return true;
1371       else 
1372         return false;
1373     } else 
1374       return false;
1375   } else if (endB) {
1376     if (addr >= endAddr)
1377       return true;
1378     else
1379       return false;
1380   } else
1381     return false;
1382 }
1383
1384 #ifndef BPATCH_LIBRARY
1385 // as per getAllFunctions, but filters out those excluded with 
1386 // e.g. mdl "exclude" command....
1387 // to clarify a function should NOT be returned from here if its 
1388 //  module is excluded (with exclude "/Code/module") or if it
1389 //  is excluded (with exclude "/Code/module/function"). 
1390 const vector<pd_Function*> &image::getIncludedFunctions() {
1391     unsigned int i;    
1392     includedFunctions.resize(0);
1393     vector<function_base *> *temp;
1394     vector<pd_Function *> *temp2;
1395
1396     //cerr << "image::getIncludedFunctions called, name = " << name () << endl;
1397     //cerr << " includedMods = " << endl;
1398     //print_module_vector_by_short_name(string("  "), &includedMods);
1399     for (i=0;i<includedMods.size();i++) {
1400          temp = includedMods[i]->getIncludedFunctions();
1401          temp2 = (vector<pd_Function *> *) temp;
1402          includedFunctions += *temp2;
1403     }
1404
1405     //cerr << " (image::getIncludedFunctions) returning : " << endl;
1406     //print_func_vector_by_pretty_name(string("  "),
1407     //           (vector<function_base*>*)&includedFunctions);
1408
1409     // what about shared objects????
1410     return includedFunctions;
1411 }
1412 #endif
1413
1414 //  COMMENTS??  HELLO?
1415 //  Here's a guess what this function tries to do:
1416 //  a. look through (data member of type Object) linkedFile,
1417 //   trying to file DYNINSTstart and DYNINSTend sections (
1418 //   beginning + ending of instrumentation code).
1419 //  b. ditto for main function (note variant names under which
1420 //   these functions are searched for)....
1421 //  c. iterate over all functions in linkedFile:
1422 //    if the function has already been defined, OR shadows the
1423 //     main function (has same address) - ignore it.
1424 //    else - 
1425 //     use (member function) inLibrary() to check
1426 //     whether function is in range of instrumented code (between
1427 //     DYNINSTstart and DYNINSTend)
1428 //     if in range - addInternalSymbol().
1429 //     else addOneFunction().
1430 //
1431 //  Questions : what do params mean????
1432 bool image::addAllFunctions(vector<Symbol> &mods,
1433                             pdmodule *lib, pdmodule *dyn, 
1434                             const bool startB, const Address startAddr,
1435                             const bool endB, const Address endAddr) {
1436
1437   Address boundary_start, boundary_end;
1438   Symbol lookUp;
1439   string symString;
1440
1441 #ifdef BPATCH_LIBRARY
1442   boundary_start = boundary_end = 0;
1443 #else
1444   if (!linkedFile.get_symbol(symString="DYNINSTfirst", lookUp) &&
1445       !linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)) {
1446     //statusLine("Internal symbol DYNINSTfirst not found");
1447     //showErrorCallback(31, "Internal symbol DYNINSTfirst not found");
1448     //return false;
1449     boundary_start = 0;
1450   } else
1451     boundary_start = lookUp.addr();
1452
1453   if (!linkedFile.get_symbol(symString="DYNINSTend", lookUp) &&
1454       !linkedFile.get_symbol(symString="_DYNINSTend", lookUp)) {
1455     //statusLine("Internal symbol DYNINSTend not found");
1456     //showErrorCallback(32, "Internal symbol DYNINSTend not found");
1457     //return false;
1458     boundary_end = 0;
1459   } else
1460     boundary_end = lookUp.addr();
1461 #endif
1462
1463   Symbol mainFuncSymbol;  //Keeps track of info on "main" function
1464
1465   //Checking "main" function names in same order as in the inst-*.C files
1466   if (linkedFile.get_symbol(symString="main",     lookUp) ||
1467       linkedFile.get_symbol(symString="_main",    lookUp) ||
1468       linkedFile.get_symbol(symString="WinMain",  lookUp) ||
1469       linkedFile.get_symbol(symString="_WinMain", lookUp)) 
1470     mainFuncSymbol = lookUp;
1471
1472   // find the real functions -- those with the correct type in the symbol table
1473   for(SymbolIter symIter(linkedFile); symIter;symIter++) {
1474     const Symbol &lookUp = symIter.currval();
1475
1476     if (funcsByAddr.defines(lookUp.addr()) ||
1477         ((lookUp.addr() == mainFuncSymbol.addr()) &&
1478          (lookUp.name() != mainFuncSymbol.name()))) {
1479       // This function has been defined 
1480       // *or*
1481       // This function has the same address as the "main" function but does 
1482       //   not have the same name as the "main" function.  Therefore, skip
1483       //   it and let the "main" function be eventually associated with this
1484       //   function address.  If we don't do this, paradynd will not have a
1485       //   "main" function to start work with.
1486       ;
1487     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
1488       if (!isValidAddress(lookUp.addr())) {
1489         string msg;
1490         char tempBuffer[40];
1491         sprintf(tempBuffer,"0x%lx",lookUp.addr());
1492         msg = string("Function") + lookUp.name() + string("has bad address ") +
1493               string(tempBuffer);
1494         statusLine(msg.string_of());
1495         showErrorCallback(29, msg);
1496         return false;
1497       }
1498
1499       insert_function_internal_static(mods, lookUp, boundary_start,
1500               boundary_end, startAddr, startB, endAddr, endB, dyn, lib);
1501     }
1502   }
1503
1504   // now find the pseudo functions -- this gets ugly
1505   // kludge has been set if the symbol could be a function
1506   for(SymbolIter symIter2(linkedFile);symIter2;symIter2++) {
1507     lookUp = symIter2.currval();
1508     if (funcsByAddr.defines(lookUp.addr())) {
1509         // This function has been defined
1510         ;
1511     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
1512         //logLine(P_strdup(symString.string_of()));
1513         // see comment under image::insert_function_internal_static,
1514         // below....
1515         insert_function_internal_static(mods, lookUp, boundary_start,
1516               boundary_end, startAddr, startB, endAddr, endB, dyn, lib);
1517     }
1518   }
1519   return true;
1520 }
1521
1522 bool image::addAllSharedObjFunctions(vector<Symbol> &mods,
1523                             pdmodule *lib, pdmodule *dyn) {
1524
1525   Symbol lookUp;
1526   string symString;
1527
1528   bool is_libdyninstRT = false; // true if this image is libdyninstRT
1529 #if defined(i386_unknown_nt4_0)
1530   if (linkedFile.get_symbol(symString="DYNINSTfirst", lookUp) ||
1531       linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp))
1532     is_libdyninstRT = true;
1533 #endif
1534
1535   // find the real functions -- those with the correct type in the symbol table
1536   for(SymbolIter symIter3(linkedFile);symIter3;symIter3++) { 
1537     const Symbol &lookUp = symIter3.currval();
1538     if (funcsByAddr.defines(lookUp.addr())) {
1539       // This function has been defined
1540       ;
1541     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
1542       if (!isValidAddress(lookUp.addr())) {
1543         string msg;
1544         char tempBuffer[40];
1545         sprintf(tempBuffer,"0x%lx",lookUp.addr());
1546         msg = string("Function") + lookUp.name() + string("has bad address ") +
1547               string(tempBuffer);
1548         statusLine(msg.string_of());
1549         showErrorCallback(29, msg);
1550         return false;
1551       }
1552       // see comment under image::insert_functions_internal_dynamic,
1553       //  below....
1554       insert_function_internal_dynamic(mods, lookUp, dyn, lib, is_libdyninstRT);
1555     }
1556   }
1557
1558   // now find the pseudo functions -- this gets ugly
1559   // kludge has been set if the symbol could be a function
1560   for(SymbolIter symIter4(linkedFile);symIter4;symIter4++) {
1561     const Symbol &lookUp = symIter4.currval();
1562     if (funcsByAddr.defines(lookUp.addr())) {
1563       // This function has been defined
1564       ;
1565     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
1566       pd_Function *pdf;
1567       addInternalSymbol(lookUp.name(), lookUp.addr());
1568       defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf);
1569     }
1570   }
1571   return true;
1572
1573
1574
1575 bool image::addAllVariables()
1576 {
1577 /* Eventually we'll have to do this on all platforms (because we'll retrieve
1578  * the type information here).
1579  */
1580 #ifdef i386_unknown_nt4_0
1581   string mangledName; 
1582   Symbol symInfo;
1583
1584   for(SymbolIter symIter(linkedFile); symIter; symIter++) {
1585      const string &mangledName = symIter.currkey();
1586      const Symbol &symInfo = symIter.currval();
1587
1588     if (symInfo.type() == Symbol::PDST_OBJECT) {
1589       char *name = cplus_demangle((char *)mangledName.string_of(), 0);
1590       const char *unmangledName;
1591       if (name) unmangledName = name;
1592       else unmangledName = mangledName.string_of();
1593       if (varsByPretty.defines(unmangledName)) {
1594           *(varsByPretty[unmangledName]) += string(mangledName);
1595       } else {
1596           vector<string> *varEntry = new vector<string>;
1597           *varEntry += string(mangledName);
1598           varsByPretty[unmangledName] = varEntry;
1599       }
1600       if (name) free(name);
1601     }
1602   }
1603 #endif
1604   return true;
1605 }
1606
1607 unsigned int int_addrHash(const Address& addr) {
1608   return (unsigned int)addr;
1609 }
1610
1611 // Please note that this is now machine independent-almost.  Let us keep it that way
1612 // COMMENTS????
1613 //  Guesses as to what this cod does....
1614 //  image constructor:
1615 //   construct an image corresponding to the executable file on path
1616 //   fileName.  Fill in err based on success or failure....
1617 image::image(const string &fileName, bool &err)
1618   : main_call_addr_(0),  
1619     modsByFileName(string::hash),
1620     modsByFullName(string::hash),
1621     includedFunctions(0),
1622     excludedFunctions(string::hash),
1623     instrumentableFunctions(0),
1624     notInstruFunctions(string::hash),
1625     funcsByAddr(addrHash4),
1626     funcsByPretty(string::hash),
1627     funcsByMangled(string::hash),
1628     file_(fileName),
1629     linkedFile(fileName, pd_log_perror),
1630     iSymsMap(string::hash),
1631     varsByPretty(string::hash),
1632     knownJumpTargets(int_addrHash, 8192)
1633 {
1634     sharedobj_cerr << "image::image for non-sharedobj; file name="
1635                    << file_ << endl;
1636
1637     // shared_object and static object (a.out) constructors merged into
1638     //  common initialize routine.... 
1639     initialize(fileName, err, 0);
1640 }
1641
1642 // 
1643 // load a shared object
1644 //
1645 image::image(const string &fileName, Address baseAddr, bool &err)
1646   : main_call_addr_(0),
1647     modsByFileName(string::hash),
1648     modsByFullName(string::hash),
1649     includedFunctions(0),
1650     excludedFunctions(string::hash),
1651     instrumentableFunctions(0),
1652     notInstruFunctions(string::hash),
1653     funcsByAddr(addrHash4),
1654     funcsByPretty(string::hash),
1655     funcsByMangled(string::hash),
1656     file_(fileName),
1657     linkedFile(fileName, baseAddr, pd_log_perror),
1658     iSymsMap(string::hash),
1659     varsByPretty(string::hash),
1660     knownJumpTargets(int_addrHash, 8192)
1661 {
1662     sharedobj_cerr << "welcome to image::image for shared obj; file name="
1663                    << file_ << endl;
1664
1665     // shared_object and static object (a.out) constructors merged into
1666     //  common initialize routine.... 
1667     initialize(fileName, err, 1, baseAddr);
1668 }
1669
1670 static bool findStartSymbol(Object &lf, Address &adr) {
1671   Symbol lookUp;
1672
1673   if (lf.get_symbol("DYNINSTstartUserCode", lookUp) ||
1674       lf.get_symbol("_DYNINSTstartUserCode", lookUp)) {
1675     adr = lookUp.addr();
1676     return true;
1677   } else
1678     return false;
1679 }
1680
1681 static bool findEndSymbol(Object &lf, Address &adr) {
1682   Symbol lookUp;
1683
1684   if (lf.get_symbol("DYNINSTendUserCode", lookUp) ||
1685       lf.get_symbol("_DYNINSTendUserCode", lookUp)) {
1686     adr = lookUp.addr();
1687     return true;
1688   } else
1689     return false;
1690 }
1691
1692 /*
1693     image::initialize - called by image a.out and shared_object 
1694     constructor to do common initialization....
1695
1696     paramaters - 
1697
1698       shared_object - pass 0 to denote initializing from statically
1699         linked executable (a.out file), pass 1 to denote initializing
1700         from shared library.
1701       base_addr - curr. used IFF shared_library == 1.
1702  */
1703 void image::initialize(const string &fileName, bool &err,
1704                        bool shared_object, Address /*base_addr*/) {
1705     // initialize (data members) codeOffset_, dataOffset_,
1706     //  codeLen_, dataLen_.
1707     codeOffset_ = linkedFile.code_off();
1708     dataOffset_ = linkedFile.data_off();
1709     codeLen_ = linkedFile.code_len();
1710     dataLen_ = linkedFile.data_len();
1711
1712     // if unable to parse object file (somehow??), try to
1713     //  notify luser/calling process + return....    
1714     if (!codeLen_ || !linkedFile.code_ptr()) {
1715         string msg = string("Parsing problem with executable file: ") + fileName;
1716         statusLine(msg.string_of());
1717         msg += "\n";
1718         logLine(msg.string_of());
1719         err = true;
1720 #if defined(BPATCH_LIBRARY)
1721         BPatch_reportError(BPatchWarning, 27, msg.string_of()); 
1722 #else
1723         showErrorCallback(27, msg); 
1724 #endif
1725         return;
1726     }
1727
1728 #if !defined(USES_LIBDYNINSTRT_SO)
1729     // on architectures where statically linked programs to be run 
1730     //  w/ paradyn need to link with the DYNINST library, try to find
1731     //  the paradyn lib version # (DYNINSTversion or _DYNINSTversion
1732     //  symbol).
1733     if (!shared_object) {
1734         Symbol version;
1735         if (!linkedFile.get_symbol("DYNINSTversion", version) &&
1736                 !linkedFile.get_symbol("_DYNINSTversion", version)) {
1737             statusLine("Could not find version number in instrumentation\n");
1738             showErrorCallback(33, "Could not find version number in instrumentation");
1739             err = true;
1740             return;
1741         }
1742
1743         Word version_number = get_instruction(version.addr());
1744         if (version_number != 1) {
1745             string msg;
1746             msg = string("Incorrect version number, expected ") + string(1) + 
1747                  string("found ") + string(version_number);
1748             statusLine(msg.string_of());
1749             showErrorCallback(30, msg);
1750             err = true;
1751             return;
1752         }
1753     }
1754 #endif
1755
1756     string msg;
1757     // give luser some feedback....
1758     if (shared_object) {
1759         msg = string("Parsing shared object file : ") + fileName;
1760     } else {
1761         msg = string("Parsing static object file : ") + fileName;
1762     }
1763     statusLine(msg.string_of());
1764
1765     // short file name
1766     name_ = extract_pathname_tail(fileName);
1767     err = false;
1768
1769     // use the *DUMMY_MODULE* until a module is defined
1770     pdmodule *dynModule = newModule(DYN_MODULE, 0);
1771     pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1772     // TODO -- define inst points in define function ?
1773
1774     // The functions cannot be verified until all of them have been seen
1775     // because calls out of each function must be tagged as calls to user
1776     // functions or call to "library" functions
1777
1778     //
1779     // sort the modules by address into a vector to allow a binary search to 
1780     // determine the module that a symbol will map to -- this 
1781     // may be bsd specific....
1782     //
1783     vector <Symbol> tmods;
1784
1785     for (SymbolIter symIter(linkedFile); symIter; symIter++) {
1786         const Symbol &lookUp = symIter.currval();
1787         if (lookUp.type() == Symbol::PDST_MODULE) {
1788
1789             const string &lookUpName = lookUp.name();
1790             const char *str = lookUpName.string_of();
1791             assert(str);
1792             int ln = lookUpName.length();
1793
1794             // directory definition -- ignored for now
1795             if (str[ln-1] != '/') {
1796                 tmods += lookUp;
1797             }
1798         }
1799     }
1800
1801     // sort the modules by address
1802     statusLine("sorting modules");
1803     tmods.sort(symbol_compare);
1804
1805     // remove duplicate entries -- some .o files may have the same 
1806     // address as .C files.  kludge is true for module symbols that 
1807     // I am guessing are modules
1808     vector<Symbol> uniq;
1809
1810     unsigned int num_zeros = 0;
1811     // must use loop+1 not mods.size()-1 since it is an unsigned compare
1812     //  which could go negative - jkh 5/29/95
1813     for (unsigned loop=0; loop < tmods.size(); loop++) {
1814         if (tmods[loop].addr() == 0) num_zeros++;
1815         if ((loop+1 < tmods.size()) && 
1816                 (tmods[loop].addr() == tmods[loop+1].addr())) {
1817             if (!tmods[loop].kludge())
1818                 tmods[loop+1] = tmods[loop];
1819         } 
1820         else
1821           uniq += tmods[loop];
1822     }
1823     // avoid case where all (ELF) module symbols have address zero
1824     if (num_zeros == tmods.size()) uniq.resize(0);
1825
1826     // define all of the functions
1827     statusLine("winnowing functions");
1828
1829     // register functions differently depending on whether parsing 
1830     //  shared object or static executable.  
1831     // THIS MAY CHANGE WHEN REMOVE DYNINSTstart && DYNINSTend hacks....
1832     if (!shared_object) {
1833         // find the "user" code boundaries
1834         statusLine("finding user code boundaries");
1835         Address startUserAddr=0, endUserAddr=0;
1836         bool startBound = findStartSymbol(linkedFile, startUserAddr);
1837         bool endBound = findEndSymbol(linkedFile, endUserAddr);
1838
1839         if (!addAllFunctions(uniq, libModule, dynModule, startBound,
1840                 startUserAddr, endBound, endUserAddr)) {
1841             err = true;
1842             return;
1843         }
1844     } else {
1845         // define all of the functions
1846         if (!addAllSharedObjFunctions(uniq, libModule, dynModule)) {
1847             err = true;
1848             return;
1849         }
1850     }
1851
1852     // ALERT ALERT - Calling on both shared_object && !shared_object path.
1853     //  In origional code, only called in !shared_object case.  Was this 
1854     //  a bug????
1855     // XXX should have a statusLine("retrieving variable information") here,
1856     //     but it's left out for now since addAllVariables only does something
1857     //     when BPATCH_LIBRARY is defined
1858     addAllVariables();
1859
1860     statusLine("checking call points");
1861     checkAllCallPoints();
1862
1863     // TODO -- remove duplicates -- see earlier note
1864     dictionary_hash<Address, unsigned> addr_dict(addrHash4);
1865     vector<pd_Function*> temp_vec;
1866
1867     // question??  Necessary to do same crap to includedFunctions &&
1868     //  excludedFunctions??
1869     unsigned f_size = instrumentableFunctions.size(), index;
1870     for (index=0; index<f_size; index++) {
1871         const Address the_address = 
1872             instrumentableFunctions[index]->getAddress(0);
1873         if (!addr_dict.defines(the_address)) {
1874             addr_dict[the_address] = 1;
1875             temp_vec += instrumentableFunctions[index];
1876         }
1877     }
1878     instrumentableFunctions = temp_vec;
1879 }
1880
1881
1882 void pdmodule::checkAllCallPoints() {
1883   unsigned fsize = funcs.size();
1884   for (unsigned f=0; f<fsize; f++)
1885       funcs[f]->checkCallPoints();
1886 }
1887
1888
1889 void image::checkAllCallPoints() {
1890   dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1891   string s; pdmodule *mod;
1892   while (di.next(s, mod))
1893     mod->checkAllCallPoints();
1894 }
1895
1896 // passing in tags allows a function to be tagged as TAG_LIB_FUNC even
1897 // if its entry is not in the tag dictionary of known functions
1898 bool image::defineFunction(pdmodule *use, const Symbol &sym, const unsigned tags,
1899                            pd_Function *&retFunc) {
1900   // We used to skip a leading underscore, but not anymore.
1901   // (I forgot why we ever did in the first place)
1902
1903   unsigned dictTags = findTags(sym.name());
1904   return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags | dictTags, retFunc));
1905 }
1906
1907 pdmodule *image::getOrCreateModule(const string &modName, 
1908                                       const Address modAddr) {
1909   const char *str = modName.string_of();
1910   int len = modName.length();
1911   assert(len>0);
1912
1913   // TODO ignore directory definitions for now
1914   if (str[len-1] == '/') {
1915     return NULL;
1916   } else {
1917     // TODO - navigate ".." and "."
1918     const char *lastSlash = P_strrchr(str, '/');
1919     if (lastSlash)
1920       return (newModule(++lastSlash, modAddr));
1921     else
1922       return (newModule(modName, modAddr));
1923   }
1924 }
1925
1926 // COMMENTS????
1927 // looks like wrapper function for (member function) newFunc.
1928 //  appears to do some fiddling with tags paramater to that
1929 //  function.
1930 // Kludge TODO - internal functions are tagged with TAG_LIB_FUNC
1931 // but they won't have tags in the tag dict, so this happens...
1932 bool image::defineFunction(pdmodule *libModule, const Symbol &sym,
1933                            const string &modName, const Address modAddr,
1934                            pd_Function *&retFunc) {
1935
1936   // We used to skip a leading underscore, but not any more.
1937
1938   unsigned tags = findTags(sym.name());
1939
1940   if (TAG_LIB_FUNC & tags)
1941     return (newFunc(libModule, sym.name(), sym.addr(), sym.size(),
1942                     tags | TAG_LIB_FUNC, retFunc));
1943   else {
1944     pdmodule *use = getOrCreateModule(modName, modAddr);
1945     assert(use);
1946     return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags, retFunc));
1947   }
1948 }
1949
1950 // Verify that this is code
1951 // Find the call points
1952 // Find the return address
1953 // TODO -- use an instruction object to remove
1954 // Sets err to false on error, true on success
1955 //
1956 // Note - this must define funcEntry and funcReturn
1957 // 
1958 pd_Function::pd_Function(const string &symbol, const string &pretty, 
1959                        pdmodule *f, Address adr, const unsigned size, 
1960                        const unsigned tg, const image *owner, bool &err) : 
1961   function_base(symbol, pretty, adr, size,tg),
1962   file_(f),
1963   funcEntry_(0),
1964 #ifndef BPATCH_LIBRARY
1965   funcResource(0),
1966 #endif
1967   relocatable_(false)
1968 {
1969   err = findInstPoints(owner) == false;
1970 }
1971
1972 // This method returns the address at which this function resides
1973 // in the process P, even if it is dynamic, even if it has been
1974 // relocated.  getAddress() (see symtab.h) does not always do this:
1975 // If the function is in a shlib and it has not been relocated,
1976 // getAddress() only returns the relative offset of the function
1977 // within its shlib.  We think that getAddress() should be fixed
1978 // to always return the effective address, but we are not sure
1979 // whether that would boggle any of its 75 callers.  Until that is
1980 // cleared up, call this method. -zandy, Apr-26-1999
1981 Address pd_Function::getEffectiveAddress(const process *p) const {
1982      assert(p);
1983      // Even if the function has been relocated, call it at its
1984      // original address since the call will be redirected to the
1985      // right place anyway.
1986      Address base;
1987      p->getBaseAddress(file()->exec(), base);
1988      return base + addr();
1989 }
1990
1991 // image::addAllFunctions dupliactes this section of code.
1992 // As part of an effort to clean up the code a bit, I merged the
1993 // duplicates into this 1 function.  
1994 void image::insert_function_internal_static(vector<Symbol> &mods,
1995         const Symbol &lookUp,
1996         const Address boundary_start,  const Address boundary_end,
1997         const Address startAddr, bool startB, const Address endAddr,
1998         bool endB, pdmodule *dyn, pdmodule *lib) {
1999     pd_Function *pdf;
2000     //  COMMENTS??
2001     //  If CONDITION??
2002     if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
2003                     startAddr, startB, endAddr, endB)) {
2004         // look at symbol name.  If it looks like "_DYNINST*" or 
2005         // "_TRACELIN*", add it to iSymsMap data member....
2006         addInternalSymbol(lookUp.name(), lookUp.addr());
2007         defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf);
2008     } else {
2009         addOneFunction(mods, lib, dyn, lookUp, pdf);
2010     } 
2011 }
2012
2013 // version of insert_function_internal_static (above) for 
2014 // shared objects....
2015 void image::insert_function_internal_dynamic(vector<Symbol> &mods,
2016         const Symbol &lookUp,
2017         pdmodule *dyn, pdmodule *lib, bool is_libdyninstRT) {
2018     pd_Function *pdf;
2019     if (is_libdyninstRT) {
2020         addInternalSymbol(lookUp.name(), lookUp.addr());
2021         defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf);
2022     } else {
2023         addOneFunction(mods, lib, dyn, lookUp, pdf);
2024     }
2025 }