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