windows build fixes and some more work on symtab serialization
[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 *) THROW_SPEC (SerializerError)
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    
330    globalVarsByName[name] = type;
331 }
332
333 void typeCollection::clearNumberedTypes() 
334 {
335    for (dyn_hash_map<int, Type *>::iterator it = typesByID.begin();
336         it != typesByID.end();
337         it ++) 
338    {
339       if (it->second)
340          it->second->decrRefCount();
341       else
342          fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
343    }
344
345    typesByID.clear();
346 }
347
348 /*
349  * localVarCollection::getAllVars()
350  * this function returns all the local variables in the collection.
351  */
352 std::vector<Type *> *typeCollection::getAllTypes() {
353    std::vector<Type *> *typesVec = new std::vector<Type *>;
354    //for (dyn_hash_map<int, Type *>::iterator it = typesByID.begin();
355    //     it != typesByID.end();
356    //     it ++) {
357    for (dyn_hash_map<string, Type *>::iterator it = typesByName.begin();
358         it != typesByName.end();
359         it ++) {
360         typesVec->push_back(it->second);
361    }
362    if(!typesVec->size()){
363        free(typesVec);
364        return NULL;
365    }
366    return typesVec;
367 }
368
369 vector<pair<string, Type *> > *typeCollection::getAllGlobalVariables() {
370     vector<pair<string, Type *> > *varsVec = new vector<pair<string, Type *> >;
371     for(dyn_hash_map<string, Type *>::iterator it = globalVarsByName.begin();
372         it != globalVarsByName.end(); it++) {
373         varsVec->push_back(pair<string, Type *>(it->first, it->second));
374    }    
375    if(!varsVec->size()){
376        free(varsVec);
377        return NULL;
378    }
379    return varsVec;
380 }
381
382 void typeCollection::serialize(SerializerBase *, const char *) THROW_SPEC (SerializerError)
383 {
384    fprintf(stderr, "%s[%d]:  IMPLEMENT ME\n", FILE__, __LINE__);
385 }
386
387 /*
388  * builtInTypeCollection::builtInTypeCollection
389  *
390  * Constructor for builtInTypeCollection.  Creates adictionary
391  * for the builtInType, by Name and ID.
392  *  XXX- Don't know if a collection is needed for types by name, but
393  * it is created just in case. jdd 4/21/99
394  */
395 builtInTypeCollection::builtInTypeCollection()
396 {
397   /* Initialize hash tables: builtInTypesByName, builtInTypesByID */
398 }
399
400 /*
401  * builtInTypeCollection::~builtInTypeCollection
402  *
403  * Destructor for builtInTypeCollection.  Deletes all builtInType objects that have
404  * been inserted into the collection.
405  */
406 builtInTypeCollection::~builtInTypeCollection()
407 {
408    dyn_hash_map<std::string, Type *>::iterator bit = builtInTypesByName.begin();
409    dyn_hash_map<int, Type *>::iterator bitid = builtInTypesByID.begin();
410      
411     // delete builtInTypesByName collection
412     for(;bit!=builtInTypesByName.end();bit++)
413         bit->second->decrRefCount();
414     // delete builtInTypesByID collection
415     for(;bitid!=builtInTypesByID.end();bit++)
416         bitid->second->decrRefCount();
417 }
418
419
420 /*
421  * builtInTypeCollection::findBuiltInType
422  *
423  * Retrieve a pointer to a type object representing the named type from
424  * the collection.  If no such type exists and no such type can be derived
425  * from existing types, then the function returns NULL.
426  *
427  * name         The name of the type to look up.
428  * id           The unique type ID of the type tp look up.
429  */
430 Type *builtInTypeCollection::findBuiltInType(std::string &name)
431 {
432     if (builtInTypesByName.find(name) != builtInTypesByName.end())
433         return builtInTypesByName[name];
434     else
435         return (Type *)NULL;
436 }
437
438 Type *builtInTypeCollection::findBuiltInType(const int ID)
439 {
440     if (builtInTypesByID.find(ID) != builtInTypesByID.end())
441         return builtInTypesByID[ID];
442     else
443         return (Type *)NULL;
444 }
445
446 void builtInTypeCollection::addBuiltInType(Type *type)
447 {
448   if(type->getName() != "") { //Type could have no name.
449     builtInTypesByName[type->getName()] = type;
450     type->incrRefCount();
451   }
452   //All built-in types have unique IDs so far jdd 4/21/99
453   builtInTypesByID[type->getID()] = type;
454   type->incrRefCount();
455 }
456
457 std::vector<Type *> *builtInTypeCollection::getAllBuiltInTypes() {
458    std::vector<Type *> *typesVec = new std::vector<Type *>;
459    for (dyn_hash_map<int, Type *>::iterator it = builtInTypesByID.begin();
460         it != builtInTypesByID.end();
461         it ++) {
462         typesVec->push_back(it->second);
463    }
464    if(!typesVec->size()){
465        free(typesVec);
466        return NULL;
467    }
468    return typesVec;
469 }