Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / BPatch_collections.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 #include "util.h"
37 #include "BPatch_collections.h"
38 #include "BPatch_Vector.h"
39 #include "BPatch.h"
40
41 // Dwarf stuff
42 #include "mapped_object.h"
43 #include "mapped_module.h"
44
45 //#include "BPatch_type.h"
46
47
48 /**************************************************************************
49  * BPatch_localVarCollection
50  *************************************************************************/
51
52 /*
53  * BPatch_localVarCollection::~BPatch_localVarCollection
54  *
55  * Destructor for BPatch_localVarCollection.  Deletes all type objects that
56  * have been inserted into the collection.
57  */
58 BPatch_localVarCollection::~BPatch_localVarCollection()
59 {
60    dictionary_hash_iter<std::string, BPatch_localVar *> li(localVariablesByName);
61        
62    std::string           name;
63    BPatch_localVar      *localVar;
64
65    // delete localVariablesByName collection
66    while (li.next(name, localVar))
67         delete localVar;
68 }
69
70 /*
71  * BPatch_localVarCollection::addLocalVar()
72  * This function adds local variables to the set of local variables
73  * for function.
74  */
75
76 void BPatch_localVarCollection::addLocalVar(BPatch_localVar * var){
77
78   localVariablesByName[var->getName()]= var;
79
80 }
81
82 /*
83  * BPatch_localVarCollection::findLocalVar()
84  * This function finds a local variable by name and returns a pointer to
85  * it or NULL if the local variable does not exist in the set of function
86  * local variables.
87  */
88 BPatch_localVar * BPatch_localVarCollection::findLocalVar(const char *name){
89
90         if (localVariablesByName.defines(name) )
91                 return localVariablesByName[name];
92         else
93                 return (BPatch_localVar *)NULL;
94 }
95
96 /*
97  * BPatch_localVarCollection::getAllVars()
98  * this function returns all the local variables in the collection.
99  */
100 BPatch_Vector<BPatch_localVar *> *BPatch_localVarCollection::getAllVars() {
101     dictionary_hash_iter<std::string, BPatch_localVar *> li(localVariablesByName);
102
103     std::string name;
104     BPatch_localVar *localVar;
105
106     BPatch_Vector<BPatch_localVar *> *localVarVec = new BPatch_Vector<BPatch_localVar *>;
107
108     // get all local vars in the localVariablesByName collection
109     while (li.next(name, localVar))
110         localVarVec->push_back(localVar);
111
112     return localVarVec;
113 }
114   
115 // Could be somewhere else... for DWARF-work.
116 dictionary_hash<std::string, BPatch_typeCollection * > BPatch_typeCollection::fileToTypesMap(::Dyninst::stringhash);
117
118 /*
119  * Reference count
120  */
121
122 BPatch_typeCollection *BPatch_typeCollection::getGlobalTypeCollection() {
123     BPatch_typeCollection *tc = new BPatch_typeCollection();
124     tc->refcount++;
125     return tc;
126 }
127
128 BPatch_typeCollection *BPatch_typeCollection::getModTypeCollection(BPatch_module *bpmod) {
129     assert(bpmod);
130     mapped_object *moduleImage = bpmod->lowlevel_mod()->obj();
131     assert( moduleImage != NULL );
132 #if defined(USES_DWARF_DEBUG)
133     // TODO: can we use this on other platforms as well?    
134     if( fileToTypesMap.defines( moduleImage->fullName().c_str() ) ) {
135         BPatch_typeCollection *cachedTC = fileToTypesMap [ moduleImage->fullName().c_str() ];
136         cachedTC->refcount++;
137         return cachedTC;
138     }
139 #endif
140
141     BPatch_typeCollection *newTC = new BPatch_typeCollection();
142     fileToTypesMap[moduleImage->fullName().c_str()] = newTC;
143     newTC->refcount++;
144     return newTC;
145 }
146
147 void BPatch_typeCollection::freeTypeCollection(BPatch_typeCollection *tc) {
148     assert(tc);
149     tc->refcount--;
150     if (tc->refcount == 0) {
151         dictionary_hash_iter<std::string, BPatch_typeCollection *> iter(fileToTypesMap);
152         for (; iter; iter++) {
153             if (iter.currval() == tc) {
154                 fileToTypesMap.undef(iter.currkey());
155                 break;
156             }
157         }
158         delete tc;
159     }
160 }
161
162 /*
163  * BPatch_typeCollection::BPatch_typeCollection
164  *
165  * Constructor for BPatch_typeCollection.  Creates the two dictionaries
166  * for the type, by Name and ID.
167  */
168 BPatch_typeCollection::BPatch_typeCollection():
169     typesByName(::Dyninst::stringhash),
170     globalVarsByName(::Dyninst::stringhash),
171     typesByID(intHash),
172     refcount(0),
173     dwarfParsed_(false)
174 {
175   /* Initialize hash tables: typesByName, typesByID */
176 }
177
178 /*
179  * BPatch_typeCollection::~BPatch_typeCollection
180  *
181  * Destructor for BPatch_typeCollection.  Deletes all type objects that have
182  * been inserted into the collection.
183  */
184 BPatch_typeCollection::~BPatch_typeCollection()
185 {
186     // We sometimes directly delete (refcount == 1) or go through the
187     // decRefCount (which will delete when refcount == 0)
188     assert(refcount == 0 ||
189            refcount == 1);
190     // delete all of the types
191     // This doesn't seem to work - jkh 1/31/00
192 #if 0
193     dictionary_hash_iter<std::string, BPatch_type *> ti(typesByName);
194     dictionary_hash_iter<int, BPatch_type *> tid(typesByID);
195     dictionary_hash_iter<std::string, BPatch_type *> gi(globalVarsByName);
196     
197     std::string      gname; 
198     std::string name;
199     BPatch_type *type;
200     int         id;
201     while (tid.next(id, type))
202         delete type;
203     
204     
205     // Underlying types deleted already just need to get rid of pointers
206     while (ti.next(name, type))
207         type = NULL;
208     
209     // delete globalVarsByName collection
210     while (gi.next(name, type))
211         delete type;
212     
213     for (dictionary_hash_iter<int, BPatch_type *> it = typesByID.begin();
214          it != typesByID.end();
215          it ++) {
216         (*it)->decrRefCount();
217     }
218     for (dictionary_hash_iter<std::string, BPatch_type *> it2 = typesByName.begin();
219          it2 != typesByName.end();
220          it2 ++) {
221         (*it2)->decrRefCount();
222     }
223 #endif    
224 }
225
226 /*
227  * BPatch_typeCollection::findType
228  *
229  * Retrieve a pointer to a BPatch_type object representing the named type from
230  * the collection.  If no such type exists and no such type can be derived
231  * from existing types, then the function returns NULL.
232  *
233  * name         The name of the type to look up.
234  * id           The unique type ID of the type tp look up.
235  */
236 BPatch_type *BPatch_typeCollection::findType(const char *name)
237 {
238     if (typesByName.defines(name))
239         return typesByName[name];
240     else {
241        if (BPatch::bpatch && BPatch::bpatch->builtInTypes)
242           return BPatch::bpatch->builtInTypes->findBuiltInType(name);
243        else
244           return NULL;
245     }
246 }
247
248 BPatch_type *BPatch_typeCollection::findTypeLocal(const char *name)
249 {
250    if (typesByName.defines(name))
251       return typesByName[name];
252    else
253       return NULL;
254 }
255
256 BPatch_type *BPatch_typeCollection::findTypeLocal(const int &ID)
257 {
258    if (typesByID.defines(ID))
259       return typesByID[ID];
260    else
261       return NULL;
262 }
263
264
265 BPatch_type * BPatch_typeCollection::findOrCreateType( const int & ID ) {
266     if( typesByID.defines(ID) ) { return typesByID[ID]; }
267
268     BPatch_type * returnType = NULL;
269     if( BPatch::bpatch && BPatch::bpatch->builtInTypes ) {
270         returnType = BPatch::bpatch->builtInTypes->findBuiltInType(ID);
271     }
272
273     if( returnType == NULL ) {
274         /* Create a placeholder type. */
275         returnType = BPatch_type::createPlaceholder(ID);
276         assert( returnType != NULL );
277
278         /* Having created the type, add it. */
279         addType( returnType );
280     }
281   
282     return returnType;
283 } /* end findOrCreateType() */
284
285 BPatch_type * BPatch_typeCollection::addOrUpdateType( BPatch_type * type ) {
286     BPatch_type * existingType = findTypeLocal( type->getID() );
287     if( existingType == NULL ) {
288         if( type->getName() != NULL ) {
289             typesByName[ type->getName() ] = type;
290             type->incrRefCount();
291         }
292         typesByID[ type->getID() ] = type;
293         type->incrRefCount();
294         return type;
295     } else {
296         /* Multiple inclusions of the same object file can result
297            in us parsing the same module types repeatedly. GCC does this
298            with some of its internal routines */
299         if (*existingType == *type) {
300            return existingType;
301         }
302 #ifdef notdef
303         //#if defined( USES_DWARF_DEBUG )
304         /* Replace the existing type wholesale. */
305         // bperr( "Updating existing type '%s' %d at %p with %p\n", type->getName(), type->getID(), existingType, type );
306         memmove( existingType, type, sizeof( BPatch_type ) );
307 #else
308         if (existingType->getDataClass() == BPatch_dataUnknownType) {
309            typesByID[type->getID()] = type;
310            type->incrRefCount();
311            existingType->decrRefCount();
312            existingType = type;
313         } else {
314            /* Merge the type information. */
315 //           existingType->merge(type);  //TODO - change
316         }
317 #endif
318     /* The type may have gained a name. */
319     if( existingType->getName() != NULL) {
320        if (typesByName.defines(existingType->getName())) {
321           if (typesByName[ existingType->getName() ] != existingType) {
322              typesByName[ existingType->getName() ]->decrRefCount();
323              typesByName[ existingType->getName() ] = existingType;
324              existingType->incrRefCount();
325           }
326        } else {
327           typesByName[ existingType->getName() ] = existingType;
328           existingType->incrRefCount();
329        }
330     }
331
332     /* Tell the parser to update its type pointer. */
333     return existingType;
334     }
335 } /* end addOrUpdateType() */
336
337 BPatch_type *BPatch_typeCollection::findType(const int & ID)
338 {
339     if (typesByID.defines(ID))
340         return typesByID[ID];
341     else {
342         BPatch_type *ret = NULL;
343         
344         if (BPatch::bpatch && BPatch::bpatch->builtInTypes) 
345             ret = BPatch::bpatch->builtInTypes->findBuiltInType(ID);
346
347         return ret;
348     }
349 }
350
351 /*
352  * BPatch_typeCollection::findVariableType
353  * (Global Variables)
354  * Retrieve a pointer to a BPatch_type object representing the named type from
355  * the collection.  If no such type exists and no such type can be derived
356  * from existing types, then the function returns NULL.
357  *
358  * name         The name of the type to look up.
359  */
360 BPatch_type *BPatch_typeCollection::findVariableType(const char *name)
361 {
362     if (globalVarsByName.defines(name))
363         return globalVarsByName[name];
364     else
365         return (BPatch_type *) NULL;
366 }
367
368 /*
369  * BPatch_typeCollection::addType
370  *
371  * Add a new type to the type collection.  Note that when a type is added to
372  * the collection, it becomes the collection's responsibility to delete it
373  * when it is no longer needed.  For one thing, this means that a type
374  * allocated on the stack should *NEVER* be put into a BPatch_typeCollection.
375  */
376 void BPatch_typeCollection::addType(BPatch_type *type)
377 {
378   if(type->getName() != NULL) { //Type could have no name.
379     typesByName[type->getName()] = type;
380     type->incrRefCount();
381   }
382
383   //Types can share the same ID for typedef, thus not adding types with
384   //same ID to the collection
385
386   // XXX - Fortran seems to restart type numbers for each subroutine
387   // if(!(this->findType(type->getID())))
388        typesByID[type->getID()] = type;
389   type->incrRefCount();
390 }
391
392 void BPatch_typeCollection::clearNumberedTypes() {
393    for (dictionary_hash_iter<int, BPatch_type *> it = typesByID.begin();
394         it != typesByID.end();
395         it ++) {
396       (*it)->decrRefCount();
397    }
398    typesByID.clear();
399 }
400
401
402 /*
403  * BPatch_builtInTypeCollection::BPatch_builtInTypeCollection
404  *
405  * Constructor for BPatch_builtInTypeCollection.  Creates adictionary
406  * for the builtInType, by Name and ID.
407  *  XXX- Don't know if a collection is needed for types by name, but
408  * it is created just in case. jdd 4/21/99
409  */
410 BPatch_builtInTypeCollection::BPatch_builtInTypeCollection():
411   builtInTypesByName(::Dyninst::stringhash),
412   builtInTypesByID(intHash)
413 {
414   /* Initialize hash tables: builtInTypesByName, builtInTypesByID */
415 }
416
417 /*
418  * BPatch_builtInTypeCollection::~BPatch_builtInTypeCollection
419  *
420  * Destructor for BPatch_builtInTypeCollection.  Deletes all builtInType objects that have
421  * been inserted into the collection.
422  */
423 BPatch_builtInTypeCollection::~BPatch_builtInTypeCollection()
424 {
425     dictionary_hash_iter<std::string, BPatch_type *> bit(builtInTypesByName);
426     dictionary_hash_iter<int, BPatch_type *> bitid(builtInTypesByID);
427      
428       std::string       name;
429     int         id;
430     BPatch_type *type;
431
432     // delete builtInTypesByName collection
433     while (bit.next(name, type))
434         type->decrRefCount();
435     // delete builtInTypesByID collection
436     while (bitid.next(id, type))
437         type->decrRefCount();
438 }
439
440
441 /*
442  * BPatch_builtInTypeCollection::findBuiltInType
443  *
444  * Retrieve a pointer to a type object representing the named type from
445  * the collection.  If no such type exists and no such type can be derived
446  * from existing types, then the function returns NULL.
447  *
448  * name         The name of the type to look up.
449  * id           The unique type ID of the type tp look up.
450  */
451 BPatch_type *BPatch_builtInTypeCollection::findBuiltInType(const char *name)
452 {
453     if (builtInTypesByName.defines(name))
454         return builtInTypesByName[name];
455     else
456         return (BPatch_type *)NULL;
457 }
458
459 BPatch_type *BPatch_builtInTypeCollection::findBuiltInType(const int & ID)
460 {
461     if (builtInTypesByID.defines(ID))
462         return builtInTypesByID[ID];
463     else
464         return (BPatch_type *)NULL;
465 }
466
467 void BPatch_builtInTypeCollection::addBuiltInType(BPatch_type *type)
468 {
469   if(type->getName() != NULL) { //Type could have no name.
470     builtInTypesByName[type->getName()] = type;
471     type->incrRefCount();
472   }
473   //All built-in types have unique IDs so far jdd 4/21/99
474   builtInTypesByID[type->getID()] = type;
475   type->incrRefCount();
476 }
477
478
479