Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / BPatch_type.C
1 /*
2  * Copyright (c) 1996-2009 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include <stdio.h>
33
34 #define BPATCH_FILE
35
36
37 #include "util.h"
38 #include "BPatch_Vector.h"
39 //#include "BPatch_typePrivate.h"
40 #include "BPatch_collections.h"
41 #include "debug.h"
42 #include "BPatch_function.h"
43 #include "BPatch.h"
44 #include "mapped_module.h"
45 //#include "Annotatable.h"
46 //#include "Serialization.h"
47
48 #ifdef i386_unknown_nt4_0
49 #define snprintf _snprintf
50 #endif
51
52 using namespace Dyninst;
53 using namespace Dyninst::SymtabAPI;
54
55 AnnotationClass<BPatch_cblock> CommonBlockUpPtrAnno("CommonBlockUpPtr");
56 AnnotationClass<BPatch_localVar> LocalVarUpPtrAnno("LocalVarUpPtrAnno");
57 AnnotationClass<BPatch_field> FieldUpPtrAnno("FieldUpPtrAnno");
58 AnnotationClass<BPatch_type> TypeUpPtrAnno("TypeUpPtr");
59 //static int findIntrensicType(const char *name);
60
61 // This is the ID that is decremented for each type a user defines. It is
62 // Global so that every type that the user defines has a unique ID.
63 // jdd 7/29/99
64 //int BPatch_type::USER_BPATCH_TYPE_ID = -1000;
65
66
67 std::map<Dyninst::SymtabAPI::Type*, BPatch_type *> BPatch_type::type_map;
68
69 /* These are the wrappers for constructing a type.  Since we can create
70    types six ways to Sunday, let's do them all in one centralized place. */
71 BPatch_type *BPatch_type::createFake(const char *_name) {
72    // Creating a fake type without a name is just silly
73    assert(_name != NULL);
74
75    BPatch_type *t = new BPatch_type(_name);
76    t->type_ = BPatch_dataNullType;
77
78    return t;
79 }
80
81 /*
82  * BPatch_type::BPatch_type
83  *
84  * EMPTY Constructor for BPatch_type.  
85  * 
86  */
87
88 BPatch_type::BPatch_type(Type *typ_): ID(typ_->getID()), typ(typ_),
89     refCount(1)
90 {
91         // if a derived type, make sure the upPtr is set for the base type.
92         // if it is not set, create a new BPatch_type for the upPtr
93
94         derivedType* derived = dynamic_cast<derivedType*>(typ_);
95         if (derived) 
96         {
97                 Type* base = derived->getConstituentType();
98
99                 assert(base);
100                 BPatch_type *bpt = NULL;
101
102                 if (!base->getAnnotation(bpt, TypeUpPtrAnno))
103                 {
104                         //fprintf(stderr, "%s[%d]:  failed to get up ptr here\n", FILE__, __LINE__);
105
106                         BPatch_type* dyninstType = new BPatch_type(base);
107                         // We might consider registering this new type in BPatch.
108                         // For now, just silence the warning:
109                         (void) dyninstType;
110                 }
111                 else
112                 {
113                         assert (bpt);
114                 }
115         }
116
117         assert(typ_);
118         typ_->addAnnotation(this, TypeUpPtrAnno);
119
120         type_ = convertToBPatchdataClass(typ_->getDataClass());
121         type_map[typ] = this;
122 }
123
124 BPatch_type::BPatch_type(const char *_name, int _ID, BPatch_dataClass _type) :
125    ID(_ID), type_(_type), typ(NULL), refCount(1)
126 {
127         if (_name != NULL)
128                 typ = new Type(_name, ID, convertToSymtabType(_type));
129         else
130                 typ = new Type("", ID, convertToSymtabType(_type));
131         assert(typ);
132
133         typ->addAnnotation(this, TypeUpPtrAnno);
134
135         type_map[typ] = this;
136 }
137
138 BPatch_type *BPatch_type::findOrCreateType(Dyninst::SymtabAPI::Type *type)  
139 {
140    std::map<Dyninst::SymtabAPI::Type*, BPatch_type *>::iterator elem = type_map.find(type);
141    if (elem != type_map.end()) {
142       return (*elem).second;
143    }
144    
145    BPatch_type *bptype = new BPatch_type(type);
146    assert(bptype);
147    return bptype;
148 }
149
150 /* BPatch_type destructor
151  * Basic destructor for proper memory management.
152  */
153 BPatch_type::~BPatch_type()
154 {
155 }
156
157 bool BPatch_type::operator==(const BPatch_type &otype) const 
158 {
159    return (ID==otype.ID && type_ == otype.type_ && typ == otype.typ);
160 }
161
162 unsigned int BPatch_type::getSizeInt()
163 {
164   return typ->getSize();
165 }
166
167 const char *BPatch_type::getName() const 
168 {
169    return typ->getName().c_str(); 
170 }
171
172 Type *BPatch_type::getSymtabType() const 
173 {
174     return typ;
175 }    
176
177 const char *BPatch_type::getLow() const 
178 {
179     rangedInterface *rangetype = dynamic_cast<rangedInterface *>(typ);
180
181     if (!rangetype)
182         return NULL;
183
184     return (const char *)(long)rangetype->getLow(); 
185 }
186
187 bool BPatch_type::isCompatibleInt(BPatch_type *otype) 
188 {
189     return typ->isCompatible(otype->typ);
190 }
191
192 BPatch_type *BPatch_type::getConstituentType() const 
193 {
194         derivedInterface *derivedType = dynamic_cast<derivedInterface *>(typ);
195
196         if (!derivedType)
197                 return NULL;
198
199         Type *ctype = derivedType->getConstituentType();
200         assert(ctype);
201
202         BPatch_type *bpt = NULL;
203
204         if (!ctype->getAnnotation(bpt, TypeUpPtrAnno))
205         {
206                 fprintf(stderr, "%s[%d]:  failed to get up ptr here\n", FILE__, __LINE__);
207         }
208         else
209         {
210                 assert(bpt);
211         }
212
213                 
214         return bpt;
215 }
216
217 BPatch_Vector<BPatch_field *> *BPatch_type::getComponents() const{
218     fieldListInterface *fieldlisttype = dynamic_cast<fieldListInterface *>(typ);
219     typeEnum *enumtype = dynamic_cast<typeEnum *>(typ);
220     derivedType *derivedtype = dynamic_cast<derivedType *>(typ);
221     if(!fieldlisttype && !enumtype && !derivedtype)
222         return NULL;    
223     BPatch_Vector<BPatch_field *> *components = new BPatch_Vector<BPatch_field *>();
224     if(fieldlisttype) {
225         vector<Field *> *comps = fieldlisttype->getComponents();
226         if(!comps){
227          free(components);
228          return NULL;
229         }    
230       for(unsigned i = 0 ; i< comps->size(); i++)
231          components->push_back(new BPatch_field((*comps)[i]));
232         return components;    
233     }
234
235     if (enumtype) 
236         {
237         vector<pair<string, int> > &constants = enumtype->getConstants();
238             for (unsigned i = 0; i < constants.size(); i++)
239                 {
240                 Field *fld = new Field(constants[i].first.c_str(), NULL);
241                 components->push_back(new BPatch_field(fld, BPatch_dataScalar, constants[i].second, 0));
242             }
243             return components;    
244     }
245
246     if(derivedtype)
247         return getConstituentType()->getComponents();
248     return NULL;
249 }
250
251 BPatch_Vector<BPatch_cblock *> *BPatch_type::getCblocks() const 
252 {
253         typeCommon *commontype = dynamic_cast<typeCommon *>(typ);
254
255         if (!commontype)
256                 return NULL;
257
258         std::vector<CBlock *> *cblocks = commontype->getCblocks();
259
260         if (!cblocks)
261                 return NULL;
262
263         BPatch_Vector<BPatch_cblock *> *ret = new BPatch_Vector<BPatch_cblock *>();
264
265         for (unsigned i = 0; i < cblocks->size(); i++)
266         {
267                 BPatch_cblock *bpcb = NULL;
268                 CBlock *cb = (*cblocks)[i];
269                 assert(cb);
270                 if (!cb->getAnnotation(bpcb, CommonBlockUpPtrAnno))
271                 {
272                         fprintf(stderr, "%s[%d]:  WARN:  No Common Block UpPtr\n", FILE__, __LINE__);
273                 }
274                 else
275                 {
276                         assert(bpcb);
277                         ret->push_back(bpcb);
278                 }
279         }
280         return ret;     
281 }
282
283 const char *BPatch_type::getHigh() const {
284     rangedInterface *rangetype = dynamic_cast<rangedInterface *>(typ);
285     if(!rangetype)
286         return NULL;
287     return (const char *)(long)rangetype->getHigh(); 
288 }
289
290 BPatch_dataClass BPatch_type::convertToBPatchdataClass(dataClass type) {
291     switch(type){
292       case dataEnum:
293           return BPatch_dataEnumerated;
294       case dataPointer:
295           return BPatch_dataPointer;
296       case dataFunction:
297           return BPatch_dataMethod;
298       case dataSubrange:
299           return BPatchSymTypeRange;
300       case dataArray:
301           return BPatch_dataArray;
302       case dataStructure:
303           return BPatch_dataStructure;
304       case dataUnion:
305           return BPatch_dataUnion;
306       case dataCommon:
307           return BPatch_dataCommon;
308       case dataScalar:
309           return BPatch_dataScalar;
310       case dataTypedef:
311           return BPatch_dataTypeDefine;
312       case dataReference:
313           return BPatch_dataReference;
314       case dataUnknownType:
315           return BPatch_dataUnknownType;
316       case dataNullType:
317           return BPatch_dataNullType;
318       case dataTypeClass:
319           return BPatch_dataTypeClass;
320       default:
321           return BPatch_dataNullType;
322     }  
323 }
324
325 Dyninst::SymtabAPI::dataClass BPatch_type::convertToSymtabType(BPatch_dataClass type){
326     switch(type){
327       case BPatch_dataScalar:
328           return dataScalar;
329       case BPatch_dataEnumerated:
330           return dataEnum;
331       case BPatch_dataTypeClass:
332           return dataTypeClass;
333       case BPatch_dataStructure:
334           return dataStructure;
335       case BPatch_dataUnion:
336           return dataUnion;
337       case BPatch_dataArray:
338           return dataArray;
339       case BPatch_dataPointer:
340           return dataPointer;
341       case BPatch_dataReferance:
342           return dataReference;
343       case BPatch_dataFunction:
344           return dataFunction;
345       case BPatch_dataReference:        // NOT sure-- TODO
346           return dataNullType;
347       case BPatch_dataUnknownType:
348           return dataUnknownType;
349       case BPatchSymTypeRange:
350           return dataSubrange;
351       case BPatch_dataMethod:
352           return dataFunction;
353       case BPatch_dataCommon:
354           return dataCommon;
355       case BPatch_dataTypeDefine:
356           return dataTypedef;
357       case BPatch_dataTypeAttrib:       //Never used
358       case BPatch_dataTypeNumber:
359       case BPatch_dataPrimitive:
360       case BPatch_dataNullType:
361       default:
362           return dataNullType;
363     }     
364 }
365
366 #ifdef IBM_BPATCH_COMPAT
367 char *BPatch_type::getName(char *buffer, int max) const
368 {
369   const char *name = typ->getName().c_str();
370   if (!name) {
371      strncpy(buffer, "bad type name", (max > strlen("bad_type_name")) ?
372              (strlen("bad_type_name") +1) : max);
373      char msg[256];
374      sprintf(msg, "%s[%d]: bad type name!", __FILE__, __LINE__);
375      BPatch_reportError(BPatchWarning, 112, msg);
376      return buffer;
377   }
378
379   if (max > strlen(name)) {
380     strcpy (buffer, name);
381     return buffer;
382   } else {
383     strncpy (buffer, name, max-1)[max-1] = '\0';
384   }
385    return NULL;
386 }
387 #endif
388
389 BPatch_field::BPatch_field(Dyninst::SymtabAPI::Field *fld_, BPatch_dataClass typeDescriptor, int value_, int size_) :
390     typeDes(typeDescriptor), value(value_), size(size_), fld(fld_)
391 {
392         if (!fld_->addAnnotation(this, FieldUpPtrAnno))
393         {
394                 fprintf(stderr, "%s[%d]: failed to add field list anno here\n", FILE__, __LINE__);
395         }
396 }
397
398 void BPatch_field::copy(BPatch_field &oField) 
399 {
400    fld = oField.fld;
401    typeDes = oField.typeDes;
402    size = oField.size;
403    value = oField.value;
404 }
405
406 BPatch_field::BPatch_field(BPatch_field &oField) : BPatch_eventLock()
407 {
408    __LOCK;
409    copy(oField);
410    __UNLOCK;
411 }
412
413 BPatch_field &BPatch_field::operator_equals(BPatch_field &oField) 
414 {
415    copy(oField);
416    return *this;
417 }
418
419 void BPatch_field::BPatch_field_dtor() 
420 {
421 }
422
423 const char *BPatch_field::getNameInt()
424 {
425   return fld->getName().c_str();
426 }
427
428 BPatch_type *BPatch_field::getTypeInt()
429 {
430         BPatch_type *bpt= NULL;
431         assert(fld);
432         Type *t = fld->getType();
433         assert(t);
434
435         if (!t->getAnnotation(bpt, TypeUpPtrAnno))
436         {
437                 //fprintf(stderr, "%s[%d]:  failed to get up ptr here\n", FILE__, __LINE__);
438                 return new BPatch_type(fld->getType());
439         }
440
441         assert(bpt);
442         return bpt;
443 }
444
445 int BPatch_field::getValueInt()
446 {
447   return value;
448 }
449
450 BPatch_visibility BPatch_field::getVisibilityInt()
451 {
452   return (BPatch_visibility)fld->getVisibility();
453 }
454
455 BPatch_dataClass BPatch_field::getTypeDescInt()
456 {
457   return typeDes;
458 }
459
460 int BPatch_field::getSizeInt()
461 {
462   return size;
463 }
464
465 int BPatch_field::getOffsetInt()
466 {
467   return fld->getOffset();
468 }
469
470 void BPatch_field::fixupUnknown(BPatch_module *module) {
471    fld->fixupUnknown(module->lowlevel_mod()->pmod()->mod());
472 }
473
474 BPatch_localVar::BPatch_localVar(localVar *lVar_) : lVar(lVar_)
475 {
476         assert(lVar);
477
478         Type *t = lVar->getType();
479         assert(t);
480         
481         if (!t->getAnnotation(type, TypeUpPtrAnno))
482         {
483                 //fprintf(stderr, "%s[%d]:  failed to get up ptr here\n", FILE__, __LINE__);
484                 type = new BPatch_type(t);
485         }
486         else
487         {
488                 assert(type);
489         }
490
491         type->incrRefCount();
492
493     vector<Dyninst::SymtabAPI::VariableLocation> &locs = lVar_->getLocationLists();
494
495     if (!locs.size())
496        storageClass = BPatch_storageFrameOffset;
497     else
498        storageClass = convertToBPatchStorage(& locs[0]);
499
500
501
502         if (!lVar->addAnnotation(this, LocalVarUpPtrAnno))
503         {
504                 fprintf(stderr, "%s[%d]:  failed to add annotation here\n", FILE__, __LINE__);
505         }
506
507 }
508
509 BPatch_storageClass BPatch_localVar::convertToBPatchStorage(Dyninst::SymtabAPI::VariableLocation *loc)
510 {
511         Dyninst::SymtabAPI::storageClass stClass = loc->stClass;
512         storageRefClass refClass = loc->refClass;
513         if((stClass == storageAddr) && (refClass == storageNoRef))
514                 return BPatch_storageAddr;
515         else if((stClass == storageAddr) && (refClass == storageRef))
516                 return BPatch_storageAddrRef;
517         else if((stClass == storageReg) && (refClass == storageNoRef))
518                 return BPatch_storageReg;
519         else if((stClass == storageReg) && (refClass == storageRef))
520        return BPatch_storageRegRef;
521    else if((stClass == storageRegOffset) && (loc->reg == -1))
522        return BPatch_storageFrameOffset;
523    else if((stClass == storageRegOffset))
524         return BPatch_storageRegOffset;
525    else {
526       assert(0);
527       return (BPatch_storageClass) -1;
528    }
529 }
530
531 localVar *BPatch_localVar::getSymtabVar(){
532     return lVar;
533 }
534                                       
535 const char *BPatch_localVar::getName() { 
536     return lVar->getName().c_str();
537 }
538
539 BPatch_type *BPatch_localVar::getType() { 
540     return type; 
541 }
542
543 int BPatch_localVar::getLineNum() { 
544     return lVar->getLineNum(); 
545 }
546
547 //TODO?? - get the first frame offset
548 long BPatch_localVar::getFrameOffset() {
549
550    vector<Dyninst::SymtabAPI::VariableLocation> &locs = lVar->getLocationLists();
551
552    if (locs.size())
553       return -1;
554
555    return locs[0].frameOffset;
556 }
557
558 int BPatch_localVar::getRegister() {
559
560     vector<Dyninst::SymtabAPI::VariableLocation> &locs = lVar->getLocationLists();
561
562     if (!locs.size())
563         return -1;
564
565     return locs[0].reg;
566 }
567
568 BPatch_storageClass BPatch_localVar::getStorageClass() {
569     return storageClass; 
570 }
571
572 /*
573  * BPatch_localVar destructor
574  *
575  */
576 BPatch_localVar::~BPatch_localVar()
577 {
578     //XXX jdd 5/25/99 More to do later
579     if(type)
580         type->decrRefCount();
581 }
582
583 void BPatch_localVar::fixupUnknown(BPatch_module *module) {
584    if (type->getDataClass() == BPatch_dataUnknownType) {
585       BPatch_type *otype = type;
586       type = module->getModuleTypes()->findType(type->getID());
587       type->incrRefCount();
588       otype->decrRefCount();
589    }
590 }
591
592 /**************************************************************************
593  * BPatch_cblock
594  *************************************************************************/
595
596 BPatch_cblock::BPatch_cblock(CBlock *cBlk_) : cBlk(cBlk_) {
597 //TODO construct components here
598 }
599
600 void BPatch_cblock::fixupUnknowns(BPatch_module *module) {
601    cBlk->fixupUnknowns(module->lowlevel_mod()->pmod()->mod());
602 }
603
604 BPatch_Vector<BPatch_field *> *BPatch_cblock::getComponentsInt()
605 {
606         BPatch_Vector<BPatch_field *> *components = new BPatch_Vector<BPatch_field *>;
607         std::vector<Field *> *vars = cBlk->getComponents();
608
609         if (!vars)
610                 return NULL;
611
612         for (unsigned i=0; i<vars->size();i++)
613         {
614                 Field *f = (*vars)[i];
615                 assert(f);
616                 BPatch_field *bpf = NULL;
617
618                 if (!f->getAnnotation(bpf, FieldUpPtrAnno))
619                 {
620                         fprintf(stderr, "%s[%d]:  no up ptr anno here\n", FILE__, __LINE__);
621                 }
622                 else
623                 {
624                         assert (bpf);
625                         components->push_back(bpf);
626                 }
627         }
628
629         return components;
630 }
631
632 BPatch_Vector<BPatch_function *> *BPatch_cblock::getFunctionsInt()
633 {
634   std::vector<Symbol *> *funcs = cBlk->getFunctions();
635   if(!funcs)
636       return NULL;   
637   assert(0);
638 //Return BPatch_functions corresponding to Symbols in SymtabAPI
639 //Lookup again from BPatch::bpatch with the name. Then return the BPatch_functions
640 //TODO
641   return NULL;
642 }
643