windows buildfixes, serialization polishing
[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     // Check to see if we're duplicating
280     for (unsigned i = 0; i < typedNames_.size(); i++) {
281         if (typedNames_[i] == name)
282             return false;
283     }
284
285     if (isPrimary) {
286         std::vector<std::string>::iterator iter = typedNames_.begin();
287         typedNames_.insert(iter, name);
288     }
289     else
290         typedNames_.push_back(name);
291     return true;
292 }
293
294 bool Aggregate::changeSymbolOffset(Symbol *sym) 
295 {
296     Offset oldOffset = getOffset();
297
298     removeSymbolInt(sym);
299
300     if (symbols_.empty()) 
301         {
302         // This was the only one; so add it back in and update our address
303         // in the Symtab.
304         symbols_.push_back(sym);
305         module_->exec()->changeAggregateOffset(this, oldOffset, getOffset());
306     }
307     else 
308         {
309         module_->exec()->addSymbolToAggregates(sym);
310     }
311     return true;
312 }
313
314 void Aggregate::restore_type_by_id(SerializerBase *sb, Type *&t, 
315                 unsigned t_id) THROW_SPEC (SerializerError)
316 {
317         if (module_)
318         {
319                 typeCollection *tc = module_->getModuleTypesPrivate();
320                 if (tc)
321                 {
322                         t = tc->findType(t_id);
323                         if (!t)
324                         {
325                                 //fprintf(stderr, "%s[%d]: failed to find type in module(%s) collection\n", 
326                                 //              FILE__, __LINE__, module_->fileName().c_str());
327                         }
328                 }
329                 else
330                 {
331                         fprintf(stderr, "%s[%d]:  no types for module\n", FILE__, __LINE__);
332                 }
333         }
334         else
335         {
336                 fprintf(stderr, "%s[%d]:  bad deserialization order??\n", FILE__, __LINE__);
337                 //SER_ERR("FIXME");
338         }
339
340         if (!t)
341         {
342                 SerContextBase *scb = sb->getContext();
343                 if (!scb)
344                 {
345                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
346                         SER_ERR("FIXME");
347                 }
348
349                 SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
350
351                 if (!scs)
352                 {
353                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
354                         SER_ERR("FIXME");
355                 }
356
357                 Symtab *st = scs->getScope();
358 #if 0
359                 ScopedSerializerBase<Symtab> *ssb = dynamic_cast<ScopedSerializerBase<Symtab> *>(sb);
360
361                 if (!ssb)
362                 {
363                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
364                         SER_ERR("FIXME");
365                 }
366
367                 Symtab *st = ssb->getScope();
368 #endif
369
370                 if (!st)
371                 {
372                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
373                         SER_ERR("FIXME");
374                 }
375
376                 t = st->findType(t_id);
377
378                 if (!t)
379                 {
380                         //  This should probably throw, but let's play nice for now
381                         fprintf(stderr, "%s[%d]:  FIXME: cannot find type with id %d\n", FILE__, __LINE__, t_id);
382                         std::vector<Module *> mods;
383                         if (!st->getAllModules(mods))
384                         {
385                                 fprintf(stderr, "%s[%d]:  failed to get all modules\n", FILE__, __LINE__);
386                         }
387                         for (unsigned int i = 0; i < mods.size(); ++i)
388                         {
389                                 std::vector<Type *> *modtypes = mods[i]->getAllTypes();
390                                 fprintf(stderr, "%s[%d]:  module %s has %ld types\n", FILE__, __LINE__, mods[i]->fileName().c_str(), (unsigned long) modtypes ? modtypes->size() : -1);
391                                 if (mods[i]->getModuleTypesPrivate()->findType(t_id))
392                                         fprintf(stderr, "%s[%d]:  found type %d in mod %s\n", FILE__, __LINE__, t_id, mods[i]->fileName().c_str());
393                         }
394                 }
395         }
396 }
397
398 void Aggregate::restore_module_by_name(SerializerBase *sb,  
399                 std::string &mname) THROW_SPEC (SerializerError)
400 {
401
402         if (!sb)
403         {
404                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
405                 SER_ERR("FIXME");
406         }
407
408 #if 0
409         Dyninst::ScopedSerializerBase<Dyninst::SymtabAPI::Symtab> *ssb = dynamic_cast<Dyninst::ScopedSerializerBase<Dyninst::SymtabAPI::Symtab> *>(sb);
410
411         if (!ssb)
412         {
413                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME: %s\n", FILE__, __LINE__, typeid(sb).name());
414                 SER_ERR("FIXME");
415         }
416         Symtab *st = ssb->getScope();
417 #endif
418                 SerContextBase *scb = sb->getContext();
419                 if (!scb)
420                 {
421                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
422                         SER_ERR("FIXME");
423                 }
424
425                 SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
426
427                 if (!scs)
428                 {
429                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
430                         SER_ERR("FIXME");
431                 }
432
433                 Symtab *st = scs->getScope();
434
435
436         if (!st)
437         {
438                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
439                 SER_ERR("FIXME");
440         }
441
442         if (!st->findModuleByName(module_, mname) || !(module_))
443         {
444                 //  This should probably throw, but let's play nice for now
445                 fprintf(stderr, "%s[%d]:  FIXME: aggregate w/out module: %s\n", FILE__, __LINE__, mname.c_str());
446         }
447 }
448
449
450 extern Symbol * getSymForID(SerializerBase *sb, Address id);
451
452 void Aggregate::rebuild_symbol_vector(SerializerBase *sb, std::vector<Address> &symids) THROW_SPEC (SerializerError)
453 {
454         Offset off_accum = 0;
455         for (unsigned long i = 0; i < symids.size(); ++i)
456         {
457                 Symbol *sym = getSymForID(sb, symids[i]);
458                 if (!sym)
459                 {
460                         fprintf(stderr, "%s[%d]:  ERROR rebuilding aggregate: ", __FILE__, __LINE__);
461                         fprintf(stderr, "cannot find symbol for id %p\n", (void *) symids[i]);
462                         continue;
463                 }
464
465                 symbols_.push_back(sym);
466
467                 //  sanity check to make sure that all our symbols share the same offset
468                 if (serializer_debug_flag())
469                 {
470                         if (!off_accum) 
471                                 off_accum = sym->getOffset();
472                         else
473                         {
474                                 if (sym->getOffset() != off_accum)
475                                 {
476                                         fprintf(stderr, "%s[%d]:  INTERNAL ERROR:  mismatch offsets: %p--%p\n", FILE__, __LINE__, (void *)off_accum, (void *)sym->getOffset());
477                                 }
478                         }
479                 }
480
481                 //  This sucks, but apparently there are symbols that are somehow
482                 //  not getting their aggregate fields set properly (before serialize
483                 //  presumably), strangely only affects 64bit cases.  Here we try
484                 //  to correct for this by setting the aggregate values of all symbols
485                 //  at this Offset.  This lookup should be avoided by solving the problem
486                 //  somewhere else (at the source, wherever it is that the rogue symbols
487                 //  are being created and/or lost)
488                 //  
489                 //  Maybe it is also somehow possible that spurious symbols are being
490                 //  created and indexed during deserialize.
491                 SerContextBase *scb = sb->getContext();
492                 if (!scb)
493                 {
494                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
495                         SER_ERR("FIXME");
496                 }
497
498                 SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
499
500                 if (!scs)
501                 {
502                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
503                         SER_ERR("FIXME");
504                 }
505
506                 Symtab *st = scs->getScope();
507
508         if (!st)
509         {
510                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
511                 SER_ERR("FIXME");
512         }
513                 std::vector<Symbol *> *syms = st->findSymbolByOffset(sym->getOffset());
514                 for (unsigned long j = 0; j < syms->size(); ++j)
515                 {
516                         (*syms)[j]->aggregate_ = this;
517                 }
518 #if 0
519                 if (sym->aggregate_)
520                 {
521                         fprintf(stderr, "%s[%d]:  WARNING:  symbol %s already has aggregate!!\n", 
522                                         FILE__, __LINE__, sym->getName().c_str());
523                 }
524
525                 sym->aggregate_ = this;
526 #endif
527         }
528 }
529 #if 0
530 void Aggregate::rebuild_symbol_vector(SerializerBase *sb,  
531                 std::vector<Offset> *sym_offsets) THROW_SPEC (SerializerError)
532 {
533 #if 0
534         ScopedSerializerBase<Symtab> *ssb = dynamic_cast<ScopedSerializerBase<Symtab> *>(sb);
535
536         if (!ssb)
537         {
538                 //fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
539                 SER_ERR("FIXME");
540         }
541
542         Symtab *st = ssb->getScope();
543 #endif
544                 SerContextBase *scb = sb->getContext();
545                 if (!scb)
546                 {
547                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
548                         SER_ERR("FIXME");
549                 }
550
551                 SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
552
553                 if (!scs)
554                 {
555                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
556                         SER_ERR("FIXME");
557                 }
558
559                 Symtab *st = scs->getScope();
560
561         if (!st)
562         {
563                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
564                 SER_ERR("FIXME");
565         }
566
567         if (!sym_offsets)
568         {
569                 //  can't have any aggregates w/out symbols
570                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
571                 SER_ERR("FIXME");
572         }
573
574         if (!sym_offsets->size())
575         {
576                 //  can't have any aggregates w/out symbols
577                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
578                 SER_ERR("FIXME");
579         }
580
581         //symbols_.resize(sym_offsets->size());
582
583         for (unsigned int i = 0; i < sym_offsets->size(); ++i)
584         {
585                 std::vector<Symbol *> *syms = st->findSymbolByOffset((*sym_offsets)[i]);
586
587                 if (!syms)
588                 {
589                         //  Should throw here, but for now let's just scream
590                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
591                 }
592                 else
593                 {
594                         //  Not sure if we should interpret multiple symbols sharing that same offset
595                         //  as an error (probably not)
596 #if 0
597                         for (unsigned int i = 0; i < syms->size(); ++i)
598                         {
599                                 Symbol *s = (*syms)[i];
600                                 assert(s);
601                                 symbols_.push_back(s);
602                                 if (!s->aggregate_)
603                                 {
604                                         s->aggregate_ = this;
605                                 }
606                                 else
607                                 {
608                                         fprintf(stderr, "%s[%d]:  WARNING:  symbol %s already has aggregate!!\n", FILE__, __LINE__, s->getName().c_str());
609                                 }
610                         }
611 #endif
612                         //  This is annoying...  apparently we have several symbols for a given offset
613                         //  ...  while this might be theoretically OK, it's really probably a bug 
614                         //  somewhere else where we build up our indexes.
615                         if (syms->size())
616                         {
617                                 Symbol *s = (*syms)[0];
618                                 assert(s);
619                                 symbols_.push_back(s);
620                                 if (!s->aggregate_)
621                                 {
622                                         s->aggregate_ = this;
623                                 }
624                                 else
625                                 {
626                                         fprintf(stderr, "%s[%d]:  WARNING:  symbol %s already has aggregate!!\n", FILE__, __LINE__, s->getName().c_str());
627                                 }
628                         }
629                         if (syms->size() > 1)
630                         {
631                                 if (*(*syms)[0] == *(*syms)[1])
632                                 {
633                                         fprintf(stderr, "%s[%d]:  DESERIALIZE:  symbols are identical\n", FILE__, __LINE__);
634                                 }
635                                 else
636                                 {
637                                         fprintf(stderr, "%s[%d]:  DESERIALIZE:  symbols are not identical: sym0:\n", FILE__, __LINE__);
638                                         std::cerr << *((*syms)[0]) << std::endl;
639                                         std::cerr << "sym1:" << std::endl;
640                                         std::cerr << *((*syms)[1]) << std::endl;
641
642                                 }
643
644                         }
645                 }
646
647         }
648 }
649 #endif
650
651 std::ostream &operator<<(std::ostream &os, const Dyninst::SymtabAPI::Aggregate &a)
652 {
653         std::string modname = a.module_ ? a.module_->fullName() : std::string("no_mod");
654         os   << "Aggregate{"
655                 << " Module=" << modname
656                 << " MangledNames=["; 
657                 for (unsigned int i = 0; i < a.mangledNames_.size(); ++i)
658                 {
659                         os << a.mangledNames_[i];
660                         if ((i + 1) < a.mangledNames_.size())
661                                 os << ", ";
662                 }
663                 os << "]";
664
665                 os << " PrettyNames=["; 
666                 for (unsigned int i = 0; i < a.prettyNames_.size(); ++i)
667                 {
668                         os << a.prettyNames_[i];
669                         if ((i + 1) < a.prettyNames_.size())
670                                 os << ", ";
671                 }
672                 os << "]";
673
674                 os << " TypedNames=["; 
675                 for (unsigned int i = 0; i < a.typedNames_.size(); ++i)
676                 {
677                         os << a.typedNames_[i];
678                         if ((i + 1) < a.typedNames_.size())
679                                 os << ", ";
680                 }
681                 os << "]";
682                 os << " }";
683
684                 return os;
685 }
686
687 void Aggregate::serialize_aggregate(SerializerBase * sb, const char * tag) THROW_SPEC (SerializerError)
688 {
689         std::string modname = module_ ? module_->fullName() : std::string("");
690         std::vector<Address> symids;
691         for (unsigned long i = 0; i < symbols_.size(); ++i)
692         {
693                 assert(symbols_[i]);
694                 assert(sizeof(Address) == sizeof(void *));
695                 symids.push_back((Address) symbols_[i]);
696         }
697
698 #if 0
699         std::vector<Offset> sym_offsets;
700         sym_offsets.resize(symbols_.size());
701
702         //fprintf(stderr, "%s[%d]:  serialize_aggregate, module = %p\n", FILE__, __LINE__, module_);
703
704         for (unsigned int i = 0; i < symbols_.size(); ++i)
705         {
706                 assert(symbols_[i]);
707                 sym_offsets[i] = symbols_[i]->offset_;
708         }
709         fprintf(stderr, "%s[%d]:  serializing modname %s, with %ld symbols\n", FILE__, __LINE__, modname.c_str(), sym_offsets.size());
710 #endif
711
712         try
713         {
714                 ifxml_start_element(sb, tag);
715                 gtranslate(sb, modname, "moduleName");
716                 //  Arguably we should be able to reconstruct these name lists from the set of 
717                 //  symbols, right?  
718                 gtranslate(sb, mangledNames_, "mangledNameList");
719                 gtranslate(sb, prettyNames_, "prettyNameList");
720                 gtranslate(sb, typedNames_, "typedNameList");
721                 gtranslate(sb, symbols_, "aggregatedSymbols", "aggregateSymbol");
722 #if 0
723                 gtranslate(sb, sym_offsets, "symbolOffsetList");
724 #endif
725                 gtranslate(sb, symids, "symbolIDList");
726                 ifxml_end_element(sb, tag);
727
728                 if (sb->isBin() && sb->isInput())
729                 {
730                         restore_module_by_name(sb, modname);
731                         rebuild_symbol_vector(sb, symids);
732                 }
733
734 #if 0
735                 if (sb->isBin() && sb->isInput())
736                 {
737                         fprintf(stderr, "%s[%d]:  DESERIALIZE AGGREGATE %s, %lu offsets\n", FILE__, __LINE__, prettyNames_.size() ? prettyNames_[0].c_str() : "no_names", sym_offsets.size());
738                         rebuild_symbol_vector(sb, &sym_offsets);
739                 }
740 #endif
741         }
742         SER_CATCH(tag);
743
744         //fprintf(stderr, "%s[%d]:  serialize_aggregate, module = %p\n", FILE__, __LINE__, module_);
745 }
746
747 bool Aggregate::operator==(const Aggregate &a)
748 {
749         if (mangledNames_.size() != a.mangledNames_.size()) return false;
750         if (prettyNames_.size() != a.prettyNames_.size()) return false;
751         if (typedNames_.size() != a.typedNames_.size()) return false;
752         if (symbols_.size() != a.symbols_.size()) return false;
753         if (module_ && !a.module_) return false;
754         if (!module_ && a.module_) return false;
755         if (module_ && (module_->fullName() != a.module_->fullName())) return false;
756
757         for (unsigned int i = 0; i < mangledNames_.size(); ++i)
758         {
759                 if (mangledNames_[i] != a.mangledNames_[i]) return false;
760         }
761         for (unsigned int i = 0; i < prettyNames_.size(); ++i)
762         {
763                 if (prettyNames_[i] != a.prettyNames_[i]) return false;
764         }
765         for (unsigned int i = 0; i < typedNames_.size(); ++i)
766         {
767                 if (typedNames_[i] != a.typedNames_[i]) return false;
768         }
769         for (unsigned int i = 0; i < symbols_.size(); ++i)
770         {
771                 Symbol *s1 = symbols_[i];
772                 Symbol *s2 = a.symbols_[i];
773                 if (s1 && !s2) return false;
774                 if (!s1 && s2) return false;
775                 if (!s1)
776                         fprintf(stderr, "%s[%d]:  WARN:  NULL Symbol pointer here\n", FILE__, __LINE__);
777                 else
778                 {
779                         //  just compare offset and a couple other params
780                         if (s1->getOffset() != s2->getOffset()) return false;
781                         if (s1->getType() != s2->getType()) return false;
782                         if (s1->getSize() != s2->getSize()) return false;
783                 }
784         }
785
786         return true;
787 }