fork/exec/exit Callbacks.
[dyninst.git] / dyninstAPI / src / BPatch_image.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: BPatch_image.C,v 1.17 2000/03/12 23:27:14 hollings Exp $
43
44 #include <stdio.h>
45 #include <assert.h>
46 #include <string.h>
47
48 #include "process.h"
49 #include "symtab.h"
50 #include "instPoint.h"
51
52 #include "BPatch.h"
53 #include "BPatch_image.h"
54 #include "BPatch_type.h"
55 #include "BPatch_collections.h"
56
57 //
58 // We made this a seperate class to allow us to only expose a pointer to
59 //    it in the public header files of the dyninst API.  This keeps 
60 //    dictionary_hash and other internal dyninst things hidden.  The
61 //    things we do decouple interface from implementation! - jkh 8/28/99
62 //
63 class AddrToVarExprHash {
64     public:
65         AddrToVarExprHash(): hash(addrHash) { }
66         dictionary_hash <Address, BPatch_variableExpr*> hash;
67 };
68
69 /*
70  * BPatch_image::BPatch_image
71  *
72  * Construct a BPatch_image for the given process.
73  */
74
75 BPatch_image::BPatch_image(process *_proc) : proc(_proc)
76 {
77     modlist = NULL;
78     AddrToVarExpr = new AddrToVarExprHash();
79
80     _srcType = BPatch_sourceProgram;
81 }
82
83 /*
84  * BPatch_image::BPatch_image
85  *
86  * Construct a BPatch_image.
87  */
88 BPatch_image::BPatch_image() : proc(NULL), modlist(NULL) 
89 {
90     AddrToVarExpr = new AddrToVarExprHash();
91
92     _srcType = BPatch_sourceProgram;
93 }
94
95 /* 
96  * Cleanup the image's memory usage when done.
97  *
98  */
99 BPatch_image::~BPatch_image()
100 {
101     // modules are shared by multuple programs, don't delete them
102     // for (unsigned int i = 0; i < modlist->size(); i++) {
103          // delete (*modlist)[i];
104     // }
105
106     delete AddrToVarExpr;
107 }
108
109 /* 
110  * getSourceObj - Return the children (modules)
111  *
112  */
113 BPatch_Vector<BPatch_sourceObj *> *BPatch_image::getSourceObj()
114 {
115     return (BPatch_Vector<BPatch_sourceObj *> *) getModules();
116 }
117
118 /* 
119  * getObjParent - Return the parent (this is the top level so its null)
120  *
121  */
122 BPatch_sourceObj *BPatch_image::getObjParent()
123 {
124     return NULL;
125 }
126
127 /*
128  * BPatch_image::getProcedures
129  *
130  * Returns a list of all procedures in the image upon success, and NULL
131  * upon failure.
132  */
133 BPatch_Vector<BPatch_function *> *BPatch_image::getProcedures()
134 {
135     BPatch_Vector<BPatch_function *> *proclist =
136         new BPatch_Vector<BPatch_function *>;
137
138     if (proclist == NULL) return NULL;
139
140     // XXX Also, what should we do about getting rid of this?  Should
141     //     the BPatch_functions already be made and kept around as long
142     //     as the process is, so the user doesn't have to delete them?
143     BPatch_Vector<BPatch_module *> *mods = getModules();
144
145     for (unsigned int i = 0; i < mods->size(); i++) {
146         BPatch_Vector<BPatch_function *> *funcs = (*mods)[i]->getProcedures();
147         for (unsigned int j=0; j < funcs->size(); j++) {
148             proclist->push_back((*funcs)[j]);
149         }
150     }
151
152     return proclist;
153 }
154
155
156 /*
157  * BPatch_image::getProcedures
158  *
159  * Returns a list of all procedures in the image upon success, and NULL
160  * upon failure.
161  */
162 BPatch_Vector<BPatch_variableExpr *> *BPatch_image::getGlobalVariables()
163 {
164     BPatch_variableExpr *var;
165     BPatch_Vector<BPatch_variableExpr *> *varlist =
166         new BPatch_Vector<BPatch_variableExpr *>;
167
168     if (varlist == NULL) return NULL;
169
170     // XXX - should this stuff really be by image ??? jkh 3/19/99
171     BPatch_Vector<BPatch_module *> *mods = getModules();
172     BPatch_type *type;
173     for (int m = 0; m < mods->size(); m++) {
174         BPatch_module *module = (*mods)[m];
175         char name[255];
176         module->getName(name, sizeof(name));
177         vector<string> keys = module->moduleTypes->globalVarsByName.keys();
178         int limit = keys.size();
179         for (int j = 0; j < limit; j++) {
180             Symbol syminfo;
181             string name = keys[j];
182             type = module->moduleTypes->globalVarsByName[name];
183             assert(type);
184             if (!proc->getSymbolInfo(name, syminfo)) {
185                 printf("unable to find variable %s\n", name.string_of());
186             }
187             var = AddrToVarExpr->hash[syminfo.addr()];
188             if (!var) {
189                 var = new BPatch_variableExpr((char *) name.string_of(), proc, 
190                     (void *)syminfo.addr(), (const BPatch_type *) type);
191                 AddrToVarExpr->hash[syminfo.addr()] = var;
192             }
193             varlist->push_back(var);
194         }
195     }
196
197
198     return varlist;
199 }
200
201 /*
202  * BPatch_image::getModules
203  *
204  * Returns a list of all procedures in the image upon success, and NULL
205  * upon failure.
206  */
207 BPatch_Vector<BPatch_module *> *BPatch_image::getModules()
208 {
209   if (modlist) {
210     return modlist;
211   }
212   
213   modlist = new BPatch_Vector<BPatch_module *>;
214   if (modlist == NULL) return NULL;
215   
216   // XXX Also, what should we do about getting rid of this?  Should
217   //     the BPatch_modules already be made and kept around as long
218   //     as the process is, so the user doesn't have to delete them?
219   vector<module *> *mods = proc->getAllModules();
220   
221   for (unsigned int m = 0; m < mods->size(); m++) {
222     pdmodule *curr = (pdmodule *) (*mods)[m];
223     BPatch_module *bpmod = new BPatch_module(proc, curr, this);
224     modlist->push_back(bpmod);
225   }
226   
227   // BPatch_procedures are only built on demand, and we need to make sure
228   //    they get built.
229   BPatch_Vector<BPatch_function *> *procedures = getProcedures();
230
231   return modlist;
232 }
233
234 /*
235  * BPatch_image::findProcedurePoint
236  *
237  * Returns a vector of the instrumentation points from a procedure that is
238  * identified by the parameters, or returns NULL upon failure.
239  *
240  * name         The name of the procedure in which to look up the points.
241  * loc          The points within the procedure to return.  The following
242  *              values are valid for this parameter:
243  *                BPatch_entry         The function's entry point.
244  *                BPatch_exit          The function's exit point(s).
245  *                BPatch_subroutine    The points at which the procedure calls
246  *                                     other procedures.
247  *                BPatch_longJump      The points at which the procedure make
248  *                                     long jump calls.
249  *                BPatch_allLocations  All of the points described above.
250  */
251 BPatch_Vector<BPatch_point*> *BPatch_image::findProcedurePoint(
252         const char *name, const BPatch_procedureLocation loc)
253 {
254     /* XXX Right now this assumes that there's only one function with
255      * the given name.
256      */
257
258     BPatch_function *func = findBPFunction(name);
259     if (func == NULL) return NULL;
260
261     return func->findPoint(loc);
262 }
263
264
265 /*
266  * BPatch_image::createInstPointAtAddr
267  *
268  * Returns a pointer to a BPatch_point object representing an
269  * instrumentation point at the given address.
270  *
271  * Returns the pointer to the BPatch_point on success, or NULL upon
272  * failure.
273  *
274  * address      The address that the instrumenation point should refer to.
275  */
276 BPatch_point *BPatch_image::createInstPointAtAddr(void *address)
277 {
278     unsigned i;
279
280     /* First look in the list of non-standard instPoints. */
281     if (proc->instPointMap.defines((Address)address)) {
282         instPoint *ip = proc->instPointMap[(Address)address];
283         return new BPatch_point(proc, NULL, ip, BPatch_allLocations);
284     }
285
286     /* Look in the regular instPoints of the enclosing function. */
287     function_base *func = proc->findFunctionIn((Address)address);
288
289     if (func != NULL) {
290         instPoint *entry = const_cast<instPoint *>(func->funcEntry(proc));
291         assert(entry);
292         if (entry->iPgetAddress() == (Address)address) {
293             return new BPatch_point(proc, NULL, entry, BPatch_entry);
294         }
295
296         const vector<instPoint*> &exits = func->funcExits(proc);
297         for (i = 0; i < exits.size(); i++) {
298             assert(exits[i]);
299             if (exits[i]->iPgetAddress() == (Address)address) {
300                 return new BPatch_point(proc, NULL, exits[i], BPatch_exit);
301             }
302         }
303
304         const vector<instPoint*> &calls = func->funcCalls(proc);
305         for (i = 0; i < calls.size(); i++) {
306             assert(calls[i]);
307             if (calls[i]->iPgetAddress() == (Address)address) {
308                 return new BPatch_point(proc, NULL, calls[i], BPatch_subroutine);
309             }
310         }
311     }
312
313     /* We don't have an instPoint for this address, so make one. */
314 #if defined(rs6000_ibm_aix4_1) || defined(alpha_dec_osf4_0)
315     /*
316      * XXX This is machine dependent and should be moved to somewhere else.
317      */
318     if (!isAligned((Address)address))
319         return NULL;
320
321     instruction instr;
322     proc->readTextSpace(address, sizeof(instruction), &instr.raw);
323
324 #if defined(rs6000_ibm_aix4_1)
325     instPoint *newpt = new instPoint((pd_Function *)func,
326                                      instr,
327                                      NULL, // image *owner - this is ignored
328                                      (Address)address,
329                                      false, // bool delayOk - this is ignored
330                                      ipOther);
331 #elif defined(alpha_dec_osf4_0)
332     instPoint *newpt = new instPoint((pd_Function *)func,
333                                     (const instructUnion &) instr,
334                                     (const image *) NULL, // image * - ignored
335                                     (Address &)address,
336                                     false, // bool delayOk - ignored
337                                     otherPoint);
338 #endif
339
340
341     proc->instPointMap[(Address)address] = newpt; // Save this instPoint
342
343     return new BPatch_point(proc, NULL, newpt, BPatch_instruction);
344 #else
345     /* Not implemented on this platform (yet). */
346     assert(false);
347     return NULL;
348 #endif
349 }
350
351
352 /*
353  * BPatch_image::findFunction
354  *
355  * Returns a NEW BPatch_function* representing the named function upon success,
356  * and NULL upon failure.
357  *
358  * name         The name of function to look up.
359  */
360 BPatch_function *BPatch_image::findFunction(const char *name)
361 {
362     function_base *func = proc->findOneFunction(name);
363
364     if (func == NULL) {
365         string fullname = string("_") + string(name);
366         func = proc->findOneFunction(fullname);
367     }
368
369     if (func == NULL) {
370         string msg = string("Unable to find function: ") + string(name);
371         showErrorCallback(100, msg);
372         return NULL;
373     }
374
375     BPatch_function *bpfunc = proc->PDFuncToBPFuncMap[func];
376     if (!bpfunc) {
377         bpfunc = new BPatch_function(proc, func, NULL);
378     }
379     return bpfunc;
380 }
381
382
383 /*
384  * BPatch_image::findVariable
385  *
386  * Returns a BPatch_variableExpr* representing the given variable in the
387  * application image.  If no such variable exists, returns NULL.
388  *
389  * name         The name of the variable to look up.
390  *
391  * First look for the name with an `_' prepended to it, and if that is not
392  *   found try the original name.
393  */
394 BPatch_variableExpr *BPatch_image::findVariable(const char *name)
395 {
396     string full_name = string("_") + string(name);
397
398     Symbol syminfo;
399     if (!proc->getSymbolInfo(full_name, syminfo)) {
400         string short_name(name);
401         if (!proc->getSymbolInfo(short_name, syminfo)) {
402             string msg = string("Unable to find variable: ") + string(name);
403             showErrorCallback(100, msg);
404             return NULL;
405         }
406     }
407     if( syminfo.type() == Symbol::PDST_FUNCTION)
408       return NULL;
409     
410     BPatch_variableExpr *bpvar = AddrToVarExpr->hash[syminfo.addr()];
411     if (bpvar) return bpvar;
412
413     // XXX - should this stuff really be by image ??? jkh 3/19/99
414     BPatch_Vector<BPatch_module *> *mods = getModules();
415     BPatch_type *type;
416     for (int m = 0; m < mods->size(); m++) {
417         BPatch_module *module = (*mods)[m];
418         //printf("The moduleType address is : %x\n", &(module->moduleTypes));
419         type = module->moduleTypes->findVariableType(name);
420         if (type) break;
421     }
422     if (!type) {
423         type = BPatch::bpatch->type_Untyped;
424     }
425
426     BPatch_variableExpr *ret = new BPatch_variableExpr((char *) name, 
427         proc, (void *)syminfo.addr(), (const BPatch_type *) type);
428     AddrToVarExpr->hash[syminfo.addr()] = ret;
429     return ret;
430 }
431
432 //
433 // findVariable
434 //      scp     - a BPatch_point that defines the scope of the current search
435 //      name    - name of the variable to find.
436 //
437 BPatch_variableExpr *BPatch_image::findVariable(BPatch_point &scp,
438                                                 const char *name)
439 {
440     // Get the function to search for it's local variables.
441     // XXX - should really use more detailed scoping info here - jkh 6/30/99
442     BPatch_function *func = (BPatch_function *) scp.getFunction();
443     if (!func) {
444         string msg = string("point passed to findVariable lacks a function\n address point type passed?");
445         showErrorCallback(100, msg);
446         return NULL;
447     }
448
449     BPatch_localVar *lv = func->findLocalVar(name);
450
451     if (!lv) {
452         // look for it in the parameter scope now
453         lv = func->findLocalParam(name);
454     }
455     if (lv) {
456         // create a local expr with the correct frame offset 
457         return new BPatch_variableExpr(proc, (void *) lv->getFrameOffset(), 
458             lv->getType(), true, &scp);
459     }
460
461     // finally check the global scope.
462     return findVariable(name);
463 }
464
465 /*
466  * BPatch_image::findType
467  *
468  * Returns a BPatch_type* representing the named type.  If no such type
469  * exists, returns NULL.
470  *
471  * name         The name of type to look up.
472  */
473 BPatch_type *BPatch_image::findType(const char *name)
474 {
475     BPatch_type *type;
476
477     assert(BPatch::bpatch != NULL);
478
479     // XXX - should this stuff really be by image ??? jkh 3/19/99
480     BPatch_Vector<BPatch_module *> *mods = getModules();
481     for (int m = 0; m < mods->size(); m++) {
482         BPatch_module *module = (*mods)[m];
483         type = module->moduleTypes->findType(name);
484         if (type) return type;
485     }
486
487     // check the default base types
488     type = BPatch::bpatch->stdTypes->findType(name);
489     if(type) return type;
490
491     // check the API types of last resort
492     return BPatch::bpatch->APITypes->findType(name);
493
494 }
495
496 /*
497  * BPatch_image::findBPFunnction
498  *
499  * Returns a BPatch_function* representing the named function or if no func
500  * exists, returns NULL.
501  *
502  * name         The name of function to look up.
503  */
504 BPatch_function  *BPatch_image::findBPFunction(const char *name)
505 {
506     BPatch_function *func;
507     BPatch_Vector<BPatch_function *> * funclist =
508       new BPatch_Vector<BPatch_function *>;
509       
510     assert(BPatch::bpatch != NULL);
511
512     // XXX - should this stuff really be by image ??? jkh 3/19/99
513     BPatch_Vector<BPatch_module *> *mods = getModules();
514     //printf(" Number of Modules %d\n",mods->size());
515     for (int m = 0; m < mods->size(); m++) {
516         BPatch_module *module = (*mods)[m];
517         func = module->findFunction(name);
518         if (func) {
519             if (func->getProc() != proc) {
520                 printf("got func in the wrong proc\n");
521             }
522             funclist->push_back(func);
523         }
524     }
525     if( funclist->size()){
526       //printf("Function list has %d functions\n", funclist->size());
527       if( funclist->size() == 2)
528         return (*funclist)[1];
529       else 
530         return (*funclist)[0];
531     }
532     // check the default base types of last resort
533     else
534       return NULL;
535 }
536
537
538 /*
539  * BPatch_image::addModule
540  *
541  * Adds a new module to the BPatch_module vector
542  * if modlist exists. 
543  *
544  * bpmod is a pointer to the BPatch_module to add to the vector
545  */
546 void BPatch_image::addModuleIfExist(BPatch_module *bpmod){
547
548   if( modlist )
549     modlist->push_back(bpmod);
550   
551 }
552
553 /*
554  * BPatch_image::ModuleListExist
555  *
556  * Checks to see if modlist has been created.
557  */
558 bool BPatch_image::ModuleListExist(){
559
560   if ( modlist )
561     return true;
562   else
563     return false;
564 }
565