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