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