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