Added code to build procedure lists for the mdl
[dyninst.git] / dyninstAPI / src / symtab.h
1 /*
2  *  Copyright 1993 Jeff Hollingsworth.  All rights reserved.
3  *
4  */
5
6 #ifndef SYMTAB_HDR
7 #define SYMTAB_HDR
8
9 /*
10  * symtab.h - interface to generic symbol table.
11  *
12  * $Log: symtab.h,v $
13  * Revision 1.15  1995/05/18 10:42:42  markc
14  * Added code to build procedure lists for the mdl
15  *
16  * Revision 1.14  1995/02/24  04:42:01  markc
17  * Check if an address could be for an instruction before checking to see if it
18  * is delayed, since we should not be checking instructions that are out of range.
19  *
20  * Revision 1.13  1995/02/21  22:03:36  markc
21  * Added slightly better error recovery, with messages!  Paradynd reports back
22  * when it attempts to run an unusable executable.  It no longer aborts.
23  *
24  * Revision 1.12  1995/02/16  08:54:25  markc
25  * Corrected error in comments -- I put a "star slash" in the comment.
26  *
27  * Revision 1.11  1995/02/16  08:35:00  markc
28  * Changed igen interfaces to use strings/vectors rather than char igen-arrays
29  * Changed igen interfaces to use bool, not Boolean.
30  * Cleaned up symbol table parsing - favor properly labeled symbol table objects
31  * Updated binary search for modules
32  * Moved machine dependnent ptrace code to architecture specific files.
33  * Moved machine dependent code out of class process.
34  * Removed almost all compiler warnings.
35  * Use "posix" like library to remove compiler warnings
36  *
37  * Revision 1.10  1994/11/09  18:40:40  rbi
38  * the "Don't Blame Me" commit
39  *
40  * Revision 1.9  1994/11/02  11:17:46  markc
41  * Added class support for image, module, function.
42  *
43  * Revision 1.7  1994/09/30  19:47:17  rbi
44  * Basic instrumentation for CMFortran
45  *
46  * Revision 1.6  1994/09/22  02:26:56  markc
47  * Made structs classes
48  *
49  * Revision 1.5  1994/08/02  18:25:08  hollings
50  * fixed modules to use list template for lists of functions.
51  *
52  * Revision 1.4  1994/07/22  19:21:11  hollings
53  * removed mistaken divid by 1Meg for predicted cost.
54  *
55  * Revision 1.3  1994/07/20  23:23:43  hollings
56  * added insn generated metric.
57  *
58  * Revision 1.2  1994/06/29  02:52:52  hollings
59  * Added metricDefs-common.{C,h}
60  * Added module level performance data
61  * cleanedup types of inferrior addresses instrumentation defintions
62  * added firewalls for large branch displacements due to text+data over 2meg.
63  * assorted bug fixes.
64  *
65  * Revision 1.1  1994/01/27  20:31:46  hollings
66  * Iinital version of paradynd speaking dynRPC igend protocol.
67  *
68  * Revision 1.4  1993/12/13  19:58:12  hollings
69  * added sibling filed for functions that occur multiple times in the same
70  * binary image (statics, and c++ template classes for example).
71  *
72  * Revision 1.3  1993/07/13  18:33:11  hollings
73  * new include file syntax.
74  *
75  * Revision 1.2  1993/06/08  20:14:34  hollings
76  * state prior to bc net ptrace replacement.
77  *
78  * Revision 1.1  1993/03/19  22:51:05  hollings
79  * Initial revision
80  *
81  *
82  */
83
84 extern "C" {
85 #include <sys/types.h>
86 #include <stdlib.h>
87 #include <stdio.h>
88 #include <assert.h>
89 }
90
91 #include "util/h/Pair.h"
92 #include "util/h/Vector.h"
93 #include "util/h/Dictionary.h"
94 #include "util/h/Object.h"
95 #include "util/h/list.h"
96 #include "dyninst.h"
97 #include "arch-sparc.h"
98 #include "util.h"
99 #include "util/h/String.h"
100 #include "resource.h"
101 #include "util/h/Types.h"
102 #include "util/h/Symbol.h"
103
104 /*
105  * List of supported languages.
106  *
107  */
108 typedef enum { langUnknown,
109                langAssembly,
110                langC,
111                langCPlusPlus,
112                langGnuCPlusPlus,
113                langFortran,
114                langCMFortran
115                } supportedLanguages;
116
117 /* contents of line number field if line is unknown */
118 #define UNKNOWN_LINE    0
119
120 #define TAG_LIB_FUNC    0x1
121 #define TAG_IO_OUT      0x2
122 #define TAG_IO_IN       0x4
123 #define TAG_MSG_SEND    0x8
124 #define TAG_MSG_RECV    0x10
125 #define TAG_SYNC_FUNC   0x20
126 #define TAG_CPU_STATE   0x40    /* does the func block waiting for ext. event */
127 #define TAG_MSG_FILT    0x80
128
129 #define DYN_MODULE "DYN_MODULE"
130 #define EXTRA_MODULE "EXTRA_MODULE"
131 #define USER_MODULE "USER_MODULE"
132 #define LIBRARY_MODULE  "LIBRARY_MODULE"
133
134 class pdFunction;
135 class instPoint;
136 class module;
137 class image;
138 class internalSym;
139 class lineTable;
140
141
142 class pdFunction {
143  public:
144     pdFunction(const string symbol, const string &pretty, module *f, Address adr,
145                const unsigned tg, const image *owner, bool &err);
146     ~pdFunction() { /* TODO */ }
147     void checkCallPoints();
148     bool defineInstPoint();
149     Address newCallPoint(const Address adr, const instruction code, const image *owner, 
150                          bool &err);
151
152     string symTabName() const { return symTabName_;}
153     string prettyName() const { return prettyName_;}
154     const module *file() const { return file_;}
155     Address addr() const { return addr_;}
156     instPoint *funcEntry() const { return funcEntry_;}
157     instPoint *funcReturn() const { return funcReturn_;}
158     inline void tagAsLib() { tag_ |= TAG_LIB_FUNC;}
159     inline void untagAsLib() { tag_ &= ~TAG_LIB_FUNC;}
160     inline bool isTagSimilar(const unsigned comp) const { return(tag_ & comp);}
161     bool isLibTag() const { return (tag_ & TAG_LIB_FUNC);}
162     vector<instPoint*> calls;           /* pointer to the calls */
163     unsigned tag() const { return tag_; }
164
165   private:
166     unsigned tag_;
167     string symTabName_;         /* name as it appears in the symbol table */
168     string prettyName_;         /* user's view of name (i.e. de-mangled) */
169     int line_;                  /* first line of function */
170     module *file_;              /* pointer to file that defines func. */
171     Address addr_;              /* address of the start of the func */
172     instPoint *funcEntry_;      /* place to instrument entry (often not addr) */
173     instPoint *funcReturn_;     /* exit point for function */
174 };
175
176 class instPoint {
177 public:
178   instPoint(pdFunction *f, const instruction &instr, const image *owner,
179             const Address adr, const bool delayOK);
180   ~instPoint() {  /* TODO */ }
181 #ifdef notdef
182   Address addr() const { return addr_; } 
183   instruction originalInstruction() const { return originalInstruction_;} 
184   instruction delaySlotInsn() const { return delaySlotInsn_; }
185   instruction aggregateInsn() const { return aggregateInsn_; }
186   bool inDelaySlot() const { return inDelaySlot_;}
187   bool isDelayed() const { return isDelayed_;}
188   bool callIndirect() const { return callIndirect_;}
189   bool callAggregate() const { return callAggregate_;}
190   pdFunction *callee() const { return callee_; }
191   pdFunction *func() const { return func_;}
192 private:
193 #endif
194
195   // can't set this in the constructor because call points can't be classified until
196   // all functions have been seen -- this might be cleaned up
197   void set_callee(pdFunction *to) { callee = to; }
198
199
200   Address addr;                   /* address of inst point */
201   instruction originalInstruction;    /* original instruction */
202   instruction delaySlotInsn;  /* original instruction */
203   instruction aggregateInsn;  /* aggregate insn */
204   bool inDelaySlot;            /* Is the instruction in a delay slot */
205   bool isDelayed;               /* is the instruction a delayed instruction */
206   bool callIndirect;            /* is it a call whose target is rt computed ? */
207   bool callAggregate;           /* calling a func that returns an aggregate
208                                    we need to reolcate three insns in this case
209                                    */
210   pdFunction *callee;           /* what function is called */
211   pdFunction *func;             /* what function we are inst */
212 };
213
214
215 /* Stores source code to address in text association for modules */
216 class lineDict {
217 public:
218   lineDict() : lineMap(uiHash) { }
219   ~lineDict() { /* TODO */ }
220   void setLineAddr (unsigned line, Address addr) { lineMap[line] = addr; }
221   inline bool getLineAddr (const unsigned line, Address &adr);
222
223 private:
224   dictionary_hash<unsigned, Address> lineMap;
225 };
226
227 class module {
228 public:
229   inline module(supportedLanguages lang, Address adr, string &fullNm,
230                 string &fileNm, image *e);
231   ~module() { /* TODO */ }
232
233   void setLineAddr(unsigned line, Address addr) { lines_.setLineAddr(line, addr); }
234   bool getLineAddr(unsigned line, Address &addr) { 
235                                          return (lines_.getLineAddr(line, addr)); }
236
237   void define();                // defines module to paradyn
238
239   inline void changeLibFlag(const bool setSuppress);
240   inline pdFunction *findFunction (const string &name);
241   void mapLines() { }           // line number info is not used now
242   void checkAllCallPoints();
243
244   string fileName() const { return fileName_; }
245   string fullName() const { return fullName_; }
246   supportedLanguages language() const { return language_;}
247   Address addr() const { return addr_; }
248   image *exec() const { return exec_; }
249
250   // Note -- why by address?, this structure is rarely used
251   // the MDL should be the most frequent user and it needs this data structure
252   // to be the same type as the function dictionary in class image
253   vector<pdFunction*> funcs;
254
255 private:
256
257   string fileName_;                   // short file 
258   string fullName_;                   // full path to file 
259   supportedLanguages language_;
260   Address addr_;                      // starting address of module
261   image *exec_;                      // what executable it came from 
262   lineDict lines_;
263 };
264
265
266 /*
267  * symbols we need to find from our RTinst library.  This is how we know
268  *   were our inst primatives got loaded as well as the data space variables
269  *   we use to put counters/timers and inst trampolines.  An array of these
270  *   is placed in the image structure.
271  *
272  */
273 class internalSym {
274 public:
275   internalSym(const Address adr, const string &nm) : name(nm), addr(adr) { }
276   Address getAddr() const { return addr;}
277
278 private:
279   string name;            /* name as it appears in the symbol table. */
280   Address addr;      /* absolute address of the symbol */
281 };
282
283 typedef struct watch_data {
284   string name;
285   bool is_lib;
286   vector<pdFunction*> *funcs;
287   vector<module*> *mods;
288   bool is_func;
289   vector<string> prefix;
290   vector<string> non_prefix;
291 } watch_data;
292
293
294 class image {
295 public:
296   static image *parseImage(const string file);
297   static void changeLibFlag(resource*, const bool);
298
299   image(const string &file, bool &err);
300   ~image() { /* TODO */ }
301
302   internalSym *findInternalSymbol(const string name, const bool warn);
303   Address findInternalAddress(const string name, const bool warn, bool &err);
304
305   // find the named module 
306   module *findModule(const string &name);
307
308   // find the function by name, address, or the first by name
309   bool findFunction(const string &name, vector<pdFunction*> &flist);
310   pdFunction *findFunction(const Address &addr);
311   pdFunction *findOneFunction(const string &name);
312
313   // report modules to paradyn
314   void defineModules();
315
316   bool symbolExists(const string); /* Does the symbol exist in the image? */
317   void postProcess(const string);          /* Load .pif file */
318
319   // data member access
320   inline Word get_instruction(Address adr) const;
321
322   string file() const {return file_;}
323   string name() const { return name_;}
324   Address codeOffset() const { return codeOffset_;}
325   Address dataOffset() const { return dataOffset_;}
326
327   // functions by address for all modules
328   dictionary_hash <Address, pdFunction*> funcsByAddr;
329
330   // TODO -- get rid of one of these
331   dictionary_hash <string, module *> modsByFileName;
332   dictionary_hash <string, module*> modsByFullName;
333
334   inline bool isValidAddress(const Address &where) const;
335
336   // Return symbol table information
337   inline bool symbol_info(string& symbol_name, Symbol& ret);
338
339   // Called from the mdl -- lists of functions to look for
340   static void watch_functions(string& name, vector<string> *vs, bool is_lib,
341                               vector<pdFunction*> *updateDict);
342
343   // called from function/module destructor, removes the pointer from the watch list
344   // TODO
345   static void destroy(pdFunction *pdf) { }
346   static void destroy(module *mod) { }
347
348   vector<pdFunction*> mdlLib;
349   vector<pdFunction*> mdlNormal;
350   vector<module*> mods;
351
352 private:
353   string file_;         /* image file name */
354   string name_;         /* filename part of file, no slashes */
355
356   Address codeOffset_;
357   unsigned codeLen_;
358   Address dataOffset_;
359   unsigned dataLen_;
360
361   // data from the symbol table 
362   Object linkedFile;
363
364   dictionary_hash <string, internalSym*> iSymsMap;   // internal RTinst symbols
365
366   static vector<image*> allImages;
367
368   dictionary_hash <string, vector<pdFunction*>*> funcsByPretty;
369   // note, a prettyName is not unique, it may map to a function appearing
370   // in several modules
371
372   bool newFunc(module *, const string name, const Address addr,
373                const unsigned tags, pdFunction *&retFunc);
374
375   void checkAllCallPoints();
376
377   bool addInternalSymbol(const string &str, const Address symValue);
378
379   // creates the module if it does not exist
380   module *getOrCreateModule (const string &modName, const Address modAddr);
381   module *newModule(const string &name, Address addr);
382
383   bool findKnownFunctions(Object &linkedFile, module *lib, module *dyn,
384                           const bool startB, const Address startAddr,
385                           const bool endB, const Address endAddr,
386                           const Address b_start, const Address b_end,
387                           vector<Symbol> &mods);
388
389   bool addOneFunction(vector<Symbol> &mods, module *lib, module *dyn,
390                       const Symbol &lookUp, pdFunction *&retFunc);
391
392   bool addAllFunctions(vector<Symbol> &mods,
393                        module *lib, module *dyn,
394                        const bool startB, const Address startAddr,
395                        const bool endB, const Address endAddr);
396
397   // if useLib = true or the functions' tags signify a library function
398   // the function is put in the library module
399   bool defineFunction(module *use, const Symbol &sym, const unsigned tags,
400                       pdFunction *&retFunc);
401   bool defineFunction(module *lib, const Symbol &sym,
402                       const string &modName, const Address modAdr,
403                       pdFunction *&retFunc);
404
405   inline bool isCode(const Address &where) const;
406   inline bool isData(const Address &where) const;
407   bool heapIsOk(const vector<sym_data>&);
408   
409   static vector<watch_data> watch_vec;
410   static void update_watch_map(unsigned index, vector<string> *vs,
411                                vector<string>& pref,
412                                vector<string>& non_pref);
413 };
414
415
416 /*
417  * a definition of a library function that we may wish to identify.  This is
418  *   how we describe it to the symbol table parser, not how it appears in
419  *   the symbol table.  Library functions are placed in a pseudo module 
420  *   named LIBRARY_MODULE. 
421  *
422  */
423
424
425 class libraryFunc {
426 public:
427   libraryFunc(const string n, unsigned t) : name(n), tags(t) { }
428   unsigned getTags() const { return tags;}
429
430 private:
431   string name;
432   unsigned tags;
433 };
434
435 // TODO -- remove this
436 extern resource *moduleRoot;
437
438 bool lineDict::getLineAddr (const unsigned line, Address &adr) {
439   if (!lineMap.defines(line)) {
440     return false;
441   } else {
442     adr = lineMap[line];
443     return true;
444   }
445 }
446
447 module::module(supportedLanguages lang, Address adr, string &fullNm,
448                string &fileNm, image *e) 
449 : fileName_(fileNm), fullName_(fullNm), language_(lang),
450   addr_(adr), exec_(e) { }
451
452 void module::changeLibFlag(const bool setSuppress) {
453   unsigned fsize = funcs.size();
454   for (unsigned f=0; f<fsize; f++) {
455     if (setSuppress)
456       funcs[f]->tagAsLib();
457     else
458       funcs[f]->untagAsLib();    
459   }
460 }
461
462 pdFunction *module::findFunction (const string &name) {
463   unsigned fsize = funcs.size();
464   for (unsigned f=0; f<fsize; f++) {
465     if (funcs[f]->prettyName() == name)
466       return funcs[f];
467   }
468   return NULL;
469 }
470
471 Word image::get_instruction(Address adr) const {
472   // TODO remove assert
473   assert(isValidAddress(adr));
474
475   if (isCode(adr)) {
476     adr -= codeOffset_;
477     adr >>= 2;
478     const Word *inst = linkedFile.code_ptr();
479     return (inst[adr]);
480   } else if (isData(adr)) {
481     adr -= dataOffset_;
482     adr >>= 2;
483     const Word *inst = linkedFile.data_ptr();
484     return (inst[adr]);
485   } else {
486     abort();
487     return 0;
488   }
489 }
490
491 // Address must be in code or data range since some code may end up
492 // in the data segment
493 bool image::isValidAddress(const Address &where) const {
494   return (!(where & 0x3) &&
495           (isCode(where) || isData(where)));
496 }
497
498 bool image::isCode(const Address &where) const {
499   return (linkedFile.code_ptr() && 
500           (where >= codeOffset_) && (where < (codeOffset_+(codeLen_<<2))));
501 }
502
503 bool image::isData(const Address &where) const {
504   return (linkedFile.data_ptr() && 
505           (where >= dataOffset_) && (where < (dataOffset_+(dataLen_<<2))));
506 }
507
508 bool image::symbol_info(string& symbol_name, Symbol &ret_sym) {
509   if (!linkedFile.get_symbol(symbol_name, ret_sym))
510     return false;
511   else
512     return true;
513 }
514
515 #endif