This commit implements the functions BPatch_function::isSharedLib() and
[dyninst.git] / dyninstAPI / src / symtab.h
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: symtab.h,v 1.117 2003/01/29 23:01:22 jodom Exp $
43
44 #ifndef SYMTAB_HDR
45 #define SYMTAB_HDR
46
47 extern "C" {
48 #include <sys/types.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <assert.h>
52 }
53
54 #include "common/h/Vector.h"
55 #include "common/h/Dictionary.h"
56 #include "common/h/List.h"
57 #include "dyninstAPI/src/Object.h"
58 #include "dyninstAPI/src/dyninst.h"
59 #include "dyninstAPI/src/arch.h"
60 #include "dyninstAPI/src/util.h"
61 #include "common/h/String.h"
62
63 #ifndef BPATCH_LIBRARY
64 #include "paradynd/src/resource.h"
65 #endif
66
67 #include "common/h/Types.h"
68 #include "common/h/Symbol.h"
69 #include "dyninstAPI/src/inst.h"
70
71 #ifndef mips_unknown_ce2_11 //ccw 8 apr 2001
72 #include "dyninstAPI/src/FunctionExpansionRecord.h"
73 class LocalAlterationSet;
74 #endif
75
76 #define RH_SEPERATOR '/'
77
78 /*
79  * List of supported languages.
80  *
81  */
82 typedef enum { lang_Unknown,
83                lang_Assembly,
84                lang_C,
85                lang_CPlusPlus,
86                lang_GnuCPlusPlus,
87                lang_Fortran,
88                lang_CMFortran
89                } supportedLanguages;
90
91  
92 /* contents of line number field if line is unknown */
93 #define UNKNOWN_LINE    0
94
95 #define TAG_LIB_FUNC    0x1
96 #define TAG_IO_OUT      0x2
97 #define TAG_IO_IN       0x4
98 #define TAG_MSG_SEND    0x8
99 #define TAG_MSG_RECV    0x10
100 #define TAG_SYNC_FUNC   0x20
101 #define TAG_CPU_STATE   0x40    /* does the func block waiting for ext. event */
102 #define TAG_MSG_FILT    0x80
103
104 #define DYN_MODULE "DYN_MODULE"
105 #define EXTRA_MODULE "EXTRA_MODULE"
106 #define USER_MODULE "USER_MODULE"
107 #define LIBRARY_MODULE  "LIBRARY_MODULE"
108
109 class image;
110 class lineTable;
111 class process;
112 class pd_Function;
113
114 // if a function needs to be relocated when it's instrumented then we need
115 // to keep track of new instrumentation points for this function on a per
116 // process basis (there is no guarentee that two processes are going to
117 // relocated this function to the same location in the heap)
118 class relocatedFuncInfo {
119 public:
120     relocatedFuncInfo(process *p,Address na):proc_(p),
121                       addr_(na),funcEntry_(0),installed_(false){}
122     
123     ~relocatedFuncInfo(){proc_ = 0;}
124     Address address(){ return addr_;}
125     const process *getProcess(){ return proc_;}
126     void setProcess(process *proc) { proc_ = proc; }
127     const pdvector<instPoint*> &funcReturns(){ return funcReturns_;}
128     const pdvector<instPoint*> &funcCallSites(){ return calls_;}
129     const pdvector<instPoint*> &funcArbitraryPoints(){ return arbitraryPoints_;}
130     const instPoint *funcEntry(){ return funcEntry_;}
131     void addFuncEntry(instPoint *e){ if(e) funcEntry_ = e; }
132     void addFuncReturn(instPoint *r){ if(r) funcReturns_.push_back(r); }
133     void addFuncCall(instPoint *c){ if(c) calls_.push_back(c); }
134     void addArbitraryPoint(instPoint *r){ if(r) arbitraryPoints_.push_back(r); }
135     bool isInstalled(){ return installed_; }
136     void setInstalled() { installed_ = true; }
137 private:
138     const process *proc_;               // process assoc. with the relocation
139     Address addr_;                      // function's relocated address
140     instPoint *funcEntry_;              // function entry point
141     bool installed_;                    // if true, function has been relocated
142     pdvector<instPoint*> funcReturns_;    // return point(s)
143     pdvector<instPoint*> calls_;          // pointer to the calls
144     pdvector<instPoint*> arbitraryPoints_;          // pointer to the calls
145 };
146
147
148 class pdmodule;
149 class module;
150
151 class function_base {
152 public:
153   static string emptyString;
154     function_base(const string &symbol, const string &pretty,
155                 Address adr, const unsigned size):
156                 line_(0), addr_(adr),size_(size) { 
157                 symTabName_.push_back(symbol); prettyName_.push_back(pretty); }
158     virtual ~function_base() { /* TODO */ }
159
160     /* The next two asserts should necver be reached, function_base has no
161      * default constructor which leaves the string vectors empty, the if
162      * is more or less a sanity check, if the asserts here are ever reached
163      * then something really bad must have happened.  Since we will never
164      * make it past the assert, in order to remove the compiler warnings
165      * we add the return to return the same string from the first part
166      * of the if statement
167      */
168     const string &symTabName() const { 
169         if (symTabName_.size() > 0) return symTabName_[0];
170         else return emptyString;
171     }
172     const string &prettyName() const {
173         if (prettyName_.size() > 0) return prettyName_[0];
174         else return emptyString;
175     }
176     pdvector<string> symTabNameVector() { return symTabName_; }
177     pdvector<string> prettyNameVector() { return prettyName_; }
178     void addSymTabName(string name) { symTabName_.push_back(name); }
179     void addPrettyName(string name) { prettyName_.push_back(name); }
180     unsigned size() const {return size_;}
181     Address addr() const {return addr_;}
182
183     bool match(function_base *p);
184
185     virtual Address getAddress(const process *p) = 0;
186     virtual Address getEffectiveAddress(const process *p) const = 0;
187     virtual const instPoint *funcEntry(process *p) const = 0;
188     virtual const pdvector<instPoint*> &funcExits(process *p) const = 0;
189     virtual const pdvector<instPoint*> &funcCalls(process *p) const = 0; 
190     virtual const pdvector<instPoint*> &funcArbitraryPoints(process *p) const = 0; 
191     virtual bool hasNoStackFrame() const = 0;
192        // formerly "isLeafFunc()" but that led to confusion, since people assign two
193        // different meanings to "leaf" fns: (1) has no stack frame, (2) makes no calls.
194        // By renaming this fn, we make clear that we're returning (1), not (2).
195     virtual bool makesNoCalls() const = 0;
196
197     // extra debuggering info....
198     ostream & operator<<(ostream &s) const;
199     friend ostream &operator<<(ostream &os, function_base &f);
200
201 #if defined(ia64_unknown_linux2_4)
202         // We need to know where all the alloc instructions in the
203         // function are to do a reasonable job of register allocation
204         // in the base tramp.  (I'd put this in pd_Function, but
205         // iPgetFunction() returns a function_base...)
206         pdvector< Address > allocs;
207 #endif
208
209 private:
210     pdvector<string> symTabName_;       /* name as it appears in the symbol table */
211     pdvector<string> prettyName_;       /* user's view of name (i.e. de-mangled) */
212     int line_;                  /* first line of function */
213     Address addr_;              /* address of the start of the func */
214     unsigned size_;             /* the function size, in bytes, used to
215                                    define the function boundaries. This may not
216                                    be exact, and may not be used on all 
217                                    platforms. */
218     
219 };
220
221
222 class instPoint;
223 class pd_Function : public function_base {
224  public:
225     pd_Function(const string &symbol, const string &pretty, pdmodule *f, 
226                 Address adr, const unsigned size, 
227                 const image *owner, bool &err);
228     ~pd_Function() { delete relocatedCode;  // delete the rewritten version 
229                      delete originalCode;   // of the function if it was 
230                      delete instructions;   // relocated      
231                                /* TODO */ }
232
233     bool findInstPoints(const image *owner);
234     void checkCallPoints();
235     bool defineInstPoint();
236     pdmodule *file() const { return file_;}
237     Address newCallPoint(
238                          Address adr,
239                          const instruction code, 
240                          const image *owner,
241                          bool &err);
242
243     // passing in a value of 0 for p will return the original address
244     // otherwise, if the process is relocated it will return the new address
245     Address getAddress(const process *p){
246         if(p && relocatable_) { 
247           for(u_int i=0; i < relocatedByProcess.size(); i++){
248             if((relocatedByProcess[i])->getProcess() == p) 
249                 return (relocatedByProcess[i])->address();
250         } }
251         return addr();
252     }
253     Address getEffectiveAddress(const process *p) const;
254     const instPoint *funcEntry(process *p) const {
255         if(p && relocatable_) { 
256           for(u_int i=0; i < relocatedByProcess.size(); i++){
257             if((relocatedByProcess[i])->getProcess() == p) {
258               return (relocatedByProcess[i])->funcEntry();
259             }
260         } }
261         return funcEntry_;
262     }
263     const pdvector<instPoint*> &funcExits(process *p) const {
264         if(p && relocatable_) {
265           for(u_int i=0; i < relocatedByProcess.size(); i++){
266             if((relocatedByProcess[i])->getProcess() == p) 
267                 return (relocatedByProcess[i])->funcReturns();
268         } }
269         return funcReturns;
270     }
271     const pdvector<instPoint*> &funcArbitraryPoints(process *p) const {
272         if(p && relocatable_) {
273           for(u_int i=0; i < relocatedByProcess.size(); i++){
274             if((relocatedByProcess[i])->getProcess() == p) 
275                 return (relocatedByProcess[i])->funcArbitraryPoints();
276         } }
277         return arbitraryPoints;
278     }
279     void addArbitraryPoint(instPoint* insp,process* p){
280         if(insp) arbitraryPoints.push_back(insp);
281
282         // Cheesy get-rid-of-compiler-warning
283         process *unused = p;
284         unused = 0;
285
286 #if defined(i386_unknown_nt4_0) || \
287     defined(i386_unknown_linux2_0) || \
288     defined(sparc_sun_solaris2_4) || \
289     defined(ia64_unknown_linux2_4)
290
291         if(insp && p && relocatable_)
292           for(u_int i=0; i < relocatedByProcess.size(); i++)
293             if((relocatedByProcess[i])->getProcess() == p) {
294                 addArbitraryPoint(insp,p,relocatedByProcess[i]);
295                 return;
296             }
297 #endif
298     }
299
300 #if defined(i386_unknown_nt4_0) || \
301     defined(i386_unknown_linux2_0) || \
302     defined(sparc_sun_solaris2_4) || \
303     defined(ia64_unknown_linux2_4) /* Temporary duplication - TLM */
304
305     void addArbitraryPoint(instPoint*,process*,relocatedFuncInfo*);
306
307 #endif
308
309     const pdvector<instPoint*> &funcCalls(process *p) const {
310         if(p && relocatable_) {
311           for(u_int i=0; i < relocatedByProcess.size(); i++){
312             if((relocatedByProcess[i])->getProcess() == p) 
313                 return (relocatedByProcess[i])->funcCallSites();
314         } }
315         return calls;
316     }
317     bool isInstalled(process *p){
318         if(p && relocatable_) {
319           for(u_int i=0; i < relocatedByProcess.size(); i++){
320             if((relocatedByProcess[i])->getProcess() == p) 
321                 return (relocatedByProcess[i])->isInstalled();
322         } }
323         return false;
324     }
325     void setInstalled(process *p){
326         if(p && relocatable_) {
327           for(u_int i=0; i < relocatedByProcess.size(); i++){
328             if((relocatedByProcess[i])->getProcess() == p) 
329                 (relocatedByProcess[i])->setInstalled();
330         } }
331     }
332     bool hasNoStackFrame() const {return noStackFrame;}
333        // formerly "isLeafFunc()" but that led to confusion, since people assign two
334        // different meanings to "leaf" fns: (1) has no stack frame, (2) makes no calls.
335        // By renaming this fn, we make clear that we're returning (1), not (2).
336     bool makesNoCalls() const {return makesNoCalls_;}
337
338     bool isTrapFunc() {return isTrap;}
339     bool needsRelocation() {return relocatable_;}
340     bool mayNeedRelocation() {return mayNeedRelocation_;}
341     void setRelocatable(bool value) { relocatable_ = value; }
342
343     bool isInstrumentable() { return isInstrumentable_; }
344     
345 #ifndef BPATCH_LIBRARY
346     // Fill in <callees> vector with pointers to all other pd functions
347     //  statically determined to be called from any call sites in 
348     //  this function.
349     // Returns false if unable to fill in that information....
350     bool getStaticCallees(process *proc, pdvector <pd_Function *> &callees);
351 #endif
352
353 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)   
354
355     bool checkInstPoints(const image *owner);
356     bool findInstPoints(const image *owner, Address adr, process *proc);
357
358     // Record a call point in a function that will be, or currently is
359     // being relocated.
360     // (if location != 0 && reloc_info != 0, then this is called when 
361     // the the function is actually being relocated)
362     void addCallPoint(const instruction instr, unsigned &callId,
363                       relocatedFuncInfo *reloc_info, instPoint *&point, 
364                       const instPoint *&location);
365
366     bool PA_attachTailCalls(LocalAlterationSet *temp_alteration_set);
367
368     //
369     // NEW routines for function code rewrites using peephole alterations....
370     //
371     bool readFunctionCode(const image *owner, instruction *into);
372     int moveOutOfDelaySlot(int offset, instruction loadedCode[],
373           int codeSize);
374 #elif defined(mips_sgi_irix6_4)  || defined(mips_unknown_ce2_11) //ccw 29 mar 2001
375     bool    checkInstPoints();
376     Address findTarget(instPoint *p);
377     Address findBranchTarget(instPoint *p, instruction i);
378     Address findJumpTarget(instPoint *p, instruction i);
379     Address findIndirectJumpTarget(instPoint *p, instruction i);
380     void    setVectorIds();
381
382     // stack frame info
383     Address findStackFrame(const image *owner);
384     // register saves into frame
385     struct regSave_t {
386       int           slot;       // stack frame ($fp) offset of saved register
387       bool          dword;      // is register saved as 64-bit doubleword?
388       Address       insn;       // offset of insn that saves this register
389     } reg_saves[NUM_REGS];
390     // $sp-style frame (common)
391     Address         sp_mod;     // offset of insn that modifies $sp
392     pdvector<Address> sp_ret;     // offset of insn that restores $sp
393     int             frame_size; // stack frame size ($sp frame only)
394     // $fp-style frame (rare)
395     Address         fp_mod;     // offset of insn that modifies $fp
396     bool            uses_fp;    // does this fn use $s8 as a frame pointer?
397
398     typedef struct inactiveRange {
399        int popOffset;
400        int retOffset;
401        } InactiveFrameRange;
402
403        pdvector<InactiveFrameRange> inactiveRanges;
404
405 #elif defined(i386_unknown_solaris2_5) || defined(i386_unknown_nt4_0) || defined(i386_unknown_linux2_0) || defined(ia64_unknown_linux2_4) /* Temporary duplication - TLM */
406
407     void instrAroundPt(instPoint *p, instruction allInstr[], int numBefore, 
408                        int numAfter, unsigned type, int index);
409
410     int getArrayOffset(Address adr, instruction code[]);
411
412     bool isTrueCallInsn(const instruction insn);
413  
414     bool canUseExtraSlot(instPoint *&ip) const;
415
416     bool usesTrap(instPoint *&ip);
417
418 #elif defined(alpha_dec_osf4_0)
419     int             frame_size; // stack frame size
420 #endif
421
422 #if defined(sparc_sun_solaris2_4)
423     bool is_o7_live(){ return o7_live; }
424 #endif
425
426     void updateForFork(process *childProcess, const process *parentProcess);
427
428 #if defined(i386_unknown_solaris2_5) || defined(i386_unknown_nt4_0) || defined(i386_unknown_linux2_0) || defined(sparc_sun_solaris2_4) || defined(ia64_unknown_linux2_4) /* Temporary duplication - TLM. */
429
430     // modifyInstPoint: change the value of the instPoint if it is wrong: 
431     // if this instPoint is from a function that was just relocated, then
432     // it may not have the correct address.  This routine finds the correct
433     // address for the instPoint
434     void modifyInstPoint(const instPoint *&location, process *proc);
435
436     bool isNearBranchInsn(const instruction insn);
437
438     bool fillInRelocInstPoints(const image *owner, process *proc,
439                                instPoint *&location, 
440                                relocatedFuncInfo *&reloc_info, Address mutatee,
441                                Address mutator, instruction oldCode[],
442                                Address newAdr, instruction newCode[],
443                                LocalAlterationSet &alteration_set);
444
445     int relocateInstructionWithFunction(bool setDisp, 
446                                         instruction *insn, 
447                                         Address origAddr, 
448                                         Address targetAddr, 
449                                         Address oldFunctionAddr, 
450                                         unsigned originalCodeSize);
451
452     int patchOffset(bool setDisp, LocalAlterationSet *alteration_set, 
453                     instruction& insn, Address adr, 
454                     Address firstAddress, unsigned originalCodeSize);
455
456     bool findAndApplyAlterations(const image *owner, 
457                                  instPoint *&location,
458                                  u_int &newAdr,
459                                  process *proc,
460                                  relocatedFuncInfo *&reloc_info, 
461                                  unsigned &size_change);
462
463     int findAlterations(const image *owner, process *proc, 
464                         instruction *&oldCode,
465                         LocalAlterationSet &normalized_alteration_set,
466                         Address &mutator, Address &mutatee);
467
468     int relocatedSizeChange(const image *owner, process *proc);
469
470     bool loadCode(const image *owner, process *proc, instruction *&oldCode, 
471                   unsigned &totalSize, Address &firstAddress);
472
473     bool expandInstPoints(const image *owner, 
474                           LocalAlterationSet *temp_alteration_set, 
475                           LocalAlterationSet &normalized_alteration_set, 
476                           Address baseAddress, Address mutator, 
477                           Address mutatee, instruction oldCode[], 
478                           unsigned numberOfInstructions);
479
480     bool PA_attachGeneralRewrites(const image *owner, 
481                                   LocalAlterationSet *temp_alteration_set, 
482                                   Address baseAddress, Address firstAddress,
483                                   instruction loadedCode[], 
484                                   unsigned numInstructions, int codeSize);
485
486
487     bool PA_attachOverlappingInstPoints(LocalAlterationSet *temp_alteration_set,
488                                         Address baseAddress,
489                                         Address firstAddress,
490                                         instruction loadedCode[], int codeSize);
491
492     bool PA_attachBranchOverlaps(LocalAlterationSet *temp_alteration_set, 
493                                  Address baseAddress, Address firstAddress,
494                                  instruction loadedCode[],
495                                  unsigned  numberOfInstructions, int codeSize);
496
497     bool discoverAlterations(LocalAlterationSet *temp_alteration_set, 
498                              LocalAlterationSet &normalized_alteration_set,
499                              Address baseAddress, Address firstAddress, 
500                              instruction originalCode[], int originalCodeSize); 
501
502     bool applyAlterations(LocalAlterationSet &normalized_alteration_set,
503                           Address mutator, Address mutatee, Address newAdr, 
504                           instruction originalCode[], 
505                           unsigned originalCodeSize, instruction newCode[]);
506
507     bool updateAlterations(LocalAlterationSet *temp_alteration_set,
508                            LocalAlterationSet &normalized_alteration_set,
509                            instruction *oldCode, 
510                            Address baseAddress, Address firstAddress,
511                            int &totalSizeChange);
512
513     bool relocateFunction(process *proc, instPoint *&location, bool &deferred);
514
515     void sorted_ips_vector(pdvector<instPoint*>&fill_in);
516
517     void copyInstruction(instruction &newInsn, instruction &oldInsn,  
518                                                unsigned &codeOffset);
519
520     int expandInstructions(LocalAlterationSet &alteration_set, 
521                            instruction &insn, 
522                            Address offset,
523                            instruction &newCodeInsn);
524
525     int fixRelocatedInstruction(bool setDisp, instruction *insn, 
526                                 Address origAddr, Address targetAddr);
527
528     bool branchInsideRange(instruction insn, Address branchAddress, 
529                        Address firstAddress, Address lastAddress);
530
531     bool trueCallInsideRange(instruction insn, Address callAddress, 
532                          Address firstAddress, Address lastAddress);
533
534     instPoint *find_overlap(pdvector<instPoint*> v, Address targetAddress);
535 #endif
536
537     void setNumInstructions(unsigned num) { numInstructions = num; }
538     unsigned getNumInstructions() { return numInstructions; }
539  
540     instruction *getInstructions() { return instructions; }
541
542
543
544 #ifndef BPATCH_LIBRARY
545     void SetFuncResource(resource *r) {
546       assert(r != NULL); 
547       funcResource = r;
548     }
549
550     string ResourceFullName() {
551       assert(funcResource); 
552       return funcResource->full_name();
553     }
554
555     bool FuncResourceSet() {
556       return (funcResource != NULL);
557     }
558 #endif
559
560   private:
561     pdmodule *file_;            /* pointer to file that defines func. */
562     instPoint *funcEntry_;      /* place to instrument entry (often not addr) */
563     pdvector<instPoint*> funcReturns;   /* return point(s). */
564     pdvector<instPoint*> calls;         /* pointer to the calls */
565     pdvector<instPoint*> arbitraryPoints;               /* pointer to the calls */
566 #ifndef BPATCH_LIBRARY
567     resource *funcResource;
568 #endif
569     
570     // these are for relocated functions
571     bool relocatable_;             // true if func will be relocated when instr
572     bool mayNeedRelocation_;       // True if func needs to be relocated to
573                                    // enable call sequence transfers to
574                                    // base trampolines 
575
576     unsigned char *relocatedCode;  // points to copy of rewritten function    
577     unsigned char *originalCode;   // points to copy of original function
578
579     unsigned numInstructions;      // num instructions in original func
580     instruction *instructions;     // instructions that correspond to the 
581                                    // original function 
582
583     bool noStackFrame; // formerly "leaf".  True iff this fn has no stack frame.
584     bool makesNoCalls_;
585
586     bool isTrap;                // true if function contains a trap instruct
587     bool isInstrumentable_;     // true if the function is instrumentable
588     pdvector<relocatedFuncInfo *> relocatedByProcess; // one element per process
589
590 #if defined(sparc_sun_solaris2_4)
591     bool o7_live;
592 #endif
593 };
594
595 /* Stores source code to address in text association for modules */
596 class lineDict {
597 public:
598   lineDict() : lineMap(uiHash) { }
599   ~lineDict() { /* TODO */ }
600   void setLineAddr (unsigned line, Address addr) { lineMap[line] = addr; }
601   inline bool getLineAddr (const unsigned line, Address &adr);
602
603 private:
604   dictionary_hash<unsigned, Address> lineMap;
605 };
606
607
608 class module {
609 public:
610     module(){}
611     module(supportedLanguages lang, Address adr, string &fullNm,
612            string &fileNm): fileName_(fileNm), fullName_(fullNm), 
613                 language_(lang), addr_(adr){}
614     virtual ~module(){}
615
616     string fileName() const { return fileName_; }
617     string fullName() const { return fullName_; }
618     supportedLanguages language() const { return language_;}
619     Address addr() const { return addr_; }
620
621     virtual function_base *findFunction (const string &name) = 0;
622     virtual function_base *findFunctionFromAll(const string &name) = 0;
623     virtual void define() = 0;    // defines module to paradyn
624     virtual pdvector<function_base *> *getFunctions() = 0;
625
626 #ifndef BPATCH_LIBRARY
627     virtual pdvector<function_base *> *getIncludedFunctions() = 0;
628 #endif
629
630 private:
631     string fileName_;                   // short file 
632     string fullName_;                   // full path to file 
633     supportedLanguages language_;
634     Address addr_;                      // starting address of module
635 };
636
637 class pdmodule: public module {
638 friend class image;
639 public:
640   pdmodule(supportedLanguages lang, Address adr, string &fullNm,
641            string &fileNm, image *e): module(lang,adr,fullNm,fileNm),
642 #ifndef BPATCH_LIBRARY
643     modResource(0),
644 #endif
645     exec_(e){
646     some_funcs_inited = FALSE;
647   }
648   ~pdmodule() { /* TODO */ }
649
650   void setLineAddr(unsigned line, Address addr) {
651         lines_.setLineAddr(line, addr);}
652   bool getLineAddr(unsigned line, Address &addr) { 
653        return (lines_.getLineAddr(line, addr)); }
654
655   image *exec() const { return exec_; }
656   void mapLines() { }           // line number info is not used now
657   void checkAllCallPoints();
658   void define();    // defines module to paradyn
659
660   void updateForFork(process *childProcess, const process *parentProcess);
661 #ifndef BPATCH_LIBRARY
662   void FillInCallGraphStatic(process *proc);
663       // fill in statically determined part of caller-callee relationship
664       //  for paradyn....
665 #endif
666
667   pdvector<function_base *> *getFunctions() { return (pdvector<function_base *>*)&funcs;} 
668   pdvector<function_base *> *getIncludedFunctions();
669   function_base *findFunction (const string &name);
670   function_base *findFunctionFromAll(const string &name);
671   bool isShared() const;
672 #ifndef BPATCH_LIBRARY
673   resource *getResource() { return modResource; }
674 #endif
675
676 private:
677 #ifndef BPATCH_LIBRARY
678   resource *modResource;
679 #endif
680   image *exec_;                      // what executable it came from 
681   lineDict lines_;
682   //  list of all found functions in module....
683   pdvector<pd_Function*> funcs;
684   pdvector<pd_Function*> notInstruFuncs;
685   // added as part of exclude support for statically linked objects.
686   //  mcheyny, 970928
687   //  list of non-excluded found functions in module....
688   pdvector<pd_Function*> some_funcs;
689   bool some_funcs_inited;
690   bool shared_;                      // if image it belongs to is shared lib
691 };
692
693
694 extern bool mdl_get_lib_constraints(pdvector<string> &);
695
696 void print_func_vector_by_pretty_name(string prefix,
697                                       pdvector<function_base *>*funcs);
698 void print_module_vector_by_short_name(string prefix,
699                                       pdvector<pdmodule*> *mods);
700 string getModuleName(string constraint);
701 string getFunctionName(string constraint);
702 //used by both sharedobject and pdmodule class....
703 bool filter_excluded_functions(pdvector<pd_Function*> all_funcs,
704     pdvector<pd_Function*>& some_funcs, string module_name);
705 bool function_is_excluded(pd_Function *func, string module_name);
706 bool module_is_excluded(pdmodule *module);
707
708
709 /*
710  * symbols we need to find from our RTinst library.  This is how we know
711  *   were our inst primatives got loaded as well as the data space variables
712  *   we use to put counters/timers and inst trampolines.  An array of these
713  *   is placed in the image structure.
714  *
715  */
716 class internalSym {
717 public:
718   internalSym() { }
719   internalSym(const Address adr, const string &nm) : name(nm), addr(adr) { }
720   Address getAddr() const { return addr;}
721
722 private:
723   string name;            /* name as it appears in the symbol table. */
724   Address addr;      /* absolute address of the symbol */
725 };
726
727
728 // modsByFileName
729 // modsbyFullName
730 // includedMods
731 // excludedMods
732 // allMods
733 // includedFunctions
734 // excludedFunctions
735 // instrumentableFunctions
736 // notInstruFunctions
737 // funcsByAddr
738 // funcsByPretty
739 // file_
740 // name_
741 // codeOffset_
742 // codeLen_
743 // dataOffset_
744 // dataLen_
745 // linkedFile
746 // iSymsMap
747 // allImages
748 // varsByPretty
749 // knownJumpTargets
750 // COMMENTS????
751 //  Image class contains information about statically and dynamically linked code 
752 //  belonging to a process....
753 class image {
754    friend class process;
755    friend class pd_Function;
756
757    //
758    // ****  PUBLIC MEMBER FUBCTIONS  ****
759    //
760 public:
761   static image *parseImage(const string file);
762   static image *parseImage(fileDescriptor *desc, Address newBaseAddr = 0); 
763
764   image(fileDescriptor *desc, bool &err, Address newBaseAddr = 0); 
765   ~image() { /* TODO */ }
766
767   // Check the list of symbols returned by the parser, return
768   // name/addr pair
769   bool findInternalSymbol(const string &name, const bool warn, internalSym &iSym);
770
771   // Check the list of symbols returned by the parser, return
772   // all which start with the given prefix
773   bool findInternalByPrefix(const string &prefix, pdvector<Symbol> &found) const;
774
775   
776   //Address findInternalAddress (const string &name, const bool warn, bool &err);
777   void updateForFork(process *childProcess, const process *parentProcess);
778
779   // find the named module  
780   pdmodule *findModule(const string &name, bool find_if_excluded = FALSE);
781   pdmodule *findModule(function_base *func);
782
783   // Note to self later: find is a const operation, [] isn't, for
784   // dictionary access. If we need to make the findFuncBy* methods
785   // consts, we can move from [] to find()
786
787   // Find the vector of functions associated with a (demangled) name
788   pdvector <pd_Function *> *findFuncVectorByPretty(const string &name);
789   // Find a (single) function by pretty (demangled) name. Picks one if more than
790   // one exists. Probably shouldn't exist.
791   pd_Function *findFuncByPretty(const string &name);
792   // Find a function by mangled (original) name. Guaranteed unique
793   pd_Function *findFuncByMangled(const string &name);
794   // Look for the function in the non instrumentable list
795   pd_Function *findNonInstruFunc(const string &name);
796   // Look for the function in the excluded list
797   pd_Function *findExcludedFunc(const string &name);
798   // Looks only for an instrumentable, non-excluded function
799   pd_Function *findFuncByName(const string &name);
800   // Looks for the name in all lists (inc. excluded and non-instrumentable)
801   pd_Function *findOneFunctionFromAll(const string &name);
802
803   // Given an address, do an exhaustive search for that function
804   pd_Function *findFuncByAddr(const Address &addr, const process *p = 0) const;
805
806   // Break apart the above
807   pd_Function *findFuncByEntryAddr(const Address &addr, const process *p = 0) const;
808   pd_Function *findFuncByRelocAddr(const Address &addr, const process *p = 0) const;
809   pd_Function *findFuncByOrigAddr(const Address &addr, const process *p = 0) const;
810
811   void findModByAddr (const Symbol &lookUp, pdvector<Symbol> &mods,
812                       string &modName, Address &modAddr, 
813                       const string &defName);
814
815   // report modules to paradyn
816   void defineModules();
817
818 #ifndef BPATCH_LIBRARY
819  // report statically determinable caller-callee relationship to paradyn....
820   void FillInCallGraphStatic(process *proc);
821 #endif
822
823   bool symbolExists(const string &); /* Does the symbol exist in the image? */
824   void postProcess(const string);          /* Load .pif file */
825
826
827   void addJumpTarget(Address addr) {
828     if (!knownJumpTargets.defines(addr)) knownJumpTargets[addr] = addr; 
829   }
830
831   bool isJumpTarget(Address addr) { 
832     return knownJumpTargets.defines(addr); 
833   }
834
835
836   // data member access
837
838   string file() const {return desc_->file();}
839   string name() const { return name_;}
840   string pathname() const { return pathname_; }
841   const fileDescriptor *desc() const { return desc_; }
842   Address codeOffset() { return codeOffset_;}
843   Address dataOffset() { return dataOffset_;}
844   Address dataLength() { return (dataLen_ << 2);} 
845   Address codeLength() { return (codeLen_ << 2);} 
846   const Object &getObject() const { return linkedFile; }
847
848   Object &getObjectNC() { return linkedFile; } //ccw 27 july 2000 : this is a TERRIBLE hack : 29 mar 2001
849
850   bool isDyninstRTLib() const { return is_libdyninstRT; }
851
852 #if !defined(BPATCH_LIBRARY) //ccw 19 apr 2002 : SPLIT
853 //  bool is_libparadynRT;
854   bool isParadynRTLib() const { return is_libparadynRT; }
855 #endif
856
857   bool isAOut() const { return is_a_out; }
858
859   inline bool isCode(const Address &where) const;
860   inline bool isData(const Address &where) const;
861   inline bool isValidAddress(const Address &where) const;
862   inline const Word get_instruction(Address adr) const;
863   inline const unsigned char *getPtrToInstruction(Address adr) const;
864
865   // Return symbol table information
866   inline bool symbol_info(const string& symbol_name, Symbol& ret);
867
868   // Called from the mdl -- lists of functions to look for
869   static void watch_functions(string& name, pdvector<string> *vs, bool is_lib,
870                               pdvector<pd_Function*> *updateDict);
871
872   // origionally return mdlNormal;....
873   // Note that (unlike name), this returns ONLY functions for which
874   // necessary instrumentation info could be found)!!!!
875   const pdvector<pd_Function*> &getAllFunctions();
876
877   // get all modules, including excluded ones....
878   const pdvector<pdmodule *> &getAllModules();
879
880 #ifndef BPATCH_LIBRARY
881   const pdvector<pd_Function*> &getIncludedFunctions();
882   const pdvector<pdmodule *> &getIncludedModules();
883   const pdvector<pdmodule *> &getExcludedModules();
884 #endif 
885
886   //
887   //  ****  PUBLIC DATA MEMBERS  ****
888   //
889
890   Address get_main_call_addr() const { return main_call_addr_; }
891  
892   private:
893
894   // Call tree:
895   //
896   // AddOneFunction:
897   //    Gets/Creates a module name ("DEFAULT_MODULE")
898   //    newFunc
899   // newFunc
900   //    new pd_Function()
901   //    if (problem determining instr)
902   //      addNotInstruFunction
903   //    else
904   //      addInstruFunction
905   //        function_is_excluded (MDL exclusion via "exclude <mod>/<func>", BUT NOT "exclude <mod>)
906   // addInstruFunction
907   //   if (excluded) [from above]
908   //     add to excludedFunctions (hash)
909   //   else
910   //     add to includedFunctions
911   //     add to funcsByAddr
912   //     add to funcsByPretty (if not already in there)
913   //     add to funcsByMangled (if not already in there)
914   // addNotInstruFunction
915   //   add to notInstruFunctions (by pretty name)
916
917   // Add a function to (if excluded) excluded list, otherwise to includedFunctions,
918   // funcsByAddr, funcsByPretty, funcsByMangled
919   void addInstruFunction(pd_Function *func, pdmodule *mod,
920         const Address addr, bool excluded);
921
922   // Add a function which could not be instrumented.  Sticks it in
923   // notInstruFuncs (list)
924   void addNotInstruFunc(pd_Function *func, pdmodule *mod);
925
926   // Determines if a function is instrumentable, and calls add(Not)InstruFunction
927   bool newFunc(pdmodule *, const string &name, const Address addr, 
928                const unsigned size);
929
930   bool addOneFunction(pdvector<Symbol> &mods,
931                       const Symbol &lookUp);
932
933   void addMultipleFunctionNames(pdvector<Symbol> &mods,
934                                 const Symbol &lookUp);
935
936   //
937   //  ****  PRIVATE MEMBERS FUNCTIONS  ****
938   //
939
940   // private methods for findind an excluded function by name or
941   //  address....
942   bool find_excluded_function(const string &name,
943       pdvector<pd_Function*> &retList);
944   pd_Function *find_excluded_function(const Address &addr);
945
946   void checkAllCallPoints();
947
948 #if 0
949   bool addInternalSymbol(const string &str, const Address symValue);
950 #endif
951   // creates the module if it does not exist
952   pdmodule *getOrCreateModule (const string &modName, const Address modAddr);
953   pdmodule *newModule(const string &name, const Address addr);
954
955   bool addAllFunctions(pdvector<Symbol> &mods);
956
957   bool addAllVariables();
958
959
960   //
961   //  ****  PRIVATE DATA MEMBERS  ****
962   //
963
964   fileDescriptor *desc_; /* file descriptor (includes name) */
965   string name_;          /* filename part of file, no slashes */
966   string pathname_;      /* file name with path */
967
968   Address codeOffset_;
969   unsigned codeLen_;
970   Address dataOffset_;
971   unsigned dataLen_;
972
973   bool is_libdyninstRT;
974 #if !defined(BPATCH_LIBRARY) //ccw 19 apr 2002 : SPLIT
975   bool is_libparadynRT;
976 #endif
977   bool is_a_out;
978   Address main_call_addr_; // address of call to main()
979
980   // data from the symbol table 
981   Object linkedFile;
982
983   //dictionary_hash <string, internalSym*> iSymsMap;   // internal RTinst symbols
984
985   // A vector of all images. Used to avoid duplicating
986   // an "image" that already exists.
987   static pdvector<image*> allImages;
988
989   // knownJumpTargets: the addresses in this image that are known to 
990   // be targets of jumps. It is used to check points with multiple 
991   // instructions.
992   // This is a subset of the addresses that are actually targets of jumps.
993   dictionary_hash<Address, Address> knownJumpTargets;
994
995   // list of modules which have not been excluded.
996   pdvector<pdmodule *> includedMods;
997   // list of excluded module.  includedMods && excludedMods
998   //  should be disjoint!!!!
999   pdvector<pdmodule *> excludedMods;
1000   // list of all modules, should = includedMods + excludedMods;
1001   // Not actually created until getAllModules called....
1002   pdvector<pdmodule *> allMods;
1003
1004   // list of all functions for which necessary instrumentation data
1005   //  could be found which are NOT excluded....
1006   pdvector<pd_Function*> includedFunctions;
1007   // includedFunctions + excludedFunctions (but not notInstruFunctions)....
1008   pdvector<pd_Function*> instrumentableFunctions;
1009
1010
1011   //
1012   // Hash Tables of Functions....
1013   //
1014
1015   // functions by address for all modules.  Only contains instrumentable
1016   //  funtions.
1017   dictionary_hash <Address, pd_Function*> funcsByAddr;
1018   // note, a prettyName is not unique, it may map to a function appearing
1019   // in several modules.  Also only contains instrumentable functions....
1020   dictionary_hash <string, pdvector<pd_Function*>*> funcsByPretty;
1021   // Hash table holding functions by mangled name.
1022   // Should contain same functions as funcsByPretty....
1023   dictionary_hash <string, pdvector<pd_Function*>*> funcsByMangled;
1024   // The functions that can't be instrumented
1025   // Note that notInstruFunctions holds list of functions for which
1026   //  necessary instrumentation data could NOT be found....
1027   dictionary_hash <string, pd_Function*> notInstruFunctions;
1028   // hash table of all functions for which necessary instrumentation data
1029   //  could be found which ARE excluded....
1030   dictionary_hash <string, pd_Function*> excludedFunctions;
1031   // TODO -- get rid of one of these
1032   // Note : as of 971001 (mcheyney), these hash tables only 
1033   //  hold entries in includedMods --> this implies that
1034   //  it may sometimes be necessary to do a linear sort
1035   //  through excludedMods if searching for a module which
1036   //  was excluded....
1037   dictionary_hash <string, pdmodule *> modsByFileName;
1038   dictionary_hash <string, pdmodule*> modsByFullName;
1039   // Variables indexed by pretty (non-mangled) name
1040   dictionary_hash <string, pdvector<string>*> varsByPretty;
1041  
1042
1043 };
1044
1045
1046 #ifndef BPATCH_LIBRARY
1047 // forward declarations....
1048 void CallGraphSetEntryFuncCallback(string exe_name, string r, int tid);
1049 void CallGraphFillDone(string exe_name);
1050 void CallGraphAddProgramCallback(string exe_name);
1051 #endif
1052 /*
1053  * a definition of a library function that we may wish to identify.  This is
1054  *   how we describe it to the symbol table parser, not how it appears in
1055  *   the symbol table.  Library functions are placed in a pseudo module 
1056  *   named LIBRARY_MODULE. 
1057  *
1058  */
1059
1060
1061 class libraryFunc {
1062 public:
1063   libraryFunc(const string n, unsigned t) : name(n), tags(t) { }
1064   unsigned getTags() const { return tags;}
1065
1066 private:
1067   string name;
1068   unsigned tags;
1069 };
1070
1071 #ifndef BPATCH_LIBRARY
1072 // TODO -- remove this
1073 extern resource *moduleRoot;
1074 #endif
1075
1076 inline bool lineDict::getLineAddr (const unsigned line, Address &adr) {
1077   if (!lineMap.defines(line)) {
1078     return false;
1079   } else {
1080     adr = lineMap[line];
1081     return true;
1082   }
1083 }
1084
1085 inline function_base *pdmodule::findFunction (const string &name) {
1086   unsigned f;
1087   
1088   for (f=0; f<funcs.size(); f++) {
1089     pdvector<string> funcNames = funcs[f]->symTabNameVector();
1090     for (unsigned i = 0; i < funcNames.size(); i++)
1091       if (funcNames[i] == name)
1092         return funcs[f];
1093     funcNames = funcs[f]->prettyNameVector();
1094     for (unsigned j = 0; j < funcNames.size(); j++)
1095       if (funcNames[j] == name)
1096         return funcs[f];
1097   }
1098
1099   return NULL;
1100 }
1101
1102 inline const Word image::get_instruction(Address adr) const{
1103   // TODO remove assert
1104   // assert(isValidAddress(adr));
1105   if(!isValidAddress(adr)){
1106       // logLine("address not valid in get_instruction\n");
1107       return 0;
1108   }
1109
1110   if (isCode(adr)) {
1111     adr -= codeOffset_;
1112     adr >>= 2;
1113     const Word *inst = linkedFile.code_ptr();
1114     return (inst[adr]);
1115   } else if (isData(adr)) {
1116     adr -= dataOffset_;
1117     adr >>= 2;
1118     const Word *inst = linkedFile.data_ptr();
1119     return (inst[adr]);
1120   } else {
1121     abort();
1122     return 0;
1123   }
1124 }
1125
1126 // return a pointer to the instruction at address adr
1127 inline const unsigned char *image::getPtrToInstruction(Address adr) const {
1128   assert(isValidAddress(adr));
1129   if (isCode(adr)) {
1130     adr -= codeOffset_;
1131     const unsigned char *inst = (const unsigned char *)linkedFile.code_ptr();
1132     return (&inst[adr]);
1133   } else if (isData(adr)) {
1134     adr -= dataOffset_;
1135     const unsigned char *inst = (const unsigned char *)linkedFile.data_ptr();
1136     return (&inst[adr]);
1137   } else {
1138     abort();
1139     return 0;
1140   }
1141 }
1142
1143
1144 // Address must be in code or data range since some code may end up
1145 // in the data segment
1146 inline bool image::isValidAddress(const Address &where) const{
1147   return (isAligned(where) && (isCode(where) || isData(where)));
1148 }
1149
1150 inline bool image::isCode(const Address &where)  const{
1151   return (linkedFile.code_ptr() && 
1152           (where >= codeOffset_) && (where < (codeOffset_+(codeLen_<<2))));
1153 }
1154
1155 inline bool image::isData(const Address &where)  const{
1156    return (linkedFile.data_ptr() && 
1157           (where >= dataOffset_) && (where < (dataOffset_+(dataLen_<<2))));
1158 }
1159
1160 inline bool image::symbol_info(const string& symbol_name, Symbol &ret_sym) {
1161
1162   if (linkedFile.get_symbol(symbol_name, ret_sym))
1163     return true;
1164
1165   if (varsByPretty.defines(symbol_name)) {
1166     pdvector<string> *mangledNames = varsByPretty[symbol_name];
1167     assert(mangledNames && mangledNames->size() == 1);
1168     if (linkedFile.get_symbol((*mangledNames)[0], ret_sym))
1169       return true;
1170   }
1171
1172   return false;
1173 }
1174
1175 #endif
1176