windows build fixes and some more work on symtab serialization
[dyninst.git] / dyninstAPI / src / BPatch_type.C
1 /* 
2  *  
3  * Copyright (c) 1996-2004 Barton P. Miller
4  * 
5  * We provide the Paradyn Parallel Performance Tools (below
6  * described as "Paradyn") on an AS IS basis, and do not warrant its
7  * validity or performance.  We reserve the right to update, modify,
8  * or discontinue this software at any time.  We shall have no
9  * obligation to supply such updates or modifications or any other
10  * form of support to you.
11  * 
12  * This license is for research uses.  For such uses, there is no
13  * charge. We define "research use" to mean you may freely use it
14  * inside your organization for whatever purposes you see fit. But you
15  * may not re-distribute Paradyn or parts of Paradyn, in any form
16  * source or binary (including derivatives), electronic or otherwise,
17  * to any other organization or entity without our permission.
18  * 
19  * (for other uses, please contact us at paradyn@cs.wisc.edu)
20  * 
21  * All warranties, including without limitation, any warranty of
22  * merchantability or fitness for a particular purpose, are hereby
23  * excluded.
24  * 
25  * By your use of Paradyn, you understand and agree that we (or any
26  * other person or entity with proprietary rights in Paradyn) are
27  * under no obligation to provide either maintenance services,
28  * update services, notices of latent defects, or correction of
29  * defects for Paradyn.
30  * 
31  * Even if advised of the possibility of such damages, under no
32  * circumstances shall we (or any other person or entity with
33  * proprietary rights in the software licensed hereunder) be liable
34  * to you or any third party for direct, indirect, or consequential
35  * damages of any character regardless of type of action, including,
36  * without limitation, loss of profits, loss of use, loss of good
37  * will, or computer failure or malfunction.  You agree to indemnify
38  * us (and any other person or entity with proprietary rights in the
39  * software licensed hereunder) for any and all liability it may
40  * incur to third parties resulting from your use of Paradyn.
41  */
42
43 #include <stdio.h>
44
45 #define BPATCH_FILE
46
47
48 #include "util.h"
49 #include "BPatch_Vector.h"
50 //#include "BPatch_typePrivate.h"
51 #include "BPatch_collections.h"
52 #include "debug.h"
53 #include "BPatch_function.h"
54 #include "BPatch.h"
55 #include "mapped_module.h"
56
57 #ifdef i386_unknown_nt4_0
58 #define snprintf _snprintf
59 #endif
60
61 using namespace Dyninst;
62 using namespace Dyninst::SymtabAPI;
63
64 //static int findIntrensicType(const char *name);
65
66 // This is the ID that is decremented for each type a user defines. It is
67 // Global so that every type that the user defines has a unique ID.
68 // jdd 7/29/99
69 //int BPatch_type::USER_BPATCH_TYPE_ID = -1000;
70
71
72 std::map<Dyninst::SymtabAPI::Type*, BPatch_type *> BPatch_type::type_map;
73
74 /* These are the wrappers for constructing a type.  Since we can create
75    types six ways to Sunday, let's do them all in one centralized place. */
76 BPatch_type *BPatch_type::createFake(const char *_name) {
77    // Creating a fake type without a name is just silly
78    assert(_name != NULL);
79
80    BPatch_type *t = new BPatch_type(_name);
81    t->type_ = BPatch_dataNullType;
82
83    return t;
84 }
85
86 /*
87  * BPatch_type::BPatch_type
88  *
89  * EMPTY Constructor for BPatch_type.  
90  * 
91  */
92
93 BPatch_type::BPatch_type(Type *typ_): ID(typ_->getID()), typ(typ_),
94     refCount(1)
95 {
96   // if a derived type, make sure the upPtr is set for the base type.
97   // if it is not set, create a new BPatch_type for the upPtr
98   derivedType* derived = dynamic_cast<derivedType*>(typ_);
99   if (derived) {
100     Type* base = derived->getConstituentType();
101     if (!base->getUpPtr()) {
102       BPatch_type* dyninstType = new BPatch_type(base);
103       // We might consider registering this new type in BPatch.
104       // For now, just silence the warning:
105       (void) dyninstType;
106     }
107   }
108
109     typ_->setUpPtr(this);
110     type_ = convertToBPatchdataClass(typ_->getDataClass());
111     type_map[typ] = this;
112 }
113
114 BPatch_type::BPatch_type(const char *_name, int _ID, BPatch_dataClass _type) :
115    ID(_ID), type_(_type), typ(NULL), refCount(1)
116 {
117   if (_name != NULL)
118      typ = new Type(_name, ID, convertToSymtabType(_type));
119   else
120      typ = new Type("", ID, convertToSymtabType(_type));
121   assert(typ);
122   typ->setUpPtr(this);
123   type_map[typ] = this;
124 }
125
126 BPatch_type *BPatch_type::findOrCreateType(Dyninst::SymtabAPI::Type *type)  
127 {
128    std::map<Dyninst::SymtabAPI::Type*, BPatch_type *>::iterator elem = type_map.find(type);
129    if (elem != type_map.end()) {
130       return (*elem).second;
131    }
132    
133    BPatch_type *bptype = new BPatch_type(type);
134    assert(bptype);
135    return bptype;
136 }
137
138 /* BPatch_type destructor
139  * Basic destructor for proper memory management.
140  */
141 BPatch_type::~BPatch_type()
142 {
143 }
144
145 bool BPatch_type::operator==(const BPatch_type &otype) const 
146 {
147    return (ID==otype.ID && type_ == otype.type_ && typ == otype.typ);
148 }
149
150 unsigned int BPatch_type::getSizeInt()
151 {
152   return typ->getSize();
153 }
154
155 const char *BPatch_type::getName() const { 
156    return typ->getName().c_str(); 
157 }
158
159 Type *BPatch_type::getSymtabType() const {
160     return typ;
161 }    
162
163 const char *BPatch_type::getLow() const {
164     rangedInterface *rangetype = dynamic_cast<rangedInterface *>(typ);
165     if(!rangetype)
166         return NULL;
167     return (const char *)(long)rangetype->getLow(); 
168 }
169
170 bool BPatch_type::isCompatibleInt(BPatch_type *otype) 
171 {
172     return typ->isCompatible(otype->typ);
173 }
174
175 BPatch_type *BPatch_type::getConstituentType() const {
176     derivedInterface *derivedType = dynamic_cast<derivedInterface *>(typ);
177     if(!derivedType)
178         return NULL;
179     return (BPatch_type *)derivedType->getConstituentType()->getUpPtr();
180 }
181
182 BPatch_Vector<BPatch_field *> *BPatch_type::getComponents() const{
183     fieldListInterface *fieldlisttype = dynamic_cast<fieldListInterface *>(typ);
184     typeEnum *enumtype = dynamic_cast<typeEnum *>(typ);
185     derivedType *derivedtype = dynamic_cast<derivedType *>(typ);
186     if(!fieldlisttype && !enumtype && !derivedtype)
187         return NULL;    
188     BPatch_Vector<BPatch_field *> *components = new BPatch_Vector<BPatch_field *>();
189     if(fieldlisttype) {
190         vector<Field *> *comps = fieldlisttype->getComponents();
191         if(!comps){
192          free(components);
193          return NULL;
194         }    
195       for(unsigned i = 0 ; i< comps->size(); i++)
196          components->push_back(new BPatch_field((*comps)[i]));
197         return components;    
198     }
199     if(enumtype) {
200         vector<pair<string, int> *> constants = enumtype->getConstants();
201             for(unsigned i = 0; i < constants.size(); i++){
202                 Field *fld = new Field(constants[i]->first.c_str(), NULL);
203                 components->push_back(new BPatch_field(fld, BPatch_dataScalar, constants[i]->second, 0));
204             }
205             return components;    
206     }
207     if(derivedtype)
208         return getConstituentType()->getComponents();
209     return NULL;
210 }
211
212 BPatch_Vector<BPatch_cblock *> *BPatch_type::getCblocks() const {
213     typeCommon *commontype = dynamic_cast<typeCommon *>(typ);
214     if(!commontype)
215         return NULL;
216         
217     std::vector<CBlock *> *cblocks = commontype->getCblocks();
218     if(!cblocks)
219         return NULL;
220     BPatch_Vector<BPatch_cblock *> *ret = new BPatch_Vector<BPatch_cblock *>();
221     for(unsigned i = 0; i < cblocks->size(); i++)
222         ret->push_back((BPatch_cblock *)(*cblocks)[i]->getUpPtr());
223     return ret; 
224 }
225
226 const char *BPatch_type::getHigh() const {
227     rangedInterface *rangetype = dynamic_cast<rangedInterface *>(typ);
228     if(!rangetype)
229         return NULL;
230     return (const char *)(long)rangetype->getHigh(); 
231 }
232
233 BPatch_dataClass BPatch_type::convertToBPatchdataClass(dataClass type) {
234     switch(type){
235       case dataEnum:
236           return BPatch_dataEnumerated;
237       case dataPointer:
238           return BPatch_dataPointer;
239       case dataFunction:
240           return BPatch_dataMethod;
241       case dataSubrange:
242           return BPatchSymTypeRange;
243       case dataArray:
244           return BPatch_dataArray;
245       case dataStructure:
246           return BPatch_dataStructure;
247       case dataUnion:
248           return BPatch_dataUnion;
249       case dataCommon:
250           return BPatch_dataCommon;
251       case dataScalar:
252           return BPatch_dataScalar;
253       case dataTypedef:
254           return BPatch_dataTypeDefine;
255       case dataReference:
256           return BPatch_dataReference;
257       case dataUnknownType:
258           return BPatch_dataUnknownType;
259       case dataNullType:
260           return BPatch_dataNullType;
261       case dataTypeClass:
262           return BPatch_dataTypeClass;
263       default:
264           return BPatch_dataNullType;
265     }  
266 }
267
268 Dyninst::SymtabAPI::dataClass BPatch_type::convertToSymtabType(BPatch_dataClass type){
269     switch(type){
270       case BPatch_dataScalar:
271           return dataScalar;
272       case BPatch_dataEnumerated:
273           return dataEnum;
274       case BPatch_dataTypeClass:
275           return dataTypeClass;
276       case BPatch_dataStructure:
277           return dataStructure;
278       case BPatch_dataUnion:
279           return dataUnion;
280       case BPatch_dataArray:
281           return dataArray;
282       case BPatch_dataPointer:
283           return dataPointer;
284       case BPatch_dataReferance:
285           return dataReference;
286       case BPatch_dataFunction:
287           return dataFunction;
288       case BPatch_dataReference:        // NOT sure-- TODO
289           return dataNullType;
290       case BPatch_dataUnknownType:
291           return dataUnknownType;
292       case BPatchSymTypeRange:
293           return dataSubrange;
294       case BPatch_dataMethod:
295           return dataFunction;
296       case BPatch_dataCommon:
297           return dataCommon;
298       case BPatch_dataTypeDefine:
299           return dataTypedef;
300       case BPatch_dataTypeAttrib:       //Never used
301       case BPatch_dataTypeNumber:
302       case BPatch_dataPrimitive:
303       case BPatch_dataNullType:
304       default:
305           return dataNullType;
306     }     
307 }
308
309 #ifdef IBM_BPATCH_COMPAT
310 char *BPatch_type::getName(char *buffer, int max) const
311 {
312   const char *name = typ->getName().c_str();
313   if (!name) {
314      strncpy(buffer, "bad type name", (max > strlen("bad_type_name")) ?
315              (strlen("bad_type_name") +1) : max);
316      char msg[256];
317      sprintf(msg, "%s[%d]: bad type name!", __FILE__, __LINE__);
318      BPatch_reportError(BPatchWarning, 112, msg);
319      return buffer;
320   }
321
322   if (max > strlen(name)) {
323     strcpy (buffer, name);
324     return buffer;
325   } else {
326     strncpy (buffer, name, max-1)[max-1] = '\0';
327   }
328    return NULL;
329 }
330 #endif
331
332 BPatch_field::BPatch_field(Dyninst::SymtabAPI::Field *fld_, BPatch_dataClass typeDescriptor, int value_, int size_) :
333     typeDes(typeDescriptor), value(value_), size(size_), fld(fld_)
334 {
335     fld_->setUpPtr(this);
336 }
337
338 void BPatch_field::copy(BPatch_field &oField) 
339 {
340    fld = oField.fld;
341    typeDes = oField.typeDes;
342    size = oField.size;
343    value = oField.value;
344 }
345
346 BPatch_field::BPatch_field(BPatch_field &oField) : BPatch_eventLock()
347 {
348    __LOCK;
349    copy(oField);
350    __UNLOCK;
351 }
352
353 BPatch_field &BPatch_field::operator_equals(BPatch_field &oField) 
354 {
355    copy(oField);
356    return *this;
357 }
358
359 void BPatch_field::BPatch_field_dtor() 
360 {
361 }
362
363 const char *BPatch_field::getNameInt()
364 {
365   return fld->getName().c_str();
366 }
367
368 BPatch_type *BPatch_field::getTypeInt()
369 {
370   if(!fld->getType()->getUpPtr())
371       return new BPatch_type (fld->getType());
372   return (BPatch_type *)fld->getType()->getUpPtr();
373 }
374
375 int BPatch_field::getValueInt()
376 {
377   return value;
378 }
379
380 BPatch_visibility BPatch_field::getVisibilityInt()
381 {
382   return (BPatch_visibility)fld->getVisibility();
383 }
384
385 BPatch_dataClass BPatch_field::getTypeDescInt()
386 {
387   return typeDes;
388 }
389
390 int BPatch_field::getSizeInt()
391 {
392   return size;
393 }
394
395 int BPatch_field::getOffsetInt()
396 {
397   return fld->getOffset();
398 }
399
400 void BPatch_field::fixupUnknown(BPatch_module *module) {
401    fld->fixupUnknown(module->lowlevel_mod()->pmod()->mod());
402 }
403
404 BPatch_localVar::BPatch_localVar(localVar *lVar_) : lVar(lVar_)
405 {
406     type = (BPatch_type *)lVar->getType()->getUpPtr();
407     if (!type)
408         type = new BPatch_type(lVar->getType());
409     type->incrRefCount();
410     vector<Dyninst::SymtabAPI::VariableLocation> *locs = lVar_->getLocationLists();
411     if (!locs)
412        storageClass = BPatch_storageFrameOffset;
413     else
414        storageClass = convertToBPatchStorage(& (*locs)[0]);
415     lVar->setUpPtr(this);
416 }
417
418 BPatch_storageClass BPatch_localVar::convertToBPatchStorage(Dyninst::SymtabAPI::VariableLocation *loc)
419 {
420    Dyninst::SymtabAPI::storageClass stClass = loc->stClass;
421    storageRefClass refClass = loc->refClass;
422    if((stClass == storageAddr) && (refClass == storageNoRef))
423        return BPatch_storageAddr;
424    else if((stClass == storageAddr) && (refClass == storageRef))
425        return BPatch_storageAddrRef;
426    else if((stClass == storageReg) && (refClass == storageNoRef))
427        return BPatch_storageReg;
428    else if((stClass == storageReg) && (refClass == storageRef))
429        return BPatch_storageRegRef;
430    else if((stClass == storageRegOffset) && (loc->reg == -1))
431        return BPatch_storageFrameOffset;
432    else if((stClass == storageRegOffset))
433         return BPatch_storageRegOffset;
434    else {
435       assert(0);
436       return (BPatch_storageClass) -1;
437    }
438 }
439
440 localVar *BPatch_localVar::getSymtabVar(){
441     return lVar;
442 }
443                                       
444 const char *BPatch_localVar::getName() { 
445     return lVar->getName().c_str();
446 }
447
448 BPatch_type *BPatch_localVar::getType() { 
449     return type; 
450 }
451
452 int BPatch_localVar::getLineNum() { 
453     return lVar->getLineNum(); 
454 }
455
456 //TODO?? - get the first frame offset
457 long BPatch_localVar::getFrameOffset() { 
458    vector<Dyninst::SymtabAPI::VariableLocation> *locs = lVar->getLocationLists();
459    if(!locs)
460       return -1;
461    return (*(locs))[0].frameOffset;
462 }
463
464 int BPatch_localVar::getRegister() { 
465     vector<Dyninst::SymtabAPI::VariableLocation> *locs = lVar->getLocationLists();
466     if(!locs)
467         return -1;
468     return (*(locs))[0].reg;
469 }
470
471 BPatch_storageClass BPatch_localVar::getStorageClass() {
472     return storageClass; 
473 }
474
475 /*
476  * BPatch_localVar destructor
477  *
478  */
479 BPatch_localVar::~BPatch_localVar()
480 {
481     //XXX jdd 5/25/99 More to do later
482     if(type)
483         type->decrRefCount();
484 }
485
486 void BPatch_localVar::fixupUnknown(BPatch_module *module) {
487    if (type->getDataClass() == BPatch_dataUnknownType) {
488       BPatch_type *otype = type;
489       type = module->getModuleTypes()->findType(type->getID());
490       type->incrRefCount();
491       otype->decrRefCount();
492    }
493 }
494
495 /**************************************************************************
496  * BPatch_cblock
497  *************************************************************************/
498
499 BPatch_cblock::BPatch_cblock(CBlock *cBlk_) : cBlk(cBlk_) {
500 //TODO construct components here
501 }
502
503 void BPatch_cblock::fixupUnknowns(BPatch_module *module) {
504    cBlk->fixupUnknowns(module->lowlevel_mod()->pmod()->mod());
505 }
506
507 BPatch_Vector<BPatch_field *> *BPatch_cblock::getComponentsInt()
508 {
509   BPatch_Vector<BPatch_field *> *components = new BPatch_Vector<BPatch_field *>;
510   std::vector<Field *> *vars = cBlk->getComponents();
511   if(!vars)
512      return NULL;
513   for(unsigned i=0; i<vars->size();i++)
514       components->push_back((BPatch_field *)(*vars)[i]->getUpPtr());
515   return components;
516 }
517
518 BPatch_Vector<BPatch_function *> *BPatch_cblock::getFunctionsInt()
519 {
520   std::vector<Symbol *> *funcs = cBlk->getFunctions();
521   if(!funcs)
522       return NULL;   
523   assert(0);
524 //Return BPatch_functions corresponding to Symbols in SymtabAPI
525 //Lookup again from BPatch::bpatch with the name. Then return the BPatch_functions
526 //TODO
527   return NULL;
528 }
529