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