added insn generated metric.
[dyninst.git] / dyninstAPI / src / symtab.C
1 /*
2  *  Copyright 1993 Jeff Hollingsworth.  All rights reserved.
3  *
4  */
5
6 #ifndef lint
7 static char Copyright[] = "@(#) Copyright (c) 1993 Jeff Hollingsowrth\
8     All rights reserved.";
9
10 static char rcsid[] = "@(#) $Header: /home/jaw/CVSROOT_20081103/CVSROOT/core/dyninstAPI/src/symtab.C,v 1.7 1994/07/20 23:23:41 hollings Exp $";
11 #endif
12
13 /*
14  * symtab.C - generic symbol routines.  Implements an ADT for a symbol
15  *   table.  The make calls to machine and a.out specific routines to handle
16  *   the implementation dependent parts.
17  *
18  * $Log: symtab.C,v $
19  * Revision 1.7  1994/07/20 23:23:41  hollings
20  * added insn generated metric.
21  *
22  * Revision 1.6  1994/07/12  19:26:15  jcargill
23  * Added internal prefix for TRACELIB
24  *
25  * Revision 1.5  1994/06/29  02:52:51  hollings
26  * Added metricDefs-common.{C,h}
27  * Added module level performance data
28  * cleanedup types of inferrior addresses instrumentation defintions
29  * added firewalls for large branch displacements due to text+data over 2meg.
30  * assorted bug fixes.
31  *
32  * Revision 1.4  1994/06/27  21:28:23  rbi
33  * Abstraction-specific resources and mapping info
34  *
35  * Revision 1.3  1994/06/27  18:57:15  hollings
36  * removed printfs.  Now use logLine so it works in the remote case.
37  * added internalMetric class.
38  * added extra paramter to metric info for aggregation.
39  *
40  * Revision 1.2  1994/05/16  22:31:55  hollings
41  * added way to request unique resource name.
42  *
43  * Revision 1.1  1994/01/27  20:31:45  hollings
44  * Iinital version of paradynd speaking dynRPC igend protocol.
45  *
46  * Revision 1.8  1993/12/13  19:57:20  hollings
47  * added nearest line match for function to support Fortran convention of making
48  * first sline record be the first executable statement in the function.
49  *
50  * Revision 1.7  1993/10/12  20:10:35  hollings
51  * zero memory on a realloc.
52  *
53  * Revision 1.6  1993/10/04  21:39:08  hollings
54  * made missing internal symbols a fatal condition.
55  *
56  * Revision 1.5  1993/08/23  23:16:05  hollings
57  * added third parameter to findInternalSymbol.
58  *
59  * Revision 1.4  1993/08/20  22:02:39  hollings
60  * removed unused local variables.
61  *
62  * Revision 1.3  1993/07/13  18:32:46  hollings
63  * new include file syntax.
64  * added name demangler.
65  *
66  * Revision 1.2  1993/06/08  20:14:34  hollings
67  * state prior to bc net ptrace replacement.
68  *
69  * Revision 1.1  1993/03/19  22:45:45  hollings
70  * Initial revision
71  *
72  *
73  */
74
75 #include <string.h>
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <assert.h>
79
80 #include "dyninst.h"
81 #include "symtab.h"
82 #include "util.h"
83
84 extern "C" char *cplus_demangle(char *, int);
85 static image *allImages;
86 stringPool pool;
87
88 /* imported from platform specific library list.  This is lists all
89    library functions we are interested in instrumenting. */
90 extern libraryList libraryFunctions;
91
92 void processLine(module *mod, int line, caddr_t addr)
93 {
94     int increment;
95
96     if (line >= mod->lines.maxLine) {
97         mod->lines.addr = (caddr_t *) 
98             xrealloc(mod->lines.addr, sizeof(caddr_t)*(line+100));
99         increment = line+100 - mod->lines.maxLine;
100         memset(&mod->lines.addr[mod->lines.maxLine],'\0',sizeof(int)*increment);
101         mod->lines.maxLine = line+100;
102     }
103     mod->lines.addr[line] = addr;
104 }
105
106 module *newModule(image *curr, char *currentDirectory, char *name, caddr_t addr)
107 {
108     module *ret;
109     char fileName[255];
110
111     ret = (module *) xcalloc(sizeof(image),1);
112     sprintf(fileName, "%s%s", currentDirectory, name);
113     ret->compileInfo = NULL;
114     ret->fullName = pool.findAndAdd(fileName);
115     ret->fileName = pool.findAndAdd(name);
116     ret->language = unknown;
117     ret->addr = addr;
118     ret->funcCount = 0;
119     ret->funcs = NULL;
120     ret->exec = curr;
121     ret->next = curr->modules;
122
123     ret->lines.maxLine = 100;
124     ret->lines.addr = (caddr_t *) xcalloc(sizeof(caddr_t), 100);
125
126     curr->modules = ret;
127     curr->moduleCount++;
128     return(ret);
129 }
130
131 module *moduleFindOrAdd(image *exec, caddr_t addr, char *name)
132 {
133     module *curr;
134
135     for (curr=exec->modules; curr; curr = curr->next) {
136         if (curr->addr == addr) {
137             return(curr);
138         }
139     }
140     sprintf(errorLine, "warning no symbol table for module %s\n", name);
141     logLine(errorLine);
142     curr = (module *) xcalloc(sizeof(module), 1);
143     curr->fileName = pool.findAndAdd(name);
144     curr->fullName = NULL;
145     curr->language = unknown;
146     curr->addr = addr;
147     curr->next = exec->modules;
148     exec->modules = curr;
149     return(curr);
150 }
151
152 char *buildDemangledName(function *func)
153 {
154     char *tempName;
155     char *prettyName;
156
157     tempName = cplus_demangle(func->symTabName, 0);
158     if (tempName) {
159         prettyName = pool.findAndAdd(tempName);
160         free(tempName);
161     } else {
162         prettyName = func->symTabName;
163     }
164     return(prettyName);
165 }
166
167 function *funcFindOrAdd(image *exec, module *mod, caddr_t addr, char *name)
168 {
169     function *func;
170
171     for (func = exec->funcs; func; func=func->next) {
172         if (func->addr == addr) {
173             return(func);
174         }
175     }
176     func = (function *) xcalloc(sizeof(function), 1);
177     func->symTabName = pool.findAndAdd(name);
178     func->prettyName = buildDemangledName(func);
179     func->line = UNKNOWN_LINE;  
180     func->file = mod;
181     func->addr = addr;
182     func->next = exec->funcs;
183
184     mod->funcs = func;
185     mod->funcCount++;
186
187     exec->funcs = func;
188     exec->funcCount++;
189     return(func);
190 }
191
192 function *newFunc(image *exec, module *mod, char *name, int addr)
193 {
194     char *p;
195     function *func;
196
197     if (!mod) {
198         logLine("Error function without module\n");
199     }
200     func = (function *) xcalloc(sizeof(function),1);
201
202     exec->funcAddrHash.add(func, (void *) addr);
203
204     p = strchr(name, ':');
205     if (p) *p = '\0';
206     func->symTabName = pool.findAndAdd(name);
207     func->prettyName = buildDemangledName(func);
208     func->line = UNKNOWN_LINE;  /* ???? fix this */
209     func->file = mod;
210     func->addr = (caddr_t) addr;
211     func->sibling = findFunction(exec, name);
212
213     mod->funcs = func;
214     mod->funcCount++;
215
216     func->next = exec->funcs;
217     exec->funcs = func;
218     exec->funcCount++;
219     return(func);
220 }
221
222 /*
223  * List of prefixes for internal symbols we need to find.
224  *
225  */
226 char *internalPrefix[] = {
227     "DYNINST",
228     "TRACELIB",
229     NULL
230 };
231
232 /*
233  * load an executable:
234  *   1.) parse symbol table and identify rotuines.
235  *   2.) scan executable to identify inst points.
236  *
237  *  offset is normally zero except on CM-5 where we have two images in one
238  *    file.  The offset passed to parseImage is the logical offset (0/1), not
239  *    the physical point in the file.  This makes it faster to "parse" multiple
240  *    copies of the same image since we don't have to stat and read to find the
241  *    physical offset. 
242  */
243 image *parseImage(char *file, int offset)
244 {
245     int i;
246     image *ret;
247     module *mod;
248     Boolean status;
249     function *func;
250     caddr_t endUserAddr;
251     resource moduleRoot;
252     resource modResource;
253     caddr_t startUserAddr;
254     internalSym *endUserFunc;
255     internalSym *startUserFunc;
256     extern findNodeOffset(char *, int);
257
258     /*
259      * Check to see if we have parsed this image at this offeset before.
260      *
261      */
262     for (ret=allImages; ret; ret = ret->next) {
263         if (!strcmp(ret->file, file) && (ret->offset == offset)) {
264             return(ret);
265         }
266     }
267
268     /*
269      * load the symbol table. (This is the a.out format specific routine).
270      *
271      */
272     ret = loadSymTable(file, findNodeOffset(file, offset), libraryFunctions, 
273         internalPrefix);
274
275     /* check that we loaded o.k. */
276     if (!ret) {
277         return(NULL);
278     }
279
280     /*
281      * Add to master image list.
282      *
283      */
284     ret->next = allImages;
285     ret->offset = offset;
286     allImages = ret;
287
288     /*
289      * mark as lib, library functions that were compiled with symbols.
290      *
291      */
292     startUserFunc = findInternalSymbol(ret, "DYNINSTstartUserCode", False);
293     startUserAddr = (caddr_t) ((startUserFunc) ? startUserFunc->addr : 0x0);
294
295     endUserFunc = findInternalSymbol(ret, "DYNINSTendUserCode", False);
296     endUserAddr = (caddr_t) ((endUserFunc && endUserFunc->addr) ? 
297         endUserFunc->addr : 0xffffffff);
298
299     if (endUserFunc) {
300         for (func = ret->funcs; func; func=func->next) {
301             if ((func->addr >= endUserAddr) ||
302                 (func->addr <= startUserAddr)) {
303                 func->tag |= TAG_LIB_FUNC;
304 //              printf ("function %s tagged as a library function\n",
305 //                      func->prettyName);
306             }
307 //          else
308 //              printf ("function %s NOT tagged as a library function\n",
309 //                      func->prettyName);
310         }
311     }
312     
313
314     /*
315      * Now identify the points in the functions to instrument.
316      *   This is the machine specific routine.
317      *
318      */
319     status = locateAllInstPoints(ret);
320     if (status == FALSE) {
321         return(NULL);
322     }
323
324     moduleRoot = newResource(rootResource, NULL, NULL, "Procedure", 0.0, FALSE);
325
326     // define all modules.
327     for (mod = ret->modules; mod; mod=mod->next) {
328         if (mod->funcs && !(mod->funcs->tag & TAG_LIB_FUNC) &&
329                             mod->funcs->line) {
330             modResource = newResource(moduleRoot, mod, NULL, mod->fileName, 
331                 0.0, FALSE);
332
333             for (func = mod->funcs, i= 0; 
334                  i < mod->funcCount; 
335                  func=func->next, i++) {
336                 if ((!func->tag & TAG_LIB_FUNC) && (func->line)) {
337                     (void) newResource(modResource, func, NULL, 
338                         func->prettyName,0.0,FALSE);
339                 } else {
340                     func->tag |= TAG_LIB_FUNC;
341                 }
342             }
343         }
344     }
345
346     free(ret->code);
347     return(ret);
348 }
349
350
351 internalSym *findInternalSymbol(image *i, char *name, Boolean warn)
352 {
353     int count;
354     char *iName;
355
356     iName = pool.findAndAdd(name);
357     for (count = 0; count < i->iSymCount; count++) {
358         if (i->iSyms[count].name == iName) {
359             return(&i->iSyms[count]);
360         }
361     }
362     if (warn) {
363         sprintf(errorLine, "unable to find internal symbol %s\n", name);
364         logLine(errorLine);
365     }
366     
367     return(NULL);
368 }
369
370 caddr_t findInternalAddress(image *i, char *name, Boolean warn)
371 {
372     int count;
373     char *iName;
374     internalSym *curr;
375
376     iName = pool.findAndAdd(name);
377     for (count = 0, curr=i->iSyms; count < i->iSymCount; count++, curr++) {
378         if (curr->name == iName) {
379             return((caddr_t) curr->addr);
380         }
381     }
382     if (warn) {
383         printf("unable to find internal symbol %s\n", name);
384         abort();
385     }
386     return(NULL);
387 }
388
389 module *findModule(image *i, char *name)
390 {
391     char *iName;
392     module *mod;
393
394     iName = pool.findAndAdd(name);
395     for (mod = i->modules; mod; mod=mod->next) {
396         if (iName == mod->fileName) {
397              return(mod);
398         } else if (iName == mod->fullName) {
399              return(mod);
400         }
401     }
402     return(NULL);
403 }
404
405 function *findFunction(image *i, char *name)
406 {
407     char *iName;
408     function *func;
409
410     iName = pool.findAndAdd(name);
411     for (func = i->funcs; func; func=func->next) {
412         if (iName == func->prettyName) {
413              return(func);
414         } else if (iName == func->symTabName) {
415              return(func);
416         }
417     }
418     return(NULL);
419 }
420
421 function *findFunctionByAddr(image *i, caddr_t addr)
422 {
423     function *func;
424
425     func = i->funcAddrHash.find((void *) addr);
426 #ifdef notdef
427     for (func = i->funcs; func; func=func->next) {
428         if (addr == func->addr) {
429              return(func);
430         }
431     }
432     return(NULL);
433 #endif
434     return(func);
435 }
436
437 int intComp(int *i, int *j)
438 {
439     return(*i - *i);
440 }
441
442 void mapLines(module *mod)
443 {
444     int i, j;
445     function *func;
446
447     if (!mod) return;
448
449     qsort(mod->lines.addr, mod->lines.maxLine, sizeof(int), intComp);
450     for (i=0, func = mod->funcs; i < mod->funcCount; i++, func=func->next) {
451         for (j=0; j < mod->lines.maxLine; j++) {
452             if (func->addr <= (caddr_t) mod->lines.addr[j]) {
453                 func->line = j;
454                 break;
455             }
456         }
457     }
458 }