Correct static initialization for built in & standard types in Symtab
[dyninst.git] / symtabAPI / src / Collections.C
1 /*
2  * Copyright (c) 1996-2011 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 #include "Variable.h"
41 #include "Serialization.h"
42
43 #include "common/h/headers.h"
44 #include "common/h/serialize.h"
45
46 using namespace std;
47 using namespace Dyninst;
48 using namespace Dyninst::SymtabAPI;
49
50 /**************************************************************************
51  * localVarCollection
52  *************************************************************************/
53
54 /*
55  * localVarCollection::~localVarCollection
56  *
57  * Destructor for localVarCollection.  Deletes all type objects that
58  * have been inserted into the collection.
59  */
60 localVarCollection::~localVarCollection()
61 {
62    std::vector<localVar *>::iterator li = localVars.begin();    
63    for(;li!=localVars.end();li++)
64    {
65            delete *li;
66    }
67    
68    localVars.clear();
69 }
70
71 /*
72  * localVarCollection::addLocalVar()
73  * This function adds local variables to the set of local variables
74  * for function.
75  */
76
77 bool localVarCollection::addItem_impl(localVar * var)
78 {
79   localVars.push_back(var);
80   return true;
81 }
82
83 void localVarCollection::addLocalVar(localVar * var)
84 {
85         if (!addItem(var))
86         {
87                 fprintf(stderr, "%s[%d]:  ERROR adding localVar\n", FILE__, __LINE__);
88         }
89 }
90
91 /*
92  * localVarCollection::findLocalVar()
93  * This function finds a local variable by name and returns a pointer to
94  * it or NULL if the local variable does not exist in the set of function
95  * local variables.
96  */
97 localVar *localVarCollection::findLocalVar(std::string &name){
98
99    std::vector<localVar *>::iterator li = localVars.begin();    
100    for(;li!=localVars.end();li++)
101    {
102       if (name == (*li)->getName()) {
103          return *li;
104       }
105    }
106    return NULL;
107 }
108
109 /*
110  * localVarCollection::getAllVars()
111  * this function returns all the local variables in the collection.
112  */
113 std::vector<localVar *> *localVarCollection::getAllVars() 
114 {
115     return &localVars;
116 }
117   
118 Serializable *localVarCollection::ac_serialize_impl(SerializerBase *s, const char *tag) THROW_SPEC (SerializerError)
119 {
120         unsigned short lvmagic = 72;
121         serialize_printf("%s[%d]:  welcome to localVarCollection: ac_serialize_impl\n", 
122                         FILE__, __LINE__);
123         ifxml_start_element(s, tag);
124         gtranslate(s, lvmagic, "LocalVarMagicID");
125         gtranslate(s, localVars, "LocalVariables");
126         s->magic_check(FILE__, __LINE__);
127         ifxml_end_element(s, tag);
128
129         if (lvmagic != 72)
130         {
131                 fprintf(stderr, "\n\n%s[%d]: FIXME:  out-of-sync\n\n\n", FILE__, __LINE__);
132         }
133
134         serialize_printf("%s[%d]:  localVarCollection: ac_serialize_impl, translate done\n", FILE__, __LINE__);
135
136         if (s->isInput())
137         {
138                 //  rebuild name->variable mapping
139                 for (unsigned int i = 0; i < localVars.size(); ++i)
140                 {
141                         localVar *lv = localVars[i];
142                         assert(lv);
143                 }
144                 serialize_printf("%s[%d]:  deserialized %ld local vars\n", FILE__, __LINE__, localVars.size());
145         }
146         else
147                 serialize_printf("%s[%d]:  serialized %ld local vars\n", FILE__, __LINE__, localVars.size());
148
149         return NULL;
150 }
151
152 // Could be somewhere else... for DWARF-work.
153 dyn_hash_map<void *, typeCollection *> typeCollection::fileToTypesMap;
154 #if 0
155 dyn_hash_map<int, std::vector<std::pair<dataClass, Type **> > > typeCollection::deferred_lookups;
156 #endif
157 dyn_hash_map<int, std::vector<std::pair<dataClass, Type **> > *> *deferred_lookups_p = NULL;
158
159 void typeCollection::addDeferredLookup(int tid, dataClass tdc,Type **th)
160 {
161         if (!deferred_lookups_p)
162                 deferred_lookups_p = new dyn_hash_map<int, std::vector<std::pair<dataClass, Type **> > *>();
163         dyn_hash_map<int, std::vector<std::pair<dataClass, Type **> > *> &deferred_lookups = *deferred_lookups_p;
164         dyn_hash_map<int, std::vector<std::pair<dataClass, Type **> > *>::iterator iter;
165
166         iter = deferred_lookups.find(tid);
167         if (iter == deferred_lookups.end())
168                 deferred_lookups[tid] = new std::vector<std::pair<dataClass, Type **> >();
169         deferred_lookups[tid]->push_back(std::make_pair(tdc, th));
170 }
171
172 bool typeCollection::doDeferredLookups(typeCollection *primary_tc)
173 {
174         if (!deferred_lookups_p) return true; // nothing to do
175         dyn_hash_map<int, std::vector<std::pair<dataClass, Type **> > *> &deferred_lookups = *deferred_lookups_p;
176         bool err = false;
177         dyn_hash_map<int, std::vector<std::pair<dataClass, Type **> > *>::iterator iter;
178         for (iter = deferred_lookups.begin(); iter != deferred_lookups.end(); iter++)
179         {
180                 std::vector<std::pair<dataClass, Type **> > *to_assign = iter->second;
181                 if (!to_assign) 
182                 {
183                         fprintf(stderr, "%s[%d]:  FIXME!\n", FILE__, __LINE__);
184                 }
185
186                 if (!to_assign->size())
187                 {
188                         fprintf(stderr, "%s[%d]:  No lookups for id %d, weird\n", 
189                                         FILE__, __LINE__, iter->first);
190                         continue;
191                 }
192
193                 for (unsigned int i = 0; i < to_assign->size(); ++i)
194                 {
195                         dataClass ldc = (*to_assign)[i].first;
196                         Type **th = (*to_assign)[i].second;
197
198                         Type *t = primary_tc->findType(iter->first);
199                         if (t && (t->getDataClass() != ldc)) t = NULL;
200
201                         if (!t)
202                         {
203                                 if (Symtab::builtInTypes())
204                                 {
205                                         t = Symtab::builtInTypes()->findBuiltInType(iter->first);
206                                         if (t && (t->getDataClass() != ldc)) t = NULL;
207                                 }
208                         }
209                         if (!t)
210                         {
211                                 if (Symtab::stdTypes())
212                                 {
213                                         t = Symtab::stdTypes()->findType(iter->first);
214                                         if (t && (t->getDataClass() != ldc)) t = NULL;
215                                 }
216                         }
217                         if (!t)
218                         {
219                                 int nfound = 0;
220                                 dyn_hash_map<void *, typeCollection *>::iterator tciter; 
221                                 for (tciter = fileToTypesMap.begin(); tciter != fileToTypesMap.end(); tciter++)
222                                 {
223                                         Type *localt = NULL;
224                                         if (tciter->second == primary_tc) continue;
225                                         localt = tciter->second->findType(iter->first);
226                                         if (localt)
227                                         {
228                                                 if (localt->getDataClass() != ldc) 
229                                                         continue;
230                                                 nfound++;
231                                                 if (t)
232                                                 {
233 #if 0
234                                                         fprintf(stderr, "%s[%d]: WARN: found %d types w/ID %d (so far)\n", 
235                                                                         FILE__, __LINE__, nfound, iter->first);
236                                                         fprintf(stderr, "%s[%d]:  have %s vs, %s\n", FILE__, __LINE__, 
237                                                                         dataClass2Str(t->getDataClass()), 
238                                                                         dataClass2Str(localt->getDataClass()));
239 #endif
240                                                 }
241                                                 t = localt;
242                                         }
243                                         //if (t) break;
244                                 }
245                         }
246                         if (t)
247                         {
248                                 *th = t;
249                         }
250                         if (!t)
251                         {
252                                 fprintf(stderr, "%s[%d]:  FIXME:  cannot find type id %d\n", 
253                                                 FILE__, __LINE__, iter->first);
254                                 err = true;
255                                 continue;
256                         }
257                 }
258         }
259         deferred_lookups.clear();
260         return (!err);
261 }
262
263 /*
264  * Reference count
265  */
266
267 #if 0
268 typeCollection *typeCollection::getGlobalTypeCollection() 
269 {
270     typeCollection *tc = new typeCollection();
271     //tc->refcount++;
272     return tc;
273 }
274 #endif
275
276 typeCollection *typeCollection::getModTypeCollection(Module *mod) 
277 {
278         if (!mod) return NULL;
279         dyn_hash_map<void *, typeCollection *>::iterator iter = fileToTypesMap.find((void *)mod);
280
281     if ( iter != fileToTypesMap.end()) 
282         {
283                 return iter->second;
284     }
285
286     typeCollection *newTC = new typeCollection();
287     fileToTypesMap[(void *)mod] = newTC;
288     return newTC;
289 }
290
291 #if 0
292 void typeCollection::freeTypeCollection(typeCollection *tc) {
293     assert(tc);
294     tc->refcount--;
295     if (tc->refcount == 0) {
296         dyn_hash_map<Module *, typeCollection *>::iterator iter = fileToTypesMap.begin();
297         for (; iter!= fileToTypesMap.end(); iter++) {
298             if (iter->second == tc) {
299                 fileToTypesMap.erase(iter->first);
300                 break;
301             }
302         }
303         delete tc;
304     }
305 }
306 #endif
307
308 /*
309  * typeCollection::typeCollection
310  *
311  * Constructor for typeCollection.  Creates the two dictionaries
312  * for the type, by Name and ID.
313  */
314 typeCollection::typeCollection() :
315         typesByName(),
316         globalVarsByName(),
317         typesByID(),
318     dwarfParsed_(false)
319 {
320   /* Initialize hash tables: typesByName, typesByID */
321 }
322
323 /*
324  * typeCollection::~typeCollection
325  *
326  * Destructor for typeCollection.  Deletes all type objects that have
327  * been inserted into the collection.
328  */
329 typeCollection::~typeCollection()
330 {
331     // We sometimes directly delete (refcount == 1) or go through the
332     // decRefCount (which will delete when refcount == 0)
333     // delete all of the types
334     // This doesn't seem to work - jkh 1/31/00
335 #if 0
336     dictionary_hash_iter<std::string, type *> ti(typesByName);
337     dictionary_hash_iter<int, type *> tid(typesByID);
338     dictionary_hash_iter<std::string, type *> gi(globalVarsByName);
339     
340     std::string      gname; 
341     std::string name;
342     type        *type;
343     int         id;
344     while (tid.next(id, type))
345         delete type;
346     
347     
348     // Underlying types deleted already just need to get rid of pointers
349     while (ti.next(name, type))
350         type = NULL;
351     
352     // delete globalVarsByName collection
353     while (gi.next(name, type))
354         delete type;
355     
356     for (dictionary_hash_iter<int, type *> it = typesByID.begin();
357          it != typesByID.end();
358          it ++) {
359         (*it)->decrRefCount();
360     }
361     for (dictionary_hash_iter<std::string, type *> it2 = typesByName.begin();
362          it2 != typesByName.end();
363          it2 ++) {
364         (*it2)->decrRefCount();
365     }
366 #endif    
367 }
368
369 /*
370  * typeCollection::findType
371  *
372  * Retrieve a pointer to a type object representing the named type from
373  * the collection.  If no such type exists and no such type can be derived
374  * from existing types, then the function returns NULL.
375  *
376  * name         The name of the type to look up.
377  * id           The unique type ID of the type tp look up.
378  */
379 Type *typeCollection::findType(std::string name)
380 {
381     if (typesByName.find(name) != typesByName.end())
382         return typesByName[name];
383         else if (Symtab::builtInTypes())
384         return Symtab::builtInTypes()->findBuiltInType(name);
385     else
386                 return NULL;
387 }
388
389 Type *typeCollection::findTypeLocal(std::string name)
390 {
391    if (typesByName.find(name) != typesByName.end())
392       return typesByName[name];
393    else
394       return NULL;
395 }
396
397 Type *typeCollection::findTypeLocal(const int ID)
398 {
399    if (typesByID.find(ID) != typesByID.end())
400       return typesByID[ID];
401    else
402       return NULL;
403 }
404
405
406 Type * typeCollection::findOrCreateType( const int ID ) 
407 {
408         if ( typesByID.find(ID) != typesByID.end()) 
409         { 
410                 return typesByID[ID]; 
411         }
412
413         Type * returnType = NULL;
414
415         if ( Symtab::builtInTypes() ) 
416         {
417                 returnType = Symtab::builtInTypes()->findBuiltInType(ID);
418
419                 if (returnType)
420                         return returnType;
421         }
422
423         /* Create a placeholder type. */
424         returnType = Type::createPlaceholder(ID);
425         assert( returnType != NULL );
426
427         /* Having created the type, add it. */
428         addType( returnType );
429
430     return returnType;
431 } /* end findOrCreateType() */
432
433 Type *typeCollection::findType(const int ID)
434 {
435         if (typesByID.find(ID) != typesByID.end())
436                 return typesByID[ID];
437         else 
438         {
439                 Type *ret = NULL;
440
441                 if (Symtab::builtInTypes()) 
442                         ret = Symtab::builtInTypes()->findBuiltInType(ID);
443
444                 return ret;
445         }
446 }
447
448 /*
449  * typeCollection::findVariableType
450  * (Global Variables)
451  * Retrieve a pointer to a type object representing the named type from
452  * the collection.  If no such type exists and no such type can be derived
453  * from existing types, then the function returns NULL.
454  *
455  * name         The name of the type to look up.
456  */
457 Type *typeCollection::findVariableType(std::string &name)
458 {
459         if (globalVarsByName.find(name) != globalVarsByName.end())
460                 return globalVarsByName[name];
461         else
462                 return (Type *) NULL;
463 }
464
465 /*
466  * typeCollection::addType
467  *
468  * Add a new type to the type collection.  Note that when a type is added to
469  * the collection, it becomes the collection's responsibility to delete it
470  * when it is no longer needed.  For one thing, this means that a type
471  * allocated on the stack should *NEVER* be put into a typeCollection.
472  */
473 void typeCollection::addType(Type *type)
474 {
475         if(type->getName() != "") { //Type could have no name.
476     typesByName[type->getName()] = type;
477     type->incrRefCount();
478   }
479
480   //Types can share the same ID for typedef, thus not adding types with
481   //same ID to the collection
482
483   // XXX - Fortran seems to restart type numbers for each subroutine
484   // if(!(this->findType(type->getID())))
485        typesByID[type->getID()] = type;
486   type->incrRefCount();
487 }
488
489 void typeCollection::addGlobalVariable(std::string &name, Type *type) 
490 {
491    
492    globalVarsByName[name] = type;
493 }
494
495 void typeCollection::clearNumberedTypes() 
496 {
497    for (dyn_hash_map<int, Type *>::iterator it = typesByID.begin();
498         it != typesByID.end();
499         it ++) 
500    {
501       if (it->second)
502          it->second->decrRefCount();
503       else
504          fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
505    }
506
507    typesByID.clear();
508 }
509
510 /*
511  * localVarCollection::getAllVars()
512  * this function returns all the local variables in the collection.
513  */
514 std::vector<Type *> *typeCollection::getAllTypes() {
515    std::vector<Type *> *typesVec = new std::vector<Type *>;
516    //for (dyn_hash_map<int, Type *>::iterator it = typesByID.begin();
517    //     it != typesByID.end();
518    //     it ++) {
519    for (dyn_hash_map<string, Type *>::iterator it = typesByName.begin();
520         it != typesByName.end();
521         it ++) {
522         typesVec->push_back(it->second);
523    }
524    if(!typesVec->size()){
525        delete typesVec;
526        return NULL;
527    }
528    return typesVec;
529 }
530
531 vector<pair<string, Type *> > *typeCollection::getAllGlobalVariables() {
532     vector<pair<string, Type *> > *varsVec = new vector<pair<string, Type *> >;
533     for(dyn_hash_map<string, Type *>::iterator it = globalVarsByName.begin();
534         it != globalVarsByName.end(); it++) {
535         varsVec->push_back(pair<string, Type *>(it->first, it->second));
536    }    
537    if(!varsVec->size()){
538        delete varsVec;
539        return NULL;
540    }
541    return varsVec;
542 }
543
544 Serializable *typeCollection::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
545 {
546         serialize_printf("%s[%d]:  enter typeCollection::serialize_impl\n", FILE__, __LINE__);
547
548         std::vector<std::pair<std::string, int> >  gvars;
549         dyn_hash_map<std::string, Type *>::iterator iter;
550         for (iter = globalVarsByName.begin(); iter != globalVarsByName.end(); iter++)
551                 gvars.push_back(std::make_pair(iter->first, iter->second->getID()));
552
553         std::vector<Type *> ltypes;
554         dyn_hash_map<int, Type *>::iterator iter2;
555         for (iter2 = typesByID.begin(); iter2 != typesByID.end(); iter2++)
556         {
557                 if (!iter2->second) assert(0);
558                 //  try skipping field list types
559                 //if (dynamic_cast<fieldListType *>(iter2->second)) continue;
560                 assert (iter2->first == iter2->second->getID());
561                 ltypes.push_back(iter2->second);
562         }
563
564         ifxml_start_element(sb, tag);
565         //gtranslate(sb, typesByID, "TypesByIDMap", "TypeToIDMapEntry");
566         gtranslate(sb, ltypes, "TypesInCollection", "TypeEntry");
567         gtranslate(sb, gvars, "GlobalVarNameToTypeMap", "GlobalVarType");
568         gtranslate(sb, dwarfParsed_, "DwarfParsedFlag");
569         ifxml_end_element(sb, tag);
570
571         if (is_input(sb))
572         {
573                 for (unsigned int i = 0; i < ltypes.size(); ++i)
574                 {
575                         typesByID[ltypes[i]->getID()] = ltypes[i];
576                 }
577                 doDeferredLookups(this);
578
579                 for (unsigned int i = 0; i < gvars.size(); ++i)
580                 {
581                         dyn_hash_map<int, Type *>::iterator iter = typesByID.find(gvars[i].second);
582                         if (iter == typesByID.end())
583                         {
584                                 serialize_printf("%s[%d]:  cannot find type w/ID %d\n", 
585                                                 FILE__, __LINE__, gvars[i].second);
586                                 continue;
587                         }
588                         Type *t = iter->second;
589                         globalVarsByName[gvars[i].first] = t;
590                 }
591
592                 dyn_hash_map<int, Type *>::iterator iter;
593                 for (iter = typesByID.begin(); iter != typesByID.end(); iter++)
594                         typesByName[iter->second->getName()] = iter->second;
595         }
596
597         serialize_printf("%s[%d]:  leave typeCollection::serialize_impl\n", FILE__, __LINE__);
598
599         return NULL;
600 }
601
602 /*
603  * builtInTypeCollection::builtInTypeCollection
604  *
605  * Constructor for builtInTypeCollection.  Creates adictionary
606  * for the builtInType, by Name and ID.
607  *  XXX- Don't know if a collection is needed for types by name, but
608  * it is created just in case. jdd 4/21/99
609  */
610 builtInTypeCollection::builtInTypeCollection()
611 {
612   /* Initialize hash tables: builtInTypesByName, builtInTypesByID */
613 }
614
615 /*
616  * builtInTypeCollection::~builtInTypeCollection
617  *
618  * Destructor for builtInTypeCollection.  Deletes all builtInType objects that have
619  * been inserted into the collection.
620  */
621 builtInTypeCollection::~builtInTypeCollection()
622 {
623    dyn_hash_map<std::string, Type *>::iterator bit = builtInTypesByName.begin();
624    dyn_hash_map<int, Type *>::iterator bitid = builtInTypesByID.begin();
625      
626     // delete builtInTypesByName collection
627     for(;bit!=builtInTypesByName.end();bit++)
628         bit->second->decrRefCount();
629     // delete builtInTypesByID collection
630     for(;bitid!=builtInTypesByID.end();bit++)
631         bitid->second->decrRefCount();
632 }
633
634
635 /*
636  * builtInTypeCollection::findBuiltInType
637  *
638  * Retrieve a pointer to a type object representing the named type from
639  * the collection.  If no such type exists and no such type can be derived
640  * from existing types, then the function returns NULL.
641  *
642  * name         The name of the type to look up.
643  * id           The unique type ID of the type tp look up.
644  */
645 Type *builtInTypeCollection::findBuiltInType(std::string &name)
646 {
647     if (builtInTypesByName.find(name) != builtInTypesByName.end())
648         return builtInTypesByName[name];
649     else
650         return (Type *)NULL;
651 }
652
653 Type *builtInTypeCollection::findBuiltInType(const int ID)
654 {
655     if (builtInTypesByID.find(ID) != builtInTypesByID.end())
656         return builtInTypesByID[ID];
657     else
658         return (Type *)NULL;
659 }
660
661 void builtInTypeCollection::addBuiltInType(Type *type)
662 {
663   if(type->getName() != "") { //Type could have no name.
664     builtInTypesByName[type->getName()] = type;
665     type->incrRefCount();
666   }
667   //All built-in types have unique IDs so far jdd 4/21/99
668   builtInTypesByID[type->getID()] = type;
669   type->incrRefCount();
670 }
671
672 std::vector<Type *> *builtInTypeCollection::getAllBuiltInTypes() {
673    std::vector<Type *> *typesVec = new std::vector<Type *>;
674    for (dyn_hash_map<int, Type *>::iterator it = builtInTypesByID.begin();
675         it != builtInTypesByID.end();
676         it ++) {
677         typesVec->push_back(it->second);
678    }
679    if(!typesVec->size()){
680        free(typesVec);
681        return NULL;
682    }
683    return typesVec;
684 }