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