Added several calls to API (waitForStatusChange, BPatch_variableExpr
[dyninst.git] / dyninstAPI / src / BPatch_snippet.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 #include <string.h>
43 #include "ast.h"
44 #include "symtab.h"
45 #include "process.h"
46
47 #include "BPatch.h"
48 #include "BPatch_snippet.h"
49 #include "BPatch_type.h"
50
51 /* XXX Should be in a dyninst API include file (right now in perfStream.h) */
52 extern double cyclesPerSecond;
53
54 /*
55  * BPatch_snippet::BPatch_snippet
56  *
57  * Copy constructor for BPatch_snippet.
58  */
59 BPatch_snippet::BPatch_snippet(const BPatch_snippet &src)
60 {
61     ast = assignAst(src.ast);
62 }
63
64
65 /*
66  * BPatch_snippet::operator=
67  *
68  * Assignment operator for BPatch_snippet.  Needed to ensure that the
69  * reference counts for the asts contained in the snippets is correct.
70  */
71 BPatch_snippet &BPatch_snippet::operator=(const BPatch_snippet &src)
72 {
73     // Check for x = x
74     if (&src == this)
75         return *this;
76
77     // Since we're copying over this snippet, release the old AST
78     if (ast != NULL)
79         removeAst(ast);
80
81     // We'll now contain another reference to the ast in the other snippet
82     ast = assignAst(src.ast);
83
84     return *this;
85 }
86
87
88 /*
89  * BPatch_snippet:getCost
90  *
91  * Returns the estimated cost of executing the snippet, in seconds.
92  */
93 float BPatch_snippet::getCost()
94 {
95     return (double)ast->cost() / cyclesPerSecond;
96 }
97
98
99 /*
100  * BPatch_snippet::~BPatch_snippet
101  *
102  * Destructor for BPatch_snippet.  Deallocates memory allocated by the
103  * snippet.
104  */
105 BPatch_snippet::~BPatch_snippet()
106 {
107     // if (ast != NULL)
108         // removeAst(ast);
109 }
110
111
112 /*
113  * BPatch_arithExpr::BPatch_arithExpr
114  *
115  * Construct a snippet representing a binary arithmetic operation.
116  *
117  * op           The desired operation.
118  * lOperand     The left operand for the operation.
119  * rOperand     The right operand.
120  */
121 BPatch_arithExpr::BPatch_arithExpr(BPatch_binOp op,
122         const BPatch_snippet &lOperand, const BPatch_snippet &rOperand)
123 {
124     assert(BPatch::bpatch != NULL);
125
126     opCode astOp;
127     switch(op) {
128       case BPatch_assign:
129         astOp = storeOp;
130         break;
131       case BPatch_plus:
132         astOp = plusOp;
133         break;
134       case BPatch_minus:
135         astOp = minusOp;
136         break;
137       case BPatch_divide:
138         astOp = divOp;
139         break;
140       case BPatch_times:
141         astOp = timesOp;
142         break;
143       case BPatch_mod:
144         /* XXX Not yet implemented. */
145         assert(0);
146         break;
147       case BPatch_ref:
148         /* XXX Not yet implemented. */
149         assert(0);
150         break;
151       case BPatch_seq:
152         ast = new AstNode(lOperand.ast, rOperand.ast);
153         ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
154         return;
155       default:
156         /* XXX handle error */
157         assert(0);
158     };
159
160     ast = new AstNode(astOp, lOperand.ast, rOperand.ast);
161     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
162 }
163
164
165 /*
166  * BPatch_boolExpr::BPatch_boolExpr
167  *
168  * Constructs a snippet representing a boolean expression.
169  *
170  * op           The operator for the boolean expression.
171  * lOperand     The left operand.
172  * rOperand     The right operand.
173  */
174 BPatch_boolExpr::BPatch_boolExpr(BPatch_relOp op,
175                                  const BPatch_snippet &lOperand,
176                                  const BPatch_snippet &rOperand)
177 {
178     opCode astOp;
179     switch(op) {
180       case BPatch_lt:
181         astOp = lessOp;
182         break;
183       case BPatch_eq:
184         astOp = eqOp;
185         break;
186       case BPatch_gt:
187         astOp = greaterOp;
188         break;
189       case BPatch_le:
190         astOp = leOp;
191         break;
192       case BPatch_ne:
193         astOp = neOp;
194         break;
195       case BPatch_ge:
196         astOp = geOp;
197         break;
198       case BPatch_and:
199         astOp = andOp;
200         break;
201       case BPatch_or:
202         astOp = orOp;
203         break;
204       default:
205         /* XXX Handle the error case here */
206         assert( 0 );
207     };
208     
209     ast = new AstNode(astOp, lOperand.ast, rOperand.ast);
210     assert(BPatch::bpatch != NULL);
211     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
212 }
213
214
215 /*
216  * BPatch_constExpr::BPatch_constExpr
217  *
218  * Constructs a snippet representing a constant integer value.
219  *
220  * value        The desired value.
221  */
222 BPatch_constExpr::BPatch_constExpr(int value)
223 {
224     ast = new AstNode(AstNode::Constant, (void *)value);
225
226     assert(BPatch::bpatch != NULL);
227     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
228
229     BPatch_type *type = BPatch::bpatch->stdTypes->findType("int");
230     assert(type != NULL);
231
232     ast->setType(type);
233 }
234
235
236 /*
237  * BPatch_constExpr::BPatch_constExpr
238  *
239  * Constructs a snippet representing a constant string value.
240  *
241  * value        The desired constant string.
242  */
243 BPatch_constExpr::BPatch_constExpr(const char *value)
244 {
245     ast = new AstNode(AstNode::ConstantString, (void *)value);
246
247     assert(BPatch::bpatch != NULL);
248     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
249
250     BPatch_type *type = BPatch::bpatch->stdTypes->findType("char *");
251     assert(type != NULL);
252
253     ast->setType(type);
254 }
255
256
257 /*
258  * BPatch_funcCallExpr::BPatch_funcCallExpr
259  *
260  * Constructs a snippet representing a function call.
261  *
262  * func         Identifies the function to call.
263  * args         A vector of the arguments to be passed to the function.
264  */
265 BPatch_funcCallExpr::BPatch_funcCallExpr(
266     const BPatch_function &func,
267     const BPatch_Vector<BPatch_snippet *> &args)
268 {
269     vector<AstNode *> ast_args;
270
271     int i;
272     for (i = 0; i < args.size(); i++)
273         ast_args += assignAst(args[i]->ast);
274
275     ast = new AstNode(func.func->prettyName(), ast_args);
276
277     for (i = 0; i < args.size(); i++)
278         removeAst(ast_args[i]);
279
280     assert(BPatch::bpatch != NULL);
281     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
282 }
283
284
285 /*
286  * BPatch_ifExpr::BPatch_ifExpr
287  *
288  * Constructs a snippet representing a conditional expression.
289  *
290  * conditional          The conditional.
291  * tClause              A snippet to execute if the conditional is true.
292  */
293 BPatch_ifExpr::BPatch_ifExpr(const BPatch_boolExpr &conditional,
294                              const BPatch_snippet &tClause)
295 {
296     ast = new AstNode(ifOp, conditional.ast, tClause.ast);
297
298     assert(BPatch::bpatch != NULL);
299     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
300 }
301
302
303 /*
304  * BPatch_ifExpr::BPatch_ifExpr
305  *
306  * Constructs a snippet representing a conditional expression with an else
307  * clause.
308  *
309  * conditional          The conditional.
310  * tClause              A snippet to execute if the conditional is true.
311  */
312 BPatch_ifExpr::BPatch_ifExpr(const BPatch_boolExpr &conditional,
313                              const BPatch_snippet &tClause,
314                              const BPatch_snippet &fClause)
315 {
316     ast = new AstNode(ifOp, conditional.ast, tClause.ast, fClause.ast);
317
318     assert(BPatch::bpatch != NULL);
319     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
320 }
321
322
323 /*
324  * BPatch_nullExpr::BPatch_nullExpr
325  *
326  * Construct a null snippet that can be used as a placeholder.
327  */
328 BPatch_nullExpr::BPatch_nullExpr()
329 {
330     ast = new AstNode;
331
332     assert(BPatch::bpatch != NULL);
333     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
334 }
335
336
337 /*
338  * BPatch_paramExpr::BPatch_paramExpr
339  *
340  * Construct a snippet representing a parameter of the function in which
341  * the snippet is inserted.
342  *
343  * n    The position of the parameter (0 is the first parameter, 1 the second,
344  *      and so on).
345  */
346 BPatch_paramExpr::BPatch_paramExpr(int n)
347 {
348     ast = new AstNode(AstNode::Param, (void *)n);
349
350     assert(BPatch::bpatch != NULL);
351     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
352 }
353
354
355 /*
356  * BPatch_retExpr::BPatch_retExpr
357  *
358  * Construct a snippet representing a return value from the function in which
359  * the snippet is inserted.
360  *
361  */
362 BPatch_retExpr::BPatch_retExpr()
363 {
364     ast = new AstNode(AstNode::ReturnVal, (void *)0);
365
366     assert(BPatch::bpatch != NULL);
367     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
368 }
369
370 /*
371  * BPatch_sequence::BPatch_sequence
372  *
373  * Construct a snippet representing a sequence of snippets.
374  *
375  * items        The snippets that are to make up the sequence.
376  */
377 BPatch_sequence::BPatch_sequence(const BPatch_Vector<BPatch_snippet *> &items)
378 {
379     if (items.size() == 0) {
380         // XXX do something to indicate an error
381         return;
382     }
383
384     assert(BPatch::bpatch != NULL);
385
386     ast = new AstNode(items[0]->ast);
387     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
388
389     for (int i = 1; i < items.size(); i++) {
390         AstNode *tempAst = new AstNode(ast, items[i]->ast);
391         tempAst->setTypeChecking(BPatch::bpatch->isTypeChecked());
392         removeAst(ast);
393         ast = tempAst;
394     }
395 }
396
397
398 /*
399  * BPatch_variableExpr::BPatch_variableExpr
400  *
401  * Construct a snippet representing a variable of the given type at the given
402  * address.
403  *
404  * in_process   The process that the variable resides in.
405  * in_address   The address of the variable in the inferior's address space.
406  * type         The type of the variable.
407  */
408 BPatch_variableExpr::BPatch_variableExpr(process *in_process,
409                                          void *in_address,
410                                          const BPatch_type *type) :
411     proc(in_process), address(in_address)
412 {
413     ast = new AstNode(AstNode::DataAddr, address);
414
415     assert(BPatch::bpatch != NULL);
416     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
417
418     ast->setType(type);
419
420     size = type->getSize();
421 }
422
423
424 /*
425  * BPatch_variableExpr::BPatch_variableExpr
426  *
427  * Construct a snippet representing an untyped variable of a given size at the
428  * given address.
429  *
430  * in_address   The address of the variable in the inferior's address space.
431  */
432 BPatch_variableExpr::BPatch_variableExpr(process *in_process,
433                                          void *in_address,
434                                          int in_size) :
435     proc(in_process), address(in_address)
436 {
437     ast = new AstNode(AstNode::DataAddr, address);
438
439     assert(BPatch::bpatch != NULL);
440     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
441
442     ast->setType(BPatch::bpatch->type_Untyped);
443
444     size = in_size;
445 }
446
447
448 /*
449  * BPatch_variableExpr::readValue
450  *
451  * Read the value of a variable in a thread's address space.
452  *
453  * dst          A pointer to a buffer in which to place the value of the
454  *              variable.  It is assumed to be the same size as the variable.
455  */
456 void BPatch_variableExpr::readValue(void *dst)
457 {
458     proc->readDataSpace(address, size, dst, true);
459 }
460
461
462 /*
463  * BPatch_variableExpr::readValue
464  *
465  * Read the a given number of bytes starting at the base address of a variable
466  * in the a thread's address space.
467  *
468  * dst          A pointer to a buffer in which to place the value of the
469  *              variable.  It is assumed to be the same size as the variable.
470  * len          Number of bytes to read.
471  */
472 void BPatch_variableExpr::readValue(void *dst, int len)
473 {
474     proc->readDataSpace(address, len, dst, true);
475 }
476
477
478 /*
479  * BPatch_variableExpr::writeValue
480  *
481  * Write a value into a variable in a thread's address space.
482  *
483  * dst          A pointer to a buffer in which to place the value of the
484  *              variable.  It is assumed to be the same size as the variable.
485  */
486 void BPatch_variableExpr::writeValue(const void *src)
487 {
488     proc->writeDataSpace(address, size, src);
489 }
490
491
492 /*
493  * BPatch_variableExpr::writeValue
494  *
495  * Write the a given number of bytes starting at the base address of a
496  * variable in the a thread's address space.
497  *
498  * dst          A pointer to a buffer in which to place the value of the
499  *              variable.  It is assumed to be the same size as the variable.
500  */
501 void BPatch_variableExpr::writeValue(const void *src, int len)
502 {
503     proc->writeDataSpace(address, len, src);
504 }
505
506
507 /**************************************************************************
508  * BPatch_function
509  *************************************************************************/
510
511 /*
512  * BPatch_function::getName
513  *
514  * Copies the name of the function into a buffer, up to a given maximum
515  * length.  Returns a pointer to the beginning of the buffer that was
516  * passed in.
517  *
518  * s            The buffer into which the name will be copied.
519  * len          The size of the buffer.
520  */
521 char *BPatch_function::getName(char *s, int len)
522 {
523     assert(func);
524     string name = func->prettyName();
525     strncpy(s, name.string_of(), len);
526
527     return s;
528 }
529
530
531 /*
532  * BPatch_function::findPoint
533  *
534  * Returns a vector of the instrumentation points from a procedure that is
535  * identified by the parameters, or returns NULL upon failure.
536  *
537  * loc          The points within the procedure to return.  The following
538  *              values are valid for this parameter:
539  *                BPatch_entry         The function's entry point.
540  *                BPatch_exit          The function's exit point(s).
541  *                BPatch_subroutine    The points at which the procedure calls
542  *                                     other procedures.
543  *                BPatch_longJump      The points at which the procedure make
544  *                                     long jump calls.
545  *                BPatch_allLocations  All of the points described above.
546  */
547 BPatch_Vector<BPatch_point*> *BPatch_function::findPoint(
548         const BPatch_procedureLocation loc)
549 {
550     if (func == NULL) return NULL;
551
552     BPatch_Vector<BPatch_point*> *result = new BPatch_Vector<BPatch_point *>;
553
554     if (loc == BPatch_entry || loc == BPatch_allLocations) {
555         BPatch_point *new_point = new BPatch_point(proc,
556                                         (instPoint *)func->funcEntry(proc));
557         result->push_back(new_point);
558     }
559     if (loc ==  BPatch_exit || loc == BPatch_allLocations) {
560         const vector<instPoint *> &points = func->funcExits(proc);
561         for (unsigned i = 0; i < points.size(); i++) {
562             BPatch_point *new_point = new BPatch_point(proc, points[i]);
563             result->push_back(new_point);
564         }
565     }
566     if (loc ==  BPatch_subroutine || loc == BPatch_allLocations) {
567         const vector<instPoint *> &points = func->funcCalls(proc);
568         for (unsigned i = 0; i < points.size(); i++) {
569             BPatch_point *new_point = new BPatch_point(proc, points[i]);
570             result->push_back(new_point);
571         }
572     }
573     if (loc ==  BPatch_longJump /* || loc == BPatch_allLocations */) {
574         /* XXX Not yet implemented */
575         assert( 0 );
576     }
577
578     return result;
579 }