small fix to prev commit
[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/main.h"
61 #include "paradynd/src/init.h"
62 #else
63 extern vector<sym_data> syms_to_find;
64 #endif
65
66 // All debug_ostream vrbles are defined in process.C (for no particular reason)
67 extern debug_ostream sharedobj_cerr;
68
69 vector<image*> image::allImages;
70
71 #if defined(i386_unknown_nt4_0)
72 extern char *cplus_demangle(char *, int);
73 #else
74 extern "C" char *cplus_demangle(char *, int);
75 #endif
76
77
78 /* imported from platform specific library list.  This is lists all
79    library functions we are interested in instrumenting. */
80
81 pdmodule *image::newModule(const string &name, const Address addr)
82 {
83     pdmodule *ret;
84     // modules can be defined several times in C++ due to templates and
85     //   in-line member functions.
86     if ((ret = findModule(name)))
87       return(ret);
88
89     string fullNm, fileNm;
90     char *out = P_strdup(name.string_of());
91     char *sl = P_strrchr(out, '/');
92     if (sl) {
93       *sl = (char)0;
94       fullNm = out;
95       fileNm = sl+1;
96     } else {
97       fullNm = string("/default/") + out;
98       fileNm = out;
99     }
100     free(out);
101
102     ret = new pdmodule(langUnknown, addr, fullNm, fileNm, this);
103     modsByFileName[ret->fileName()] = ret;
104     modsByFullName[ret->fullName()] = ret;
105     mods += ret;
106     return(ret);
107 }
108
109
110 // TODO -- is this g++ specific
111 bool buildDemangledName(const string &mangled, string &use)
112 {
113  /* The C++ demangling function demangles MPI__Allgather (and other MPI__
114   * functions with start with A) into the MPI constructor.  In order to
115   * prevent this a hack needed to be made, and this seemed the cleanest
116   * approach.
117   */
118   if(!mangled.prefixed_by("MPI__")) {
119     char *tempName = P_strdup(mangled.string_of());
120     char *demangled = cplus_demangle(tempName, 0);
121     
122     if (demangled) {
123       use = demangled;
124       free(tempName);
125       free(demangled);
126       return true;
127     } else {
128       free(tempName);
129       return false;
130     }
131   }
132   return(false);
133 }
134
135 // err is true if the function can't be defined
136 bool image::newFunc(pdmodule *mod, const string &name, const Address addr, 
137                     const unsigned size, const unsigned tag, 
138                     pd_Function *&retFunc) {
139   pd_Function *func;
140   retFunc = NULL;
141   // KLUDGE
142   if ((func = findFunction(addr))){
143     string temp = name;
144     temp += string(" findFunction failed\n");
145     logLine(P_strdup(temp.string_of()));
146     return false;
147   }
148
149   if (!mod) {
150     logLine("Error function without module\n");
151     showErrorCallback(34, "Error function without module");
152     return false;
153   }
154
155   string mangled_name = name;
156   const char *p = P_strchr(name.string_of(), ':');
157   if (p) {
158      unsigned nchars = p - name.string_of();
159      mangled_name = string(name.string_of(), nchars);
160   }
161      
162   string demangled;
163   if (!buildDemangledName(mangled_name, demangled)) 
164     demangled = mangled_name;
165
166   bool err;
167
168   func = new pd_Function(name, demangled, mod, addr, size, tag, this, err);
169   //cout << name << " pretty: " << demangled << " addr :" << addr <<endl;
170   retFunc = func;
171   if (err) {
172     //delete func;
173     retFunc = NULL;
174     notInstruFunction += func;
175     return false;
176   }
177   
178   funcsByAddr[addr] = func;
179   mod->funcs += func;
180
181   vector<pd_Function*> *funcsByPrettyEntry;
182   if (!funcsByPretty.find(func->prettyName(), funcsByPrettyEntry)) {
183     funcsByPrettyEntry = new vector<pd_Function*>;
184     funcsByPretty[func->prettyName()] = funcsByPrettyEntry;
185   }
186
187   // several functions may have the same demangled name, and each one
188   // will appear in a different module
189 //  vector<pdFunction*> *ap = funcsByPretty[func->prettyName()];
190   assert(funcsByPrettyEntry);
191   (*funcsByPrettyEntry) += func;
192   return true;
193 }
194
195 #ifdef DEBUG_TIME
196 static timer loadTimer;
197 static FILE *timeOut=0;
198 #endif /* DEBUG_TIME */
199
200 /*
201  * load an executable:
202  *   1.) parse symbol table and identify rotuines.
203  *   2.) scan executable to identify inst points.
204  *
205  *  offset is normally zero except on CM-5 where we have two images in one
206  *    file.  The offset passed to parseImage is the logical offset (0/1), not
207  *    the physical point in the file.  This makes it faster to "parse" multiple
208  *    copies of the same image since we don't have to stat and read to find the
209  *    physical offset. 
210  */
211 image *image::parseImage(const string file)
212 {
213   /*
214    * Check to see if we have parsed this image at this offeset before.
215    */
216   // TODO -- better method to detect same image/offset --> offset only for CM5
217
218   unsigned numImages = allImages.size();
219
220   for (unsigned u=0; u<numImages; u++)
221     if (file == allImages[u]->file())
222       return allImages[u];
223
224   /*
225    * load the symbol table. (This is the a.out format specific routine).
226    */
227
228   statusLine("Process executable file");
229   bool err;
230
231   // TODO -- kill process here
232   image *ret = new image(file, err);
233   if (err || !ret) {
234     if (ret)
235       delete ret;
236     return NULL;
237   }
238
239   // Add to master image list.
240   image::allImages += ret;
241
242   // define all modules.
243 #ifndef BPATCH_LIBRARY
244   tp->resourceBatchMode(true);
245 #endif
246
247   statusLine("defining modules");
248   ret->defineModules();
249
250 //  statusLine("ready"); // this shouldn't be here, right? (cuz we're not done, right?)
251
252 #ifndef BPATCH_LIBRARY
253   tp->resourceBatchMode(false);
254 #endif
255
256   return(ret);
257 }
258
259 /*
260  * load a shared object:
261  *   1.) parse symbol table and identify rotuines.
262  *   2.) scan executable to identify inst points.
263  *
264  */
265 image *image::parseImage(const string file,u_int baseAddr)
266 {
267   /*
268    * Check to see if we have parsed this image at this offeset before.
269    */
270   // TODO -- better method to detect same image/offset --> offset only for CM5
271
272   unsigned theSize = allImages.size();
273
274   for (unsigned u=0; u<theSize; u++)
275     if (file == allImages[u]->file())
276       return allImages[u];
277
278   /*
279    * load the symbol table. (This is the a.out format specific routine).
280    */
281
282   if(!baseAddr) statusLine("Processing an executable file");
283   else  statusLine("Processing a shared object file");
284   bool err;
285
286   // TODO -- kill process here
287   image *ret = new image(file, baseAddr,err);
288   if (err || !ret) {
289     if (ret)
290       delete ret;
291     logLine("error after new image in parseImage\n");
292     return NULL;
293   }
294
295   // Add to master image list.
296   image::allImages += ret;
297
298   // define all modules.
299   ret->defineModules();
300   return(ret);
301 }
302
303 bool image::addInternalSymbol(const string &str, const Address symValue) {
304   // Internal symbols are prefixed by { DYNINST, TRACELIB }
305   // don't ignore the underscore
306   static string dyn = "_DYNINST"; 
307   static string tlib = "_TRACELIB";
308
309
310   // normalize all symbols -- remove the leading "_"
311   if (str.prefixed_by(dyn)) {
312     const char *s = str.string_of(); s++;
313     if (!iSymsMap.defines(s)){
314       iSymsMap[s] = new internalSym(symValue, s);
315     }
316     return true;
317   } else if (str.prefixed_by(tlib)) {
318     const char *s = str.string_of(); s++;
319     if (!iSymsMap.defines(s))
320       iSymsMap[s] = new internalSym(symValue, s);
321     return true;
322   } else {
323     if (!iSymsMap.defines(str))
324       iSymsMap[str] = new internalSym(symValue, str);
325     return true;
326   }
327   return false;
328 }
329
330 /*
331  * will search for symbol NAME or _NAME
332  * returns false on failure 
333  */
334 bool image::findInternalSymbol(const string &name, const bool warn, internalSym &ret_sym){
335    Symbol lookUp;
336
337    if(linkedFile.get_symbol(name,lookUp)){
338       ret_sym = internalSym(lookUp.addr(),name); 
339       return true;
340    }
341    else {
342        string new_sym;
343        new_sym = string("_") + name;
344        if(linkedFile.get_symbol(new_sym,lookUp)){
345           ret_sym = internalSym(lookUp.addr(),name); 
346           return true;
347        }
348    } 
349    if(warn){
350       string msg;
351       msg = string("Unable to find symbol: ") + name;
352       statusLine(msg.string_of());
353       showErrorCallback(28, msg);
354    }
355    return false;
356 }
357
358 Address image::findInternalAddress(const string &name, const bool warn, bool &err)
359 {
360
361   err = false;
362
363   internalSym *theSym; // filled in by find()
364   if (!iSymsMap.find(name, theSym)) {
365     // not found!
366     if (warn) {
367       string msg = string("Unable to find symbol: ") + name;
368       statusLine(msg.string_of());
369       showErrorCallback(28, msg);
370     }
371     err = true;
372     return 0;
373   } 
374   else
375     return (theSym->getAddr());
376 }
377
378 pdmodule *image::findModule(const string &name)
379 {
380   if (modsByFileName.defines(name))
381     return (modsByFileName[name]);
382   else if (modsByFullName.defines(name))
383     return (modsByFullName[name]);
384   else
385     return NULL;
386 }
387
388 // TODO -- this is only being used in cases where only one function
389 // should exist -- should I assert that the vector size <= 1 ?
390 pd_Function *image::findOneFunction(const string &name)
391 {
392   string demangName;
393
394   if (funcsByPretty.defines(name)) {
395     vector<pd_Function*> *a = funcsByPretty[name];
396     assert(a);
397     if (!a->size())
398       return NULL;
399     else
400       return ((*a)[0]);
401   } else if (buildDemangledName(name, demangName)) {
402     if (funcsByPretty.defines(demangName)) {
403       vector<pd_Function*> *a = funcsByPretty[demangName];
404       assert(a);
405       if (!a->size())
406         return NULL;
407       else
408         return ((*a)[0]);
409     } else
410       return NULL;
411   } else
412     return NULL;
413 }
414
415 // This function supposely is only used to find function that
416 // is not instrumentable which may not be totally defined.
417 // Use with caution.  
418 pd_Function *image::findOneFunctionFromAll(const string &name) {
419
420     pd_Function *ret;
421     if ((ret = findOneFunction(name))) 
422         return ret;
423     else {
424         for (unsigned i = 0; i < notInstruFunction.size(); i++) {
425             ret = notInstruFunction[i];
426             if (ret->prettyName() == name)
427                 return ret;
428         }
429     }
430     return NULL;
431 }
432
433 bool image::findFunction(const string &name, vector<pd_Function*> &retList) {
434
435   if (funcsByPretty.defines(name)) {
436     retList = *funcsByPretty[name];
437     return true;
438   } else
439     return false;
440 }
441
442 pd_Function *image::findFunction(const Address &addr) 
443 {
444   pd_Function *result; // filled in by find()
445   if (funcsByAddr.find(addr, result))
446      return result;
447   else
448      return NULL;
449 }
450   
451 pd_Function *image::findFunctionIn(const Address &addr,const process *p) const 
452 {
453   pd_Function *pdf;
454
455   dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
456   Address adr;
457   while (mi.next(adr, pdf)) {
458       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size()))) 
459           return pdf;
460   }
461   
462   // If not found, we are going to search them in the 
463   // uninstrumentable function
464   for (unsigned i = 0; i < notInstruFunction.size(); i++) {
465       pdf = notInstruFunction[i];
466       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size()))) 
467           return pdf;
468   }
469
470   return NULL; 
471 }
472
473
474 #ifndef BPATCH_LIBRARY
475 void image::changeLibFlag(resource *res, const bool setSuppress)
476 {
477   image *ret;
478   pdmodule *mod;
479
480   unsigned numImages = image::allImages.size();
481   for (unsigned u=0; u<numImages; u++) {
482     ret = image::allImages[u];
483     mod = ret->findModule(res->part_name());
484     if (mod) {
485       // suppress all procedures.
486       mod->changeLibFlag(setSuppress);
487     } else {
488       // more than one function may have this name --> templates, statics
489       vector<pd_Function*> pdfA;
490       if (ret->findFunction(res->part_name(), pdfA)) {
491         for (unsigned i=0; i<pdfA.size(); ++i) {
492           if (setSuppress) 
493             pdfA[i]->tagAsLib();
494           else
495             pdfA[i]->untagAsLib();
496         }
497       }
498     }
499   }
500 }
501 #endif
502
503
504 /* 
505  * return 0 if symbol <symname> exists in image, non-zero if it does not
506  */
507 bool image::symbolExists(const string &symname)
508 {
509   pd_Function *dummy = findOneFunction(symname);
510   return (dummy != NULL);
511 }
512
513 void image::postProcess(const string pifname)
514 {
515   FILE *Fil;
516   string fname, errorstr;
517   char key[5000];
518   char tmp1[5000], abstraction[500];
519 #ifndef BPATCH_LIBRARY
520   resource *parent;
521 #endif
522
523   return;
524
525   /* What file to open? */
526   if (!(pifname == (char*)NULL)) {
527     fname = pifname;
528   } else {
529     fname = file_ + ".pif";
530   }
531
532   /* Open the file */
533   Fil = P_fopen(fname.string_of(), "r");
534
535   if (Fil == NULL) {
536     errorstr = string("Tried to open PIF file ") + fname;
537     errorstr += string(", but could not (continuing)\n");
538     logLine(P_strdup(errorstr.string_of()));
539     showErrorCallback(35, errorstr); 
540     return;
541   }
542
543   /* Process the file */
544   while (!feof(Fil)) {
545     fscanf(Fil, "%s", key);
546     switch (key[0]) {
547     case 'M':
548       /* Ignore mapping information for right now */
549       fgets(tmp1, 5000, Fil);
550       break;
551     case 'R':
552 #ifndef BPATCH_LIBRARY
553       /* Create a new resource */
554       fscanf(Fil, "%s {", abstraction);
555       parent = rootResource;
556       do {
557         fscanf(Fil, "%s", tmp1);
558         if (tmp1[0] != '}') {
559           parent = resource::newResource(parent, NULL,
560                                          abstraction,
561                                          tmp1, 0.0,
562                                          nullString, // uniqifier
563                                          MDL_T_STRING,
564                                          true);
565         } else {
566           parent = NULL;
567         }
568       } while (parent != NULL);
569 #endif
570       break;
571     default:
572       errorstr = string("Ignoring bad line key (") + fname;
573       errorstr += string(") in file %s\n");
574       logLine(P_strdup(errorstr.string_of()));
575       fgets(tmp1, 5000, Fil);
576       break;
577     }
578   }
579   return;
580 }
581
582 void image::defineModules() {
583   string pds; pdmodule *mod;
584   dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
585
586   while (mi.next(pds, mod)){
587     mod->define();
588   }
589
590 #ifdef DEBUG_MDL
591   char buffer[100];
592   ostrstream osb(buffer, 100, ios::out);
593   osb << "IMAGE_" << name() << "__" << getpid() << ends;
594   ofstream of(buffer, ios::app);
595   unsigned n_size = mdlNormal.size();
596   of << "NORMAL\n";
597   for (unsigned ni=0; ni<n_size; ni++) {
598     of << mdlNormal[ni]->prettyName() << "\t\t" << mdlNormal[ni]->addr() << "\t\t" << 
599       mdlNormal[ni]->isLibTag() << endl;
600   }
601   n_size = mdlLib.size();
602   of << "\n\nLIB\n";
603   for (ni=0; ni<n_size; ni++) {
604     of << mdlLib[ni]->prettyName() << "\t\t" << mdlLib[ni]->addr() << "\t\t" <<
605       mdlLib[ni]->isLibTag() << endl;
606   }
607 #endif
608 }
609
610 void pdmodule::define() {
611 #ifndef BPATCH_LIBRARY
612   resource *modResource = NULL;
613 #endif
614 #ifdef DEBUG_MODS
615   char buffer[100];
616   ostrstream osb(buffer, 100, ios::out);
617   osb << "MODS_" << exec->name() << "__" << getpid() << ends;
618   ofstream of(buffer, ios::app);
619 #endif
620
621   unsigned f_size = funcs.size();
622
623   for (unsigned f=0; f<f_size; f++) {
624     pd_Function *pdf = funcs[f];
625 #ifdef DEBUG_MODS
626     of << fileName << ":  " << pdf->prettyName() <<  "  " <<
627       pdf->isLibTag() << "  " << pdf->addr() << endl;
628 #endif
629     // ignore line numbers for now 
630
631 #ifndef BPATCH_LIBRARY
632     if (!(pdf->isLibTag())) {
633       // see if we have created module yet.
634       if (!modResource) {
635         modResource = resource::newResource(moduleRoot, this,
636                                             nullString, // abstraction
637                                             fileName(), // name
638                                             0.0, // creation time
639                                             string::nil, // unique-ifier
640                                             MDL_T_MODULE,
641                                             false);
642       }
643       resource::newResource(modResource, pdf,
644                             nullString, // abstraction
645                             pdf->prettyName(), 0.0,
646                             nullString, // uniquifier
647                             MDL_T_PROCEDURE,
648                             false);
649     }
650 #endif
651   }
652
653   resource::send_now();
654 }
655
656 static inline bool findStartSymbol(Object &lf, Address &adr) {
657   Symbol lookUp;
658
659   if (lf.get_symbol("DYNINSTstartUserCode", lookUp) ||
660       lf.get_symbol("_DYNINSTstartUserCode", lookUp)) {
661     adr = lookUp.addr();
662     return true;
663   } else
664     return false;
665 }
666
667 static inline bool findEndSymbol(Object &lf, Address &adr) {
668   Symbol lookUp;
669
670   if (lf.get_symbol("DYNINSTendUserCode", lookUp) ||
671       lf.get_symbol("_DYNINSTendUserCode", lookUp)) {
672     adr = lookUp.addr();
673     return true;
674   } else
675     return false;
676 }
677
678 // TODO this assumes an ordering in the symbol table wrt modules KLUDGE
679 static inline bool notInUserRange(const Address adr,
680                                   const bool start, const Address startAdr,
681                                   const bool end, const Address endAdr) {
682   return ((start && (adr < startAdr)) || (end && (adr >= endAdr)));
683 }
684
685 static void binSearch (const Symbol &lookUp, vector<Symbol> &mods,
686                        string &modName, Address &modAddr, const string &def) {
687   int start=0, end=mods.size()-1, index;
688   bool found=false;
689
690   if (!mods.size()) {
691     modAddr = 0;
692     modName = def;
693     return;
694   }
695
696   while ((start <= end) && !found) {
697     index = (start+end)/2;
698
699     if ((index == (((int)mods.size())-1)) ||
700         ((mods[index].addr() <= lookUp.addr()) && (mods[index+1].addr() > lookUp.addr()))) {
701       modName = mods[index].name();
702       modAddr = mods[index].addr();      
703       found = true;
704     } else if (lookUp.addr() < mods[index].addr()) {
705       end = index - 1;
706     } else {
707       start = index + 1;
708     }
709   }
710   if (!found) {
711     modName = mods[0].name();
712     modAddr = mods[0].addr();
713   }
714 }
715
716 bool image::addOneFunction(vector<Symbol> &mods, pdmodule *lib, pdmodule *dyn,
717                            const Symbol &lookUp, pd_Function  *&retFunc) {
718   // TODO mdc
719   // find the module
720   // this is a "user" symbol
721   string modName = lookUp.module();
722   Address modAddr = 0;
723   
724   string progName = name_ + "_module";
725
726 #if defined (sparc_sun_solaris2_4) || defined (i386_unknown_solaris2_5) 
727   // In solaris there is no address for modules in the symbol table, 
728   // so the binary search will not work. The module field in a symbol
729   // already has the correct module name for a symbol, if it can be
730   // obtained from the symbol table, otherwise the module is an empty
731   // string.
732   if (modName == "") {
733     modName = progName;
734   }
735 #else
736   binSearch(lookUp, mods, modName, modAddr, progName);
737 #endif
738
739   return (defineFunction(lib, lookUp, modName, modAddr, retFunc));
740 }
741
742 bool inLibrary(Address addr, Address boundary_start, Address boundary_end,
743                       Address startAddr, bool startB,
744                       Address endAddr, bool endB) {
745   if ((addr >= boundary_start) && (addr <= boundary_end))
746     return true;
747   else if (startB) {
748     if (addr <= startAddr)
749       return true;
750     else if (endB) {
751       if (addr >= endAddr)
752         return true;
753       else 
754         return false;
755     } else 
756       return false;
757   } else if (endB) {
758     if (addr >= endAddr)
759       return true;
760     else
761       return false;
762   } else
763     return false;
764 }
765
766 bool image::addAllFunctions(vector<Symbol> &mods,
767                             pdmodule *lib, pdmodule *dyn, 
768                             const bool startB, const Address startAddr,
769                             const bool endB, const Address endAddr) {
770
771   Address boundary_start, boundary_end;
772   Symbol lookUp;
773   string symString;
774   SymbolIter symIter(linkedFile);
775
776 #ifdef BPATCH_LIBRARY
777   boundary_start = boundary_end = NULL;
778 #else
779   if (!linkedFile.get_symbol(symString="DYNINSTfirst", lookUp) &&
780       !linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)) {
781     //statusLine("Internal symbol DYNINSTfirst not found");
782     //showErrorCallback(31, "Internal symbol DYNINSTfirst not found");
783     //return false;
784     boundary_start = NULL;
785   } else
786     boundary_start = lookUp.addr();
787
788   if (!linkedFile.get_symbol(symString="DYNINSTend", lookUp) &&
789       !linkedFile.get_symbol(symString="_DYNINSTend", lookUp)) {
790     //statusLine("Internal symbol DYNINSTend not found");
791     //showErrorCallback(32, "Internal symbol DYNINSTend not found");
792     //return false;
793     boundary_end = NULL;
794   } else
795     boundary_end = lookUp.addr();
796 #endif
797
798   Symbol mainFuncSymbol;  //Keeps track of info on "main" function
799
800   //Checking "main" function names in same order as in the inst-*.C files
801   if (linkedFile.get_symbol(symString="main",     lookUp) ||
802       linkedFile.get_symbol(symString="_main",    lookUp) ||
803       linkedFile.get_symbol(symString="WinMain",  lookUp) ||
804       linkedFile.get_symbol(symString="_WinMain", lookUp)) 
805     mainFuncSymbol = lookUp;
806
807   // find the real functions -- those with the correct type in the symbol table
808   while (symIter.next(symString, lookUp)) {
809
810     if (funcsByAddr.defines(lookUp.addr()) ||
811         ((lookUp.addr() == mainFuncSymbol.addr()) &&
812          (lookUp.name() != mainFuncSymbol.name()))) {
813       // This function has been defined 
814       // *or*
815       // This function has the same address as the "main" function but does 
816       //   not have the same name as the "main" function.  Therefore, skip
817       //   it and let the "main" function be eventually associated with this
818       //   function address.  If we don't do this, paradynd will not have a
819       //   "main" function to start work with.
820       ;
821     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
822       if (!isValidAddress(lookUp.addr())) {
823         string msg;
824         char tempBuffer[40];
825         sprintf(tempBuffer,"%x",lookUp.addr());
826         msg = string("Function") + lookUp.name() + string("has bad address ") +
827               string(tempBuffer);
828         statusLine(msg.string_of());
829         showErrorCallback(29, msg);
830         return false;
831       }
832       pd_Function *pdf;
833       if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
834                     startAddr, startB, endAddr, endB)) {
835         addInternalSymbol(lookUp.name(), lookUp.addr());
836         if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
837           assert(pdf); mdlLib += pdf;
838         }
839       } else {
840         if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
841           assert(pdf); mdlNormal += pdf;
842         }
843       }
844     }
845   }
846
847   // now find the pseudo functions -- this gets ugly
848   // kludge has been set if the symbol could be a function
849   symIter.reset();
850   while (symIter.next(symString, lookUp)) {
851     if (funcsByAddr.defines(lookUp.addr())) {
852       // This function has been defined
853       ;
854     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
855       //logLine(P_strdup(symString.string_of()));
856       pd_Function *pdf;
857       if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
858                     startAddr, startB, endAddr, endB)) {
859         addInternalSymbol(lookUp.name(), lookUp.addr());
860         if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
861           assert(pdf); mdlLib += pdf;
862         }
863       } else {
864         if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
865           assert(pdf); mdlNormal += pdf;
866         }
867       }
868     }
869   }
870   return true;
871 }
872
873 bool image::addAllSharedObjFunctions(vector<Symbol> &mods,
874                             pdmodule *lib, pdmodule *dyn) {
875
876   Symbol lookUp;
877   string symString;
878   SymbolIter symIter(linkedFile);
879
880   bool is_libdyninstRT = false; // true if this image is libdyninstRT
881 #if defined(i386_unknown_nt4_0)
882   if (linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)
883       || linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp))
884     is_libdyninstRT = true;
885 #endif
886
887   // find the real functions -- those with the correct type in the symbol table
888   while (symIter.next(symString, lookUp)) {
889
890     if (funcsByAddr.defines(lookUp.addr())) {
891       // This function has been defined
892       ;
893     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
894       if (!isValidAddress(lookUp.addr())) {
895         string msg;
896         char tempBuffer[40];
897         sprintf(tempBuffer,"%x",lookUp.addr());
898         msg = string("Function") + lookUp.name() + string("has bad address ") +
899               string(tempBuffer);
900         statusLine(msg.string_of());
901         showErrorCallback(29, msg);
902         return false;
903       }
904       pd_Function *pdf;
905       if (is_libdyninstRT) {
906         addInternalSymbol(lookUp.name(), lookUp.addr());
907         if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
908           assert(pdf); mdlLib += pdf;
909         }
910       } else if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
911         assert(pdf); mdlNormal += pdf;
912       }
913     }
914   }
915
916   // now find the pseudo functions -- this gets ugly
917   // kludge has been set if the symbol could be a function
918   symIter.reset();
919   while (symIter.next(symString, lookUp)) {
920     if (funcsByAddr.defines(lookUp.addr())) {
921       // This function has been defined
922       ;
923     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
924       //logLine(P_strdup(symString.string_of()));
925       pd_Function *pdf;
926       addInternalSymbol(lookUp.name(), lookUp.addr());
927       if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
928           assert(pdf); mdlLib += pdf;
929       }
930     }
931   }
932   return true;
933
934
935
936 int symCompare(const void *s1, const void *s2) {
937   const Symbol *sym1 = (const Symbol*)s1, *sym2 = (const Symbol*)s2;
938   // TODO mdc
939   return (sym1->addr() - sym2->addr());
940 }
941
942
943 unsigned int_addrHash(const unsigned &addr) {
944   return addr;
945 }
946
947 // Please note that this is now machine independent-almost.  Let us keep it that way
948 // 
949 image::image(const string &fileName, bool &err)
950 :   funcsByAddr(addrHash4),
951     modsByFileName(string::hash),
952     modsByFullName(string::hash),
953     file_(fileName),
954     linkedFile(fileName, pd_log_perror),
955     iSymsMap(string::hash),
956     funcsByPretty(string::hash),
957     knownJumpTargets(int_addrHash, 8192)
958 {
959 sharedobj_cerr << "image::image for non-sharedobj; file name=" << file_ << endl;
960
961   codeOffset_ = linkedFile.code_off();
962   dataOffset_ = linkedFile.data_off();
963   codeLen_ = linkedFile.code_len();
964   dataLen_ = linkedFile.data_len();
965
966 #if defined(hppa1_1_hp_hpux)
967   unwind   = linkedFile.unwind;
968 #endif
969
970   if (!codeLen_ || !linkedFile.code_ptr()) {
971     string msg = string("Unable to open executable file: ") + fileName;
972     statusLine(msg.string_of());
973
974     msg += "\n";
975     logLine(msg.string_of());
976
977     err = true;
978
979     showErrorCallback(27, msg); 
980     return;
981   }
982
983 #if !defined(i386_unknown_nt4_0)
984   Symbol version;
985   if (!linkedFile.get_symbol("DYNINSTversion", version) &&
986       !linkedFile.get_symbol("_DYNINSTversion", version)) {
987     statusLine("Could not find version number in instrumentation\n");
988     showErrorCallback(33, "Could not find version number in instrumentation");
989     err = true;
990     return;
991   }
992
993   Word version_number = get_instruction(version.addr());
994   if (version_number != 1) {
995     string msg;
996     msg = string("Incorrect version number, expected ") + string(1) + 
997           string("found ") + string(version_number);
998     statusLine(msg.string_of());
999     showErrorCallback(30, msg);
1000     err = true;
1001     return;
1002   }
1003 #endif
1004
1005   const char *nm = fileName.string_of();
1006   const char *pos = P_strrchr(nm, '/');
1007
1008   err = false;
1009   if (pos)
1010     name_ = pos + 1;
1011   else
1012     name_ = fileName;
1013
1014   // find the "user" code boundaries
1015   statusLine("finding user code boundaries");
1016   Address startUserAddr=0, endUserAddr=0;
1017   bool startBound = findStartSymbol(linkedFile, startUserAddr);
1018   bool endBound = findEndSymbol(linkedFile, endUserAddr);
1019
1020   // use the *DUMMY_MODULE* until a module is defined
1021   pdmodule *dynModule = newModule(DYN_MODULE, 0);
1022   pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1023   // TODO -- define inst points in define function ?
1024
1025   // The functions cannot be verified until all of them have been seen
1026   // because calls out of each function must be tagged as calls to user
1027   // functions or call to "library" functions
1028
1029   Symbol lookUp;
1030   string symString;
1031   SymbolIter symIter(linkedFile);
1032
1033   // sort the modules by address into a vector to allow a binary search to 
1034   // determine the module that a symbol will map to -- this may be bsd specific
1035   vector<Symbol> mods;
1036
1037   while (symIter.next(symString, lookUp)) {
1038
1039     if (lookUp.type() == Symbol::PDST_MODULE) {
1040       const string &lookUpName = lookUp.name();
1041       const char *str = lookUpName.string_of();
1042       assert(str);
1043       int ln = lookUpName.length();
1044
1045       // directory definition -- ignored for now
1046       if (str[ln-1] != '/')
1047         mods += lookUp;
1048     }
1049   }
1050
1051   // sort the modules by address
1052   statusLine("sorting modules");
1053   mods.sort(symCompare);
1054 //  assert(mods.sorted(symCompare));
1055
1056   // remove duplicate entries -- some .o files may have the same address as .C files
1057   // kludge is true for module symbols that I am guessing are modules
1058   vector<Symbol> uniq;
1059   unsigned loop=0;
1060
1061   // must use loop+1 not mods.size()-1 since it is an unsigned compare
1062   //  which could go negative - jkh 5/29/95
1063   for (loop=0; loop < mods.size(); loop++) {
1064     if ((loop+1 < mods.size()) && 
1065         (mods[loop].addr() == mods[loop+1].addr())) {
1066       if (!mods[loop].kludge())
1067         mods[loop+1] = mods[loop];
1068     } else
1069       uniq += mods[loop];
1070   }
1071
1072   // define all of the functions
1073   statusLine("winnowing functions");
1074   if (!addAllFunctions(uniq, libModule, dynModule, startBound, startUserAddr,
1075                        endBound, endUserAddr)) {
1076     err = true;
1077     return;
1078   }
1079   statusLine("checking call points");
1080   checkAllCallPoints();
1081
1082 //  statusLine("ready"); // this shouldn't be here, right? (cuz we're not really ready)
1083
1084   // TODO -- remove duplicates -- see earlier note
1085   dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1086   vector<pd_Function*> temp_vec;
1087   unsigned f_size = mdlLib.size(), index;
1088   for (index=0; index<f_size; index++) {
1089     const unsigned the_address = (unsigned)mdlLib[index]->getAddress(0);
1090     if (!addr_dict.defines(the_address)) {
1091       addr_dict[the_address] = 1;
1092       temp_vec += mdlLib[index];
1093     }
1094   }
1095   mdlLib = temp_vec;
1096   temp_vec.resize(0); addr_dict.clear();
1097   f_size = mdlNormal.size();
1098   for (index=0; index<f_size; index++) {
1099     const unsigned the_address = (unsigned)mdlNormal[index]->getAddress(0);
1100     if (!addr_dict.defines(the_address)) {
1101       addr_dict[the_address] = 1;
1102       temp_vec += mdlNormal[index];
1103     }
1104   }
1105   mdlNormal = temp_vec;
1106 }
1107
1108 // 
1109 // load a shared object
1110 //
1111 image::image(const string &fileName, u_int baseAddr, bool &err)
1112 :   funcsByAddr(addrHash4),
1113     modsByFileName(string::hash),
1114     modsByFullName(string::hash),
1115     file_(fileName),
1116     linkedFile(fileName, baseAddr,pd_log_perror),
1117     iSymsMap(string::hash),
1118     funcsByPretty(string::hash),
1119     knownJumpTargets(int_addrHash, 8192)
1120 {
1121 sharedobj_cerr << "welcome to image::image for shared obj; file name=" << file_ << endl;
1122
1123   codeOffset_ = linkedFile.code_off();
1124   dataOffset_ = linkedFile.data_off();
1125   codeLen_ = linkedFile.code_len();
1126   dataLen_ = linkedFile.data_len();
1127   //logLine("IN image::image\n");
1128
1129 #if defined(hppa1_1_hp_hpux)
1130   unwind   = linkedFile.unwind;
1131 #endif
1132
1133   if (!codeLen_ || !linkedFile.code_ptr()) {
1134     string msg = string("Unable to open shared object file: ") + fileName;
1135     statusLine(msg.string_of());
1136     
1137     msg += "\n";
1138     logLine(msg.string_of());
1139
1140     err = true;
1141     showErrorCallback(27, msg); 
1142
1143     assert(false);
1144
1145     return;
1146   }
1147   else {
1148     string msg = string("Parsing shared object file: ") + fileName;
1149     statusLine(msg.string_of());
1150   }
1151
1152   const char *nm = fileName.string_of();
1153   const char *pos = P_strrchr(nm, '/');
1154
1155   err = false;
1156   if (pos)
1157     name_ = pos + 1;
1158   else
1159     name_ = fileName;
1160
1161   // use the *DUMMY_MODULE* until a module is defined
1162   pdmodule *dynModule = newModule(DYN_MODULE, 0);
1163   pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1164   // TODO -- define inst points in define function ?
1165
1166   // The functions cannot be verified until all of them have been seen
1167   // because calls out of each function must be tagged as calls to user
1168   // functions or call to "library" functions
1169
1170   Symbol lookUp;
1171   string symString;
1172   SymbolIter symIter(linkedFile);
1173
1174   // sort the modules by address into a vector to allow a binary search to 
1175   // determine the module that a symbol will map to -- this may be bsd specific
1176   vector<Symbol> mods;
1177
1178   while (symIter.next(symString, lookUp)) {
1179
1180     if (lookUp.type() == Symbol::PDST_MODULE) {
1181       const char *str = (lookUp.name()).string_of();
1182       assert(str);
1183       int ln = P_strlen(str);
1184
1185       // directory definition -- ignored for now
1186       if (str[ln-1] != '/')
1187         mods += lookUp;
1188       // string temp = string("NEW MODULE: ");
1189       // temp += lookUp.name();
1190       // temp += string("\n");
1191       // logLine(P_strdup(temp.string_of()));
1192     }
1193   }
1194
1195   // sort the modules by address
1196   mods.sort(symCompare);
1197 //  assert(mods.sorted(symCompare));
1198
1199   // remove duplicate entries -- some .o files may have the same address as .C files
1200   // kludge is true for module symbols that I am guessing are modules
1201   vector<Symbol> uniq;
1202   unsigned loop=0;
1203
1204   // must use loop+1 not mods.size()-1 since it is an unsigned compare
1205   //  which could go negative - jkh 5/29/95
1206   for (loop=0; loop < mods.size(); loop++) {
1207     if ((loop+1 < mods.size()) && 
1208          (mods[loop].addr() == mods[loop+1].addr())) {
1209       if (!mods[loop].kludge())
1210         mods[loop+1] = mods[loop];
1211     } else
1212       uniq += mods[loop];
1213   }
1214
1215   // define all of the functions
1216   if (!addAllSharedObjFunctions(uniq, libModule, dynModule)) {
1217     err = true;
1218     return;
1219   }
1220   checkAllCallPoints();
1221
1222   // TODO -- remove duplicates -- see earlier note
1223   dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1224   vector<pd_Function*> temp_vec;
1225   unsigned f_size = mdlLib.size(), index;
1226   for (index=0; index<f_size; index++) {
1227     const unsigned the_address = (unsigned)mdlLib[index]->getAddress(0);
1228     if (!addr_dict.defines(the_address)) {
1229       addr_dict[the_address] = 1;
1230       temp_vec += mdlLib[index];
1231     }
1232   }
1233   mdlLib = temp_vec;
1234   temp_vec.resize(0); addr_dict.clear();
1235   f_size = mdlNormal.size();
1236   for (index=0; index<f_size; index++) {
1237     const unsigned the_address = (unsigned)mdlNormal[index]->getAddress(0);
1238     if (!addr_dict.defines(the_address)) {
1239       addr_dict[the_address] = 1;
1240       temp_vec += mdlNormal[index];
1241     }
1242   }
1243   mdlNormal = temp_vec;
1244
1245 }
1246
1247
1248 void pdmodule::checkAllCallPoints() {
1249   unsigned fsize = funcs.size();
1250   for (unsigned f=0; f<fsize; f++)
1251       funcs[f]->checkCallPoints();
1252 }
1253
1254
1255 void image::checkAllCallPoints() {
1256   dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1257   string s; pdmodule *mod;
1258   while (di.next(s, mod))
1259     mod->checkAllCallPoints();
1260 }
1261
1262 // passing in tags allows a function to be tagged as TAG_LIB_FUNC even
1263 // if its entry is not in the tag dictionary of known functions
1264 bool image::defineFunction(pdmodule *use, const Symbol &sym, const unsigned tags,
1265                            pd_Function *&retFunc) {
1266   // We used to skip a leading underscore, but not anymore.
1267   // (I forgot why we ever did in the first place)
1268
1269   unsigned dictTags = findTags(sym.name());
1270   return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags | dictTags, retFunc));
1271 }
1272
1273 pdmodule *image::getOrCreateModule(const string &modName, 
1274                                       const Address modAddr) {
1275   const char *str = modName.string_of();
1276   int len = modName.length();
1277   assert(len>0);
1278
1279   // TODO ignore directory definitions for now
1280   if (str[len-1] == '/') {
1281     return NULL;
1282   } else {
1283     // TODO - navigate ".." and "."
1284     const char *lastSlash = P_strrchr(str, '/');
1285     if (lastSlash)
1286       return (newModule(++lastSlash, modAddr));
1287     else
1288       return (newModule(modName, modAddr));
1289   }
1290 }
1291
1292 // KLUDGE TODO - internal functions are tagged with TAG_LIB_FUNC
1293 // but they won't have tags in the tag dict, so this happens...
1294 bool image::defineFunction(pdmodule *libModule, const Symbol &sym,
1295                            const string &modName, const Address modAddr,
1296                            pd_Function *&retFunc) {
1297
1298   // We used to skip a leading underscore, but not any more.
1299
1300   unsigned tags = findTags(sym.name());
1301
1302   if (TAG_LIB_FUNC & tags)
1303     return (newFunc(libModule, sym.name(), sym.addr(), sym.size(),
1304                     tags | TAG_LIB_FUNC, retFunc));
1305   else {
1306     pdmodule *use = getOrCreateModule(modName, modAddr);
1307     assert(use);
1308     return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags, retFunc));
1309   }
1310 }
1311
1312 // Verify that this is code
1313 // Find the call points
1314 // Find the return address
1315 // TODO -- use an instruction object to remove
1316 // Sets err to false on error, true on success
1317 //
1318 // Note - this must define funcEntry and funcReturn
1319 // 
1320 pd_Function::pd_Function(const string &symbol, const string &pretty, 
1321                        pdmodule *f, Address adr, const unsigned size, 
1322                        const unsigned tg, const image *owner, bool &err) : 
1323   function_base(symbol, pretty, adr, size,tg),
1324   file_(f),
1325   funcEntry_(0),
1326   relocatable_(false)
1327 {
1328   err = findInstPoints(owner) == false;
1329 }
1330