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