Right now, the BPatch_deref and BPatch_regExpr do not specify the size.
[dyninst.git] / dyninstAPI / src / BPatch_snippet.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 // $Id: BPatch_snippet.C,v 1.108 2008/06/19 19:52:55 legendre Exp $
32
33 #define BPATCH_FILE
34
35 #include <string.h>
36
37 #include "common/src/Time.h"
38 #include "common/src/timing.h"
39
40 #include "BPatch.h"
41 #include "BPatch_addressSpace.h"
42 #include "BPatch_snippet.h"
43 #include "BPatch_type.h"
44 #include "BPatch_function.h"
45 #include "BPatch_collections.h"
46 #include "BPatch_Vector.h"
47 #include "BPatch_libInfo.h"
48 #include "BPatch_point.h"
49
50 #include "addressSpace.h"
51 #include "mapped_object.h" // for savetheworld
52 #include "mapped_module.h"
53 #include "ast.h"
54 #include "function.h"
55 #include "instPoint.h"
56 #include "registerSpace.h"
57 #include "debug.h"
58 #include "dynProcess.h"
59 #include "pcEventHandler.h"
60
61 #include "RegisterConversion.h"
62
63 #include "symtabAPI/h/Type.h"
64 #include "symtabAPI/h/Variable.h"
65
66
67 using namespace Dyninst;
68 using namespace Dyninst::SymtabAPI;
69
70 // Need REG_MT_POS, defined in inst-<arch>...
71
72 #if defined(arch_x86) || defined(arch_x86_64)
73 #include "inst-x86.h"
74 #elif defined(arch_power)
75 #include "inst-power.h"
76 #elif defined(arch_aarch64)
77 #include "inst-aarch64.h"
78 #else
79 #error "Unknown architecture, expected x86, x86_64, power or aarch64"
80 #endif
81
82
83 /*
84  * BPatch_snippet::BPatch_snippet
85  *
86  * The default constructor was exposed as public, so we're
87  * stuck with it even though that _should_ be an error.
88  * For now, make it a null node (and hope nobody ever
89  * tries to generate code)
90  */
91 BPatch_snippet::BPatch_snippet() {
92     ast_wrapper = AstNodePtr(AstNode::nullNode());
93 }
94
95 /*
96  * BPatch_snippet::BPatch_snippet
97  *
98  * Copy constructor for BPatch_snippet.
99  */
100 BPatch_snippet::BPatch_snippet(const BPatch_snippet &src)
101 {
102     ast_wrapper = src.ast_wrapper;
103 }
104
105 BPatch_snippet::BPatch_snippet(const AstNodePtr &node)
106 {
107    ast_wrapper = node;
108 }
109
110 /*
111  * BPatch_snippet::operator=
112  *
113  * Assignment operator for BPatch_snippet.  Needed to ensure that the
114  * reference counts for the asts contained in the snippets is correct.
115  */
116 BPatch_snippet &BPatch_snippet::operator=(const BPatch_snippet &src)
117 {
118     // Check for x = x
119     if (&src == this)
120         return *this;
121
122     // We'll now contain another reference to the ast in the other snippet
123     ast_wrapper = src.ast_wrapper;
124
125     return *this;
126 }
127
128 /*
129  * BPatch_snippet::getType
130  */
131
132 BPatch_type *BPatch_snippet::getType(){
133    return ast_wrapper->getType();
134 }
135
136 /*
137  * BPatch_snippet:getCost
138  *
139  * Deprecated.
140  */
141 float BPatch_snippet::getCost()
142 {
143     return 0.0;
144 }
145 /*
146  * BPatch_snippet:getCostAtPoint
147  *
148  * Deprecated.
149  */
150 float BPatch_snippet::getCostAtPoint(BPatch_point *)
151 {
152     return 0.0;
153 }
154
155 bool BPatch_snippet::is_trivial()
156 {
157   return (ast_wrapper == NULL);
158 }
159
160 /*
161  * BPatch_snippet::~BPatch_snippet
162  *
163  * Destructor for BPatch_snippet.  Deallocates memory allocated by the
164  * snippet.  Well, decrements a reference count.
165  */
166 BPatch_snippet::~BPatch_snippet()
167 {
168     //if (ast_wrapper) delete ast_wrapper;
169 }
170
171
172 AstNodePtr generateVariableBase(const BPatch_snippet &lOperand)
173 {
174   AstNodePtr variableBase;
175   if(lOperand.ast_wrapper->getoType() == AstNode::variableValue)
176   {
177     variableBase = AstNode::operandNode(AstNode::variableAddr, lOperand.ast_wrapper->getOVar());
178   }
179   else if(lOperand.ast_wrapper->getoType() == AstNode::variableAddr)
180   {
181     variableBase = lOperand.ast_wrapper;
182   }
183   else
184   {
185     variableBase = AstNode::operatorNode(getAddrOp, lOperand.ast_wrapper);
186   }
187   return variableBase;
188 }
189
190
191 //
192 // generateArrayRef - Construct an Ast expression for an array.
193 //
194 AstNodePtr generateArrayRef(const BPatch_snippet &lOperand,
195                             const BPatch_snippet &rOperand)
196 {
197         if (lOperand.ast_wrapper == AstNodePtr()) return AstNodePtr();
198         if (rOperand.ast_wrapper == AstNodePtr()) return AstNodePtr();
199
200         if (lOperand.ast_wrapper->getType() == NULL)
201         {
202                 BPatch_reportError(BPatchSerious, 109,
203                                 "array reference has no type information");
204         }
205
206         //  We have to be a little forgiving of the
207
208         typeArray *arrayType = lOperand.ast_wrapper->getType()->getSymtabType()->getArrayType();
209         if (!arrayType)
210         {
211                 if (lOperand.ast_wrapper->getType() == NULL)
212                 {
213                         BPatch_reportError(BPatchSerious, 109,
214                                         "array reference has no type information");
215                 }
216                 else
217                 {
218                         fprintf(stderr, "%s[%d]:  error here: type is %s\n", FILE__, __LINE__,
219                                         lOperand.ast_wrapper->getType()->getName());
220                         BPatch_reportError(BPatchSerious, 109,
221                                         "array reference has array reference to non-array type");
222                 }
223                 assert(0);
224                 return AstNodePtr();
225         }
226
227         Type *elementType = arrayType->getBaseType();
228         assert(elementType);
229         long int elementSize = elementType->getSize();
230
231         // check that the type of the right operand is an integer.
232         //  We have to be a little forgiving of this parameter, since we could
233         //  be indexing using a funcCall snippet, for which no return type is available.
234         //  Ideally we could always know this information, but until then, if no
235         //  type information is available, assume that the user knows what they're doing
236         //  (just print a warning, don't fail).
237
238         BPatch_type *indexType = const_cast<BPatch_type *>(rOperand.ast_wrapper->getType());
239
240         if (!indexType)
241         {
242                 char err_buf[512];
243                 sprintf(err_buf, "%s[%d]:  %s %s\n",
244                                 __FILE__, __LINE__,
245                                 "Warning:  cannot ascertain type of index parameter is of integral type, ",
246                                 "This is not a failure... but be warned that type-checking has failed. ");
247                 BPatch_reportError(BPatchWarning, 109, err_buf);
248
249         }
250         else if (strcmp(indexType->getName(), "int")
251                         && strcmp(indexType->getName(), "short")
252                         && strcmp(indexType->getName(), "long")
253                         && strcmp(indexType->getName(), "signed")
254                         && strcmp(indexType->getName(), "unsigned int")
255                         && strcmp(indexType->getName(), "unsigned short")
256                         && strcmp(indexType->getName(), "unsigned long")
257                         && strcmp(indexType->getName(), "unsigned"))
258         {
259                 char err_buf[256];
260                 sprintf(err_buf, "%s[%d]: non-integer array index type %s\n",
261                                 __FILE__, __LINE__,  indexType->getName());
262                 fprintf(stderr, "%s\n", err_buf);
263                 BPatch_reportError(BPatchSerious, 109, err_buf);
264                 assert(0);
265                 return AstNodePtr();
266         }
267
268         //fprintf(stderr, "%s[%d]:  indexing with type %s\n", __FILE__, __LINE__,
269         //        indexType->getName());
270
271         //
272         // Convert a[i] into *(&a + (* i sizeof(element)))
273         //
274
275         AstNodePtr arrayBase = generateVariableBase(lOperand);
276         AstNodePtr ast = AstNode::operandNode(AstNode::DataIndir,
277                         AstNode::operatorNode(plusOp,
278                                 arrayBase,
279                                 AstNode::operatorNode(timesOp,
280                                         AstNode::operandNode(AstNode::Constant,
281                                                 (void *)elementSize),
282                                         rOperand.ast_wrapper)));
283
284         BPatch_type *elem_bptype = NULL;
285         extern AnnotationClass<BPatch_type> TypeUpPtrAnno;
286
287         if (!elementType->getAnnotation(elem_bptype, TypeUpPtrAnno))
288         {
289                 //  BPatch_type ctor adds itself as an anonotation to the symtab
290                 //  type, so no need to do it here.
291                 elem_bptype = new BPatch_type(elementType);
292         }
293         else
294         {
295                 assert(elem_bptype);
296         }
297
298         ast->setType(elem_bptype);
299
300         return AstNodePtr(ast);
301 }
302
303
304 //
305 // generateFieldRef - Construct an Ast expression for an structure field.
306 //
307 AstNodePtr generateFieldRef(const BPatch_snippet &lOperand,
308                 const BPatch_snippet &rOperand)
309 {
310         if (lOperand.ast_wrapper == AstNodePtr()) return AstNodePtr();
311         if (rOperand.ast_wrapper == AstNodePtr()) return AstNodePtr();
312
313         if (lOperand.ast_wrapper->getType() == NULL)
314         {
315                 BPatch_reportError(BPatchSerious, 109,
316                                 "array reference has no type information");
317         }
318
319         typeStruct *structType = lOperand.ast_wrapper->getType()->getSymtabType()->getStructType();
320
321         if (!structType)
322         {
323                 BPatch_reportError(BPatchSerious, 109,
324                                 "structure reference has no type information, or structure reference to non-structure type");
325                 assert(0);
326                 return AstNodePtr();
327         }
328
329         // check that the type of the right operand is a string.
330
331         BPatch_type *fieldType = const_cast<BPatch_type *>(rOperand.ast_wrapper->getType());
332
333         if (rOperand.ast_wrapper->getoType()!=AstNode::ConstantString
334                         || !fieldType
335                         || strcmp(fieldType->getName(), "char *"))
336         {
337                 // XXX - Should really check if this is a short/long too
338                 BPatch_reportError(BPatchSerious, 109,
339                                 "field name is not of type char *");
340                 assert(0);
341                 return AstNodePtr();
342         }
343
344         Field *field = NULL;
345
346         // check that the name of the right operand is a field of the left operand
347
348         auto fields = structType->getComponents();
349
350         unsigned int i;
351
352         for (i=0; i < fields->size(); i++)
353         {
354                 field = (*fields)[i];
355                 if (!strcmp(field->getName().c_str(), (const char *) rOperand.ast_wrapper->getOValue()))
356                         break;
357         }
358
359         if (i==fields->size())
360         {
361                 BPatch_reportError(BPatchSerious, 109,
362                                 "field name not found in structure");
363                 assert(0);
364                 return AstNodePtr();
365         }
366
367         if (! field ) {
368            assert(0);
369            return AstNodePtr();
370         }
371
372         long int offset = (field->getOffset() / 8);
373
374         //
375         // Convert s.f into *(&s + offset(s,f))
376         //
377
378         AstNodePtr structBase = generateVariableBase(lOperand);
379
380         AstNodePtr ast = AstNode::operandNode(AstNode::DataIndir,
381                         AstNode::operatorNode(plusOp,
382                                 structBase,
383                                 AstNode::operandNode(AstNode::Constant,
384                                         (void *)offset)));
385
386         extern AnnotationClass<BPatch_type> TypeUpPtrAnno;
387         BPatch_type *field_bptype = NULL;
388         SymtabAPI::Type *field_type = field->getType();
389         assert(field_type);
390
391
392         if (!field_type->getAnnotation(field_bptype, TypeUpPtrAnno))
393         {
394                 //  BPatch_type ctor adds itself as an annotation of the symtab type
395                 //  so no need to do it here.
396
397                 field_bptype = new BPatch_type(field_type);
398         }
399         else
400         {
401                 assert(field_bptype);
402         }
403
404         ast->setType(field_bptype);
405
406         return AstNodePtr(ast);
407 }
408
409 /*
410  * BPatch_arithExpr::BPatch_arithExpr
411  *
412  * Construct a snippet representing a binary arithmetic operation.
413  *
414  * op           The desired operation.
415  * lOperand     The left operand for the operation.
416  * rOperand     The right operand.
417  */
418 BPatch_arithExpr::BPatch_arithExpr(BPatch_binOp op,
419                 const BPatch_snippet &lOperand, const BPatch_snippet &rOperand)
420 {
421         assert(BPatch::bpatch != NULL);
422
423    std::vector<BPatch_snippet *> argVect;
424
425         opCode astOp = undefOp; // Quiet the compiler
426         switch(op) {
427                 case BPatch_assign:
428                         astOp = storeOp;
429                         break;
430                 case BPatch_plus:
431                         astOp = plusOp;
432                         break;
433                 case BPatch_minus:
434                         astOp = minusOp;
435                         break;
436                 case BPatch_xor:
437                         astOp = xorOp;
438                         break;
439                 case BPatch_divide:
440                         astOp = divOp;
441                         break;
442                 case BPatch_times:
443                         astOp = timesOp;
444                         break;
445                 case BPatch_mod:
446                         /* XXX Not yet implemented. */
447                         assert(0);
448                         break;
449                 case BPatch_ref:
450          ast_wrapper = generateArrayRef(lOperand, rOperand);
451                         if (!ast_wrapper) {
452             BPatch_reportError(BPatchSerious, 100 /* what # to use? */,
453                                                 "could not generate array reference.");
454                                 BPatch_reportError(BPatchSerious, 100,
455                                                 "resulting snippet is invalid.");
456                         }
457                         return;
458                         break;
459                 case BPatch_fieldref:
460                         ast_wrapper = generateFieldRef(lOperand, rOperand);
461                         if (!ast_wrapper) {
462                                 BPatch_reportError(BPatchSerious, 100 /* what # to use? */,
463                                                 "could not generate field reference.");
464                                 BPatch_reportError(BPatchSerious, 100,
465                                                 "resulting snippet is invalid.");
466                         }
467                         return;
468                         break;
469                 case BPatch_seq:
470                         {
471                                 pdvector<AstNodePtr > sequence;
472                                 sequence.push_back(lOperand.ast_wrapper);
473                                 sequence.push_back(rOperand.ast_wrapper);
474
475                                 ast_wrapper = AstNode::sequenceNode(sequence);
476                                 ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
477                                 return;
478                         }
479                 default:
480                         /* XXX handle error */
481                         assert(0);
482         };
483
484         ast_wrapper = AstNodePtr(AstNode::operatorNode(astOp,
485                                 lOperand.ast_wrapper,
486                                 rOperand.ast_wrapper));
487         ast_wrapper->setType(lOperand.ast_wrapper->getType());
488         ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
489 }
490
491
492 /*
493  * BPatch_arithExpr::BPatch_arithExpr
494  *
495  * Construct a snippet representing a unary arithmetic operation.
496  *
497  * op           The desired operation.
498  * lOperand     The left operand for the operation.
499  */
500 BPatch_arithExpr::BPatch_arithExpr(BPatch_unOp op,
501                                    const BPatch_snippet &lOperand)
502 {
503         assert(BPatch::bpatch != NULL);
504
505         switch(op) {
506                 case BPatch_negate: {
507                                                                 AstNodePtr negOne = AstNode::operandNode(AstNode::Constant,
508                                                                                 (void *)-1);
509           BPatch_type *type = BPatch::bpatch->stdTypes->findType("int");
510           assert(type != NULL);
511           negOne->setType(type);
512           ast_wrapper =  AstNodePtr(AstNode::operatorNode(timesOp,
513                                                           negOne,
514                                                           lOperand.ast_wrapper));
515           break;
516       }
517    case BPatch_addr:  {
518      ast_wrapper = AstNodePtr(generateVariableBase(lOperand));
519        // create a new type which is a pointer to type
520        BPatch_type *baseType = const_cast<BPatch_type *>
521            (lOperand.ast_wrapper->getType());
522        BPatch_type *type = BPatch::bpatch->createPointer("<PTR>",
523                                                          baseType, sizeof(void *));
524        assert(type);
525        ast_wrapper->setType(type);
526        break;
527    }
528
529    case BPatch_deref: {
530 #if 0
531        // Handle constant addresses...
532        if (lOperand.ast_wrapper->getoType() == AstNode::Constant) {
533            ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::DataAddr,
534                                                          const_cast<void *>(lOperand.ast_wrapper->getOValue())));
535        }
536        else {
537            ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::DataIndir, lOperand.ast_wrapper));
538        }
539 #endif
540           ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::DataIndir, lOperand.ast_wrapper));
541
542           BPatch_type *type = const_cast<BPatch_type *> (lOperand.ast_wrapper->getType());
543           if (!type || (type->getDataClass() != BPatch_dataPointer)) {
544               ast_wrapper->setType(BPatch::bpatch->stdTypes->findType("long"));
545           } else {
546               ast_wrapper->setType(type->getConstituentType());
547 //              ast_wrapper->setType(dynamic_cast<BPatch_typePointer *>(type)->getConstituentType());
548           }
549           break;
550       }
551
552       default:
553          /* XXX handle error */
554          assert(0);
555    };
556
557    ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
558 }
559
560 /*
561  * BPatch_boolExpr::BPatch_boolExpr
562  *
563  * Constructs a snippet representing a boolean expression.
564  *
565  * op           The operator for the boolean expression.
566  * lOperand     The left operand.
567  * rOperand     The right operand.
568  */
569 BPatch_boolExpr::BPatch_boolExpr(BPatch_relOp op,
570                                          const BPatch_snippet &lOperand,
571                                          const BPatch_snippet &rOperand)
572 {
573     opCode astOp = undefOp;
574     switch(op) {
575       case BPatch_lt:
576         astOp = lessOp;
577         break;
578       case BPatch_eq:
579         astOp = eqOp;
580         break;
581       case BPatch_gt:
582         astOp = greaterOp;
583         break;
584       case BPatch_le:
585         astOp = leOp;
586         break;
587       case BPatch_ne:
588         astOp = neOp;
589         break;
590       case BPatch_ge:
591         astOp = geOp;
592         break;
593       case BPatch_and:
594         astOp = andOp;
595         break;
596       case BPatch_or:
597         astOp = orOp;
598         break;
599       default:
600         /* XXX Handle the error case here */
601         assert( 0 );
602     };
603
604     ast_wrapper = AstNodePtr(AstNode::operatorNode(astOp, lOperand.ast_wrapper, rOperand.ast_wrapper));
605     assert(BPatch::bpatch != NULL);
606     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
607 }
608
609
610 /*
611  * BPatch_constExpr::BPatch_constExpr
612  *
613  * Constructs a snippet representing a constant integer value.
614  *
615  * value        The desired value.
616  */
617
618 BPatch_constExpr::BPatch_constExpr( signed int value ) {
619         assert( BPatch::bpatch != NULL );
620
621         ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::Constant,
622                                                                  (void *)(uintptr_t) value));
623         ast_wrapper->setTypeChecking( BPatch::bpatch->isTypeChecked() );
624
625         BPatch_type * type = BPatch::bpatch->stdTypes->findType( "int" );
626         assert( type != NULL );
627         ast_wrapper->setType( type );
628 }
629
630 BPatch_constExpr::BPatch_constExpr( unsigned int value ) {
631         assert( BPatch::bpatch != NULL );
632
633         ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::Constant,
634                                                                  (void *)(uintptr_t) value));
635         ast_wrapper->setTypeChecking( BPatch::bpatch->isTypeChecked() );
636
637         BPatch_type * type = BPatch::bpatch->stdTypes->findType( "unsigned int" );
638         assert( type != NULL );
639         ast_wrapper->setType( type );
640         }
641
642 BPatch_constExpr::BPatch_constExpr( signed long value ) {
643         assert( BPatch::bpatch != NULL );
644
645         ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::Constant,
646                                                                  (void *)(uintptr_t) value));
647         ast_wrapper->setTypeChecking( BPatch::bpatch->isTypeChecked() );
648
649         BPatch_type * type = BPatch::bpatch->stdTypes->findType( "long" );
650         assert( type != NULL );
651         ast_wrapper->setType( type );
652         }
653
654 BPatch_constExpr::BPatch_constExpr( unsigned long value ) {
655         assert( BPatch::bpatch != NULL );
656
657         ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::Constant,
658                                                                  (void *)(uintptr_t) value));
659         ast_wrapper->setTypeChecking( BPatch::bpatch->isTypeChecked() );
660         BPatch_type * type = BPatch::bpatch->stdTypes->findType( "unsigned long" );
661         assert( type != NULL );
662         ast_wrapper->setType( type );
663         }
664
665 BPatch_constExpr::BPatch_constExpr(unsigned long long value) {
666         assert(BPatch::bpatch != NULL);
667
668         ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::Constant,
669                 (void *)(uintptr_t)value));
670         ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
671         BPatch_type * type = BPatch::bpatch->stdTypes->findType("unsigned long long");
672         assert(type != NULL);
673         ast_wrapper->setType(type);
674 }
675
676 /*
677  * BPatch_constExpr::BPatch_constExpr
678  *
679  * Constructs a snippet representing a constant string value.
680  *
681  * value        The desired constant string.
682  */
683 BPatch_constExpr::BPatch_constExpr(const char *value)
684 {
685     ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::ConstantString, (void *)const_cast<char *>(value)));
686
687     assert(BPatch::bpatch != NULL);
688     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
689
690     BPatch_type *type = BPatch::bpatch->stdTypes->findType("char *");
691     assert(type != NULL);
692
693     ast_wrapper->setType(type);
694 }
695
696
697 /*
698  * BPatch_constExpr::BPatch_constExpr
699  *
700  * Constructs a snippet representing a constant pointer.
701  *
702  * value        The desired constant pointer.
703  */
704 BPatch_constExpr::BPatch_constExpr(const void *value)
705 {
706     ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::Constant, (void *)const_cast<void *>(value)));
707
708     assert(BPatch::bpatch != NULL);
709     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
710
711     BPatch_type *type = BPatch::bpatch->stdTypes->findType("void *");
712     assert(type != NULL);
713
714     ast_wrapper->setType(type);
715 }
716
717 BPatch_constExpr::BPatch_constExpr(long long value)
718 {
719    ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::Constant, (void *)(uintptr_t)value));
720
721     assert(BPatch::bpatch != NULL);
722     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
723
724     BPatch_type* type = BPatch::bpatch->stdTypes->findType("long long");
725
726     assert(type != NULL);
727     ast_wrapper->setType(type);
728 }
729
730 #ifdef IBM_BPATCH_COMPAT
731
732 char *BPatch_variableExpr::getNameWithLength(char *buffer, int max)
733 {
734   if (max > name.length()) {
735     strcpy (buffer, name.c_str());
736     return buffer;
737   } else {
738     strncpy (buffer, name.c_str(), max-1)[max-1]='\0';
739   }
740   return NULL;
741 }
742
743 void *BPatch_variableExpr::getAddress()
744 {
745   return address;
746 }
747
748
749 BPatch_constExpr::BPatch_constExprFloat(float value)
750 {
751         // XXX fix me, puting value into int register.
752         int ivalue = (int) value;
753         BPatch_constExpr((int) ivalue);
754 }
755
756 #endif
757
758 /*
759  * BPatch_whileExpr::BPatch_whileExpr
760  *
761  * Creates a while loop; the first parameter is the
762  * conditional (true indicates executing the body of the loop)
763  * and the second is the body of the loop.
764  */
765
766 BPatch_whileExpr::BPatch_whileExpr(const BPatch_snippet &conditional,
767                                     const BPatch_snippet &body) {
768    ast_wrapper = AstNodePtr(AstNode::operatorNode(whileOp, 
769                                                   conditional.ast_wrapper, 
770                                                   body.ast_wrapper));
771    assert(BPatch::bpatch != NULL);
772    ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
773 }
774
775 /*
776  * BPatch_regExpr::BPatch_regExpr
777  *
778  * Constructs a snippet representing a register.
779  *
780  * value        index of register.
781  *
782  * Note:  introduced for paradyn-seperation (paradyn needs access
783  *        to register REG_MT_POS)  -- there are other ways to do this.
784  *        This happens to be expedient -- not sure if we want to be
785  *        really exposing this to API users.  Thus this class may be
786  *        temporary -- avoid using it.
787  */
788
789 BPatch_regExpr::BPatch_regExpr(unsigned int value)
790 {
791     ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::DataReg, (void *)(unsigned long int) value));
792
793     assert(BPatch::bpatch != NULL);
794     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
795
796     BPatch_type *type = BPatch::bpatch->stdTypes->findType("long");
797     assert(type != NULL);
798
799     ast_wrapper->setType(type);
800 }
801
802 /*
803  * BPatch_funcCallExpr::BPatch_funcCallExpr
804  *
805  * Constructs a snippet representing a function call.
806  *
807  * func         Identifies the function to call.
808  * args         A vector of the arguments to be passed to the function.
809  */
810 BPatch_funcCallExpr::BPatch_funcCallExpr(
811     const BPatch_function &func,
812     const BPatch_Vector<BPatch_snippet *> &args)
813 {
814     pdvector<AstNodePtr> ast_args;
815
816     unsigned int i;
817     for (i = 0; i < args.size(); i++) {
818         assert(args[i]->ast_wrapper);
819         ast_args.push_back(args[i]->ast_wrapper);
820     }
821
822     //  jaw 08/03  part of cplusplus bugfix -- using pretyName
823     //  to generate function calls can lead to non uniqueness probs
824     //  in the case of overloaded callee functions.
825
826     ast_wrapper = AstNodePtr(AstNode::funcCallNode(func.lowlevel_func(), ast_args));
827
828     assert(BPatch::bpatch != NULL);
829     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
830
831     BPatch_type *ret_type = const_cast<BPatch_function &>(func).getReturnType();
832       ast_wrapper->setType(ret_type);
833 }
834
835 /*
836  * BPatch_ifExpr::BPatch_ifExpr
837  *
838  * Constructs a snippet representing a conditional expression.
839  *
840  * conditional          The conditional.
841  * tClause              A snippet to execute if the conditional is true.
842  */
843 BPatch_ifExpr::BPatch_ifExpr(const BPatch_boolExpr &conditional,
844                                      const BPatch_snippet &tClause)
845 {
846     ast_wrapper = AstNodePtr(AstNode::operatorNode(ifOp, conditional.ast_wrapper, tClause.ast_wrapper));
847
848     assert(BPatch::bpatch != NULL);
849     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
850 }
851
852
853 /*
854  * BPatch_ifExpr::BPatch_ifExpr
855  *
856  * Constructs a snippet representing a conditional expression with an else
857  * clause.
858  *
859  * conditional          The conditional.
860  * tClause              A snippet to execute if the conditional is true.
861  */
862  BPatch_ifExpr::BPatch_ifExpr(const BPatch_boolExpr &conditional,
863                                           const BPatch_snippet &tClause,
864                                           const BPatch_snippet &fClause)
865 {
866     ast_wrapper = AstNodePtr(AstNode::operatorNode(ifOp,
867                                                    conditional.ast_wrapper,
868                                                    tClause.ast_wrapper,
869                                                    fClause.ast_wrapper));
870
871     assert(BPatch::bpatch != NULL);
872     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
873 }
874
875
876 /*
877  * BPatch_nullExpr::BPatch_nullExpr
878  *
879  * Construct a null snippet that can be used as a placeholder.
880  */
881 BPatch_nullExpr::BPatch_nullExpr()
882 {
883     ast_wrapper = AstNodePtr(AstNode::nullNode());
884
885     assert(BPatch::bpatch != NULL);
886     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
887 }
888
889
890 /*
891  * BPatch_paramExpr::BPatch_paramExpr
892  *
893  * Construct a snippet representing a parameter of the function in which
894  * the snippet is inserted.
895  *
896  * n    The position of the parameter (0 is the first parameter, 1 the second,
897  *      and so on).
898  */
899 BPatch_paramExpr::BPatch_paramExpr(int n, BPatch_ploc loc)
900 {
901     AstNode::operandType opType;
902     switch(loc) {
903         case (BPatch_ploc_guess):
904             opType = AstNode::Param;
905             break;
906         case (BPatch_ploc_call):
907             opType = AstNode::ParamAtCall;
908             break;
909         case (BPatch_ploc_entry):
910             opType = AstNode::ParamAtEntry;
911             break;
912         default:
913             assert(0);
914             break;
915     }
916
917     ast_wrapper = AstNodePtr(AstNode::operandNode(opType,
918                                                   (void *)(long)n));
919
920     assert(BPatch::bpatch != NULL);
921     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
922 }
923
924
925 /*
926  * BPatch_retExpr::BPatch_retExpr
927  *
928  * Construct a snippet representing a return value from the function in which
929  * the snippet is inserted.
930  *
931  */
932 BPatch_retExpr::BPatch_retExpr()
933 {
934     ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::ReturnVal, (void *)0));
935
936     assert(BPatch::bpatch != NULL);
937     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
938 }
939
940
941 /*
942  * BPatch_retAddrExpr::BPatch_retAddrExpr
943  *
944  * Construct a snippet representing a return value from the function in which
945  * the snippet is inserted.
946  *
947  */
948 BPatch_retAddrExpr::BPatch_retAddrExpr()
949 {
950     ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::ReturnAddr, (void *)0));
951     assert(BPatch::bpatch != NULL);
952     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
953 }
954
955
956 /*
957  * BPatch_registerExpr::BPatch_registerExpr
958  *
959  * Construct a snippet representing a register in original code. Can be read
960  * or written.
961  *
962  */
963 BPatch_registerExpr::BPatch_registerExpr(BPatch_register reg)
964 {
965     ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::origRegister,
966                                                       (void *)(long)reg.number_));
967
968     assert(BPatch::bpatch != NULL);
969
970     // Registers can hold a lot of different types...
971     ast_wrapper->setTypeChecking(false);
972     //ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
973 }
974
975 BPatch_registerExpr::BPatch_registerExpr(Dyninst::MachRegister mach) {
976    bool whocares;
977    Register reg = convertRegID(mach, whocares);
978    ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::origRegister,
979                                                  (void *)(intptr_t)reg));
980     assert(BPatch::bpatch != NULL);
981
982     // Registers can hold a lot of different types...
983     ast_wrapper->setTypeChecking(false);
984     //ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
985 }
986
987 /*
988  * BPatch_sequence::BPatch_sequence
989  *
990  * Construct a snippet representing a sequence of snippets.
991  *
992  * items        The snippets that are to make up the sequence.
993  */
994 BPatch_sequence::BPatch_sequence(const BPatch_Vector<BPatch_snippet *> &items)
995 {
996     if (items.size() == 0) {
997         // XXX do something to indicate an error
998         return;
999     }
1000
1001     assert(BPatch::bpatch != NULL);
1002
1003     pdvector<AstNodePtr >sequence;
1004     for (unsigned i = 0; i < items.size(); i++) {
1005         assert(items[i]->ast_wrapper);
1006         sequence.push_back(items[i]->ast_wrapper);
1007     }
1008     ast_wrapper = AstNodePtr(AstNode::sequenceNode(sequence));
1009
1010     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1011 }
1012
1013
1014 /*
1015  * BPatch_variableExpr::BPatch_variableExpr
1016  *
1017  * Construct a snippet representing a variable of the given type and the passed
1018  *   ast.
1019  *
1020  * in_process   The BPatch_process that the variable resides in.
1021  * in_address   The address of the variable in the inferior's address space.
1022  * type         The type of the variable.
1023  * ast          The ast expression for the variable
1024  */
1025 BPatch_variableExpr::BPatch_variableExpr(const char *in_name,
1026                                          BPatch_addressSpace *in_addSpace,
1027                                          AddressSpace *in_lladdSpace,
1028                                          AstNodePtr ast_wrapper_,
1029                                          BPatch_type *typ,
1030                                          void* in_address) :
1031   name(in_name),
1032   appAddSpace(in_addSpace),
1033   lladdrSpace(in_lladdSpace),
1034   address(in_address),
1035   scope(NULL),
1036   isLocal(false),
1037   type(typ),
1038   intvar(NULL)
1039 {
1040     ast_wrapper = ast_wrapper_;
1041     assert(ast_wrapper);
1042
1043     assert(BPatch::bpatch != NULL);
1044     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1045
1046     ast_wrapper->setType(type);
1047
1048     size = type->getSize();
1049 }
1050
1051 BPatch_variableExpr::BPatch_variableExpr(BPatch_addressSpace *in_addSpace,
1052                                          AddressSpace *ll_addSpace, int_variable *iv,
1053                                          BPatch_type *type)
1054   : name(),
1055     appAddSpace(in_addSpace),
1056     lladdrSpace(ll_addSpace),
1057     address(NULL),
1058     scope(NULL),
1059     isLocal(false),
1060     type(type),
1061     intvar(NULL)
1062 {
1063   const image_variable* img_var = NULL;
1064   if(iv)
1065   {
1066     name = iv->symTabName();
1067     address = reinterpret_cast<void*>(iv->getAddress());
1068     intvar = iv;
1069     img_var = iv->ivar();
1070   }
1071   size = type->getSize();
1072   if(img_var)
1073   {
1074     ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::variableValue, img_var));
1075   }
1076   else
1077   {
1078     ast_wrapper = AstNodePtr(AstNode::operandNode(AstNode::DataAddr, (void*)(NULL)));
1079   }
1080
1081
1082   ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1083   ast_wrapper->setType(type);
1084
1085 }
1086
1087
1088 BPatch_variableExpr* BPatch_variableExpr::makeVariableExpr(BPatch_addressSpace* in_addSpace,
1089                                                  int_variable* v,
1090                                                  BPatch_type* type)
1091 {
1092   AddressSpace* llAS = v->mod()->proc();
1093   return new BPatch_variableExpr(in_addSpace, llAS, v, type);
1094 }
1095
1096 BPatch_variableExpr* BPatch_variableExpr::makeVariableExpr(BPatch_addressSpace* in_addSpace,
1097                                                            AddressSpace* in_llAddSpace,
1098                                                            std::string name,
1099                                                            void* offset,
1100                                                            BPatch_type* type)
1101 {
1102
1103     int_variable* v = in_llAddSpace->getAOut()->getDefaultModule()->createVariable(name,
1104                                                                                    reinterpret_cast<Address>(offset),
1105                                                                                    type->getSize());
1106     return new BPatch_variableExpr(in_addSpace, in_llAddSpace, v, type);
1107 }
1108
1109
1110 unsigned int BPatch_variableExpr::getSize() const
1111 {
1112   return size;
1113 }
1114
1115 /*
1116  * BPatch_variableExpr::getType
1117  *
1118  *    Return the variable's type
1119  *
1120 */
1121 const BPatch_type *BPatch_variableExpr::getType()
1122 {
1123   if (!type){
1124      return BPatch::bpatch->type_Untyped;
1125   }
1126   return type;
1127 }
1128
1129 /*
1130  * BPatch_variableExpr::setType
1131  *
1132  *    Set the variable's type
1133  *
1134 */
1135 bool BPatch_variableExpr::setType(BPatch_type *newType)
1136 {
1137     size = newType->getSize();
1138     type = newType;
1139     ast_wrapper->setType(newType);
1140     return true;
1141 }
1142 /*
1143  * BPatch_variableExpr::seSize
1144  *
1145  *    Set the variable's size
1146  *
1147 */
1148 bool BPatch_variableExpr::setSize(int sz)
1149 {
1150     size = sz;
1151     return true;
1152 }
1153
1154
1155 /*
1156  * BPatch_variableExpr::BPatch_variableExpr
1157  *
1158  * Construct a snippet representing a variable of the given type at the given
1159  * address.
1160  *
1161  * in_addSpace  The BPatch_addressSpace that the variable resides in.
1162  * in_address   The address of the variable in the inferior's address space.
1163  * in_register  The register of the variable in the inferior's address space.
1164  * type         The type of the variable.
1165  * in_storage   Enum of how this variable is stored.
1166  */
1167 BPatch_variableExpr::BPatch_variableExpr(BPatch_addressSpace *in_addSpace,
1168                                          AddressSpace *in_lladdrSpace,
1169                                          void *in_address,
1170                                          int in_register,
1171                                          BPatch_type *typ,
1172                                          BPatch_storageClass in_storage,
1173                                          BPatch_point *scp) :
1174    name(),
1175    appAddSpace(in_addSpace),
1176    lladdrSpace(in_lladdrSpace),
1177    address(in_address),
1178    type(typ),
1179    intvar(NULL)
1180 {
1181    vector<AstNodePtr> variableASTs;
1182    AstNodePtr variableAst;
1183
1184    if (!type)
1185      type = BPatch::bpatch->type_Untyped;
1186    switch (in_storage) {
1187       case BPatch_storageAddr:
1188           variableAst = AstNodePtr(AstNode::operandNode(AstNode::DataAddr, address));
1189           isLocal = false;
1190          break;
1191       case BPatch_storageAddrRef:
1192          assert( 0 ); // Not implemented yet.
1193          isLocal = false;
1194          break;
1195       case BPatch_storageReg:
1196          variableAst = AstNodePtr(AstNode::operandNode(AstNode::origRegister,
1197                                                            (void *)(long)in_register));
1198          isLocal = true;
1199          break;
1200       case BPatch_storageRegRef:
1201          assert( 0 ); // Not implemented yet.
1202          isLocal = true;
1203          break;
1204       case BPatch_storageRegOffset:
1205          variableAst = AstNodePtr(AstNode::operandNode(AstNode::RegOffset,
1206                                         AstNode::operandNode(AstNode::DataAddr,
1207                                                              address)));
1208          variableAst->setOValue( (void *)(long int)in_register );
1209          isLocal = true;
1210          break;
1211       case BPatch_storageFrameOffset:
1212          variableAst = AstNodePtr(AstNode::operandNode(AstNode::FrameAddr, address));
1213          isLocal = true;
1214          break;
1215    }
1216
1217    variableAst->setTypeChecking(BPatch::bpatch->isTypeChecked());
1218    variableAst->setType(type);
1219    variableASTs.push_back(variableAst);
1220    ast_wrapper = AstNode::variableNode(variableASTs);
1221    //    ast_wrapper = variableAst;
1222    assert(BPatch::bpatch != NULL);
1223    ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1224
1225    size = type->getSize();
1226    ast_wrapper->setType(type);
1227
1228    scope = scp;
1229 }
1230
1231 /*
1232  * BPatch_variableExpr::BPatch_variableExpr
1233  *
1234  * Construct a snippet representing a variable of the given type at the given
1235  * address.
1236  *
1237  * in_addSpace  The BPatch_addressSpace that the variable resides in.
1238  * lv           The local variable handle
1239  * type             The type of the variable.
1240  *
1241  */
1242 BPatch_variableExpr::BPatch_variableExpr(BPatch_addressSpace *in_addSpace,
1243                                          AddressSpace *in_lladdSpace,
1244                                          BPatch_localVar *lv, BPatch_type *typ,
1245                                          BPatch_point *scp):
1246    name(),
1247    appAddSpace(in_addSpace),
1248    lladdrSpace(in_lladdSpace),
1249    address(NULL),
1250    isLocal(false),
1251    type(typ),
1252    intvar(NULL)
1253 {
1254
1255         //Create Ast's for all members in the location list.
1256         //This will likely be done only for local variables within a function
1257         if (!type)
1258                 type = BPatch::bpatch->type_Untyped;
1259
1260         Address baseAddr =  scp->getFunction()->lowlevel_func()->obj()->codeBase();
1261         vector<AstNodePtr> variableASTs;
1262         vector<pair<Offset, Offset> > *ranges = new vector<pair<Offset, Offset> >;
1263         vector<Dyninst::VariableLocation> &locs = lv->getSymtabVar()->getLocationLists();
1264         for (unsigned i=0; i<locs.size(); i++)
1265         {
1266                 AstNodePtr variableAst;
1267                 BPatch_storageClass in_storage = lv->convertToBPatchStorage(& locs[i]);
1268                 void *in_address = (void *) locs[i].frameOffset;
1269                 bool ignored;
1270                 int in_register = convertRegID(locs[i].mr_reg, ignored);
1271                 switch (in_storage) {
1272                         case BPatch_storageAddr:
1273                                 variableAst = AstNode::operandNode(AstNode::DataAddr, in_address);
1274                                 isLocal = false;
1275                                 address = in_address;
1276                                 break;
1277                         case BPatch_storageAddrRef:
1278                                 //assert( 0 ); // Not implemented yet.
1279                                 continue;
1280                         case BPatch_storageReg:
1281                                 variableAst = AstNode::operandNode(AstNode::origRegister,
1282                                                 (void *)(long)in_register);
1283                                 isLocal = true;
1284                                 break;
1285                         case BPatch_storageRegRef:
1286                                 //assert( 0 ); // Not implemented yet.
1287                                 continue;
1288                         case BPatch_storageRegOffset:
1289                                 variableAst = AstNode::operandNode(AstNode::RegOffset,
1290                                                 AstNode::operandNode(AstNode::DataAddr,
1291                                                         in_address));
1292                                 variableAst->setOValue( (void *)(long int)in_register );
1293                                 isLocal = true;
1294                                 break;
1295                         case BPatch_storageFrameOffset:
1296                                 variableAst = AstNode::operandNode(AstNode::FrameAddr, in_address);
1297                                 isLocal = true;
1298                                 break;
1299                 }
1300                 variableAst->setTypeChecking(BPatch::bpatch->isTypeChecked());
1301                 variableAst->setType(type);
1302                 variableASTs.push_back(variableAst);
1303                    
1304                                 Address low, hi;
1305                                 if (locs[i].lowPC == 0 && locs[i].hiPC == (Address) -1) {
1306                                         low = 0;
1307                                         hi = (Address) -1;
1308                                 }
1309                                 else {
1310                                         low = locs[i].lowPC + baseAddr;
1311                                         hi = locs[i].hiPC + baseAddr;
1312                                 }
1313
1314                 ranges->push_back(pair<Address, Address>(low, hi));
1315         }
1316         ast_wrapper = AstNodePtr(AstNode::variableNode(variableASTs, ranges));
1317         //    ast_wrapper = variableAst;
1318         assert(BPatch::bpatch != NULL);
1319         ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1320
1321         ast_wrapper->setType(type);
1322         size = type->getSize();
1323
1324         scope = scp;
1325 }
1326
1327
1328
1329
1330 /*
1331  * BPatch_variableExpr::readValue
1332  *
1333  * Read the value of a variable in a thread's address space.
1334  *
1335  * dst          A pointer to a buffer in which to place the value of the
1336  *              variable.  It is assumed to be the same size as the variable.
1337  */
1338 bool BPatch_variableExpr::readValue(void *dst)
1339 {
1340         if (isLocal) {
1341                 char msg[2048];
1342                 sprintf(msg, "variable %s is not a global variable, cannot read using readValue()",name.c_str());
1343                 BPatch_reportError(BPatchWarning, 109,msg);
1344                 return false;
1345         }
1346
1347         if (size == 2 || size == 4 || size == 8) {
1348                 // XXX - We should be going off of type here, not just size.
1349                 if (!lladdrSpace->readDataWord(address, size, dst, true)) return false;
1350                 return true;
1351         } else if (size) {
1352                 if (!lladdrSpace->readDataSpace(address, size, dst, true)) return false;
1353                 return true;
1354         } else {
1355                 return false;
1356         }
1357 }
1358
1359
1360 /*
1361  * BPatch_variableExpr::readValue
1362  *
1363  * Read the a given number of bytes starting at the base address of a variable
1364  * in the a thread's address space.
1365  *
1366  * dst          A pointer to a buffer in which to place the value of the
1367  *              variable.  It is assumed to be the same size as the variable.
1368  * len          Number of bytes to read.
1369  */
1370 bool BPatch_variableExpr::readValue(void *dst, int len)
1371 {
1372         if (isLocal) {
1373                 char msg[2048];
1374                 sprintf(msg, "variable %s is not a global variable, cannot read using readValue()",name.c_str());
1375                 BPatch_reportError(BPatchWarning, 109,msg);
1376                 return false;
1377         }
1378
1379         return lladdrSpace->readDataSpace(address, len, dst, true);
1380 }
1381
1382
1383 /*
1384  * BPatch_variableExpr::writeValue
1385  *
1386  * Write a value into a variable in a thread's address space.
1387  *
1388  * dst          A pointer to a buffer in which to place the value of the
1389  *              variable.  It is assumed to be the same size as the variable.
1390  *
1391  * returns false if the type info isn't available (i.e. we don't know the size)
1392  */
1393
1394 bool BPatch_variableExpr::writeValue(const void *src, bool /* saveWorld */)
1395 {
1396   if (isLocal) {
1397     char msg[2048];
1398     sprintf(msg, "variable %s is not a global variable, cannot write",name.c_str());
1399     BPatch_reportError(BPatchWarning, 109,msg);
1400     return false;
1401   }
1402
1403   if (size) {
1404       bool writeStatus;
1405
1406       if (size == 2 || size == 4 || size == 8)
1407           writeStatus = lladdrSpace->writeDataWord(address, size, src);
1408       else
1409           writeStatus = lladdrSpace->writeDataSpace(address, size, src);
1410
1411       if (!writeStatus) {
1412         std::stringstream errorMsg;
1413         errorMsg << "variable " << name << " in .bss section, cannot write";
1414         BPatch_reportError(BPatchWarning, 109, errorMsg.str().c_str());
1415         return false;
1416       }
1417       return true;
1418   }
1419   else {
1420       return false;
1421   }
1422 }
1423
1424
1425 /*
1426  * BPatch_variableExpr::writeValue
1427  *
1428  * Write the a given number of bytes starting at the base address of a
1429  * variable in the a thread's address space.
1430  *
1431  * dst          A pointer to a buffer in which to place the value of the
1432  *              variable.  It is assumed to be the same size as the variable.
1433  */
1434 bool BPatch_variableExpr::writeValue(const void *src, int len, bool /*saveWorld*/)
1435 {
1436   if (isLocal) {
1437     char msg[2048];
1438     sprintf(msg, "variable %s is not a global variable, cannot write",name.c_str());
1439     BPatch_reportError(BPatchWarning, 109,msg);
1440     return false;
1441   }
1442
1443   if (!lladdrSpace->writeDataSpace(address, len, src)) {
1444     std::stringstream errorMsg;
1445     errorMsg << "variable " << name << " in .bss section, cannot write";
1446     BPatch_reportError(BPatchWarning, 109, errorMsg.str().c_str());
1447     return false;
1448   }
1449   return true;
1450 }
1451
1452 AddressSpace *BPatch_variableExpr::getAS()
1453 {
1454    return lladdrSpace;
1455 }
1456
1457 const char *BPatch_variableExpr::getName()
1458 {
1459   return name.empty() ? NULL : name.c_str();
1460 }
1461
1462 void *BPatch_variableExpr::getBaseAddr()
1463 {
1464   return address;
1465 }
1466 /*
1467  * getComponents() - return variable expressions for all of the fields
1468  *     in the passed structure/union.
1469  */
1470 BPatch_Vector<BPatch_variableExpr *> *BPatch_variableExpr::getComponents()
1471 {
1472     const BPatch_Vector<BPatch_field *> *fields;
1473     BPatch_Vector<BPatch_variableExpr *> *retList = new BPatch_Vector<BPatch_variableExpr *>;
1474     fields = getType()->getComponents();
1475     if (fields == NULL) return NULL;
1476     for (unsigned int i=0; i < fields->size(); i++) {
1477
1478        BPatch_field *field = (*fields)[i];
1479        long int offset = (field->getOffset() / 8);
1480        BPatch_variableExpr *newVar;
1481
1482        // convert to *(&basrVar + offset)
1483        AstNodePtr fieldExpr = AstNode::operandNode(AstNode::DataIndir,
1484                                                    AstNode::operatorNode(plusOp,
1485                                                                          generateVariableBase(*this),
1486                                                    AstNode::operandNode(AstNode::Constant, (void *)offset)));
1487        if( field->getType() != NULL ) {
1488            AstNodePtr newAst = fieldExpr;
1489            newVar = new BPatch_variableExpr(const_cast<char *> (field->getName()),
1490                                             appAddSpace, lladdrSpace,
1491                                             newAst,
1492                                             field->getType(),
1493                                             (char*)address + offset);
1494            retList->push_back(newVar);
1495        } else {
1496            bperr( "Warning: not returning field '%s' with NULL type.\n", field->getName() );
1497        }
1498     }
1499     return retList;
1500 }
1501
1502 /*
1503  * BPatch_breakPointExpr::BPatch_breakPointExpr
1504  *
1505  * Construct a snippet representing a breakpoint.
1506  *
1507  */
1508 BPatch_breakPointExpr::BPatch_breakPointExpr()
1509 {
1510     pdvector<AstNodePtr > null_args;
1511
1512     ast_wrapper = AstNodePtr(AstNode::funcCallNode("DYNINST_snippetBreakpoint", null_args));
1513
1514     assert(BPatch::bpatch != NULL);
1515
1516     ast_wrapper->setType(BPatch::bpatch->type_Untyped);
1517     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1518 }
1519
1520
1521 /*
1522  * BPatch_effectiveAddressExpr::BPatch_effectiveAddressExpr
1523  *
1524  * Construct a snippet representing an effective address.
1525  */
1526 BPatch_effectiveAddressExpr::BPatch_effectiveAddressExpr(int _which)
1527 {
1528 #if defined(i386_unknown_nt4_0)
1529   assert(_which >= 0 && _which <= 2);
1530 #elif defined (__XLC__) || defined(__xlC__)
1531   assert(_which >= 0 && _which <= 1);
1532 #else
1533   assert(_which >= 0 && _which <= (int) BPatch_instruction::nmaxacc_NP);
1534 #endif
1535   ast_wrapper = AstNodePtr(AstNode::memoryNode(AstNode::EffectiveAddr, _which));
1536 };
1537
1538
1539 /*
1540  * BPatch_bytesAccessedExpr::BPatch_bytesAccessedExpr
1541  *
1542  * Construct a snippet representing the number of bytes accessed.
1543  */
1544 BPatch_bytesAccessedExpr::BPatch_bytesAccessedExpr(int _which)
1545 {
1546 #if defined(i386_unknown_nt4_0)
1547   assert(_which >= 0 && _which <= 2);
1548 #elif defined (__XLC__) || defined(__xlC__)
1549   assert(_which >= 0 && _which <= 1);
1550 #else
1551   assert(_which >= 0 && _which <= (int)BPatch_instruction::nmaxacc_NP);
1552 #endif
1553   ast_wrapper = AstNodePtr(AstNode::memoryNode(AstNode::BytesAccessed, _which));
1554 };
1555
1556
1557 BPatch_ifMachineConditionExpr::BPatch_ifMachineConditionExpr(const BPatch_snippet &tClause)
1558 {
1559     ast_wrapper = AstNodePtr(AstNode::operatorNode(ifMCOp, tClause.ast_wrapper));
1560
1561     assert(BPatch::bpatch != NULL);
1562     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1563 };
1564
1565 BPatch_threadIndexExpr::BPatch_threadIndexExpr()
1566 {
1567     ast_wrapper = AstNodePtr(AstNode::threadIndexNode());
1568
1569     assert(BPatch::bpatch != NULL);
1570     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1571     BPatch_type *type = BPatch::bpatch->stdTypes->findType("int");
1572     assert(type != NULL);
1573     //ast_wrapper->setType(type);
1574
1575 }
1576
1577 BPatch_tidExpr::BPatch_tidExpr(BPatch_process *proc)
1578 {
1579   BPatch_Vector<BPatch_function *> thread_funcs;
1580   proc->getImage()->findFunction("dyn_pthread_self", thread_funcs);
1581   if (thread_funcs.size() != 1)
1582   {
1583     fprintf(stderr, "[%s:%u] - Internal Dyninst error.  Found %lu copies of "
1584             "DYNINSTthreadIndex.  Expected 1\n", __FILE__, __LINE__, (long) thread_funcs.size());
1585     if (!thread_funcs.size())
1586       return;
1587   }
1588   BPatch_function *thread_func = thread_funcs[0];
1589
1590   pdvector<AstNodePtr> args;
1591   ast_wrapper = AstNodePtr(AstNode::funcCallNode(thread_func->lowlevel_func(), args));
1592
1593   assert(BPatch::bpatch != NULL);
1594   ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1595   BPatch_type *type = BPatch::bpatch->stdTypes->findType("long");
1596   assert(type != NULL);
1597   ast_wrapper->setType(type);
1598 }
1599
1600 // BPATCH INSN EXPR
1601
1602
1603 /* Causes us to create only one StopThreadCallback per
1604    BPatchStopThreadCallback, though we create a function call snippet
1605    to DYNINST_stopThread for each individual stopThreadExpr.  It's not
1606    necessary that we limit StopThreadCallbacks creations like this. */
1607 static std::set<BPatchStopThreadCallback> *stopThread_cbs=NULL;
1608
1609 static void constructorHelper(
1610    const BPatchStopThreadCallback &bp_cb,
1611    bool useCache,
1612    BPatch_stInterpret interp,
1613    AstNodePtr &idNode,
1614    AstNodePtr &icNode)
1615 {
1616     //register the callback if it's new
1617     if (stopThread_cbs == NULL) {
1618         stopThread_cbs = new std::set<BPatchStopThreadCallback>;
1619     }
1620
1621     std::set<BPatchStopThreadCallback>::iterator cbIter = 
1622         stopThread_cbs->find(bp_cb);
1623     if (cbIter == stopThread_cbs->end()) {
1624        stopThread_cbs->insert(bp_cb);
1625        BPatch::bpatch->registerStopThreadCallback(bp_cb);
1626     }
1627
1628     // create callback ID argument
1629     intptr_t cb_id = BPatch::bpatch->getStopThreadCallbackID(bp_cb); 
1630     idNode = AstNode::operandNode(AstNode::Constant, (void*) cb_id );
1631     BPatch_type *inttype = BPatch::bpatch->stdTypes->findType("int");
1632     assert(inttype != NULL);
1633     idNode->setType(inttype);
1634
1635     // create interpret/usecache argument
1636     intptr_t ic = 0;
1637     if (useCache)
1638         ic += 1;
1639     if (interp == BPatch_interpAsTarget)
1640         ic += 2;
1641     else if (interp == BPatch_interpAsReturnAddr)
1642         ic += 4;
1643     icNode = AstNode::operandNode(AstNode::Constant, (void*) ic );
1644     icNode->setType(inttype);
1645 }
1646
1647 /* BPatch_stopThreadExpr
1648  *
1649  *  This snippet type stops the thread that executes it.  It
1650  *  evaluates a calculation snippet and triggers a callback to the
1651  *  user program with the result of the calculation and a pointer to
1652  *  the BPatch_point at which the snippet was inserted
1653  */
1654 BPatch_stopThreadExpr::BPatch_stopThreadExpr
1655       (const BPatchStopThreadCallback &bp_cb,
1656        const BPatch_snippet &calculation,
1657        bool useCache,
1658        BPatch_stInterpret interp)
1659 {
1660     AstNodePtr idNode;
1661     AstNodePtr icNode;
1662     constructorHelper(bp_cb, useCache, interp, idNode, icNode);
1663
1664     // set up funcCall args
1665     pdvector<AstNodePtr> ast_args;
1666     ast_args.push_back(AstNode::actualAddrNode());
1667     ast_args.push_back(idNode);
1668     ast_args.push_back(icNode);
1669     ast_args.push_back(calculation.ast_wrapper);
1670
1671     // create func call & set type
1672     ast_wrapper = AstNodePtr(AstNode::funcCallNode("DYNINST_stopThread", ast_args));
1673     ast_wrapper->setType(BPatch::bpatch->type_Untyped);
1674     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1675 }
1676
1677
1678   // for internal use in conjunction with memory emulation and defensive
1679   // mode analysis
1680 BPatch_stopThreadExpr::BPatch_stopThreadExpr(
1681    const BPatchStopThreadCallback &bp_cb,
1682    const BPatch_snippet &calculation,
1683    const mapped_object &obj,
1684    bool useCache,
1685    BPatch_stInterpret interp)
1686 {
1687     AstNodePtr idNode;
1688     AstNodePtr icNode;
1689     constructorHelper(bp_cb, useCache, interp, idNode, icNode);
1690
1691     Address objStart = obj.codeBase();
1692     Address objEnd = objStart + obj.imageSize();
1693     AstNodePtr objStartNode = AstNode::operandNode(
1694         AstNode::Constant, (void*) objStart);
1695     AstNodePtr objEndNode = AstNode::operandNode(
1696         AstNode::Constant, (void*) objEnd);
1697     BPatch_type *ulongtype = BPatch::bpatch->stdTypes->findType("unsigned long");
1698     objStartNode->setType(ulongtype);
1699     objEndNode->setType(ulongtype);
1700
1701     // set up funcCall args
1702     pdvector<AstNodePtr> ast_args;
1703     ast_args.push_back(AstNode::actualAddrNode());
1704     ast_args.push_back(idNode);
1705     ast_args.push_back(icNode);
1706     ast_args.push_back(calculation.ast_wrapper);
1707     ast_args.push_back(objStartNode);
1708     ast_args.push_back(objEndNode);
1709
1710     // create func call & set type
1711     ast_wrapper = AstNodePtr(AstNode::funcCallNode("DYNINST_stopInterProc", ast_args));
1712     ast_wrapper->setType(BPatch::bpatch->type_Untyped);
1713     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1714 }
1715
1716
1717 BPatch_shadowExpr::BPatch_shadowExpr
1718       (bool entry,
1719       const BPatchStopThreadCallback &bp_cb,
1720        const BPatch_snippet &calculation,
1721        bool useCache,
1722        BPatch_stInterpret interp)
1723 {
1724     AstNodePtr idNode;
1725     AstNodePtr icNode;
1726     constructorHelper(bp_cb, useCache, interp, idNode, icNode);
1727
1728     // set up funcCall args
1729     pdvector<AstNodePtr> ast_args;
1730     if (entry) {
1731         ast_args.push_back(AstNode::operandNode(AstNode::Constant, (void *)1));
1732     }
1733     else {
1734         ast_args.push_back(AstNode::operandNode(AstNode::Constant, (void *)0));
1735     }
1736     ast_args.back()->setType(BPatch::bpatch->type_Untyped);
1737
1738     ast_args.push_back(AstNode::actualAddrNode());
1739     ast_args.push_back(idNode);
1740     ast_args.push_back(icNode);
1741     ast_args.push_back(calculation.ast_wrapper);
1742
1743     // create func call & set type
1744     ast_wrapper = AstNodePtr(AstNode::funcCallNode("RThandleShadow", ast_args));
1745     ast_wrapper->setType(BPatch::bpatch->type_Untyped);
1746     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1747 }
1748
1749 BPatch_originalAddressExpr::BPatch_originalAddressExpr() {
1750     ast_wrapper = AstNodePtr(AstNode::originalAddrNode());
1751
1752     assert(BPatch::bpatch != NULL);
1753     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1754     BPatch_type *type = BPatch::bpatch->stdTypes->findType("long");
1755     assert(type != NULL);
1756     ast_wrapper->setType(type);
1757 }
1758
1759 BPatch_actualAddressExpr::BPatch_actualAddressExpr() {
1760     ast_wrapper = AstNodePtr(AstNode::actualAddrNode());
1761
1762     assert(BPatch::bpatch != NULL);
1763     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1764     BPatch_type *type = BPatch::bpatch->stdTypes->findType("long");
1765     assert(type != NULL);
1766     ast_wrapper->setType(type);
1767 }
1768
1769 BPatch_dynamicTargetExpr::BPatch_dynamicTargetExpr() {
1770     ast_wrapper = AstNodePtr(AstNode::dynamicTargetNode());
1771
1772     assert(BPatch::bpatch != NULL);
1773     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1774     BPatch_type *type = BPatch::bpatch->stdTypes->findType("long");
1775     assert(type != NULL);
1776     ast_wrapper->setType(type);
1777 }
1778
1779 BPatch_scrambleRegistersExpr::BPatch_scrambleRegistersExpr(){
1780
1781
1782     ast_wrapper = AstNodePtr(AstNode::scrambleRegistersNode());
1783     ast_wrapper->setType(BPatch::bpatch->type_Untyped);
1784     ast_wrapper->setTypeChecking(BPatch::bpatch->isTypeChecked());
1785    
1786 }
1787
1788 // Conversions
1789 Dyninst::PatchAPI::Snippet::Ptr Dyninst::PatchAPI::convert(const BPatch_snippet *snip) {
1790    // TODO when this class exists
1791    return snip->ast_wrapper;
1792 }
1793
1794 bool BPatch_snippet::checkTypesAtPoint(BPatch_point* p) const
1795 {
1796   if(!p) return true;
1797   
1798   return ast_wrapper->checkType(p->getFunction()) != BPatch::bpatch->type_Error;
1799 }
1800