Changes to work towards compatability with IBM's version of dyninst.
[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 // $Id: BPatch_snippet.C,v 1.31 2001/08/29 23:25:27 hollings Exp $
43
44 #define BPATCH_FILE
45
46 #include <string.h>
47 #include "ast.h"
48 #include "symtab.h"
49 #include "process.h"
50 #include "instPoint.h"
51
52 #include "BPatch.h"
53 #include "BPatch_snippet.h"
54 #include "BPatch_type.h"
55 #include "BPatch_collections.h"
56 #include "BPatch_Vector.h"
57 #include "common/h/Time.h"
58 #include "common/h/timing.h"
59
60 /*
61  * BPatch_snippet::BPatch_snippet
62  *
63  * Copy constructor for BPatch_snippet.
64  */
65 BPatch_snippet::BPatch_snippet(const BPatch_snippet &src)
66 {
67     ast = assignAst(src.ast);
68 }
69
70
71 /*
72  * BPatch_snippet::operator=
73  *
74  * Assignment operator for BPatch_snippet.  Needed to ensure that the
75  * reference counts for the asts contained in the snippets is correct.
76  */
77 BPatch_snippet &BPatch_snippet::operator=(const BPatch_snippet &src)
78 {
79     // Check for x = x
80     if (&src == this)
81         return *this;
82
83     // Since we're copying over this snippet, release the old AST
84     if (ast != NULL)
85         removeAst(ast);
86
87     // We'll now contain another reference to the ast in the other snippet
88     ast = assignAst(src.ast);
89
90     return *this;
91 }
92
93
94 /*
95  * BPatch_snippet:getCost
96  *
97  * Returns the estimated cost of executing the snippet, in seconds.
98  */
99 float BPatch_snippet::getCost()
100 {
101   timeLength costv = timeLength(ast->cost(), getCyclesPerSecond());
102   float retCost = static_cast<float>(costv.getD(timeUnit::sec()));
103   return retCost;
104 }
105
106
107 /*
108  * BPatch_snippet::~BPatch_snippet
109  *
110  * Destructor for BPatch_snippet.  Deallocates memory allocated by the
111  * snippet.
112  */
113 BPatch_snippet::~BPatch_snippet()
114 {
115     // if (ast != NULL)
116         // removeAst(ast);
117 }
118
119
120 //
121 // generateArrayRef - Construct an Ast expression for an array.
122 //
123 AstNode *generateArrayRef(const BPatch_snippet &lOperand, 
124                           const BPatch_snippet &rOperand)
125 {
126     AstNode *ast;
127
128     if (!lOperand.ast || !rOperand.ast) {
129         return NULL;
130     }
131     BPatch_type *arrayType = const_cast<BPatch_type *>(lOperand.ast->getType());
132     if (!arrayType) {
133         BPatch_reportError(BPatchSerious, 109,
134                "array reference has not type information");
135         return NULL;
136     }
137     if (arrayType->getDataClass() != BPatch_dataArray) {
138         BPatch_reportError(BPatchSerious, 109,
139                "array reference to non-array type");
140         return NULL;
141     }
142     BPatch_type *elementType = arrayType->getConstituentType();
143
144     assert(elementType);
145     int elementSize = elementType->getSize();
146
147     // check that the type of the right operand is an integer.
148     BPatch_type *indexType = const_cast<BPatch_type *>(rOperand.ast->getType());
149     if (!indexType || strcmp(indexType->getName(), "int")) {
150         // XXX - Should really check if this is a short/long too
151         BPatch_reportError(BPatchSerious, 109,
152                            "array index is not of type int");
153         return NULL;
154     }
155
156     //
157     // Convert a[i] into *(&a + (* i sizeof(element)))
158     //
159     AstNode *elementExpr = new AstNode(AstNode::Constant, (void *) elementSize);
160     AstNode *offsetExpr = new AstNode(timesOp, elementExpr, rOperand.ast);
161     AstNode *addrExpr = new AstNode(plusOp, 
162         new AstNode(getAddrOp, lOperand.ast), offsetExpr);
163     ast = new AstNode(AstNode::DataIndir, addrExpr);
164     ast->setType(elementType);
165
166     return ast;
167 }
168
169 /*
170  * BPatch_arithExpr::BPatch_arithExpr
171  *
172  * Construct a snippet representing a binary arithmetic operation.
173  *
174  * op           The desired operation.
175  * lOperand     The left operand for the operation.
176  * rOperand     The right operand.
177  */
178 BPatch_arithExpr::BPatch_arithExpr(BPatch_binOp op,
179         const BPatch_snippet &lOperand, const BPatch_snippet &rOperand)
180 {
181     assert(BPatch::bpatch != NULL);
182
183     opCode astOp;
184     switch(op) {
185       case BPatch_assign:
186         astOp = storeOp;
187         break;
188       case BPatch_plus:
189         astOp = plusOp;
190         break;
191       case BPatch_minus:
192         astOp = minusOp;
193         break;
194       case BPatch_divide:
195         astOp = divOp;
196         break;
197       case BPatch_times:
198         astOp = timesOp;
199         break;
200       case BPatch_mod:
201         /* XXX Not yet implemented. */
202         assert(0);
203         break;
204       case BPatch_ref:
205         ast = generateArrayRef(lOperand, rOperand);
206         return;
207
208         break;
209
210       case BPatch_seq:
211         ast = new AstNode(lOperand.ast, rOperand.ast);
212         ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
213         return;
214       default:
215         /* XXX handle error */
216         assert(0);
217     };
218
219 #ifdef alpha_dec_osf4_0
220     /* XXX
221      * A special kludge for the Alpha: there's no hardware divide on the
222      * Alpha, and our code in inst-alpha.C to call a software divide doesn't
223      * work right (yet?).  So, we never generate a divOp AstNode; instead we
224      * generate a callNode AST that calls a divide function.
225      */
226     if (astOp == divOp) {
227         vector<AstNode *> args;
228
229         args.push_back(assignAst(lOperand.ast));
230         args.push_back(assignAst(rOperand.ast));
231
232         ast = new AstNode("divide", args);
233
234         removeAst(args[0]);
235         removeAst(args[1]);
236     } else {
237         ast = new AstNode(astOp, lOperand.ast, rOperand.ast);
238     }
239 #else
240     ast = new AstNode(astOp, lOperand.ast, rOperand.ast);
241 #endif
242
243     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
244 }
245
246
247 /*
248  * BPatch_arithExpr::BPatch_arithExpr
249  *
250  * Construct a snippet representing a unary arithmetic operation.
251  *
252  * op           The desired operation.
253  * lOperand     The left operand for the operation.
254  */
255 BPatch_arithExpr::BPatch_arithExpr(BPatch_unOp op, 
256     const BPatch_snippet &lOperand)
257 {
258     assert(BPatch::bpatch != NULL);
259
260     switch(op) {
261       case BPatch_negate: {
262         AstNode *negOne = new AstNode(AstNode::Constant, (void *) -1);
263         BPatch_type *type = BPatch::bpatch->stdTypes->findType("int");
264         assert(type != NULL);
265
266         negOne->setType(type);
267         ast = new AstNode(timesOp, negOne, lOperand.ast);
268         break;
269       }
270
271       case BPatch_addr:  {
272         ast = new AstNode(getAddrOp, lOperand.ast);
273         // create a new type which is a pointer to type 
274         BPatch_type *baseType = const_cast<BPatch_type *> 
275             (lOperand.ast->getType());
276         BPatch_type *type = BPatch::bpatch->createPointer("<PTR>", 
277             baseType, sizeof(void *));
278         assert(type);
279         ast->setType(type);
280         break;
281       }
282
283       case BPatch_deref: {
284         ast = new AstNode(AstNode::DataIndir, lOperand.ast);
285         BPatch_type *type = const_cast<BPatch_type *> ((lOperand.ast)->getType());
286         if (!type || (type->getDataClass() != BPatch_dataPointer)) {
287             ast->setType(BPatch::bpatch->stdTypes->findType("int"));
288         } else {
289             ast->setType(type->getConstituentType());
290         }
291         break;
292       }
293
294       default:
295         /* XXX handle error */
296         assert(0);
297     };
298
299     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
300 }
301
302 /*
303  * BPatch_boolExpr::BPatch_boolExpr
304  *
305  * Constructs a snippet representing a boolean expression.
306  *
307  * op           The operator for the boolean expression.
308  * lOperand     The left operand.
309  * rOperand     The right operand.
310  */
311 BPatch_boolExpr::BPatch_boolExpr(BPatch_relOp op,
312                                  const BPatch_snippet &lOperand,
313                                  const BPatch_snippet &rOperand)
314 {
315     opCode astOp;
316     switch(op) {
317       case BPatch_lt:
318         astOp = lessOp;
319         break;
320       case BPatch_eq:
321         astOp = eqOp;
322         break;
323       case BPatch_gt:
324         astOp = greaterOp;
325         break;
326       case BPatch_le:
327         astOp = leOp;
328         break;
329       case BPatch_ne:
330         astOp = neOp;
331         break;
332       case BPatch_ge:
333         astOp = geOp;
334         break;
335       case BPatch_and:
336         astOp = andOp;
337         break;
338       case BPatch_or:
339         astOp = orOp;
340         break;
341       default:
342         /* XXX Handle the error case here */
343         assert( 0 );
344     };
345     
346     ast = new AstNode(astOp, lOperand.ast, rOperand.ast);
347     assert(BPatch::bpatch != NULL);
348     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
349 }
350
351
352 /*
353  * BPatch_constExpr::BPatch_constExpr
354  *
355  * Constructs a snippet representing a constant integer value.
356  *
357  * value        The desired value.
358  */
359 BPatch_constExpr::BPatch_constExpr(int value)
360 {
361     ast = new AstNode(AstNode::Constant, (void *)value);
362
363     assert(BPatch::bpatch != NULL);
364     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
365
366     BPatch_type *type = BPatch::bpatch->stdTypes->findType("int");
367
368     assert(type != NULL);
369
370     ast->setType(type);
371 }
372
373
374 /*
375  * BPatch_constExpr::BPatch_constExpr
376  *
377  * Constructs a snippet representing a constant string value.
378  *
379  * value        The desired constant string.
380  */
381 BPatch_constExpr::BPatch_constExpr(const char *value)
382 {
383     ast = new AstNode(AstNode::ConstantString, (void*)const_cast<char*>(value));
384
385     assert(BPatch::bpatch != NULL);
386     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
387
388     BPatch_type *type = BPatch::bpatch->stdTypes->findType("char *");
389     assert(type != NULL);
390
391     ast->setType(type);
392 }
393
394
395 /*
396  * BPatch_constExpr::BPatch_constExpr
397  *
398  * Constructs a snippet representing a constant pointer.
399  *
400  * value        The desired constant pointer.
401  */
402 BPatch_constExpr::BPatch_constExpr(const void *value)
403 {
404     ast = new AstNode(AstNode::Constant, (void*)const_cast<void*>(value));
405
406     assert(BPatch::bpatch != NULL);
407     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
408
409     BPatch_type *type = BPatch::bpatch->stdTypes->findType("void *");
410     assert(type != NULL);
411
412     ast->setType(type);
413 }
414
415
416 #ifdef IBM_BPATCH_COMPAT
417 //
418 // this is long long only in size, it will fail if a true long long
419 //    with high bits is passed.
420
421 BPatch_constExpr::BPatch_constExpr(long long value)
422 {
423     assert(value < 0x00000000ffffffff);
424
425     ast = new AstNode(AstNode::Constant, (void *)(value & 0x00000000ffffffff));
426
427     assert(BPatch::bpatch != NULL);
428     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
429
430     BPatch_type *type = BPatch::bpatch->stdTypes->findType("long long");
431     printf("size of const expr type long long is %d\n", type->getSize());
432
433     assert(type != NULL);
434
435     ast->setType(type);
436     printf("generating long long constant\n");
437     fflush(stdout);
438 }
439
440
441 BPatch_constExpr::BPatch_constExpr(float value)
442 {
443         // XXX fix me, puting value into int register.
444         int ivalue = (int) value;
445         BPatch_constExpr((int) ivalue);
446 }
447 #endif
448
449 /*
450  * BPatch_funcCallExpr::BPatch_funcCallExpr
451  *
452  * Constructs a snippet representing a function call.
453  *
454  * func         Identifies the function to call.
455  * args         A vector of the arguments to be passed to the function.
456  */
457 BPatch_funcCallExpr::BPatch_funcCallExpr(
458     const BPatch_function &func,
459     const BPatch_Vector<BPatch_snippet *> &args)
460 {
461     vector<AstNode *> ast_args;
462
463     int i;
464     for (i = 0; i < args.size(); i++)
465         ast_args.push_back(assignAst(args[i]->ast));
466
467     ast = new AstNode(func.func->prettyName(), ast_args);
468
469     for (i = 0; i < args.size(); i++)
470         removeAst(ast_args[i]);
471
472     assert(BPatch::bpatch != NULL);
473     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
474 }
475
476 /*
477  * BPatch_funcJumpExpr::BPatch_funcJumpExpr
478  *
479  * Constructs a snippet representing a jump to a function without
480  * linkage.
481  *
482  * func Identifies the function to jump to.  */
483 BPatch_funcJumpExpr::BPatch_funcJumpExpr(
484     const BPatch_function &func)
485 {
486 #if defined(sparc_sun_solaris2_4) || defined(alpha_dec_osf4_0)
487     ast = new AstNode(func.func);
488     assert(BPatch::bpatch != NULL);
489     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
490 #else
491     BPatch_reportError(BPatchSerious, 109,
492                        "BPatch_funcJumpExpr is not implemented on this platform");
493 #endif
494 }
495
496
497 /*
498  * BPatch_ifExpr::BPatch_ifExpr
499  *
500  * Constructs a snippet representing a conditional expression.
501  *
502  * conditional          The conditional.
503  * tClause              A snippet to execute if the conditional is true.
504  */
505 BPatch_ifExpr::BPatch_ifExpr(const BPatch_boolExpr &conditional,
506                              const BPatch_snippet &tClause)
507 {
508     ast = new AstNode(ifOp, conditional.ast, tClause.ast);
509
510     assert(BPatch::bpatch != NULL);
511     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
512 }
513
514
515 /*
516  * BPatch_ifExpr::BPatch_ifExpr
517  *
518  * Constructs a snippet representing a conditional expression with an else
519  * clause.
520  *
521  * conditional          The conditional.
522  * tClause              A snippet to execute if the conditional is true.
523  */
524 BPatch_ifExpr::BPatch_ifExpr(const BPatch_boolExpr &conditional,
525                              const BPatch_snippet &tClause,
526                              const BPatch_snippet &fClause)
527 {
528     ast = new AstNode(ifOp, conditional.ast, tClause.ast, fClause.ast);
529
530     assert(BPatch::bpatch != NULL);
531     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
532 }
533
534
535 /*
536  * BPatch_nullExpr::BPatch_nullExpr
537  *
538  * Construct a null snippet that can be used as a placeholder.
539  */
540 BPatch_nullExpr::BPatch_nullExpr()
541 {
542     ast = new AstNode;
543
544     assert(BPatch::bpatch != NULL);
545     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
546 }
547
548
549 /*
550  * BPatch_paramExpr::BPatch_paramExpr
551  *
552  * Construct a snippet representing a parameter of the function in which
553  * the snippet is inserted.
554  *
555  * n    The position of the parameter (0 is the first parameter, 1 the second,
556  *      and so on).
557  */
558 BPatch_paramExpr::BPatch_paramExpr(int n)
559 {
560     ast = new AstNode(AstNode::Param, (void *)n);
561
562     assert(BPatch::bpatch != NULL);
563     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
564 }
565
566
567 /*
568  * BPatch_retExpr::BPatch_retExpr
569  *
570  * Construct a snippet representing a return value from the function in which
571  * the snippet is inserted.
572  *
573  */
574 BPatch_retExpr::BPatch_retExpr()
575 {
576     ast = new AstNode(AstNode::ReturnVal, (void *)0);
577
578     assert(BPatch::bpatch != NULL);
579     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
580 }
581
582 /*
583  * BPatch_sequence::BPatch_sequence
584  *
585  * Construct a snippet representing a sequence of snippets.
586  *
587  * items        The snippets that are to make up the sequence.
588  */
589 BPatch_sequence::BPatch_sequence(const BPatch_Vector<BPatch_snippet *> &items)
590 {
591     if (items.size() == 0) {
592         // XXX do something to indicate an error
593         return;
594     }
595
596     assert(BPatch::bpatch != NULL);
597
598     ast = new AstNode(items[0]->ast);
599     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
600
601     for (int i = 1; i < items.size(); i++) {
602         AstNode *tempAst = new AstNode(ast, items[i]->ast);
603         tempAst->setTypeChecking(BPatch::bpatch->isTypeChecked());
604         removeAst(ast);
605         ast = tempAst;
606     }
607 }
608
609
610 /*
611  * BPatch_variableExpr::BPatch_variableExpr
612  *
613  * Construct a snippet representing a variable of the given type at the given
614  * address.
615  *
616  * in_process   The process that the variable resides in.
617  * in_address   The address of the variable in the inferior's address space.
618  * type         The type of the variable.
619  */
620 BPatch_variableExpr::BPatch_variableExpr(char *in_name,
621                                          process *in_process,
622                                          void *in_address,
623                                          const BPatch_type *type) :
624     name(in_name), proc(in_process), address(in_address), scope(NULL)
625 {
626     ast = new AstNode(AstNode::DataAddr, address);
627
628     assert(BPatch::bpatch != NULL);
629     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
630
631     ast->setType(type);
632
633     size = type->getSize();
634 }
635
636 /*
637  * BPatch_variableExpr::BPatch_variableExpr
638  *
639  * Construct a snippet representing a variable of the given type and the passed
640  *   ast.
641  *
642  * in_process   The process that the variable resides in.
643  * in_address   The address of the variable in the inferior's address space.
644  * type         The type of the variable.
645  * ast          The ast expression for the variable
646  */
647 BPatch_variableExpr::BPatch_variableExpr(char *in_name,
648                                          process *in_process,
649                                          AstNode *_ast,
650                                          const BPatch_type *type) :
651     name(in_name), proc(in_process), address(NULL), scope(NULL)
652 {
653     ast = _ast;
654
655     assert(BPatch::bpatch != NULL);
656     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
657
658     ast->setType(type);
659
660     size = type->getSize();
661 }
662
663
664 /*
665  * BPatch_variableExpr::getType
666  *
667  *    Return the variable's type
668  *
669 */
670 BPatch_type *BPatch_variableExpr::getType()
671 {
672     return (const_cast<BPatch_type *>(ast->getType()));
673 }
674
675 /*
676  * BPatch_variableExpr::setType
677  *
678  *    Return the variable's type
679  *
680 */
681 void BPatch_variableExpr::setType(BPatch_type *newType)
682 {
683     size = newType->getSize();
684     ast->setType(newType);
685 }
686
687 /*
688  * BPatch_variableExpr::BPatch_variableExpr
689  *
690  * Construct a snippet representing a variable of the given type at the given
691  * address.
692  *
693  * in_process   The process that the variable resides in.
694  * in_address   The address of the variable in the inferior's address space.
695  * type         The type of the variable.
696  * frameRelative        Is the address a frame offset, not absolute address
697  *
698  */
699 BPatch_variableExpr::BPatch_variableExpr(process *in_process,
700                                          void *in_address,
701                                          const BPatch_type *type,
702                                          bool frameRelative,
703                                          BPatch_point *scp) :
704     proc(in_process), address(in_address)
705 {
706     if (frameRelative) {
707         ast = new AstNode(AstNode::FrameAddr, address);
708     } else {
709         ast = new AstNode(AstNode::DataAddr, address);
710     }
711
712     assert(BPatch::bpatch != NULL);
713     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
714
715     size = type->getSize();
716     ast->setType(type);
717
718     scope = scp;
719 }
720
721 /*
722  * BPatch_variableExpr::BPatch_variableExpr
723  *
724  * Construct a snippet representing an untyped variable of a given size at the
725  * given address.
726  *
727  * in_address   The address of the variable in the inferior's address space.
728  */
729 BPatch_variableExpr::BPatch_variableExpr(process *in_process,
730                                          void *in_address,
731                                          int in_size) :
732     proc(in_process), address(in_address), scope(NULL)
733 {
734     ast = new AstNode(AstNode::DataAddr, address);
735
736     assert(BPatch::bpatch != NULL);
737     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
738
739     ast->setType(BPatch::bpatch->type_Untyped);
740
741     size = in_size;
742 }
743
744
745 /*
746  * BPatch_variableExpr::readValue
747  *
748  * Read the value of a variable in a thread's address space.
749  *
750  * dst          A pointer to a buffer in which to place the value of the
751  *              variable.  It is assumed to be the same size as the variable.
752  */
753 bool BPatch_variableExpr::readValue(void *dst)
754 {
755     if (size) {
756         proc->readDataSpace(address, size, dst, true);
757         return true;
758     } else {
759         return false;
760     }
761 }
762
763
764 /*
765  * BPatch_variableExpr::readValue
766  *
767  * Read the a given number of bytes starting at the base address of a variable
768  * in the a thread's address space.
769  *
770  * dst          A pointer to a buffer in which to place the value of the
771  *              variable.  It is assumed to be the same size as the variable.
772  * len          Number of bytes to read.
773  */
774 void BPatch_variableExpr::readValue(void *dst, int len)
775 {
776     proc->readDataSpace(address, len, dst, true);
777 }
778
779
780 /*
781  * BPatch_variableExpr::writeValue
782  *
783  * Write a value into a variable in a thread's address space.
784  *
785  * dst          A pointer to a buffer in which to place the value of the
786  *              variable.  It is assumed to be the same size as the variable.
787  *
788  * returns false if the type info isn't available (i.e. we don't know the size)
789  */
790 bool BPatch_variableExpr::writeValue(const void *src)
791 {
792     if (size) {
793         proc->writeDataSpace(address, size, src);
794         return true;
795     } else {
796         return false;
797     }
798 }
799
800
801 /*
802  * BPatch_variableExpr::writeValue
803  *
804  * Write the a given number of bytes starting at the base address of a
805  * variable in the a thread's address space.
806  *
807  * dst          A pointer to a buffer in which to place the value of the
808  *              variable.  It is assumed to be the same size as the variable.
809  */
810 void BPatch_variableExpr::writeValue(const void *src, int len)
811 {
812     proc->writeDataSpace(address, len, src);
813 }
814
815 /*
816  * getComponents() - return variable expressions for all of the fields
817  *     in the passed structure/union.
818  */
819 BPatch_Vector<BPatch_variableExpr *> *BPatch_variableExpr::getComponents()
820 {
821     BPatch_type *type;
822     BPatch_Vector<BPatch_field *> *fields;
823     BPatch_Vector<BPatch_variableExpr *> *retList;
824
825     type = const_cast<BPatch_type *>(getType());
826     if ((type->getDataClass() != BPatch_dataStructure) && (type->getDataClass() != BPatch_dataUnion)) {
827         return NULL;
828     }
829
830     retList = new BPatch_Vector<BPatch_variableExpr *>;
831     assert(retList);
832
833     fields = type->getComponents();
834     for (int i=0; i < fields->size(); i++) {
835
836         BPatch_field *field = (*fields)[i];
837         int offset = (field->offset / 8);
838
839         BPatch_variableExpr *newVar;
840
841         // convert to *(&basrVar + offset)
842         AstNode *offsetExpr = new AstNode(AstNode::Constant, (void *) offset);
843         AstNode *addrExpr = new AstNode(plusOp,
844                 new AstNode(getAddrOp, ast), offsetExpr);
845         AstNode *fieldExpr = new AstNode(AstNode::DataIndir, addrExpr);
846
847         newVar = new BPatch_variableExpr(const_cast<char *> (field->getName()),
848             proc, fieldExpr, const_cast<BPatch_type *>(field->_type));
849         retList->push_back(newVar);
850     }
851
852     return retList;
853 }
854
855 /*
856  * BPatch_breakPointExpr::BPatch_breakPointExpr
857  *
858  * Construct a snippet representing a breakpoint.
859  *
860  */
861 BPatch_breakPointExpr::BPatch_breakPointExpr()
862 {
863     vector<AstNode *> null_args;
864
865     ast = new AstNode("DYNINSTbreakPoint", null_args);
866
867     assert(BPatch::bpatch != NULL);
868
869     ast->setType(BPatch::bpatch->type_Untyped);
870     ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
871 }