Fix compilation warnings
[dyninst.git] / symtabAPI / src / Aggregate.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 "Annotatable.h"
33 #include "Serialization.h"
34 #include "common/h/serialize.h"
35
36 #include "Symtab.h"
37 #include "symutil.h"
38 #include "Module.h"
39 #include "Collections.h"
40
41 #include "Function.h"
42 #include "Variable.h"
43
44 #include "symtabAPI/src/Object.h"
45
46
47 #include "Aggregate.h"
48 #include "Symbol.h"
49
50 using namespace std;
51 using namespace Dyninst;
52 using namespace Dyninst::SymtabAPI;
53
54 Aggregate::Aggregate() :
55     module_(NULL)
56 {
57 }
58
59 Aggregate::Aggregate(Symbol *sym) :
60     module_(NULL)
61 {
62     assert(sym);
63     module_ = sym->getModule();
64     symbols_.push_back(sym);
65     mangledNames_.push_back(sym->getMangledName());
66     prettyNames_.push_back(sym->getPrettyName());
67     typedNames_.push_back(sym->getTypedName());
68 }
69
70
71 Offset Aggregate::getOffset() const 
72
73         Symbol *s = getFirstSymbol();
74         if (!s)
75         {
76                 fprintf(stderr, "%s[%d]:  ERROR:  Aggregate w/out symbols\n", FILE__, __LINE__);
77                 return (Offset) 0L;
78         }
79         return s->getOffset();
80 }
81
82 unsigned Aggregate::getSize() const 
83
84         Symbol *s = getFirstSymbol();
85         if (!s)
86         {
87                 fprintf(stderr, "%s[%d]:  ERROR:  Aggregate w/out symbols\n", FILE__, __LINE__);
88                 return (unsigned) 0;
89         }
90         return s->getSize(); 
91 }
92
93 Region * Aggregate::getRegion() const
94 {
95         Symbol *s = getFirstSymbol();
96         if (!s)
97         {
98                 fprintf(stderr, "%s[%d]:  ERROR:  Aggregate w/out symbols\n", FILE__, __LINE__);
99                 return NULL;
100         }
101         return s->getRegion();
102 }
103
104 const vector<std::string> &Aggregate::getAllMangledNames() 
105 {
106     return mangledNames_;
107 }
108
109 const vector<std::string> &Aggregate::getAllPrettyNames() 
110 {
111     return prettyNames_;
112 }
113
114 const vector<std::string> &Aggregate::getAllTypedNames() 
115 {
116     return typedNames_;
117 }
118
119 bool Aggregate::addSymbol(Symbol *sym) {
120
121     // We keep a "primary" module, which is defined as "anything not DEFAULT_MODULE".
122     if (module_ == NULL) {
123         module_ = sym->getModule();
124     }
125     else if (module_->fileName() == "DEFAULT_MODULE") {
126         module_ = sym->getModule();
127     }
128     // else keep current module.
129
130     symbols_.push_back(sym);
131
132     // We need to add the symbol names (if they aren't there already)
133     // We can have multiple identical names - for example, there are
134     // often two symbols for main (static and dynamic symbol table)
135     
136     bool found = false;
137     for (unsigned j = 0; j < mangledNames_.size(); j++) {
138         if (sym->getMangledName() == mangledNames_[j]) {
139             found = true;
140             break;
141         }
142     }
143     if (!found) mangledNames_.push_back(sym->getMangledName());
144
145     found = false;
146
147     for (unsigned j = 0; j < prettyNames_.size(); j++) {
148         if (sym->getPrettyName() == prettyNames_[j]) {
149             found = true;
150             break;
151         }
152     }
153     if (!found) prettyNames_.push_back(sym->getPrettyName());
154
155     found = false;
156     for (unsigned j = 0; j < typedNames_.size(); j++) {
157         if (sym->getTypedName() == typedNames_[j]) {
158             found = true;
159             break;
160         }
161     }
162     if (!found) typedNames_.push_back(sym->getTypedName());;
163
164     return true;
165 }
166
167 bool Aggregate::removeSymbolInt(Symbol *sym) {
168     std::vector<Symbol *>::iterator iter;
169     for (iter = symbols_.begin(); iter != symbols_.end(); iter++) {
170         if ((*iter) == sym) {
171             symbols_.erase(iter);
172             break;
173         }
174     }
175     return true;
176 }
177
178 bool Aggregate::getSymbols(std::vector<Symbol *> &syms) const 
179 {
180     syms = symbols_;
181     return true;
182 }
183
184 Symbol * Aggregate::getFirstSymbol() const
185 {
186     if (!symbols_.size())
187                 return NULL;
188     return symbols_[0];
189 }
190
191 SYMTAB_EXPORT bool Aggregate::addMangledName(string name, bool isPrimary) 
192  {
193     // Check to see if we're duplicating
194     for (unsigned i = 0; i < mangledNames_.size(); i++) {
195         if (mangledNames_[i] == name)
196             return false;
197     }
198
199     if (isPrimary) {
200         std::vector<std::string>::iterator iter = mangledNames_.begin();
201         mangledNames_.insert(iter, name);
202     }
203     else
204         mangledNames_.push_back(name);
205
206     if (addMangledNameInt(name, isPrimary) == false) return false;
207      return true;
208  }                                                                                                                                      
209  
210  SYMTAB_EXPORT bool Aggregate::addPrettyName(string name, bool isPrimary) 
211  {
212     // Check to see if we're duplicating
213     for (unsigned i = 0; i < prettyNames_.size(); i++) {
214         if (prettyNames_[i] == name)
215             return false;
216     }
217
218     if (isPrimary) {
219         std::vector<std::string>::iterator iter = prettyNames_.begin();
220         prettyNames_.insert(iter, name);
221     }
222     else
223         prettyNames_.push_back(name);
224     if (addPrettyNameInt(name, isPrimary) == false) return false;
225      return true;
226  }                                                                                                                                      
227  
228  SYMTAB_EXPORT bool Aggregate::addTypedName(string name, bool isPrimary) 
229  {
230     // Check to see if we're duplicating
231     for (unsigned i = 0; i < typedNames_.size(); i++) {
232         if (typedNames_[i] == name)
233             return false;
234     }
235     if (addTypedNameInt(name, isPrimary) == false) return false;
236
237     if (isPrimary) {
238         std::vector<std::string>::iterator iter = typedNames_.begin();
239         typedNames_.insert(iter, name);
240     }
241     else
242         typedNames_.push_back(name);
243         return true;
244  }
245
246 bool Aggregate::addMangledNameInt(string name, bool isPrimary) {
247     // Check to see if we're duplicating
248     for (unsigned i = 0; i < mangledNames_.size(); i++) {
249         if (mangledNames_[i] == name)
250             return false;
251     }
252
253     if (isPrimary) {
254         std::vector<std::string>::iterator iter = mangledNames_.begin();
255         mangledNames_.insert(iter, name);
256     }
257     else
258         mangledNames_.push_back(name);
259     return true;
260 }
261
262 bool Aggregate::addPrettyNameInt(string name, bool isPrimary) {
263     // Check to see if we're duplicating
264     for (unsigned i = 0; i < prettyNames_.size(); i++) {
265         if (prettyNames_[i] == name)
266             return false;
267     }
268
269     if (isPrimary) {
270         std::vector<std::string>::iterator iter = prettyNames_.begin();
271         prettyNames_.insert(iter, name);
272     }
273     else
274         prettyNames_.push_back(name);
275     return true;
276 }
277
278 bool Aggregate::addTypedNameInt(string name, bool isPrimary) 
279 {
280     // Check to see if we're duplicating
281     for (unsigned i = 0; i < typedNames_.size(); i++) {
282         if (typedNames_[i] == name)
283             return false;
284     }
285
286     if (isPrimary) {
287         std::vector<std::string>::iterator iter = typedNames_.begin();
288         typedNames_.insert(iter, name);
289     }
290     else
291         typedNames_.push_back(name);
292     return true;
293 }
294
295 bool Aggregate::changeSymbolOffset(Symbol *sym) 
296 {
297     Offset oldOffset = getOffset();
298
299     removeSymbolInt(sym);
300
301     if (symbols_.empty()) 
302         {
303         // This was the only one; so add it back in and update our address
304         // in the Symtab.
305         symbols_.push_back(sym);
306         module_->exec()->changeAggregateOffset(this, oldOffset, getOffset());
307     }
308     else 
309         {
310         module_->exec()->addSymbolToAggregates(sym);
311     }
312     return true;
313 }
314
315 void Aggregate::restore_type_by_id(SerializerBase *sb, Type *&t, 
316                 unsigned t_id) THROW_SPEC (SerializerError)
317 {
318         if (module_)
319         {
320                 typeCollection *tc = module_->getModuleTypesPrivate();
321                 if (tc)
322                 {
323                         t = tc->findType(t_id);
324                         if (!t)
325                         {
326                                 //fprintf(stderr, "%s[%d]: failed to find type in module(%s) collection\n", 
327                                 //              FILE__, __LINE__, module_->fileName().c_str());
328                         }
329                 }
330                 else
331                 {
332                         fprintf(stderr, "%s[%d]:  no types for module\n", FILE__, __LINE__);
333                 }
334         }
335         else
336         {
337                 fprintf(stderr, "%s[%d]:  bad deserialization order??\n", FILE__, __LINE__);
338                 //SER_ERR("FIXME");
339         }
340
341         if (!t)
342         {
343                 SerContextBase *scb = sb->getContext();
344                 if (!scb)
345                 {
346                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
347                         SER_ERR("FIXME");
348                 }
349
350                 SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
351
352                 if (!scs)
353                 {
354                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
355                         SER_ERR("FIXME");
356                 }
357
358                 Symtab *st = scs->getScope();
359
360                 if (!st)
361                 {
362                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
363                         SER_ERR("FIXME");
364                 }
365
366                 t = st->findType(t_id);
367
368                 if (!t)
369                 {
370                         //  This should probably throw, but let's play nice for now
371                         fprintf(stderr, "%s[%d]:  FIXME: cannot find type with id %d\n", FILE__, __LINE__, t_id);
372                         std::vector<Module *> mods;
373                         if (!st->getAllModules(mods))
374                         {
375                                 fprintf(stderr, "%s[%d]:  failed to get all modules\n", FILE__, __LINE__);
376                         }
377                         for (unsigned int i = 0; i < mods.size(); ++i)
378                         {
379                                 std::vector<Type *> *modtypes = mods[i]->getAllTypes();
380                                 fprintf(stderr, "%s[%d]:  module %s has %ld types\n", FILE__, __LINE__, mods[i]->fileName().c_str(), (signed long) (modtypes ? modtypes->size() : -1));
381                                 if (mods[i]->getModuleTypesPrivate()->findType(t_id))
382                                         fprintf(stderr, "%s[%d]:  found type %d in mod %s\n", FILE__, __LINE__, t_id, mods[i]->fileName().c_str());
383                         }
384                 }
385         }
386 }
387
388 void Aggregate::restore_module_by_name(SerializerBase *sb,  
389                 std::string &mname) THROW_SPEC (SerializerError)
390 {
391
392         if (!sb)
393         {
394                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
395                 SER_ERR("FIXME");
396         }
397
398                 SerContextBase *scb = sb->getContext();
399                 if (!scb)
400                 {
401                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
402                         SER_ERR("FIXME");
403                 }
404
405                 SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
406
407                 if (!scs)
408                 {
409                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
410                         SER_ERR("FIXME");
411                 }
412
413                 Symtab *st = scs->getScope();
414
415
416         if (!st)
417         {
418                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
419                 SER_ERR("FIXME");
420         }
421
422         if (!st->findModuleByName(module_, mname) || !(module_))
423         {
424                 //  This should probably throw, but let's play nice for now
425                 fprintf(stderr, "%s[%d]:  FIXME: aggregate w/out module: %s\n", FILE__, __LINE__, mname.c_str());
426         }
427 }
428
429
430 extern Symbol * getSymForID(SerializerBase *sb, Address id);
431
432 void Aggregate::rebuild_symbol_vector(SerializerBase *sb, std::vector<Address> &symids) THROW_SPEC (SerializerError)
433 {
434         Offset off_accum = 0;
435         for (unsigned long i = 0; i < symids.size(); ++i)
436         {
437                 Symbol *sym = getSymForID(sb, symids[i]);
438                 if (!sym)
439                 {
440                         fprintf(stderr, "%s[%d]:  ERROR rebuilding aggregate: ", __FILE__, __LINE__);
441                         fprintf(stderr, "cannot find symbol for id %p\n", (void *) symids[i]);
442                         continue;
443                 }
444
445                 symbols_.push_back(sym);
446
447                 //  sanity check to make sure that all our symbols share the same offset
448                 if (serializer_debug_flag())
449                 {
450                         if (!off_accum) 
451                                 off_accum = sym->getOffset();
452                         else
453                         {
454                                 if (sym->getOffset() != off_accum)
455                                 {
456                                         fprintf(stderr, "%s[%d]:  INTERNAL ERROR:  mismatch offsets: %p--%p\n", FILE__, __LINE__, (void *)off_accum, (void *)sym->getOffset());
457                                 }
458                         }
459                 }
460
461                 //  This sucks, but apparently there are symbols that are somehow
462                 //  not getting their aggregate fields set properly (before serialize
463                 //  presumably), strangely only affects 64bit cases.  Here we try
464                 //  to correct for this by setting the aggregate values of all symbols
465                 //  at this Offset.  This lookup should be avoided by solving the problem
466                 //  somewhere else (at the source, wherever it is that the rogue symbols
467                 //  are being created and/or lost)
468                 //  
469                 //  Maybe it is also somehow possible that spurious symbols are being
470                 //  created and indexed during deserialize.
471                 SerContextBase *scb = sb->getContext();
472                 if (!scb)
473                 {
474                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
475                         SER_ERR("FIXME");
476                 }
477
478                 SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
479
480                 if (!scs)
481                 {
482                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
483                         SER_ERR("FIXME");
484                 }
485
486                 Symtab *st = scs->getScope();
487
488         if (!st)
489         {
490                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
491                 SER_ERR("FIXME");
492         }
493                 std::vector<Symbol *> *syms = st->findSymbolByOffset(sym->getOffset());
494                 for (unsigned long j = 0; j < syms->size(); ++j)
495                 {
496                         (*syms)[j]->aggregate_ = this;
497                 }
498         }
499 }
500
501 std::ostream &operator<<(std::ostream &os, const Dyninst::SymtabAPI::Aggregate &a)
502 {
503         std::string modname = a.module_ ? a.module_->fullName() : std::string("no_mod");
504         os   << "Aggregate{"
505                 << " Module=" << modname
506                 << " MangledNames=["; 
507                 for (unsigned int i = 0; i < a.mangledNames_.size(); ++i)
508                 {
509                         os << a.mangledNames_[i];
510                         if ((i + 1) < a.mangledNames_.size())
511                                 os << ", ";
512                 }
513                 os << "]";
514
515                 os << " PrettyNames=["; 
516                 for (unsigned int i = 0; i < a.prettyNames_.size(); ++i)
517                 {
518                         os << a.prettyNames_[i];
519                         if ((i + 1) < a.prettyNames_.size())
520                                 os << ", ";
521                 }
522                 os << "]";
523
524                 os << " TypedNames=["; 
525                 for (unsigned int i = 0; i < a.typedNames_.size(); ++i)
526                 {
527                         os << a.typedNames_[i];
528                         if ((i + 1) < a.typedNames_.size())
529                                 os << ", ";
530                 }
531                 os << "]";
532                 os << " }";
533
534                 return os;
535 }
536
537 void Aggregate::serialize_aggregate(SerializerBase * sb, const char * tag) THROW_SPEC (SerializerError)
538 {
539         std::string modname = module_ ? module_->fullName() : std::string("");
540         std::vector<Address> symids;
541         for (unsigned long i = 0; i < symbols_.size(); ++i)
542         {
543                 assert(symbols_[i]);
544                 assert(sizeof(Address) == sizeof(void *));
545                 symids.push_back((Address) symbols_[i]);
546         }
547
548         try
549         {
550                 ifxml_start_element(sb, tag);
551                 gtranslate(sb, modname, "moduleName");
552                 //  Arguably we should be able to reconstruct these name lists from the set of 
553                 //  symbols, right?  
554                 gtranslate(sb, mangledNames_, "mangledNameList");
555                 gtranslate(sb, prettyNames_, "prettyNameList");
556                 gtranslate(sb, typedNames_, "typedNameList");
557 #if 0
558                 gtranslate(sb, symbols_, "aggregatedSymbols", "aggregateSymbol");
559                 gtranslate(sb, sym_offsets, "symbolOffsetList");
560 #endif
561                 gtranslate(sb, symids, "symbolIDList");
562                 ifxml_end_element(sb, tag);
563
564                 if (sb->isBin() && sb->isInput())
565                 {
566                         restore_module_by_name(sb, modname);
567                         rebuild_symbol_vector(sb, symids);
568                 }
569
570 #if 0
571                 if (sb->isBin() && sb->isInput())
572                 {
573                         fprintf(stderr, "%s[%d]:  DESERIALIZE AGGREGATE %s, %lu offsets\n", FILE__, __LINE__, prettyNames_.size() ? prettyNames_[0].c_str() : "no_names", sym_offsets.size());
574                         rebuild_symbol_vector(sb, &sym_offsets);
575                 }
576 #endif
577         }
578         SER_CATCH(tag);
579
580         serialize_printf("%s[%d]:  %sSERIALIZE AGGREGATE, nsyms = %lu\n", FILE__, __LINE__, 
581                         sb->isInput() ? "DE" : "", symbols_.size());
582 }
583
584 bool Aggregate::operator==(const Aggregate &a)
585 {
586         if (mangledNames_.size() != a.mangledNames_.size()) return false;
587         if (prettyNames_.size() != a.prettyNames_.size()) return false;
588         if (typedNames_.size() != a.typedNames_.size()) return false;
589         if (symbols_.size() != a.symbols_.size()) return false;
590         if (module_ && !a.module_) return false;
591         if (!module_ && a.module_) return false;
592         if (module_ && (module_->fullName() != a.module_->fullName())) return false;
593
594         for (unsigned int i = 0; i < mangledNames_.size(); ++i)
595         {
596                 if (mangledNames_[i] != a.mangledNames_[i]) return false;
597         }
598         for (unsigned int i = 0; i < prettyNames_.size(); ++i)
599         {
600                 if (prettyNames_[i] != a.prettyNames_[i]) return false;
601         }
602         for (unsigned int i = 0; i < typedNames_.size(); ++i)
603         {
604                 if (typedNames_[i] != a.typedNames_[i]) return false;
605         }
606         for (unsigned int i = 0; i < symbols_.size(); ++i)
607         {
608                 Symbol *s1 = symbols_[i];
609                 Symbol *s2 = a.symbols_[i];
610                 if (s1 && !s2) return false;
611                 if (!s1 && s2) return false;
612                 if (!s1)
613                         fprintf(stderr, "%s[%d]:  WARN:  NULL Symbol pointer here\n", FILE__, __LINE__);
614                 else
615                 {
616                         //  just compare offset and a couple other params
617                         if (s1->getOffset() != s2->getOffset()) return false;
618                         if (s1->getType() != s2->getType()) return false;
619                         if (s1->getSize() != s2->getSize()) return false;
620                 }
621         }
622
623         return true;
624 }