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