patch to fix exclude whole module
[dyninst.git] / dyninstAPI / src / symtab.h
1
2 /*
3  * Copyright (c) 1996 Barton P. Miller
4  * 
5  * We provide the Paradyn Parallel Performance Tools (below
6  * described as Paradyn") on an AS IS basis, and do not warrant its
7  * validity or performance.  We reserve the right to update, modify,
8  * or discontinue this software at any time.  We shall have no
9  * obligation to supply such updates or modifications or any other
10  * form of support to you.
11  * 
12  * This license is for research uses.  For such uses, there is no
13  * charge. We define "research use" to mean you may freely use it
14  * inside your organization for whatever purposes you see fit. But you
15  * may not re-distribute Paradyn or parts of Paradyn, in any form
16  * source or binary (including derivatives), electronic or otherwise,
17  * to any other organization or entity without our permission.
18  * 
19  * (for other uses, please contact us at paradyn@cs.wisc.edu)
20  * 
21  * All warranties, including without limitation, any warranty of
22  * merchantability or fitness for a particular purpose, are hereby
23  * excluded.
24  * 
25  * By your use of Paradyn, you understand and agree that we (or any
26  * other person or entity with proprietary rights in Paradyn) are
27  * under no obligation to provide either maintenance services,
28  * update services, notices of latent defects, or correction of
29  * defects for Paradyn.
30  * 
31  * Even if advised of the possibility of such damages, under no
32  * circumstances shall we (or any other person or entity with
33  * proprietary rights in the software licensed hereunder) be liable
34  * to you or any third party for direct, indirect, or consequential
35  * damages of any character regardless of type of action, including,
36  * without limitation, loss of profits, loss of use, loss of good
37  * will, or computer failure or malfunction.  You agree to indemnify
38  * us (and any other person or entity with proprietary rights in the
39  * software licensed hereunder) for any and all liability it may
40  * incur to third parties resulting from your use of Paradyn.
41  */
42
43 #ifndef SYMTAB_HDR
44 #define SYMTAB_HDR
45
46 extern "C" {
47 #include <sys/types.h>
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <assert.h>
51 }
52
53 #include "util/h/Pair.h"
54 #include "util/h/Vector.h"
55 #include "util/h/Dictionary.h"
56 #include "util/h/Object.h"
57 #include "util/h/list.h"
58 #include "dyninstAPI/src/dyninst.h"
59 #include "dyninstAPI/src/arch.h"
60 #include "dyninstAPI/src/util.h"
61 #include "util/h/String.h"
62 #ifndef BPATCH_LIBRARY
63 #include "paradynd/src/resource.h"
64 #endif
65 #include "util/h/Types.h"
66 #include "util/h/Symbol.h"
67 #include "dyninstAPI/src/inst.h"
68
69 #define RH_SEPERATOR '/'
70
71 /*
72  * List of supported languages.
73  *
74  */
75 typedef enum { langUnknown,
76                langAssembly,
77                langC,
78                langCPlusPlus,
79                langGnuCPlusPlus,
80                langFortran,
81                langCMFortran
82                } supportedLanguages;
83
84  
85 /* contents of line number field if line is unknown */
86 #define UNKNOWN_LINE    0
87
88 #define TAG_LIB_FUNC    0x1
89 #define TAG_IO_OUT      0x2
90 #define TAG_IO_IN       0x4
91 #define TAG_MSG_SEND    0x8
92 #define TAG_MSG_RECV    0x10
93 #define TAG_SYNC_FUNC   0x20
94 #define TAG_CPU_STATE   0x40    /* does the func block waiting for ext. event */
95 #define TAG_MSG_FILT    0x80
96
97 #define DYN_MODULE "DYN_MODULE"
98 #define EXTRA_MODULE "EXTRA_MODULE"
99 #define USER_MODULE "USER_MODULE"
100 #define LIBRARY_MODULE  "LIBRARY_MODULE"
101
102 class image;
103 class lineTable;
104 class process;
105
106 // if a function needs to be relocated when it's instrumented then we need
107 // to keep track of new instrumentation points for this function on a per
108 // process basis (there is no guarentee that two processes are going to
109 // relocated this function to the same location in the heap)
110 class relocatedFuncInfo {
111 public:
112     relocatedFuncInfo(process *p,Address na):proc_(p),
113                       addr_(na),funcEntry_(0),installed_(false){}
114     ~relocatedFuncInfo(){proc_ = 0;}
115     Address address(){ return addr_;}
116     const process *getProcess(){ return proc_;}
117     const vector<instPoint*> &funcReturns(){ return funcReturns_;}
118     const vector<instPoint*> &funcCallSites(){ return calls_;}
119     const instPoint *funcEntry(){ return funcEntry_;}
120     void addFuncEntry(instPoint *e){ if(e) funcEntry_ = e; }
121     void addFuncReturn(instPoint *r){ if(r) funcReturns_ += r; }
122     void addFuncCall(instPoint *c){ if(c) calls_ += c; }
123     bool isInstalled(){ return installed_; }
124     void setInstalled() { installed_ = true; }
125 private:
126     const process *proc_;               // process assoc. with the relocation
127     Address addr_;                      // function's relocated address
128     instPoint *funcEntry_;              // function entry point
129     bool installed_;                    // if true, function has been relocated
130     vector<instPoint*> funcReturns_;    // return point(s)
131     vector<instPoint*> calls_;          // pointer to the calls
132 };
133
134 class pdmodule;
135 class module;
136
137 class function_base {
138 public:
139     function_base(const string symbol, const string &pretty,
140                 Address adr, const unsigned size,const unsigned tg):
141                 symTabName_(symbol),prettyName_(pretty),line_(0),
142                 addr_(adr),size_(size),tag_(tg) { }
143     virtual ~function_base() { /* TODO */ }
144     const string &symTabName() const { return symTabName_;}
145     const string &prettyName() const { return prettyName_;}
146     unsigned size() const {return size_;}
147     unsigned addr() const {return addr_;}
148     unsigned tag() const { return tag_;}
149     void setTag(unsigned tg){ tag_ = tg; }
150
151     virtual Address getAddress(const process *p) = 0;
152     virtual const instPoint *funcEntry(process *p) const = 0;
153     virtual const vector<instPoint*> &funcExits(process *p) const = 0;
154     virtual const vector<instPoint*> &funcCalls(process *p) const = 0; 
155     virtual bool hasNoStackFrame() const = 0;
156        // formerly "isLeafFunc()" but that led to confusion, since people assign two
157        // different meanings to "leaf" fns: (1) has no stack frame, (2) makes no calls.
158        // By renaming this fn, we make clear that we're returning (1), not (2).
159
160     // extra debuggering info....
161     ostream & operator<<(ostream &s) const;
162     friend ostream &operator<<(ostream &os, function_base &f);
163 private:
164     string symTabName_;         /* name as it appears in the symbol table */
165     string prettyName_;         /* user's view of name (i.e. de-mangled) */
166     int line_;                  /* first line of function */
167     Address addr_;              /* address of the start of the func */
168     unsigned size_;             /* the function size, in bytes, used to
169                                    define the function boundaries. This may not
170                                    be exact, and may not be used on all 
171                                    platforms. */
172     
173     unsigned tag_;
174 };
175
176 class pd_Function : public function_base {
177  public:
178     pd_Function(const string &symbol, const string &pretty, pdmodule *f, 
179                 Address adr, const unsigned size, const unsigned tg, 
180                 const image *owner, bool &err);
181     ~pd_Function() { /* TODO */ }
182
183     bool findInstPoints(const image *owner);
184     void checkCallPoints();
185     bool defineInstPoint();
186     pdmodule *file() const { return file_;}
187     Address newCallPoint(Address adr, const instruction code, 
188                          const image *owner, bool &err);
189     // passing in a value of 0 for p will return the original address
190     // otherwise, if the process is relocated it will return the new address
191     Address getAddress(const process *p){
192         if(p && relocatable_) { 
193           for(u_int i=0; i < relocatedByProcess.size(); i++){
194             if((relocatedByProcess[i])->getProcess() == p) 
195                 return (relocatedByProcess[i])->address();
196         } }
197         return addr();
198     }
199     const instPoint *funcEntry(process *p) const {
200         if(relocatable_) { 
201           for(u_int i=0; i < relocatedByProcess.size(); i++){
202             if((relocatedByProcess[i])->getProcess() == p) 
203                 return (relocatedByProcess[i])->funcEntry();
204         } }
205         return funcEntry_;
206     }
207     const vector<instPoint*> &funcExits(process *p) const {
208         if(relocatable_) {
209           for(u_int i=0; i < relocatedByProcess.size(); i++){
210             if((relocatedByProcess[i])->getProcess() == p) 
211                 return (relocatedByProcess[i])->funcReturns();
212         } }
213         return funcReturns;
214     }
215     const vector<instPoint*> &funcCalls(process *p) const {
216         if(relocatable_) {
217           for(u_int i=0; i < relocatedByProcess.size(); i++){
218             if((relocatedByProcess[i])->getProcess() == p) 
219                 return (relocatedByProcess[i])->funcCallSites();
220         } }
221         return calls;
222     }
223     bool isInstalled(process *p){
224         if(relocatable_) {
225           for(u_int i=0; i < relocatedByProcess.size(); i++){
226             if((relocatedByProcess[i])->getProcess() == p) 
227                 return (relocatedByProcess[i])->isInstalled();
228         } }
229         return false;
230     }
231     void setInstalled(process *p){
232         if(relocatable_) {
233           for(u_int i=0; i < relocatedByProcess.size(); i++){
234             if((relocatedByProcess[i])->getProcess() == p) 
235                 (relocatedByProcess[i])->setInstalled();
236         } }
237     }
238     inline void tagAsLib(){ unsigned tg=tag(); tg |= TAG_LIB_FUNC; setTag(tg);}
239     inline void untagAsLib() { 
240         unsigned t = tag(); 
241         t &= ~TAG_LIB_FUNC; 
242         setTag(t);
243     }
244     inline bool isTagSimilar(const unsigned comp) const { 
245         unsigned tg = tag();
246         return(tg & comp);
247     }
248     bool isLibTag() const { return (tag() & TAG_LIB_FUNC);}
249
250     bool hasNoStackFrame() const {return noStackFrame;}
251        // formerly "isLeafFunc()" but that led to confusion, since people assign two
252        // different meanings to "leaf" fns: (1) has no stack frame, (2) makes no calls.
253        // By renaming this fn, we make clear that we're returning (1), not (2).
254
255     bool isTrapFunc() {return isTrap;}
256
257 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)   
258
259     bool checkInstPoints(const image *owner);
260     bool findInstPoints(const image *owner, Address adr, process *proc);
261     bool findNewInstPoints(const image *owner, 
262                           const instPoint *&location, Address adr, 
263                           process *proc,
264                           vector<instruction> &extra_instrs, 
265                           relocatedFuncInfo *reloc_info);
266     bool relocateFunction(process *proc, const instPoint *&location,
267                           vector<instruction> &extra_instrs);
268     // Add a new call point to a function that will be, or currently is
269     // being relocated (if location != 0 && reloc_info != 0,  then this is
270     // called when the the function is actually being relocated
271     Address newCallPoint(Address &adr, const instruction code, const 
272                          image *owner, bool &err, int &id, Address &addr,
273                          relocatedFuncInfo *reloc_info,
274                          const instPoint *&location);
275     // modifyInstPoint: change the value of the instPoint if it is wrong: 
276     // if this instPoint is from a function that was just relocated, then
277     // it may not have the correct address.  This routine finds the correct
278     // address for the instPoint
279     void modifyInstPoint(const instPoint *&location,process *proc);
280 #endif
281
282   private:
283     pdmodule *file_;            /* pointer to file that defines func. */
284     instPoint *funcEntry_;      /* place to instrument entry (often not addr) */
285     vector<instPoint*> funcReturns;     /* return point(s). */
286     vector<instPoint*> calls;           /* pointer to the calls */
287
288     // these are for relocated functions
289     bool relocatable_;          // true if func will be relocated when instr
290
291     bool noStackFrame; // formerly "leaf".  True iff this fn has no stack frame.
292
293     bool isTrap;                // true if function contains a trap instruct
294     vector<relocatedFuncInfo *> relocatedByProcess; // one element per process
295 };
296
297 /* Stores source code to address in text association for modules */
298 class lineDict {
299 public:
300   lineDict() : lineMap(uiHash) { }
301   ~lineDict() { /* TODO */ }
302   void setLineAddr (unsigned line, Address addr) { lineMap[line] = addr; }
303   inline bool getLineAddr (const unsigned line, Address &adr);
304
305 private:
306   dictionary_hash<unsigned, Address> lineMap;
307 };
308
309
310 class module {
311 public:
312     module(){}
313     module(supportedLanguages lang, Address adr, string &fullNm,
314            string &fileNm): fileName_(fileNm), fullName_(fullNm), 
315                 language_(lang), addr_(adr){}
316     virtual ~module(){}
317
318     string fileName() const { return fileName_; }
319     string fullName() const { return fullName_; }
320     supportedLanguages language() const { return language_;}
321     Address addr() const { return addr_; }
322
323     virtual function_base *findFunction (const string &name) = 0;
324     virtual void define() = 0;    // defines module to paradyn
325     virtual vector<function_base *> *getFunctions() = 0;
326     virtual vector<function_base *> *getIncludedFunctions() = 0;
327
328 private:
329     string fileName_;                   // short file 
330     string fullName_;                   // full path to file 
331     supportedLanguages language_;
332     Address addr_;                      // starting address of module
333 };
334
335 class pdmodule: public module {
336 friend class image;
337 public:
338   pdmodule(supportedLanguages lang, Address adr, string &fullNm,
339            string &fileNm, image *e): module(lang,adr,fullNm,fileNm),
340            exec_(e){
341     some_funcs_inited = FALSE;
342   }
343   ~pdmodule() { /* TODO */ }
344
345   void setLineAddr(unsigned line, Address addr) {
346         lines_.setLineAddr(line, addr);}
347   bool getLineAddr(unsigned line, Address &addr) { 
348        return (lines_.getLineAddr(line, addr)); }
349
350   image *exec() const { return exec_; }
351   void mapLines() { }           // line number info is not used now
352   void checkAllCallPoints();
353   inline void changeLibFlag(const bool setSuppress);
354   void define();    // defines module to paradyn
355   vector<function_base *> *getFunctions() { return (vector<function_base *>*)&funcs;} 
356   vector<function_base *> *getIncludedFunctions();
357   function_base *findFunction (const string &name);
358
359 private:
360   image *exec_;                      // what executable it came from 
361   lineDict lines_;
362   //  list of all found functions in module....
363   vector<pd_Function*> funcs;
364   // added as part of exclude support for statically linked objects.
365   //  mcheyny, 970928
366   //  list of non-excluded found functions in module....
367   vector<pd_Function*> some_funcs;
368   bool some_funcs_inited;
369 };
370
371
372 extern bool mdl_get_lib_constraints(vector<string> &);
373
374 void print_func_vector_by_pretty_name(string prefix,
375                                       vector<function_base *>*funcs);
376 void print_module_vector_by_short_name(string prefix,
377                                       vector<pdmodule*> *mods);
378 string getModuleName(string constraint);
379 string getFunctionName(string constraint);
380 //used by both sharedobject and pdmodule class....
381 bool filter_excluded_functions(vector<pd_Function*> all_funcs,
382     vector<pd_Function*>& some_funcs, string module_name);
383 bool function_is_excluded(pd_Function *func, string module_name);
384 bool module_is_excluded(pdmodule *module);
385
386 /*
387  * symbols we need to find from our RTinst library.  This is how we know
388  *   were our inst primatives got loaded as well as the data space variables
389  *   we use to put counters/timers and inst trampolines.  An array of these
390  *   is placed in the image structure.
391  *
392  */
393 class internalSym {
394 public:
395   internalSym() { }
396   internalSym(const Address adr, const string &nm) : name(nm), addr(adr) { }
397   Address getAddr() const { return addr;}
398
399 private:
400   string name;            /* name as it appears in the symbol table. */
401   Address addr;      /* absolute address of the symbol */
402 };
403
404
405 // modsByFileName
406 // modsbyFullName
407 // includedMods
408 // excludedMods
409 // allMods
410 // includedFunctions
411 // excludedFunctions
412 // instrumentableFunctions
413 // notInstruFunctions
414 // funcsByAddr
415 // funcsByPretty
416 // file_
417 // name_
418 // codeOffset_
419 // codeLen_
420 // dataOffset_
421 // dataLen_
422 // linkedFile
423 // iSymsMap
424 // allImages
425 // varsByPretty
426 // knownJumpTargets
427 // COMMENTS????
428 //  Image class contains information about statically and dynamically linked code 
429 //  belonging to a process....
430 class image {
431    friend class process;
432
433    //
434    // ****  PUBLIC MEMBER FUBCTIONS  ****
435    //
436 public:
437   static image *parseImage(const string file);
438   static image *parseImage(const string file,u_int baseAddr);
439 #ifndef BPATCH_LIBRARY
440   static void changeLibFlag(resource*, const bool);
441 #endif
442
443   image(const string &file, bool &err);
444   image(const string &file, u_int baseAddr, bool &err);
445   ~image() { /* TODO */ }
446
447   // True if symbol can be found, regardless of whether it is
448   // excluded!!!! 
449   bool findInternalSymbol(const string &name, const bool warn, internalSym &iSym);
450   // Non-NULL if symbol can be found, even if it it is excluded!!!!
451   Address findInternalAddress(const string &name, const bool warn, bool &err);
452
453   // find the named module  
454   pdmodule *findModule(const string &name, bool find_if_excluded = FALSE);
455
456   // find the function by name, address, or the first by name
457   // find_if_excluded specifies whether to include "excluded" 
458   // functions in search.
459   bool findFunction(const string &name, vector<pd_Function*> &flist,
460     bool find_if_excluded = FALSE);
461   // find_if_excluded specifies whether to include "excluded" 
462   // functions in search.
463   pd_Function *findFunction(const Address &addr,
464     bool find_if_excluded = FALSE);
465
466   // return NULL if function is excluded!!!!
467   pd_Function *findOneFunction(const string &name);
468   // not NULL if function can be found, even if excluded!!!!
469   pd_Function *findOneFunctionFromAll(const string &name);
470
471   // non-NULL even if function is excluded!!!!
472   pd_Function *findFunctionIn(const Address &addr,const process *p) const;
473   // as per findFunctionIn....
474   pd_Function *findFunctionInInstAndUnInst(const Address &addr, const process *p) const;
475
476   // report modules to paradyn
477   void defineModules();
478
479   bool symbolExists(const string &); /* Does the symbol exist in the image? */
480   void postProcess(const string);          /* Load .pif file */
481
482
483   void addJumpTarget(Address addr) {
484     if (!knownJumpTargets.defines(addr)) knownJumpTargets[addr] = addr; 
485   }
486
487   bool isJumpTarget(Address addr) { 
488     return knownJumpTargets.defines(addr); 
489   }
490
491
492   // data member access
493   inline const Word get_instruction(Address adr) const;
494
495   inline const unsigned char *getPtrToInstruction(Address adr) const;
496
497   string file() const {return file_;}
498   string name() const { return name_;}
499   Address codeOffset() { return codeOffset_;}
500   Address dataOffset() { return dataOffset_;}
501   Address dataLength() { return (dataLen_ << 2);} 
502   Address codeLength() { return (codeLen_ << 2);} 
503   inline bool isCode(const Address &where) const;
504   inline bool isData(const Address &where) const;
505   const Object &getObject() const { return linkedFile; }
506
507   inline bool isValidAddress(const Address &where) const;
508
509   // Return symbol table information
510   inline bool symbol_info(const string& symbol_name, Symbol& ret);
511
512   // Called from the mdl -- lists of functions to look for
513   static void watch_functions(string& name, vector<string> *vs, bool is_lib,
514                               vector<pd_Function*> *updateDict);
515
516   // origionally return mdlNormal;....
517   // Note that (unlike name), this returns ONLY functions for which
518   // necessary instrumentation info could be found)!!!!
519   const vector<pd_Function*> &getAllFunctions();
520
521   const vector<pd_Function*> &getIncludedFunctions();
522
523   // get all modules, including excluded ones....
524   const vector<pdmodule *> &getAllModules();
525   const vector<pdmodule *> &getIncludedModules();
526
527   //
528   //  ****  PUBLIC DATA MEMBERS  ****
529   //
530
531  
532   // 
533   //  **** PRIVATE DATA MEMBERS ****
534   //
535   private:
536
537   // TODO -- get rid of one of these
538   // Note : as of 971001 (mcheyney), these hash tables only 
539   //  hold entries in includedMods --> this implies that
540   //  it may sometimes be necessary to do a linear sort
541   //  through excludedMods if searching for a module which
542   //  was excluded....
543   dictionary_hash <string, pdmodule *> modsByFileName;
544   dictionary_hash <string, pdmodule*> modsByFullName;
545
546   // list of modules which have not been excluded.
547   vector<pdmodule *> includedMods;
548   // list of excluded module.  includedMods && excludedMods
549   //  should be disjoint!!!!
550   vector<pdmodule *> excludedMods;
551   // list of all modules, should = includedMods + excludedMods;
552   // Not actually created until getAllModules called....
553   vector<pdmodule *> allMods;
554
555   //
556   // Lists of Functions....
557   //
558   //  ALERT ALERT!!!!  class image used to contain :
559   //vector<pd_Function*> mdlLib;       // functions NOT linked between
560   //                                   //   DYNINSTstart && DYNINSTend.
561   //vector<pd_Function*> mdlNormal;    // functions linked between 
562   //                                   //   DYNINSTstart && DYNINSTend.
563   //  changed to :
564   // list of all functions for which necessary instrumentation data
565   //  could be found which are NOT excluded....
566   vector<pd_Function*> includedFunctions;
567   // hash table of all functions for which necessary instrumentation data
568   //  could be found which ARE excluded....
569   dictionary_hash <string, pd_Function*> excludedFunctions;
570   // Note that notInstruFunctions holds list of functions for which
571   //  necessary instrumentation data could NOT be found....
572
573   // includedFunctions + excludedFunctions (but not notInstruFunctions)....
574   vector<pd_Function*> instrumentableFunctions;
575
576   dictionary_hash <string, pd_Function*> notInstruFunctions;
577   // The functions that we are not going to instrument
578
579   //
580   // Hash Tables of Functions....
581   //
582   // functions by address for all modules.  Only contains instrumented
583   //  funtions.
584   dictionary_hash <Address, pd_Function*> funcsByAddr;
585   dictionary_hash <string, vector<pd_Function*>*> funcsByPretty;
586   // note, a prettyName is not unique, it may map to a function appearing
587   // in several modules.  Also only contains instrumented functions....
588
589
590   //
591   // Private Member Functions for placing pd_Functions in includedFunctions,
592   //  excludedFunctions, notInstruFunctions, instrumentableFunctions, 
593   //  and the assorted hash tables associated with them....
594   //
595   // Add a function which was successfully instrumented, and specify 
596   //  if excluded (e.g. via mdl "exclude" command).  Sticks it in 
597   //  instrumentableFunctions, mod->funcs, and for:
598   // excluded:
599   //   excludedFunctions, excludedFunctionsByName
600   // not excluded:
601   //   includedFunctions, funcsByPretty, funcsByAddr
602   void addInstruFunction(pd_Function *func, pdmodule *mod,
603         const Address addr, bool excluded);
604   // Add a function which could not be instrumented.  Sticks it in
605   // notInstruFuncs (list), and notInstruFunctionsByName (hash table).
606   void addNotInstruFunc(pd_Function *func);
607
608   //
609   //  ****  PRIVATE MEMBERS FUNCTIONS  ****
610   //
611
612   // private methods for findind an excluded function by name or
613   //  address....
614   bool find_excluded_function(const string &name,
615       vector<pd_Function*> &retList);
616   pd_Function *find_excluded_function(const Address &addr);
617
618   // merged code from shared_object and static executable constructor
619   //  versions....
620   void initialize(const string &fileName, bool &err,
621         bool shared_library, u_int baseAddr = 0);
622
623   bool newFunc(pdmodule *, const string &name, const Address addr, 
624                const unsigned size, const unsigned tags, pd_Function *&retFunc);
625
626   void checkAllCallPoints();
627
628   bool addInternalSymbol(const string &str, const Address symValue);
629
630   // creates the module if it does not exist
631   pdmodule *getOrCreateModule (const string &modName, const Address modAddr);
632   pdmodule *newModule(const string &name, const Address addr);
633
634   bool addOneFunction(vector<Symbol> &mods, pdmodule *lib, pdmodule *dyn,
635                       const Symbol &lookUp, pd_Function *&retFunc);
636
637   bool addAllFunctions(vector<Symbol> &mods,
638                        pdmodule *lib, pdmodule *dyn,
639                        const bool startB, const Address startAddr,
640                        const bool endB, const Address endAddr);
641
642   bool addAllSharedObjFunctions(vector<Symbol> &mods,
643                        pdmodule *lib, pdmodule *dyn);
644
645   bool addAllVariables();
646
647   // if useLib = true or the functions' tags signify a library function
648   // the function is put in the library module
649   bool defineFunction(pdmodule *use, const Symbol &sym, const unsigned tags,
650                       pd_Function *&retFunc);
651   bool defineFunction(pdmodule *lib, const Symbol &sym,
652                       const string &modName, const Address modAdr,
653                       pd_Function *&retFunc);
654
655
656   void insert_function_internal_static(vector<Symbol> &mods,
657         const Symbol &lookUp,
658         const Address boundary_start,  const Address boundary_end,
659         const Address startAddr, bool startB, const Address endAddr,
660         bool endB, pdmodule *dyn, pdmodule *lib);
661   void image::insert_function_internal_dynamic(vector<Symbol>& mods,
662       const Symbol &lookUp,
663       pdmodule *dyn, pdmodule *lib, bool is_libdyninstRT);
664
665   //
666   //  ****  PRIVATE DATA MEMBERS  ****
667   //
668
669   string file_;         /* image file name */
670   string name_;         /* filename part of file, no slashes */
671
672   Address codeOffset_;
673   unsigned codeLen_;
674   Address dataOffset_;
675   unsigned dataLen_;
676
677   // data from the symbol table 
678   Object linkedFile;
679
680   dictionary_hash <string, internalSym*> iSymsMap;   // internal RTinst symbols
681
682   static vector<image*> allImages;
683
684   dictionary_hash <string, vector<string>*> varsByPretty;
685  
686   // knownJumpTargets: the addresses in this image that are known to 
687   // be targets of jumps. It is used to check points with multiple 
688   // instructions.
689   // This is a subset of the addresses that are actually targets of jumps.
690   dictionary_hash<Address, Address> knownJumpTargets;
691
692 };
693
694
695 /*
696  * a definition of a library function that we may wish to identify.  This is
697  *   how we describe it to the symbol table parser, not how it appears in
698  *   the symbol table.  Library functions are placed in a pseudo module 
699  *   named LIBRARY_MODULE. 
700  *
701  */
702
703
704 class libraryFunc {
705 public:
706   libraryFunc(const string n, unsigned t) : name(n), tags(t) { }
707   unsigned getTags() const { return tags;}
708
709 private:
710   string name;
711   unsigned tags;
712 };
713
714 #ifndef BPATCH_LIBRARY
715 // TODO -- remove this
716 extern resource *moduleRoot;
717 #endif
718
719 inline bool lineDict::getLineAddr (const unsigned line, Address &adr) {
720   if (!lineMap.defines(line)) {
721     return false;
722   } else {
723     adr = lineMap[line];
724     return true;
725   }
726 }
727
728 inline void pdmodule::changeLibFlag(const bool setSuppress) {
729   unsigned fsize = funcs.size();
730   for (unsigned f=0; f<fsize; f++) {
731     if (setSuppress)
732       funcs[f]->tagAsLib();
733     else
734       funcs[f]->untagAsLib();    
735   }
736 }
737
738 inline function_base *pdmodule::findFunction (const string &name) {
739   unsigned fsize = funcs.size();
740   for (unsigned f=0; f<fsize; f++) {
741     if (funcs[f]->prettyName() == name)
742       return funcs[f];
743   }
744   return NULL;
745 }
746
747 inline const Word image::get_instruction(Address adr) const{
748   // TODO remove assert
749   // assert(isValidAddress(adr));
750   if(!isValidAddress(adr)){
751       // logLine("address not valid in get_instruction\n");
752       return 0;
753   }
754
755   if (isCode(adr)) {
756     adr -= codeOffset_;
757     adr >>= 2;
758     const Word *inst = linkedFile.code_ptr();
759     return (inst[adr]);
760   } else if (isData(adr)) {
761     adr -= dataOffset_;
762     adr >>= 2;
763     const Word *inst = linkedFile.data_ptr();
764     return (inst[adr]);
765   } else {
766     abort();
767     return 0;
768   }
769 }
770
771 // return a pointer to the instruction at address adr
772 inline const unsigned char *image::getPtrToInstruction(Address adr) const {
773   assert(isValidAddress(adr));
774   if (isCode(adr)) {
775     adr -= codeOffset_;
776     const unsigned char *inst = (const unsigned char *)linkedFile.code_ptr();
777     return (&inst[adr]);
778   } else if (isData(adr)) {
779     adr -= dataOffset_;
780     const unsigned char *inst = (const unsigned char *)linkedFile.data_ptr();
781     return (&inst[adr]);
782   } else {
783     abort();
784     return 0;
785   }
786 }
787
788
789 // Address must be in code or data range since some code may end up
790 // in the data segment
791 inline bool image::isValidAddress(const Address &where) const{
792   return (isAligned(where) && (isCode(where) || isData(where)));
793 }
794
795 inline bool image::isCode(const Address &where)  const{
796   return (linkedFile.code_ptr() && 
797           (where >= codeOffset_) && (where < (codeOffset_+(codeLen_<<2))));
798 }
799
800 inline bool image::isData(const Address &where)  const{
801    return (linkedFile.data_ptr() && 
802           (where >= dataOffset_) && (where < (dataOffset_+(dataLen_<<2))));
803 }
804
805 inline bool image::symbol_info(const string& symbol_name, Symbol &ret_sym) {
806   if (linkedFile.get_symbol(symbol_name, ret_sym))
807     return true;
808
809   if (varsByPretty.defines(symbol_name)) {
810     vector<string> *mangledNames = varsByPretty[symbol_name];
811     assert(mangledNames && mangledNames->size() == 1);
812     if (linkedFile.get_symbol((*mangledNames)[0], ret_sym))
813       return true;
814   }
815
816   return false;
817 }
818
819 #endif
820