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