windows build fixes and some more work on symtab serialization
[dyninst.git] / symtabAPI / src / Symtab.C
1 /*
2  * Copyright (c) 1996-2008 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 <stdlib.h>
34 #include <assert.h>
35 #include <string.h>
36 #include <algorithm>
37
38 #include "common/h/Timer.h"
39 #include "common/h/debugOstream.h"
40 #include "common/h/serialize.h"
41 #include "common/h/pathName.h"
42
43 #include "Serialization.h"
44 #include "Symtab.h"
45 #include "Module.h"
46 #include "Collections.h"
47 #include "Function.h"
48 #include "Variable.h"
49
50 #include "annotations.h"
51
52 #include "debug.h"
53
54 #include "symtabAPI/src/Object.h"
55
56 #if !defined(os_windows)
57 #include <dlfcn.h>
58 #else
59 #include <windows.h>
60 #endif
61
62 #include <iomanip>
63 #include <stdarg.h>
64
65 using namespace Dyninst;
66 using namespace Dyninst::SymtabAPI;
67 using namespace std;
68
69 static std::string errMsg;
70 extern bool parseCompilerType(Object *);
71
72 void pd_log_perror(const char *msg)
73 {
74    errMsg = std::string(msg);
75 };
76
77
78 SymtabError serr;
79
80 std::vector<Symtab *> Symtab::allSymtabs;
81 builtInTypeCollection *Symtab::builtInTypes = NULL;
82 typeCollection *Symtab::stdTypes = NULL;
83  
84 SymtabError Symtab::getLastSymtabError()
85 {
86     return serr;
87 }
88
89 void setSymtabError(SymtabError new_err)
90 {
91    serr = new_err;
92 }
93
94 std::string Symtab::printError(SymtabError serr)
95 {
96     switch (serr)
97     {
98        case Obj_Parsing:
99            return "Failed to parse the Object"+errMsg;
100        case Syms_To_Functions:
101            return "Failed to convert Symbols to Functions";
102        case No_Such_Function:
103            return "Function does not exist";
104        case No_Such_Variable:
105            return "Variable does not exist";
106        case No_Such_Module:
107           return "Module does not exist";
108        case No_Such_Region:
109            return "Region does not exist";
110        case No_Such_Symbol:
111            return "Symbol does not exist";
112        case Not_A_File:
113            return "Not a File. Call openArchive()";
114        case Not_An_Archive:
115            return "Not an Archive. Call openFile()";
116        case Export_Error:
117            return "Error Constructing XML"+errMsg;
118        case Invalid_Flags:
119           return "Flags passed are invalid.";
120        case No_Error:
121           return "No previous Error.";
122        default:
123           return "Unknown Error";
124     }           
125 }
126
127 void Symtab::setupTypes()
128 {
129     /*
130      * Create the "error" and "untyped" types.
131      */
132     std::string name = "<error>";
133     type_Error   = Type::createFake(name);
134     name = "<no type>";
135     type_Untyped = Type::createFake(name);
136     setupStdTypes();
137 }    
138
139 void Symtab::setupStdTypes() 
140 {
141    if (builtInTypes)
142         return;
143
144    builtInTypes = new builtInTypeCollection;
145    typeScalar *newType;
146
147    // NOTE: integral type  mean twos-complement
148    // -1  int, 32 bit signed integral type
149    // in stab document, size specified in bits, system size is in bytes
150    builtInTypes->addBuiltInType(newType = new typeScalar(-1, 4, "int", true));
151    newType->decrRefCount();
152    // -2  char, 8 bit type holding a character. GDB & dbx(AIX) treat as signed
153    builtInTypes->addBuiltInType(newType = new typeScalar(-2, 1, "char", true));
154    newType->decrRefCount();
155    // -3  short, 16 bit signed integral type
156    builtInTypes->addBuiltInType(newType = new typeScalar(-3, 2, "short", true));
157    newType->decrRefCount();
158    // -4  long, 32/64 bit signed integral type
159    builtInTypes->addBuiltInType(newType = new typeScalar(-4, sizeof(long), "long", true));
160    newType->decrRefCount();
161    // -5  unsigned char, 8 bit unsigned integral type
162    builtInTypes->addBuiltInType(newType = new typeScalar(-5, 1, "unsigned char"));
163    newType->decrRefCount();
164    // -6  signed char, 8 bit signed integral type
165    builtInTypes->addBuiltInType(newType = new typeScalar(-6, 1, "signed char", true));
166    newType->decrRefCount();
167    // -7  unsigned short, 16 bit unsigned integral type
168    builtInTypes->addBuiltInType(newType = new typeScalar(-7, 2, "unsigned short"));
169    newType->decrRefCount();
170    // -8  unsigned int, 32 bit unsigned integral type
171    builtInTypes->addBuiltInType(newType = new typeScalar(-8, 4, "unsigned int"));
172    newType->decrRefCount();
173    // -9  unsigned, 32 bit unsigned integral type
174    builtInTypes->addBuiltInType(newType = new typeScalar(-9, 4, "unsigned"));
175    newType->decrRefCount();
176    // -10 unsigned long, 32 bit unsigned integral type
177    builtInTypes->addBuiltInType(newType = new typeScalar(-10, sizeof(unsigned long), "unsigned long"));
178    newType->decrRefCount();
179    // -11 void, type indicating the lack of a value
180    //  XXX-size may not be correct jdd 4/22/99
181    builtInTypes->addBuiltInType(newType = new typeScalar(-11, 0, "void", false));
182    newType->decrRefCount();
183    // -12 float, IEEE single precision
184    builtInTypes->addBuiltInType(newType = new typeScalar(-12, sizeof(float), "float", true));
185    newType->decrRefCount();
186    // -13 double, IEEE double precision
187    builtInTypes->addBuiltInType(newType = new typeScalar(-13, sizeof(double), "double", true));
188    newType->decrRefCount();
189    // -14 long double, IEEE double precision, size may increase in future
190    builtInTypes->addBuiltInType(newType = new typeScalar(-14, sizeof(long double), "long double", true));
191    newType->decrRefCount();
192    // -15 integer, 32 bit signed integral type
193    builtInTypes->addBuiltInType(newType = new typeScalar(-15, 4, "integer", true));
194    newType->decrRefCount();
195    // -16 boolean, 32 bit type. GDB/GCC 0=False, 1=True, all other values
196    //  have unspecified meaning
197    builtInTypes->addBuiltInType(newType = new typeScalar(-16, sizeof(bool), "boolean"));
198    newType->decrRefCount();
199    // -17 short real, IEEE single precision
200    //  XXX-size may not be correct jdd 4/22/99
201    builtInTypes->addBuiltInType(newType = new typeScalar(-17, sizeof(float), "short real", true));
202    newType->decrRefCount();
203    // -18 real, IEEE double precision XXX-size may not be correct jdd 4/22/99
204    builtInTypes->addBuiltInType(newType = new typeScalar(-18, sizeof(double), "real", true));
205    newType->decrRefCount();
206    // -19 stringptr XXX- size of void * -- jdd 4/22/99
207    builtInTypes->addBuiltInType(newType = new typeScalar(-19, sizeof(void *), "stringptr"));
208    newType->decrRefCount();
209    // -20 character, 8 bit unsigned character type
210    builtInTypes->addBuiltInType(newType = new typeScalar(-20, 1, "character"));
211    newType->decrRefCount();
212    // -21 logical*1, 8 bit type (Fortran, used for boolean or unsigned int)
213    builtInTypes->addBuiltInType(newType = new typeScalar(-21, 1, "logical*1"));
214    newType->decrRefCount();
215    // -22 logical*2, 16 bit type (Fortran, some for boolean or unsigned int)
216    builtInTypes->addBuiltInType(newType = new typeScalar(-22, 2, "logical*2"));
217    newType->decrRefCount();
218    // -23 logical*4, 32 bit type (Fortran, some for boolean or unsigned int)
219    builtInTypes->addBuiltInType(newType = new typeScalar(-23, 4, "logical*4"));
220    newType->decrRefCount();
221    // -24 logical, 32 bit type (Fortran, some for boolean or unsigned int)
222    builtInTypes->addBuiltInType(newType = new typeScalar(-24, 4, "logical"));
223    newType->decrRefCount();
224    // -25 complex, consists of 2 IEEE single-precision floating point values
225    builtInTypes->addBuiltInType(newType = new typeScalar(-25, sizeof(float)*2, "complex", true));
226    newType->decrRefCount();
227    // -26 complex, consists of 2 IEEE double-precision floating point values
228    builtInTypes->addBuiltInType(newType = new typeScalar(-26, sizeof(double)*2, "complex*16", true));
229    newType->decrRefCount();
230    // -27 integer*1, 8 bit signed integral type
231    builtInTypes->addBuiltInType(newType = new typeScalar(-27, 1, "integer*1", true));
232    newType->decrRefCount();
233    // -28 integer*2, 16 bit signed integral type
234    builtInTypes->addBuiltInType(newType = new typeScalar(-28, 2, "integer*2", true));
235    newType->decrRefCount();
236
237    /* Quick hack to make integer*4 compatible with int for Fortran
238       jnb 6/20/01 */
239    // This seems questionable - let's try removing that hack - jmo 05/21/04
240    /*
241      builtInTypes->addBuiltInType(newType = new type("int",-29,
242      built_inType, 4));
243      newType->decrRefCount();
244    */
245    // -29 integer*4, 32 bit signed integral type
246    builtInTypes->addBuiltInType(newType = new typeScalar(-29, 4, "integer*4", true));
247    newType->decrRefCount();
248    // -30 wchar, Wide character, 16 bits wide, unsigned (unknown format)
249    builtInTypes->addBuiltInType(newType = new typeScalar(-30, 2, "wchar"));
250    newType->decrRefCount();
251 #if defined(os_windows)
252    // -31 long long, 64 bit signed integral type
253    builtInTypes->addBuiltInType(newType = new typeScalar(-31, sizeof(LONGLONG), "long long", true));
254    newType->decrRefCount();
255    // -32 unsigned long long, 64 bit unsigned integral type
256    builtInTypes->addBuiltInType(newType = new typeScalar(-32, sizeof(ULONGLONG), "unsigned long long"));
257    newType->decrRefCount();
258 #else
259    // -31 long long, 64 bit signed integral type
260    builtInTypes->addBuiltInType(newType = new typeScalar(-31, sizeof(long long), "long long", true));
261    newType->decrRefCount();
262    // -32 unsigned long long, 64 bit unsigned integral type
263    builtInTypes->addBuiltInType(newType = new typeScalar(-32, sizeof(unsigned long long), "unsigned long long"));
264    newType->decrRefCount();
265 #endif
266    // -33 logical*8, 64 bit unsigned integral type
267    builtInTypes->addBuiltInType(newType = new typeScalar(-33, 8, "logical*8"));
268    newType->decrRefCount();
269    // -34 integer*8, 64 bit signed integral type
270    builtInTypes->addBuiltInType(newType = new typeScalar(-34, 8, "integer*8", true));
271    newType->decrRefCount();
272
273         /*
274     * Initialize hash table of standard types.
275     */
276         if (stdTypes)
277         return;
278
279    stdTypes = typeCollection::getGlobalTypeCollection();
280    stdTypes->addType(newType = new typeScalar(-1, sizeof(int), "int"));
281    newType->decrRefCount();
282
283    Type *charType = new typeScalar(-2, sizeof(char), "char");
284    stdTypes->addType(charType);
285
286         std::string tName = "char *";
287         typePointer *newPtrType;
288    stdTypes->addType(newPtrType = new typePointer(-3, charType, tName));
289    charType->decrRefCount();
290    newPtrType->decrRefCount();
291
292    Type *voidType = new typeScalar(-11, 0, "void", false);
293    stdTypes->addType(voidType);
294
295         tName = "void *";
296    stdTypes->addType(newPtrType = new typePointer(-4, voidType, tName));
297    voidType->decrRefCount();
298    newPtrType->decrRefCount();
299
300    stdTypes->addType(newType = new typeScalar(-12, sizeof(float), "float"));
301    newType->decrRefCount();
302
303 #if defined(i386_unknown_nt4_0)
304    stdTypes->addType(newType = new typeScalar(-31, sizeof(LONGLONG), "long long"));    
305 #else
306    stdTypes->addType(newType = new typeScalar(-31, sizeof(long long), "long long"));
307 #endif
308
309         newType->decrRefCount();
310
311    return;
312 }
313
314 SYMTAB_EXPORT unsigned Symtab::getAddressWidth() const 
315 {
316    return address_width_;
317 }
318  
319 SYMTAB_EXPORT bool Symtab::isNativeCompiler() const 
320 {
321     return nativeCompiler; 
322 }
323  
324
325 SYMTAB_EXPORT Symtab::Symtab(MappedFile *mf_) :
326    AnnotatableSparse(),
327    mf(mf_), 
328    mfForDebugInfo(mf_),
329    obj_private(NULL)
330 {   
331     init_debug_symtabAPI();
332 }   
333
334
335 SYMTAB_EXPORT Symtab::Symtab() :
336    obj_private(NULL)
337 {
338     init_debug_symtabAPI();
339     create_printf("%s[%d]: Created symtab via default constructor\n", FILE__, __LINE__);
340     defaultNamespacePrefix = "";
341 }
342
343 SYMTAB_EXPORT bool Symtab::isExec() const 
344 {
345     return is_a_out; 
346 }
347
348 SYMTAB_EXPORT bool Symtab::isStripped() 
349 {
350 #if defined(os_linux) || defined(os_solaris)
351     Region *sec;
352     return findRegion(sec,".symtab");
353 #else
354     return (no_of_symbols==0);
355 #endif
356 }
357
358 SYMTAB_EXPORT Offset Symtab::imageOffset() const 
359 {
360     return imageOffset_;
361 }
362
363 SYMTAB_EXPORT Offset Symtab::dataOffset() const 
364
365     return dataOffset_;
366 }
367
368 SYMTAB_EXPORT Offset Symtab::dataLength() const 
369 {
370     return dataLen_;
371
372
373 SYMTAB_EXPORT Offset Symtab::imageLength() const 
374 {
375     return imageLen_;
376 }
377 /*
378 SYMTAB_EXPORT char* Symtab::image_ptr ()  const 
379 {
380    return code_ptr_;
381 }
382
383 SYMTAB_EXPORT char* Symtab::data_ptr ()  const 
384
385    return data_ptr_;
386 }
387 */
388 SYMTAB_EXPORT const char*  Symtab::getInterpreterName() const 
389 {
390    if (interpreter_name_.length())
391       return interpreter_name_.c_str();
392    return NULL;
393 }
394  
395 SYMTAB_EXPORT Offset Symtab::getEntryOffset() const 
396
397    return entry_address_;
398 }
399
400 SYMTAB_EXPORT Offset Symtab::getBaseOffset() const 
401 {
402    return base_address_;
403 }
404
405 SYMTAB_EXPORT Offset Symtab::getLoadOffset() const 
406
407    return load_address_;
408 }
409
410 SYMTAB_EXPORT Offset Symtab::getTOCoffset() const 
411 {
412    return toc_offset_;
413 }
414
415 SYMTAB_EXPORT string Symtab::getDefaultNamespacePrefix() const
416 {
417     return defaultNamespacePrefix;
418 }
419         
420         
421 // TODO -- is this g++ specific
422 bool Symtab::buildDemangledName( const std::string &mangled, 
423       std::string &pretty,
424       std::string &typed,
425       bool nativeCompiler, 
426       supportedLanguages lang )
427 {
428    /* The C++ demangling function demangles MPI__Allgather (and other MPI__
429     * functions with start with A) into the MPI constructor.  In order to
430     * prevent this a hack needed to be made, and this seemed the cleanest
431     * approach.
432     */
433
434    if ((mangled.length()>5) && (mangled.substr(0,5)==std::string("MPI__"))) 
435    {
436       return false;
437    }      
438
439    /* If it's Fortran, eliminate the trailing underscores, if any. */
440    if (lang == lang_Fortran 
441          || lang == lang_CMFortran 
442          || lang == lang_Fortran_with_pretty_debug )
443    {
444       if ( mangled[ mangled.length() - 1 ] == '_' ) 
445       {
446          char * demangled = P_strdup( mangled.c_str() );
447          demangled[ mangled.length() - 1 ] = '\0';
448          pretty = std::string( demangled );
449
450          free ( demangled );
451          return true;
452       }
453       else 
454       {
455          /* No trailing underscores, do nothing */
456          return false;
457       }
458    } /* end if it's Fortran. */
459
460    //  Check to see if we have a gnu versioned symbol on our hands.
461    //  These are of the form <symbol>@<version> or <symbol>@@<version>
462    //
463    //  If we do, we want to create a "demangled" name for the one that
464    //  is of the form <symbol>@@<version> since this is, by definition,
465    //  the default.  The "demangled" name will just be <symbol>
466
467    //  NOTE:  this is just a 0th order approach to dealing with versioned
468    //         symbols.  We may need to do something more sophisticated
469    //         in the future.  JAW 10/03
470
471 #if !defined(os_windows)
472
473    char *atat;
474
475    if (NULL != (atat = strstr(mangled.c_str(), "@@"))) 
476    {
477         pretty = mangled.substr(0 /*start pos*/, 
478                         (int)(atat - mangled.c_str())/*len*/);
479         //char msg[256];
480         //sprintf(msg, "%s[%d]: 'demangling' versioned symbol: %s, to %s",
481         //          __FILE__, __LINE__, mangled.c_str(), pretty.c_str());
482
483         //cerr << msg << endl;
484         //logLine(msg);
485       
486         return true;
487     }
488
489 #endif
490
491     bool retval = false;
492   
493     /* Try demangling it. */
494     char * demangled = P_cplus_demangle( mangled.c_str(), nativeCompiler, false);
495     if (demangled) 
496     {
497         pretty = std::string( demangled );
498         retval = true;
499     }
500   
501     char *t_demangled = P_cplus_demangle(mangled.c_str(), nativeCompiler, true);
502     if (t_demangled && (strcmp(t_demangled, demangled) != 0)) 
503     {
504         typed = std::string(t_demangled);
505         retval = true;
506     }
507
508     if (demangled)
509         free(demangled);
510     if (t_demangled)
511         free(t_demangled);
512
513     return retval;
514 } /* end buildDemangledName() */
515
516
517 /*
518  * extractSymbolsFromFile
519  *
520  * Create a Symtab-level list of symbols by pulling out data
521  * from the low-level parse (linkedFile).
522  * Technically this causes a duplication of symbols; however,
523  * we will be rewriting these symbols and so we need our own
524  * copy. 
525  *
526  * TODO: delete the linkedFile once we're done?
527  */
528
529 bool Symtab::extractSymbolsFromFile(Object *linkedFile, std::vector<Symbol *> &raw_syms) 
530 {
531     for (SymbolIter symIter(*linkedFile); symIter; symIter++) {
532         Symbol *sym = symIter.currval();
533
534         // If a symbol starts with "." we want to skip it. These indicate labels in the
535         // code. 
536         
537         // removed 1/09: this should be done in Dyninst, not Symtab
538 #if 0
539         if (sym->getMangledName()[0] == '.') 
540             continue;
541 #endif
542
543         // check for undefined dynamic symbols. Used when rewriting relocation section.
544         // relocation entries have references to these undefined dynamic symbols.
545         // We also have undefined symbols for the static binary case.
546         
547         if (sym->getSec() == NULL && !sym->isAbsolute()) {
548             undefDynSyms[sym->getMangledName()].push_back(sym);
549             continue;
550         }
551
552         // Check whether this symbol has a valid offset. If they do not we have a
553         // consistency issue. This should be a null check.
554
555         // Symbols can have an offset of 0 if they don't refer to things within a file.
556 #if 0
557         if (!isValidOffset(sym->getAddr())) {
558             fprintf(stderr, "Symbol %s has invalid offset 0x%lx\n", sym->getName().c_str(), sym->getAddr());
559             fprintf(stderr, "... in file %s\n", name().c_str());
560             return false;
561         }
562 #endif
563
564         raw_syms.push_back(sym);
565     }
566
567     return true;
568 }
569
570 /*
571  * fixSymModules
572  * 
573  * Add Module information to all symbols. 
574  */
575
576 bool Symtab::fixSymModules(std::vector<Symbol *> &raw_syms) 
577 {
578     for (unsigned i = 0; i < raw_syms.size(); i++) {
579         fixSymModule(raw_syms[i]);
580     }
581     return true;
582 }
583
584 /*
585  * demangleSymbols
586  *
587  * Perform name demangling on all symbols.
588  */
589
590 bool Symtab::demangleSymbols(std::vector<Symbol *> &raw_syms) 
591 {
592     for (unsigned i = 0; i < raw_syms.size(); i++) {
593         demangleSymbol(raw_syms[i]);
594     }
595     return true;
596 }
597
598 /*
599  * createIndices
600  *
601  * We index symbols by various attributes for quick lookup. Build those
602  * indices here. 
603  */
604
605 bool Symtab::createIndices(std::vector<Symbol *> &raw_syms) {
606     for (unsigned i = 0; i < raw_syms.size(); i++) {
607         addSymbolToIndices(raw_syms[i]);
608     }
609     return true;
610 }
611
612 /*
613  * createAggregates
614  *
615  * Frequently there will be multiple Symbols that refer to a single 
616  * code object (e.g., function or variable). We use separate objects
617  * to refer to these aggregates, and build those objects here. 
618  */
619
620 bool Symtab::createAggregates() 
621 {
622     for (unsigned i = 0; i < everyDefinedSymbol.size(); i++) 
623         {
624         addSymbolToAggregates(everyDefinedSymbol[i]);
625     }
626     return true;
627 }
628  
629 bool Symtab::fixSymModule(Symbol *&sym) 
630 {
631     //////////
632     //////////
633     //////////
634     //
635     // It has been decided that all libraries shall have only one
636     // module named after the library. The a.out has one module
637     // per (reported) source file, plus DEFAULT_MODULE for everything
638     // else. This is enforced here, although the Object-* files might
639     // do it as well.
640     Module *mod = NULL;
641     if (getObjectType() == obj_SharedLib) {
642         mod = getDefaultModule();
643     }
644     else {
645         std::string modName = getObject()->findModuleForSym(sym);
646         if (modName.length() == 0) {
647             mod = getDefaultModule();
648         }
649         else {
650             mod = getOrCreateModule(modName, sym->getOffset());
651         }
652     }
653     if (!mod)
654         return false;
655
656     sym->setModule(mod);
657     return true;
658 }
659
660 bool Symtab::demangleSymbol(Symbol *&sym) {
661     switch (sym->getType()) {
662     case Symbol::ST_FUNCTION: {
663         Module *rawmod = sym->getModule();
664         assert(rawmod);
665         
666         // At this point we need to generate the following information:
667         // A symtab name.
668         // A pretty (demangled) name.
669         // The symtab name goes in the global list as well as the module list.
670         // Same for the pretty name.
671         // Finally, check addresses to find aliases.
672         
673         std::string mangled_name = sym->getMangledName();
674         std::string working_name = mangled_name;
675         
676 #if !defined(os_windows)        
677         //Remove extra stabs information
678         const char *p = strchr(working_name.c_str(), ':');
679         if( p ) {
680             unsigned nchars = p - mangled_name.c_str();
681             working_name = std::string(mangled_name.c_str(), nchars);
682         }
683 #endif        
684         
685         std::string pretty_name = working_name;
686         std::string typed_name = working_name;
687         
688         if (!buildDemangledName(working_name, pretty_name, typed_name,
689                                 nativeCompiler, rawmod->language())) {
690             pretty_name = working_name;
691         }
692
693         sym->prettyName_ = pretty_name;
694         sym->typedName_ = typed_name;
695         
696         break;
697     }
698     default: {
699         // All cases where there really shouldn't be a mangled
700         // name, since mangling is for functions.
701         
702         char *prettyName = P_cplus_demangle(sym->getMangledName().c_str(), nativeCompiler, false);
703         if (prettyName) {
704             sym->prettyName_ = prettyName;
705         }
706         break;
707     }
708     }
709     return true;
710 }
711
712 bool Symtab::addSymbolToIndices(Symbol *&sym) 
713 {
714         assert(sym);
715         sym->index_ = everyDefinedSymbol.size();
716
717     everyDefinedSymbol.push_back(sym);
718     
719     symsByOffset[sym->getAddr()].push_back(sym);
720     
721     symsByMangledName[sym->getMangledName()].push_back(sym);
722
723     symsByPrettyName[sym->getPrettyName()].push_back(sym);
724
725     symsByTypedName[sym->getTypedName()].push_back(sym);
726
727     return true;
728 }
729
730 bool Symtab::addSymbolToAggregates(Symbol *&sym) 
731 {
732     switch(sym->getType()) {
733     case Symbol::ST_FUNCTION: {
734         // We want to do the following:
735         // If no function exists, create and add. 
736         // Combine this information
737         //   Add this symbol's names to the function.
738         //   Keep module information 
739
740         Function *func = NULL;
741         findFuncByEntryOffset(func, sym->getAddr());
742         if (!func) {
743             // Create a new function
744             // Also, update the symbol to point to this function.
745
746             func = new Function(sym);
747
748             everyFunction.push_back(func);
749             sorted_everyFunction = false;
750             funcsByOffset[sym->getAddr()] = func;
751         }
752         else {
753             func->addSymbol(sym);
754         }
755         sym->setFunction(func);
756
757         break;
758     }
759     case Symbol::ST_OBJECT: {
760         // The same as the above, but with variables.
761         Variable *var = NULL;
762         findVariableByOffset(var, sym->getAddr());
763         if (!var) {
764             // Create a new function
765             // Also, update the symbol to point to this function.
766             var = new Variable(sym);
767             
768             everyVariable.push_back(var);
769             varsByOffset[sym->getAddr()] = var;
770         }
771         else {
772             var->addSymbol(sym);
773         }
774         sym->setVariable(var);
775         break;
776     }
777     default: {
778         break;
779     }
780     }
781     return true;
782 }
783
784 /* Add the new name to the appropriate symbol index */
785
786 bool Symtab::updateIndices(Symbol *sym, std::string newName, NameType nameType) {
787     if (nameType & mangledName) {
788         // Add this symbol under the given name (as mangled)
789         symsByMangledName[newName].push_back(sym);
790     }
791     if (nameType & prettyName) {
792         // Add this symbol under the given name (as pretty)
793         symsByPrettyName[newName].push_back(sym);
794     }
795     if (nameType & typedName) {
796         // Add this symbol under the given name (as typed)
797         symsByTypedName[newName].push_back(sym);
798     }
799     return true;
800 }
801
802 #if 0
803 /* checkPPC64DescriptorSymbols() is no longer needed.  3-word descriptor
804  * symbols are properly taken care of during symbol parsing.  See
805  * parse_symbols() in Object-elf.C for details.
806  */
807
808 #if defined(ppc64_linux)
809 /* Special case for ppc64 ELF binaries. Sometimes a function has a 3-byte descriptor symbol
810  * along with it in the symbol table and "." preceding its original pretty name for the correct
811  * function symbol. This checks to see if we have a corresponding 3-byte descriptor symbol existing
812  * and if it does we remove the preceding "." from the name of the symbol
813  */
814
815 void Symtab::checkPPC64DescriptorSymbols(Object *linkedFile)
816 {
817    // find the real functions -- those with the correct type in the symbol table
818    for(SymbolIter symIter(*linkedFile); symIter;symIter++)
819    {
820       Symbol *lookUp = symIter.currval();
821       const char *np = lookUp->getMangledName().c_str();
822       if(!np)
823          continue;
824
825       if(np[0] == '.' && (lookUp->getType() == Symbol::ST_FUNCTION))
826       {
827          std::vector<Symbol *>syms;
828          std::string newName = np+1;
829          if(linkedFile->get_symbols(newName, syms) && (syms[0]->getSize() == 24 || syms[0]->getSize() == 0))
830          {
831             //Remove the "." from the name
832             lookUp->mangledNames[0] = newName;
833
834             //Change the type of the descriptor symbol
835             syms[0]->type_ = Symbol::ST_NOTYPE;
836          }
837       }
838    }
839
840 }
841
842 #endif
843 #endif
844
845 //  setModuleLanguages is only called after modules have been defined.
846 //  it attempts to set each module's language, information which is needed
847 //  before names can be demangled.
848 void Symtab::setModuleLanguages(dyn_hash_map<std::string, supportedLanguages> *mod_langs)
849 {
850    if (!mod_langs->size())
851       return;  // cannot do anything here
852    //  this case will arise on non-stabs platforms until language parsing can be introduced at this level
853    std::vector<Module *> *modlist;
854    Module *currmod = NULL;
855    modlist = &_mods;
856    //int dump = 0;
857
858    for (unsigned int i = 0;  i < modlist->size(); ++i)
859    {
860       currmod = (*modlist)[i];
861       supportedLanguages currLang;
862       if (currmod->isShared()) {
863          continue;  // need to find some way to get shared object languages?
864       }
865
866       const std::string fn = currmod->fileName();
867       if (mod_langs->find(currmod->fileName()) != mod_langs->end())
868       {
869          currLang = (*mod_langs)[fn];
870       }
871       else if (fn.rfind(".s") != std::string::npos ||
872             fn.rfind(".asm") != std::string::npos)
873       {
874          currLang = lang_Assembly;
875       }
876       else if (fn.rfind(".c") != std::string::npos)
877       {
878          currLang = lang_C;
879       }
880       else if (fn.rfind(".cpp") != std::string::npos ||
881             fn.rfind(".cc") != std::string::npos ||
882             fn.rfind(".C") != std::string::npos)
883       {
884          currLang = lang_CPlusPlus;
885       }
886       else
887       {
888          continue;
889       }
890       currmod->setLanguage(currLang);
891    }
892 }
893
894 void Symtab::createDefaultModule() {
895     Module *mod = NULL;
896     if (getObjectType() == obj_SharedLib) {
897         mod = new Module(lang_Unknown, 
898                          imageOffset_,
899                          name(),
900                          this);
901     }
902     else {
903         mod = new Module(lang_Unknown, 
904                          imageOffset_,
905                          "DEFAULT_MODULE",
906                          this);
907     }
908     modsByFileName[mod->fileName()] = mod;
909     modsByFullName[mod->fullName()] = mod;
910     _mods.push_back(mod);
911 }
912
913
914
915 Module *Symtab::getOrCreateModule(const std::string &modName, 
916                                   const Offset modAddr)
917 {
918    std::string nameToUse;
919    if (modName.length() > 0)
920       nameToUse = modName;
921    else
922       nameToUse = "DEFAULT_MODULE";
923
924    Module *fm = NULL;
925    if (findModuleByName(fm, nameToUse)) 
926    {
927       return fm;
928    }
929
930     const char *str = nameToUse.c_str();
931     int len = nameToUse.length();
932     assert(len>0);
933
934     // TODO ignore directory definitions for now
935     if (str[len-1] == '/') 
936         return NULL;
937
938     return (newModule(nameToUse, modAddr, lang_Unknown));
939 }
940  
941 Module *Symtab::newModule(const std::string &name, const Offset addr, supportedLanguages lang)
942 {
943     Module *ret = NULL;
944     // modules can be defined several times in C++ due to templates and
945     //   in-line member functions.
946
947     if (findModuleByName(ret, name)) 
948     {
949         return(ret);
950     }
951
952     //parsing_printf("=== image, creating new pdmodule %s, addr 0x%x\n",
953     //                          name.c_str(), addr);
954     
955     std::string fileNm, fullNm;
956     fullNm = name;
957     fileNm = extract_pathname_tail(name);
958
959     // /* DEBUG */ fprintf( stderr, "%s[%d]: In %p: Creating new pdmodule '%s'/'%s'\n", FILE__, __LINE__, this, fileNm.c_str(), fullNm.c_str() );
960
961     ret = new Module(lang, addr, fullNm, this);
962     assert(ret);
963
964     if (modsByFileName.end() != modsByFileName.find(ret->fileName()))
965     {
966        fprintf(stderr, "%s[%d]:  WARN:  LEAK?  already have module with name %s\n", 
967              FILE__, __LINE__, ret->fileName().c_str());
968     }
969
970     if (modsByFullName.end() != modsByFullName.find(ret->fullName()))
971     {
972        fprintf(stderr, "%s[%d]:  WARN:  LEAK?  already have module with name %s\n", 
973              FILE__, __LINE__, ret->fullName().c_str());
974     }
975
976     modsByFileName[ret->fileName()] = ret;
977     modsByFullName[ret->fullName()] = ret;
978     _mods.push_back(ret);
979     
980     return (ret);
981 }
982
983 Symtab::Symtab(std::string filename,bool &err) :
984    is_a_out(false), 
985    main_call_addr_(0),
986    nativeCompiler(false), 
987    isLineInfoValid_(false), 
988    isTypeInfoValid_(false),
989    obj_private(NULL),
990    type_Error(NULL), 
991    type_Untyped(NULL)
992 {
993     init_debug_symtabAPI();
994    // Initialize error parameter
995    err = false;
996    
997    create_printf("%s[%d]: created symtab for %s\n", FILE__, __LINE__, filename.c_str());
998
999 #if defined (os_windows)
1000    extern void fixup_filename(std::string &);
1001    fixup_filename(filename);
1002 #endif
1003
1004    //  createMappedFile handles reference counting
1005    mf = MappedFile::createMappedFile(filename);
1006    if (!mf) {
1007       create_printf("%s[%d]: WARNING: creating symtab for %s, " 
1008                     "createMappedFile() failed\n", FILE__, __LINE__, 
1009                     filename.c_str());
1010       err = true;
1011       return;
1012    }
1013
1014    obj_private = new Object(mf, mfForDebugInfo, pd_log_perror, true);
1015
1016    if (!extractInfo(obj_private))
1017    {
1018       create_printf("%s[%d]: WARNING: creating symtab for %s, extractInfo() " 
1019                     "failed\n", FILE__, __LINE__, filename.c_str());
1020       err = true;
1021    }
1022
1023    defaultNamespacePrefix = "";
1024 }
1025
1026 Symtab::Symtab(char *mem_image, size_t image_size, bool &err) :
1027    is_a_out(false), 
1028    main_call_addr_(0),
1029    nativeCompiler(false),
1030    isLineInfoValid_(false),
1031    isTypeInfoValid_(false),
1032    obj_private(NULL),
1033    type_Error(NULL), 
1034    type_Untyped(NULL)
1035 {
1036    // Initialize error parameter
1037    err = false;
1038   
1039    create_printf("%s[%d]: created symtab for memory image at addr %u\n", 
1040                  FILE__, __LINE__, mem_image);
1041
1042    //  createMappedFile handles reference counting
1043    mf = MappedFile::createMappedFile(mem_image, image_size);
1044    if (!mf) {
1045       create_printf("%s[%d]: WARNING: creating symtab for memory image at " 
1046                     "addr %u, createMappedFile() failed\n", FILE__, __LINE__, 
1047                     mem_image);
1048       err = true;
1049       return;
1050    }
1051
1052    obj_private = new Object(mf, mfForDebugInfo, pd_log_perror, true);
1053
1054    if (!extractInfo(obj_private))
1055    {
1056       create_printf("%s[%d]: WARNING: creating symtab for memory image at addr" 
1057                     "%u, extractInfo() failed\n", FILE__, __LINE__, mem_image);
1058       err = true;
1059    }
1060
1061    defaultNamespacePrefix = "";
1062 }
1063
1064 // Symtab constructor for archive members
1065 #if defined(os_aix) || defined(os_linux) || defined(os_solaris)
1066 Symtab::Symtab(std::string filename, std::string member_name, Offset offset, 
1067                bool &err, void *base) :
1068    member_name_(member_name), 
1069    member_offset_(offset),
1070    is_a_out(false),
1071    main_call_addr_(0), 
1072    nativeCompiler(false), 
1073    isLineInfoValid_(false),
1074    isTypeInfoValid_(false), 
1075    obj_private(NULL),
1076    type_Error(NULL), 
1077    type_Untyped(NULL)
1078 {
1079    mf = MappedFile::createMappedFile(filename);
1080    assert(mf);
1081    obj_private = new Object(mf, mfForDebugInfo, member_name, offset, pd_log_perror, base);
1082    err = extractInfo(obj_private);
1083    defaultNamespacePrefix = "";
1084 }
1085 #else
1086 Symtab::Symtab(std::string, std::string, Offset, bool &, void *)
1087 {
1088     assert(0);
1089 }
1090 #endif
1091
1092 #if defined(os_aix) || defined(os_linux) || defined(os_solaris)
1093 Symtab::Symtab(char *mem_image, size_t image_size, std::string member_name,
1094                        Offset offset, bool &err, void *base) :
1095    member_name_(member_name), 
1096    is_a_out(false), 
1097    main_call_addr_(0),
1098    nativeCompiler(false), 
1099    isLineInfoValid_(false), 
1100    isTypeInfoValid_(false), 
1101    type_Error(NULL), 
1102    type_Untyped(NULL)
1103 {
1104    mf = MappedFile::createMappedFile(mem_image, image_size);
1105    assert(mf);
1106    obj_private = new Object(mf, mf, member_name, offset, pd_log_perror, base);
1107    err = extractInfo(obj_private);
1108    defaultNamespacePrefix = "";
1109 }
1110 #else 
1111 Symtab::Symtab(char *, size_t, std::string , Offset, bool &, void *)
1112 {
1113     assert(0);
1114 }
1115 #endif
1116
1117 bool sort_reg_by_addr(const Region* a, const Region* b)
1118 {
1119    return a->getRegionAddr() < b->getRegionAddr();
1120 }
1121
1122
1123 extern void print_symbols( std::vector< Symbol *>& allsymbols );
1124 extern void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols);
1125
1126 bool Symtab::extractInfo(Object *linkedFile)
1127 {
1128 #if defined(TIMED_PARSE)
1129     struct timeval starttime;
1130     gettimeofday(&starttime, NULL);
1131 #endif
1132     mfForDebugInfo = linkedFile->getMappedFileForDebugInfo();
1133
1134     bool err = true;
1135     imageOffset_ = linkedFile->code_off();
1136     dataOffset_ = linkedFile->data_off();
1137
1138     imageLen_ = linkedFile->code_len();
1139     dataLen_ = linkedFile->data_len();
1140     
1141     if (0 == imageLen_ || 0 == linkedFile->code_ptr()) 
1142     {
1143         // for AIX, code_ptr()==NULL is normal behavior
1144 #if !defined(os_aix)
1145        if (0 == linkedFile->code_ptr()) {
1146           //fprintf(stderr, "[%s][%d]WARNING: null code pointer in Symtab for"
1147           //" file %s, possibly due to a missing .text section.\n",
1148           //__FILE__,__LINE__, file().c_str());
1149           linkedFile->code_ptr_ = (char *) linkedFile->code_off();
1150        }
1151        else 
1152 #endif
1153        {
1154           serr = Obj_Parsing;
1155           return false;
1156        }
1157    }
1158         
1159   //  if (!imageLen_ || !linkedFile->code_ptr()) {
1160   //      serr = Obj_Parsing; 
1161   //      return false; 
1162    // }
1163
1164     no_of_sections = linkedFile->no_of_sections();
1165     newSectionInsertPoint = no_of_sections;
1166     no_of_symbols = linkedFile->no_of_symbols();
1167
1168     hasRel_ = false;
1169     hasRela_ = false;
1170     regions_ = linkedFile->getAllRegions();
1171
1172     for (unsigned index=0;index<regions_.size();index++)
1173     {
1174         if ( regions_[index]->isLoadable() ) 
1175         {
1176            if (     (regions_[index]->getRegionPermissions() == Region::RP_RX) 
1177                  || (regions_[index]->getRegionPermissions() == Region::RP_RWX)) 
1178            {
1179               codeRegions_.push_back(regions_[index]);
1180            }
1181            else 
1182            {
1183                 dataRegions_.push_back(regions_[index]);
1184             }
1185         }
1186
1187         regionsByEntryAddr[regions_[index]->getRegionAddr()] = regions_[index];
1188
1189         if (regions_[index]->getRegionType() == Region::RT_REL) 
1190         {
1191             hasRel_ = true;
1192         }
1193
1194         if (regions_[index]->getRegionType() == Region::RT_RELA) 
1195         {
1196             hasRela_ = true;
1197         }
1198     }
1199     // sort regions_ & codeRegions_ vectors
1200
1201     std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
1202     std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
1203     std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
1204
1205     /* insert error check here. check if parsed */
1206     address_width_ = linkedFile->getAddressWidth();
1207     is_a_out = linkedFile->is_aout();
1208     code_ptr_ = linkedFile->code_ptr();
1209     data_ptr_ = linkedFile->data_ptr();
1210
1211     if (linkedFile->interpreter_name())
1212        interpreter_name_ = std::string(linkedFile->interpreter_name());
1213
1214     entry_address_ = linkedFile->getEntryAddress();
1215     base_address_ = linkedFile->getBaseAddress();
1216     load_address_ = linkedFile->getLoadAddress();
1217     toc_offset_ = linkedFile->getTOCoffset();
1218     object_type_  = linkedFile->objType();
1219     is_eel_ = linkedFile->isEEL();
1220     linkedFile->getSegments(segments_);
1221
1222 #if !defined(os_aix) && !defined(os_windows)
1223     linkedFile->getDependencies(deps_);
1224 #endif
1225
1226 #if defined (os_aix)
1227     //  These should go away
1228     linkedFile->get_stab_info(stabstr_, nstabs_, stabs_, stringpool_);
1229     linkedFile->get_line_info(nlines_, lines_, fdptr_);
1230 #endif
1231
1232 #if defined(os_solaris) || defined(os_aix) || defined(os_linux)
1233     // make sure we're using the right demangler
1234     
1235     nativeCompiler = parseCompilerType(linkedFile);
1236     //parsing_printf("isNativeCompiler: %d\n", nativeCompiler);
1237 #endif
1238     
1239     // define all of the functions
1240     //statusLine("winnowing functions");
1241
1242 #if defined(ppc64_linux)
1243     //checkPPC64DescriptorSymbols(linkedFile);
1244 #endif
1245
1246     // a vector to hold all created symbols until they are properly classified
1247     std::vector<Symbol *> raw_syms;
1248
1249 #ifdef BINEDIT_DEBUG
1250     printf("== from linkedFile...\n");
1251     print_symbol_map(linkedFile->getAllSymbols());
1252 #endif
1253
1254     if (!extractSymbolsFromFile(linkedFile, raw_syms)) 
1255     {
1256         err = false;
1257         serr = Syms_To_Functions;
1258         return false;
1259     }
1260
1261 #ifdef BINEDIT_DEBUG
1262     printf("== in Symtab now...\n");
1263     //print_symbols(raw_syms);
1264     std::vector<Symbol *> undefsyms;
1265     std::map<std::string, std::vector<Symbol *> >::iterator iter;
1266     std::vector<Symbol *>::iterator siter;
1267     for (iter = undefDynSyms.begin(); iter != undefDynSyms.end(); iter++)
1268         for (siter = iter->second.begin(); siter != iter->second.end(); siter++)
1269             undefsyms.push_back(*siter);
1270     //print_symbols(undefsyms);
1271     printf("%d total symbol(s)\n", raw_syms.size() + undefsyms.size());
1272 #endif
1273
1274     // don't sort the symbols--preserve the original ordering
1275     //sort(raw_syms.begin(),raw_syms.end(),symbol_compare);
1276
1277     createDefaultModule();
1278
1279     if (!fixSymModules(raw_syms)) 
1280     {
1281         err = false;
1282         serr = Syms_To_Functions;
1283         return false;
1284     }
1285     getObject()->clearSymsToMods();
1286
1287     // wait until all modules are defined before applying languages to
1288     // them we want to do it this way so that module information comes
1289     // from the function symbols, first and foremost, to avoid any
1290     // internal module-function mismatching.
1291             
1292     // get Information on the language each modules is written in
1293     // (prior to making modules)
1294
1295     dyn_hash_map<std::string, supportedLanguages> mod_langs;
1296     linkedFile->getModuleLanguageInfo(&mod_langs);
1297     setModuleLanguages(&mod_langs);
1298         
1299     // Be sure that module languages are set before demangling, or
1300     // we won't get very far.
1301
1302     if (!demangleSymbols(raw_syms)) 
1303     {
1304         err = false;
1305         serr = Syms_To_Functions;
1306         return false;
1307     }
1308
1309     if (!createIndices(raw_syms)) 
1310     {
1311         err = false;
1312         serr = Syms_To_Functions;
1313         return false;
1314     }
1315
1316     if (!createAggregates()) 
1317     {
1318         err = false;
1319         serr = Syms_To_Functions;
1320         return false;
1321     }
1322         
1323 #if 0
1324     // define all of the functions, this also defines all of the modules
1325     if (!symbolsToFunctions(linkedFile, &raw_syms))
1326     {
1327         fprintf(stderr, "%s[%d] Error converting symbols to functions in file %s\n", 
1328                 __FILE__, __LINE__, mf->filename().c_str());
1329         err = false;
1330         serr = Syms_To_Functions;
1331         return false;
1332     }
1333 #endif
1334         
1335     // Once languages are assigned, we can build demangled names (in
1336     // the wider sense of demangling which includes stripping _'s from
1337     // fortran names -- this is why language information must be
1338     // determined before this step).
1339     
1340     // Also identifies aliases (multiple names with equal addresses)
1341     
1342     //addSymtabVariables();
1343     linkedFile->getAllExceptions(excpBlocks);
1344
1345     vector<relocationEntry >fbt;
1346     linkedFile->get_func_binding_table(fbt);
1347     for(unsigned i=0; i<fbt.size();i++)
1348         relocation_table_.push_back(fbt[i]);
1349     return true;
1350 }
1351
1352 Symtab::Symtab(const Symtab& obj) :
1353    LookupInterface(),
1354    Serializable(),
1355    AnnotatableSparse()
1356 {
1357     create_printf("%s[%d]: Creating symtab 0x%p from symtab 0x%p\n", FILE__, __LINE__, this, &obj);
1358   
1359     member_name_ = obj.member_name_;
1360     imageOffset_ = obj.imageOffset_;
1361     imageLen_ = obj.imageLen_;
1362     dataOffset_ = obj.dataOffset_;
1363     dataLen_ = obj.dataLen_;
1364
1365    isLineInfoValid_ = obj.isLineInfoValid_;
1366    isTypeInfoValid_ = obj.isTypeInfoValid_;
1367
1368    is_a_out = obj.is_a_out;
1369    main_call_addr_ = obj.main_call_addr_; // address of call to main()
1370
1371    nativeCompiler = obj.nativeCompiler;
1372    defaultNamespacePrefix = obj.defaultNamespacePrefix;
1373
1374    //sections
1375    no_of_sections = obj.no_of_sections;
1376    unsigned i;
1377
1378    for (i=0;i<obj.regions_.size();i++)
1379       regions_.push_back(new Region(*(obj.regions_[i])));
1380
1381    for (i=0;i<regions_.size();i++)
1382       regionsByEntryAddr[regions_[i]->getRegionAddr()] = regions_[i];
1383
1384    // TODO FIXME: copying symbols/Functions/Variables
1385
1386    for (i=0;i<obj._mods.size();i++)
1387    {
1388       Module *m = new Module(*(obj._mods[i]));
1389       _mods.push_back(m);
1390       modsByFileName[m->fileName()] = m;
1391       modsByFullName[m->fullName()] = m;
1392       fprintf(stderr, "%s[%d]:  copy ctor creating new module %s\n", 
1393             FILE__, __LINE__, m->fileName().c_str());
1394    }
1395
1396    for (i=0; i<relocation_table_.size();i++) 
1397    {
1398       relocation_table_.push_back(relocationEntry(obj.relocation_table_[i]));
1399       //undefDynSyms[obj.relocation_table_[i].name()] = relocation_table_[i].getDynSym();
1400       undefDynSyms[obj.relocation_table_[i].name()].push_back(relocation_table_[i].getDynSym());
1401
1402    }
1403
1404    for (i=0;i<excpBlocks.size();i++)
1405    {
1406       excpBlocks.push_back(new ExceptionBlock(*(obj.excpBlocks[i])));
1407    }
1408
1409    deps_ = obj.deps_;
1410    setupTypes();
1411 }
1412
1413 // Address must be in code or data range since some code may end up
1414 // in the data segment
1415 bool Symtab::isValidOffset(const Offset where) const
1416 {
1417    return isCode(where) || isData(where);
1418 }
1419
1420 /* Performs a binary search on the codeRegions_ vector, which must
1421  * be kept in sorted order
1422  */
1423 bool Symtab::isCode(const Offset where)  const
1424 {
1425    if (!codeRegions_.size()) 
1426    {
1427       fprintf(stderr, "%s[%d] No code regions in %s \n",
1428             __FILE__, __LINE__, mf->filename().c_str());
1429       return false;
1430    }
1431
1432    // search for "where" in codeRegions_ (code regions must not overlap)
1433    int first = 0; 
1434    int last = codeRegions_.size() - 1;
1435
1436    while (last >= first) 
1437    {
1438       Region *curreg = codeRegions_[(first + last) / 2];
1439       if (where >= curreg->getRegionAddr()
1440             && where < (curreg->getRegionAddr()
1441                + curreg->getDiskSize())) 
1442       {
1443          return true;
1444       }
1445       else if (where < curreg->getRegionAddr()) 
1446       {
1447          last = ((first + last) / 2) - 1;
1448       }
1449       else if (where >= (curreg->getRegionAddr() + curreg->getMemSize()))
1450       {
1451          first = ((first + last) / 2) + 1;
1452       }
1453       else 
1454       {  // "where" is in the range: 
1455          // [memOffset + diskSize , memOffset + memSize)
1456          // meaning that it's in an uninitialized data region 
1457          return false;
1458       }
1459    }
1460
1461    return false;
1462 }
1463
1464 /* Performs a binary search on the dataRegions_ vector, which must
1465  * be kept in sorted order */
1466 bool Symtab::isData(const Offset where)  const
1467 {
1468    if (!dataRegions_.size()) 
1469    {
1470       fprintf(stderr, "%s[%d] No data regions in %s \n",
1471             __FILE__,__LINE__,mf->filename().c_str());
1472       return false;
1473    }
1474
1475    int first = 0; 
1476    int last = dataRegions_.size() - 1;
1477
1478    while (last >= first) 
1479    {
1480       Region *curreg = dataRegions_[(first + last) / 2];
1481
1482       if (     (where >= curreg->getRegionAddr())
1483             && (where < (curreg->getRegionAddr() + curreg->getRegionSize())))
1484       {
1485          return true;
1486       }
1487       else if (where < curreg->getRegionAddr()) 
1488       {
1489          last = ((first + last) / 2) - 1;
1490       }
1491       else 
1492       {
1493          first = ((first + last) / 2) + 1;
1494       }
1495    }
1496
1497    return false;
1498 }
1499
1500 bool Symtab::getFuncBindingTable(std::vector<relocationEntry> &fbt) const
1501 {
1502    fbt = relocation_table_;
1503    return true;
1504 }
1505
1506 SYMTAB_EXPORT std::vector<std::string> &Symtab::getDependencies(){
1507     return deps_;
1508 }
1509
1510
1511 Symtab::~Symtab()
1512 {
1513    // Doesn't do anything yet, moved here so we don't mess with symtab.h
1514    // Only called if we fail to create a process.
1515    // Or delete the a.out...
1516
1517
1518    for (unsigned i = 0; i < regions_.size(); i++) 
1519    {
1520       delete regions_[i];
1521    }
1522
1523    regions_.clear();
1524    codeRegions_.clear();
1525    dataRegions_.clear();
1526    regionsByEntryAddr.clear();
1527
1528    std::vector<Region *> *user_regions = NULL;
1529    getAnnotation(user_regions, UserRegionsAnno);
1530
1531    if (user_regions)
1532    {
1533       for (unsigned i = 0; i < user_regions->size(); ++i) 
1534          delete (*user_regions)[i];
1535       user_regions->clear();
1536    }
1537
1538    // Symbols are copied from linkedFile, and NOT deleted
1539    everyDefinedSymbol.clear();
1540    undefDynSyms.clear();
1541
1542    // TODO make annotation
1543    userAddedSymbols.clear();
1544    symsByOffset.clear();
1545    symsByMangledName.clear();
1546    symsByPrettyName.clear();
1547    symsByTypedName.clear();
1548
1549    for (unsigned i = 0; i < everyFunction.size(); i++) 
1550    {
1551       delete everyFunction[i];
1552    }
1553
1554    everyFunction.clear();
1555    funcsByOffset.clear();
1556
1557    for (unsigned i = 0; i < everyVariable.size(); i++) 
1558    {
1559       delete everyVariable[i];
1560    }
1561
1562    everyVariable.clear();
1563    varsByOffset.clear();
1564
1565    for (unsigned i = 0; i < _mods.size(); i++) 
1566    {
1567       delete _mods[i];
1568    }
1569    _mods.clear();
1570    modsByFileName.clear();
1571    modsByFullName.clear();
1572
1573    for (unsigned i=0;i<excpBlocks.size();i++)
1574       delete excpBlocks[i];
1575
1576    create_printf("%s[%d]: Symtab::~Symtab removing %p from allSymtabs\n", 
1577          FILE__, __LINE__, this);
1578
1579    deps_.clear();
1580
1581    for (unsigned i = 0; i < allSymtabs.size(); i++) 
1582    {
1583       if (allSymtabs[i] == this)
1584          allSymtabs.erase(allSymtabs.begin()+i);
1585    }
1586
1587    //fprintf(stderr, "%s[%d]:  symtab DTOR, mf = %p: %s\n", FILE__, __LINE__, mf, mf->filename().c_str());
1588    //if (mf) MappedFile::closeMappedFile(mf);
1589    //if (mfForDebugInfo) MappedFile::closeMappedFile(mfForDebugInfo);
1590 }       
1591
1592 bool Symtab::exportXML(string file)
1593 {
1594 #if defined (cap_serialization)
1595    try 
1596    {
1597       SerializerXML sb("XMLTranslator", file, sd_serialize, true);
1598       serialize(&sb, "Symtab");
1599 #if 0
1600       SymtabTranslatorXML trans(this, file);
1601       if ( serialize(*this, trans))
1602          return true;
1603 #endif
1604    } 
1605    catch (const SerializerError &err) 
1606    {
1607       fprintf(stderr, "%s[%d]: error serializing xml: %s\n", FILE__, __LINE__, err.what());
1608       return false;
1609    }
1610
1611    return false;
1612 #else
1613    fprintf(stderr, "%s[%d]:  WARNING:  cannot produce %s, serialization not available\n", FILE__, __LINE__, file.c_str());
1614    return false;
1615 #endif
1616 }
1617
1618 #if defined (cap_serialization)
1619 bool Symtab::exportBin(string file)
1620 {
1621    try
1622    {
1623       //  This needs some work (probably want to do object cacheing and retrieval)
1624       SerializerBin sb("BinSerializer", file, sd_serialize, true);
1625       serialize(&sb, "Symtab");
1626
1627 #if 0 
1628       bool verbose = false;
1629       if (strstr(file.c_str(), "cache_ld")) verbose = true;
1630       SymtabTranslatorBin *transptr = SymtabTranslatorBin::getTranslator(this, file, sd_serialize, verbose);
1631       assert(transptr);
1632       SymtabTranslatorBin &trans = *transptr;
1633       if (serialize(*this, trans))
1634          return true;
1635 #endif
1636       fprintf(stderr, "%s[%d]:  binary serialization ok\n", __FILE__, __LINE__);
1637       return true;
1638    }
1639    catch (const SerializerError &err)
1640    {
1641       if (err.code() == SerializerError::ser_err_disabled) 
1642       {
1643          fprintf(stderr, "%s[%d]:  WARN:  serialization is disabled for file %s\n",
1644                FILE__, __LINE__, file.c_str());
1645          return true;
1646       }
1647       else 
1648       {
1649          fprintf(stderr, "%s[%d]: %s\n\tfrom %s[%d], code %d\n", FILE__, __LINE__,
1650                err.what(), err.file().c_str(), err.line(), err.code());
1651       }
1652    }
1653
1654    fprintf(stderr, "%s[%d]:  error doing binary serialization\n", __FILE__, __LINE__);
1655    return false;
1656 }
1657 #else
1658 bool Symtab::exportBin(string) 
1659 {
1660    fprintf(stderr, "%s[%d]:  WARNING:  serialization not available\n", FILE__, __LINE__);
1661    return false;
1662 }
1663 #endif
1664
1665 Symtab *Symtab::importBin(std::string file)
1666 {
1667 #if defined (cap_serialization)
1668    MappedFile *mf= MappedFile::createMappedFile(file);
1669    if (!mf) 
1670    {
1671       fprintf(stderr, "%s[%d]:  failed to map file %s\n", FILE__, __LINE__, file.c_str());
1672       return NULL;
1673    }
1674
1675    Symtab *st = new Symtab(mf);
1676
1677    try
1678    {
1679       bool verbose = false;
1680       if (strstr(file.c_str(), "ld-")) verbose = true;
1681       SerializerBin sb("BinTranslator", file, sd_deserialize, true);
1682       st->serialize(&sb);
1683 #if 0
1684       SymtabTranslatorBin *transptr = SymtabTranslatorBin::getTranslator(st, file, sd_deserialize, verbose);
1685       assert(transptr);
1686       SymtabTranslatorBin &trans = *transptr;
1687       if (deserialize(*st, trans)) {
1688          fprintf(stderr, "%s[%d]:  deserialized '%s' from cache\n", FILE__, __LINE__, file.c_str());
1689          if (!st) fprintf(stderr, "%s[%d]:  FIXME:  no symtab\n", FILE__, __LINE__);
1690          return st;
1691       }
1692 #endif
1693    }
1694
1695    catch (const SerializerError &err)
1696    {
1697       if (err.code() == SerializerError::ser_err_disabled) 
1698       {
1699          fprintf(stderr, "%s[%d]:  WARN:  serialization is disabled for file %s\n",
1700                FILE__, __LINE__, file.c_str());
1701          return NULL;
1702       }
1703
1704       fprintf(stderr, "%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
1705             err.what(), err.file().c_str(), err.line());
1706    }
1707
1708
1709    fprintf(stderr, "%s[%d]:  error doing binary deserialization\n", __FILE__, __LINE__);
1710    delete st;
1711    return NULL;
1712 #else
1713    fprintf(stderr, "%s[%d]:  WARNING:  cannot produce %s, serialization not available\n", FILE__, __LINE__, file.c_str());
1714    return NULL;
1715 #endif
1716 }
1717
1718
1719 bool Symtab::openFile(Symtab *&obj, char *mem_image, size_t size)
1720 {
1721    bool err = false;
1722 #if defined(TIMED_PARSE)
1723    struct timeval starttime;
1724    gettimeofday(&starttime, NULL);
1725 #endif
1726    obj = new Symtab(mem_image, size, err);
1727
1728 #if defined(TIMED_PARSE)
1729     struct timeval endtime;
1730     gettimeofday(&endtime, NULL);
1731     unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1732     unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1733     unsigned long difftime = lendtime - lstarttime;
1734     double dursecs = difftime/(1000 );
1735     cout << __FILE__ << ":" << __LINE__ <<": openFile "<< filename<< " took "<<dursecs <<" msecs" << endl;
1736 #endif
1737     if(!err)
1738     {
1739        allSymtabs.push_back(obj);
1740        obj->setupTypes();       
1741     }
1742     else
1743     {
1744         delete obj;
1745        obj = NULL;
1746     }
1747     // returns true on success (not an error)
1748     return !err;
1749 }
1750
1751 bool Symtab::openFile(Symtab *&obj, std::string filename)
1752 {
1753    bool err = false;
1754 #if defined(TIMED_PARSE)
1755    struct timeval starttime;
1756    gettimeofday(&starttime, NULL);
1757 #endif
1758    unsigned numSymtabs = allSymtabs.size();
1759
1760    // AIX: it's possible that we're reparsing a file with better information
1761    // about it. If so, yank the old one out of the allSymtabs std::vector -- replace
1762    // it, basically.
1763    if ( filename.find("/proc") == std::string::npos)
1764    {
1765       for (unsigned u=0; u<numSymtabs; u++) 
1766       {
1767          assert(allSymtabs[u]);
1768          if (filename == allSymtabs[u]->file()) 
1769          {
1770             // return it
1771             obj = allSymtabs[u];
1772             return true;
1773          }
1774       }   
1775    }
1776
1777 #if defined (cap_serialization)
1778    obj = importBin(filename);
1779
1780    if (!obj) 
1781    {
1782       fprintf(stderr, "%s[%d]:  importBin failed\n", FILE__, __LINE__);
1783    }
1784    else 
1785    {
1786       return true;
1787    }
1788 #endif
1789
1790    obj = new Symtab(filename, err);
1791 #if defined(TIMED_PARSE)
1792    struct timeval endtime;
1793    gettimeofday(&endtime, NULL);
1794    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1795    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1796    unsigned long difftime = lendtime - lstarttime;
1797    double dursecs = difftime/(1000 );
1798    cout << __FILE__ << ":" << __LINE__ <<": openFile "<< filename<< " took "<<dursecs <<" msecs" << endl;
1799 #endif
1800
1801    if (!err)
1802    {
1803       if (filename.find("/proc") == std::string::npos)
1804          allSymtabs.push_back(obj);
1805
1806       obj->setupTypes();        
1807
1808 #if defined (cap_serialization)
1809       fprintf(stderr, "%s[%d]:  doing bin-serialize for %s\n", 
1810             FILE__, __LINE__, filename.c_str());
1811
1812       if (!obj->exportBin(filename))
1813       {
1814          fprintf(stderr, "%s[%d]:  failed to export symtab\n", FILE__, __LINE__);
1815       }
1816       else
1817          fprintf(stderr, "%s[%d]:  did bin-serialize for %s\n", 
1818                FILE__, __LINE__, filename.c_str());
1819 #endif
1820
1821     }
1822     else
1823     {
1824        create_printf("%s[%d]: WARNING: failed to open symtab for %s\n", 
1825              FILE__, __LINE__, filename.c_str());
1826        delete obj;
1827        obj = NULL;
1828     }
1829
1830    // returns true on success (not an error)
1831    return !err;
1832 }
1833
1834 bool Symtab::addRegion(Offset vaddr, void *data, unsigned int dataSize, std::string name, Region::RegionType rType_, bool loadable)
1835 {
1836    Region *sec;
1837    unsigned i;
1838    if (loadable)
1839    {
1840       sec = new Region(newSectionInsertPoint, name, vaddr, dataSize, vaddr, 
1841             dataSize, (char *)data, Region::RP_R, rType_, true);
1842
1843       regions_.insert(regions_.begin()+newSectionInsertPoint, sec);
1844
1845       for (i = newSectionInsertPoint+1; i < regions_.size(); i++)
1846       {
1847          regions_[i]->setRegionNumber(regions_[i]->getRegionNumber() + 1);
1848       }
1849
1850       if (    (sec->getRegionType() == Region::RT_TEXT) 
1851             || (sec->getRegionType() == Region::RT_TEXTDATA))
1852       {
1853          codeRegions_.push_back(sec);
1854          std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
1855       }
1856
1857       if (    (sec->getRegionType() == Region::RT_DATA) 
1858             || (sec->getRegionType() == Region::RT_TEXTDATA))
1859       {
1860          dataRegions_.push_back(sec);
1861          std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
1862       }
1863    }
1864    else
1865    {
1866       sec = new Region(regions_.size()+1, name, vaddr, dataSize, 0, 0, 
1867             (char *)data, Region::RP_R, rType_);
1868       regions_.push_back(sec);
1869    }
1870
1871    addUserRegion(sec);
1872    std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
1873    return true;
1874 }
1875
1876 bool Symtab::addUserRegion(Region *reg)
1877 {
1878    std::vector<Region *> *user_regions = NULL;
1879
1880    if (!getAnnotation(user_regions, UserRegionsAnno))
1881    {
1882       user_regions = new std::vector<Region *>();
1883       if (!addAnnotation(user_regions, UserRegionsAnno))
1884       {
1885          fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
1886          return false;
1887       }
1888    }
1889
1890    if (!user_regions)
1891    {
1892       fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
1893       return false;
1894    }
1895
1896    user_regions->push_back(reg);
1897
1898    return true;
1899 }
1900
1901 bool Symtab::addUserType(Type *t)
1902 {
1903    std::vector<Type *> *user_types = NULL;
1904
1905    if (!getAnnotation(user_types, UserTypesAnno))
1906    {
1907       user_types = new std::vector<Type *>();
1908       if (!addAnnotation(user_types, UserTypesAnno))
1909       {
1910          fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
1911          return false;
1912       }
1913    }
1914    if (!user_types)
1915    {
1916       fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
1917       return false;
1918    }
1919
1920    user_types->push_back(t);
1921
1922    return true;
1923 }
1924
1925 bool Symtab::addRegion(Region *sec)
1926 {
1927    regions_.push_back(sec);
1928    std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
1929    addUserRegion(sec);
1930    return true;
1931 }
1932
1933 void Symtab::parseLineInformation()
1934 {
1935    dyn_hash_map<std::string, LineInformation> *lineInfo = new dyn_hash_map <std::string, LineInformation>;
1936
1937    Object *linkedFile = getObject();
1938    linkedFile->parseFileLineInfo(this, *lineInfo);
1939
1940    isLineInfoValid_ = true;     
1941    dyn_hash_map <std::string, LineInformation>::iterator iter;
1942
1943    for (iter = lineInfo->begin(); iter!=lineInfo->end(); iter++)
1944    {
1945       Module *mod = NULL;
1946       if (findModuleByName(mod, iter->first))
1947       {
1948          mod->setLineInfo(&(iter->second));
1949       }
1950       else if (findModuleByName(mod, mf->filename()))
1951       {
1952          LineInformation *lineInformation = mod->getLineInformation();
1953          if (!lineInformation) 
1954          {
1955             mod->setLineInfo(&(iter->second));
1956          } 
1957          else 
1958          {
1959             lineInformation->addLineInfo(&(iter->second));
1960             mod->setLineInfo(lineInformation);
1961          }
1962       }
1963       else 
1964       {
1965          object_printf("[%s:%u] - Couldn't find module %s to go with line info\n",
1966                __FILE__, __LINE__, iter->first.c_str()); 
1967       }
1968    }
1969 }
1970
1971 SYMTAB_EXPORT bool Symtab::getAddressRanges(std::vector<pair<Offset, Offset> >&ranges,
1972       std::string lineSource, unsigned int lineNo)
1973 {
1974    unsigned int originalSize = ranges.size();
1975
1976    /* Iteratate over the modules, looking for ranges in each. */
1977
1978    for ( unsigned int i = 0; i < _mods.size(); i++ ) 
1979    {
1980       LineInformation *lineInformation = _mods[i]->getLineInformation();
1981
1982       if (lineInformation)
1983          lineInformation->getAddressRanges( lineSource.c_str(), lineNo, ranges );
1984
1985    } /* end iteration over modules */
1986
1987    if ( ranges.size() != originalSize )
1988       return true;
1989
1990    fprintf(stderr, "%s[%d]:  failing to getAdressRanges for %s[%d]\n", FILE__, __LINE__, lineSource.c_str(), lineNo);
1991    return false;
1992 }
1993
1994 SYMTAB_EXPORT bool Symtab::getSourceLines(std::vector<LineNoTuple> &lines, Offset addressInRange)
1995 {
1996    unsigned int originalSize = lines.size();
1997
1998    /* Iteratate over the modules, looking for ranges in each. */
1999    for ( unsigned int i = 0; i < _mods.size(); i++ ) 
2000    {
2001       LineInformation *lineInformation = _mods[i]->getLineInformation();
2002
2003       if (lineInformation)
2004          lineInformation->getSourceLines( addressInRange, lines );
2005
2006    } /* end iteration over modules */
2007
2008    if ( lines.size() != originalSize )
2009       return true;
2010
2011    return false;
2012
2013 }
2014
2015 SYMTAB_EXPORT bool Symtab::addLine(std::string lineSource, unsigned int lineNo,
2016       unsigned int lineOffset, Offset lowInclAddr,
2017       Offset highExclAddr)
2018 {
2019    Module *mod;
2020
2021    if (!findModuleByName(mod, lineSource))
2022    {
2023       std::string fileNm = extract_pathname_tail(lineSource);
2024
2025       if (!findModuleByName(mod, fileNm))
2026       {
2027          if (!findModuleByName(mod, mf->pathname()))
2028             return false;
2029       }    
2030    }
2031
2032    LineInformation *lineInfo = mod->getLineInformation();
2033
2034    if (!lineInfo)
2035       return false;
2036
2037    return (lineInfo->addLine(lineSource.c_str(), lineNo, lineOffset, 
2038             lowInclAddr, highExclAddr));
2039 }
2040
2041 SYMTAB_EXPORT bool Symtab::addAddressRange( Offset lowInclusiveAddr, Offset highExclusiveAddr,
2042       std::string lineSource, unsigned int lineNo,
2043       unsigned int lineOffset)
2044 {
2045    Module *mod;
2046
2047    if (!findModuleByName(mod, lineSource))
2048    {
2049       std::string fileNm = extract_pathname_tail(lineSource);
2050
2051       if (!findModuleByName(mod, fileNm))
2052          return false;
2053    }
2054
2055    LineInformation *lineInfo = mod->getLineInformation();
2056
2057    if (!lineInfo)
2058       return false;
2059
2060    return (lineInfo->addAddressRange(lowInclusiveAddr, highExclusiveAddr, 
2061             lineSource.c_str(), lineNo, lineOffset));
2062 }
2063
2064
2065 void Symtab::parseTypes()
2066 {
2067    Object *linkedFile = getObject();
2068    linkedFile->parseTypeInfo(this);
2069    isTypeInfoValid_ = true;
2070 }
2071
2072 bool Symtab::addType(Type *type)
2073 {
2074   bool result = addUserType(type);
2075   if (!result)
2076     return false;
2077
2078   typeCollection *globaltypes = typeCollection::getGlobalTypeCollection();
2079   globaltypes->addType(type);
2080
2081   return true;
2082 }
2083
2084 SYMTAB_EXPORT vector<Type *> *Symtab::getAllstdTypes()
2085 {
2086    setupStdTypes();
2087    return stdTypes->getAllTypes();      
2088 }
2089
2090 SYMTAB_EXPORT vector<Type *> *Symtab::getAllbuiltInTypes()
2091 {
2092    setupStdTypes();
2093    return builtInTypes->getAllBuiltInTypes();
2094 }
2095
2096 SYMTAB_EXPORT bool Symtab::findType(Type *&type, std::string name)
2097 {
2098    parseTypesNow();
2099
2100    if (!_mods.size())
2101       return false;
2102
2103    type = _mods[0]->getModuleTypes()->findType(name);
2104
2105    if (type == NULL)
2106       return false;
2107
2108    return true; 
2109 }
2110
2111 SYMTAB_EXPORT Type *Symtab::findType(unsigned type_id)
2112 {
2113         Type *t;
2114    parseTypesNow();
2115
2116    if (!_mods.size())
2117       return NULL;
2118
2119    t = _mods[0]->getModuleTypes()->findType(type_id);
2120
2121    if (t == NULL)
2122       return NULL;
2123
2124    return t;    
2125 }
2126 SYMTAB_EXPORT bool Symtab::findVariableType(Type *&type, std::string name)
2127 {
2128    parseTypesNow();
2129
2130    if (!_mods.size())
2131       return false;
2132
2133    type = _mods[0]->getModuleTypes()->findVariableType(name);
2134
2135    if (type == NULL)
2136       return false;
2137
2138    return true; 
2139 }
2140
2141 SYMTAB_EXPORT bool Symtab::findLocalVariable(std::vector<localVar *>&vars, std::string name)
2142 {
2143    parseTypesNow();
2144    unsigned origSize = vars.size();
2145
2146    for (unsigned i = 0; i < everyFunction.size(); i++)
2147    {
2148       everyFunction[i]->findLocalVariable(vars, name);
2149    }
2150
2151    if (vars.size()>origSize)
2152       return true;
2153
2154    return false;        
2155 }
2156
2157 SYMTAB_EXPORT bool Symtab::hasRel() const
2158 {
2159    return hasRel_;
2160 }
2161
2162 SYMTAB_EXPORT bool Symtab::hasRela() const
2163 {
2164    return hasRela_;
2165 }
2166
2167 bool Symtab::setDefaultNamespacePrefix(string &str)
2168 {
2169    defaultNamespacePrefix = str;
2170    return true;
2171 }
2172
2173 SYMTAB_EXPORT bool Symtab::emitSymbols(Object *linkedFile,std::string filename, unsigned flag)
2174 {
2175     // Start with all the defined symbols
2176     std::vector<Symbol *> allSyms;
2177     for (unsigned i = 0; i < everyDefinedSymbol.size(); i++) {
2178         allSyms.push_back(everyDefinedSymbol[i]);
2179     }
2180
2181     // Add the undefined dynamic symbols
2182     map<string, std::vector<Symbol *> >::iterator iter;
2183     std::vector<Symbol *>::iterator siter;
2184
2185     for (iter = undefDynSyms.begin(); iter != undefDynSyms.end(); iter++)
2186         for (siter=iter->second.begin(); siter != iter->second.end(); siter++)
2187             allSyms.push_back(*siter);
2188
2189     // Write the new file
2190     return linkedFile->emitDriver(this, filename, allSyms, flag);
2191 }
2192
2193 SYMTAB_EXPORT bool Symtab::emit(std::string filename, unsigned flag)
2194 {
2195     return emitSymbols(getObject(), filename, flag);
2196 }
2197
2198 SYMTAB_EXPORT void Symtab::addDynLibSubstitution(std::string oldName, std::string newName)
2199 {
2200    dynLibSubs[oldName] = newName;
2201 }
2202
2203 SYMTAB_EXPORT std::string Symtab::getDynLibSubstitution(std::string name)
2204 {
2205 #ifdef BINEDIT_DEBUG
2206    map<std::string, std::string>::iterator iter = dynLibSubs.begin();
2207
2208    printf ("substitutions for %s:\n", mf->filename().c_str());
2209
2210    while (iter != dynLibSubs.end()) 
2211    {
2212       printf("  \"%s\" => \"%s\"\n", iter->first.c_str(), iter->second.c_str());
2213       iter++;
2214    }
2215 #endif
2216
2217    map<std::string, std::string>::iterator loc = dynLibSubs.find(name);
2218
2219    if (loc == dynLibSubs.end())
2220       return name;
2221    else
2222       return loc->second;
2223 }
2224
2225 SYMTAB_EXPORT bool Symtab::getSegments(vector<Segment> &segs) const
2226 {
2227    segs = segments_;
2228
2229    if (!segments_.size()) 
2230       return false;
2231
2232    return true;
2233 }
2234
2235 SYMTAB_EXPORT bool Symtab::getMappedRegions(std::vector<Region *> &mappedRegs) const
2236 {
2237    unsigned origSize = mappedRegs.size();
2238
2239    for (unsigned i = 0; i < regions_.size(); i++)
2240    {
2241       if (regions_[i]->isLoadable())
2242          mappedRegs.push_back(regions_[i]);
2243    }
2244
2245    if (mappedRegs.size() > origSize)
2246       return true;
2247
2248    return false;
2249 }
2250
2251 SYMTAB_EXPORT bool Symtab::updateCode(void *buffer, unsigned size)
2252 {
2253    Region *sec;
2254
2255    if (!findRegion(sec, ".text"))
2256       return false;
2257
2258    sec->setPtrToRawData(buffer, size);
2259
2260    return true;
2261 }
2262
2263 SYMTAB_EXPORT bool Symtab::updateData(void *buffer, unsigned size)
2264 {
2265    Region *sec;
2266
2267    if (!findRegion(sec, ".data"))
2268       return false;
2269
2270    sec->setPtrToRawData(buffer, size);
2271
2272    return true;
2273 }
2274
2275 SYMTAB_EXPORT Offset Symtab::getFreeOffset(unsigned size) 
2276 {
2277    // Look through sections until we find a gap with
2278    // sufficient space.
2279    Offset highWaterMark = 0;
2280    Offset secoffset = 0;
2281    Offset prevSecoffset = 0;
2282
2283    Object *linkedFile = getObject();
2284    assert(linkedFile);
2285
2286    for (unsigned i = 0; i < regions_.size(); i++) 
2287    {
2288       //Offset end = regions_[i]->getRegionAddr() + regions_[i]->getDiskSize();
2289           Offset end = regions_[i]->getRegionAddr() + regions_[i]->getRegionSize();
2290       if (regions_[i]->getRegionAddr() == 0) 
2291          continue;
2292
2293       prevSecoffset = secoffset;
2294
2295       unsigned region_offset = (unsigned)((char *)(regions_[i]->getPtrToRawData())
2296             - linkedFile->mem_image());
2297
2298       if (region_offset < (unsigned)prevSecoffset)
2299       {
2300          //secoffset += regions_[i]->getDiskSize();
2301                  secoffset += regions_[i]->getRegionSize();
2302       }
2303       else 
2304       {
2305          secoffset = (char *)(regions_[i]->getPtrToRawData()) - linkedFile->mem_image();
2306          //secoffset += regions_[i]->getDiskSize();
2307                  secoffset += regions_[i]->getRegionSize();
2308       }
2309
2310       /*fprintf(stderr, "%d: secAddr 0x%lx, size %d, end 0x%lx, looking for %d\n",
2311         i, regions_[i]->getSecAddr(), regions_[i]->getSecSize(),
2312         end,size);*/
2313
2314       if (end > highWaterMark) 
2315       {
2316          //fprintf(stderr, "Increasing highWaterMark...\n");
2317          newSectionInsertPoint = i+1;
2318          highWaterMark = end;
2319       }
2320
2321       if (     (i < (regions_.size()-2)) 
2322             && ((end + size) < regions_[i+1]->getRegionAddr())) 
2323       {
2324          /*      fprintf(stderr, "Found a hole between sections %d and %d\n",
2325                  i, i+1);
2326                  fprintf(stderr, "End at 0x%lx, next one at 0x%lx\n",
2327                  end, regions_[i+1]->getSecAddr());
2328           */   
2329          newSectionInsertPoint = i+1;
2330          highWaterMark = end;
2331          break;
2332       }
2333    }
2334
2335    //   return highWaterMark;
2336
2337    #if defined (os_windows)
2338         unsigned pgSize = getObject()-> getSecAlign();
2339         //printf("pgSize:0x%x\n", pgSize);
2340         Offset newaddr = highWaterMark  - (highWaterMark & (pgSize-1));
2341         while(newaddr < highWaterMark)
2342         newaddr += pgSize;
2343         //printf("getfreeoffset:%lu\n", newaddr);
2344         return newaddr;
2345
2346 #else
2347         unsigned pgSize = P_getpagesize();
2348         Offset newaddr = highWaterMark  - (highWaterMark & (pgSize-1)) + (secoffset & (pgSize-1));
2349         if(newaddr < highWaterMark)
2350                 newaddr += pgSize;
2351          return newaddr;
2352 #endif  
2353 }
2354
2355 SYMTAB_EXPORT ObjectType Symtab::getObjectType() const 
2356 {
2357    return object_type_;
2358 }
2359
2360 SYMTAB_EXPORT char *Symtab::mem_image() const 
2361 {
2362    return (char *)mf->base_addr();
2363 }
2364
2365 SYMTAB_EXPORT std::string Symtab::file() const 
2366 {
2367    assert(mf);
2368    return mf->pathname();
2369 }
2370
2371 SYMTAB_EXPORT std::string Symtab::name() const 
2372 {
2373    return mf->filename();
2374 }
2375
2376 SYMTAB_EXPORT unsigned Symtab::getNumberofRegions() const 
2377 {
2378    return no_of_sections; 
2379 }
2380
2381 SYMTAB_EXPORT unsigned Symtab::getNumberofSymbols() const 
2382 {
2383    return no_of_symbols; 
2384 }
2385
2386 bool Symtab::setup_module_up_ptrs(SerializerBase *, Symtab *st)
2387 {
2388    std::vector<Module *> &mods = st->_mods;
2389
2390    for (unsigned int i = 0; i < mods.size(); ++i) 
2391    {
2392       Module *m = mods[i];
2393       m->exec_ = st;
2394    }
2395
2396    return true;
2397 }
2398
2399 bool Symtab::fixup_relocation_symbols(SerializerBase *, Symtab *st)
2400 {
2401    std::vector<Module *> &mods = st->_mods;
2402
2403    for (unsigned int i = 0; i < mods.size(); ++i) 
2404    {
2405       Module *m = mods[i];
2406       m->exec_ = st;
2407    }
2408
2409    return true;
2410 }
2411
2412 void Symtab::serialize(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
2413 {
2414    try 
2415    {
2416       ifxml_start_element(sb, tag);
2417       gtranslate(sb, imageOffset_, "imageOffset");
2418       gtranslate(sb, imageLen_, "imageLen");
2419       gtranslate(sb, dataOffset_, "dataOff");
2420       gtranslate(sb, dataLen_, "dataLen");
2421       gtranslate(sb, is_a_out, "isExec");
2422       gtranslate(sb, _mods, "Modules", "Module");
2423       //gtranslate(sb, everyUniqueFunction, "EveryUniqueFunction", "UniqueFunction");
2424       //gtranslate(sb, everyUniqueVariable, "EveryUniqueVariable", "UniqueVariable");
2425       //gtranslate(sb, modSyms, "ModuleSymbols", "ModuleSymbol");
2426       gtranslate(sb, excpBlocks, "ExceptionBlocks", "ExceptionBlock");
2427       ifxml_end_element(sb, tag);
2428
2429
2430 #if 0
2431       ifinput(Symtab::setup_module_up_ptrs, sb, this);
2432       ifinput(fixup_relocation_symbols, sb, this);
2433 #endif
2434
2435       //  Patch up module's exec_ (pointer to Symtab) at a higher level??
2436       //if (getSD().iomode() == sd_deserialize)
2437       //   param.exec_ = parent_symtab;
2438    } SER_CATCH("Symtab");
2439 }
2440
2441 SYMTAB_EXPORT LookupInterface::LookupInterface() 
2442 {
2443 }
2444
2445 SYMTAB_EXPORT LookupInterface::~LookupInterface()
2446 {
2447 }
2448
2449
2450 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(Offset tStart, 
2451       unsigned tSize, 
2452       Offset cStart) 
2453 : tryStart_(tStart), trySize_(tSize), catchStart_(cStart), hasTry_(true) 
2454 {
2455 }
2456
2457    SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(Offset cStart) 
2458 : tryStart_(0), trySize_(0), catchStart_(cStart), hasTry_(false) 
2459 {
2460 }
2461
2462 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(const ExceptionBlock &eb) :
2463    Serializable(),
2464    tryStart_(eb.tryStart_), trySize_(eb.trySize_), 
2465    catchStart_(eb.catchStart_), hasTry_(eb.hasTry_) 
2466 {
2467 }
2468 SYMTAB_EXPORT bool ExceptionBlock::hasTry() const
2469
2470    return hasTry_; 
2471 }
2472
2473 SYMTAB_EXPORT Offset ExceptionBlock::tryStart() const
2474
2475    return tryStart_; 
2476 }
2477
2478 SYMTAB_EXPORT Offset ExceptionBlock::tryEnd() const
2479
2480    return tryStart_ + trySize_; 
2481 }
2482
2483 SYMTAB_EXPORT Offset ExceptionBlock::trySize() const
2484 {
2485    return trySize_; 
2486 }
2487
2488 SYMTAB_EXPORT bool ExceptionBlock::contains(Offset a) const
2489
2490    return (a >= tryStart_ && a < tryStart_ + trySize_); 
2491 }
2492
2493 void ExceptionBlock::serialize(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
2494 {
2495    try 
2496    {
2497       ifxml_start_element(sb, tag);
2498       gtranslate(sb, tryStart_, "tryStart");
2499       gtranslate(sb, trySize_, "trySize");
2500       gtranslate(sb, catchStart_, "catchStart");
2501       gtranslate(sb, hasTry_, "hasTry");
2502       ifxml_end_element(sb, tag);
2503    } SER_CATCH("Symtab");
2504 }
2505
2506
2507 SYMTAB_EXPORT relocationEntry::relocationEntry() :
2508    target_addr_(0), 
2509    rel_addr_(0), 
2510    addend_(0), 
2511    rtype_(Region::RT_REL), 
2512    name_(""), 
2513    dynref_(NULL), 
2514    relType_(0)
2515 {
2516 }   
2517
2518 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, std::string n, 
2519       Symbol *dynref, unsigned long relType) :
2520    target_addr_(ta), 
2521    rel_addr_(ra), 
2522    addend_(0), 
2523    rtype_(Region::RT_REL), 
2524    name_(n), 
2525    dynref_(dynref), 
2526    relType_(relType)
2527 {
2528 }   
2529
2530 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, Offset add, 
2531       std::string n, Symbol *dynref, unsigned long relType) :
2532    target_addr_(ta), 
2533    rel_addr_(ra), 
2534    addend_(add), 
2535    rtype_(Region::RT_REL), 
2536    name_(n), 
2537    dynref_(dynref), 
2538    relType_(relType)
2539 {
2540 }
2541
2542 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ra, std::string n, 
2543       Symbol *dynref, unsigned long relType, Region::RegionType rtype) :
2544    target_addr_(0), 
2545    rel_addr_(ra), 
2546    addend_(0), 
2547    rtype_(rtype), 
2548    name_(n), 
2549    dynref_(dynref), 
2550    relType_(relType)
2551 {
2552 }   
2553
2554 SYMTAB_EXPORT const relocationEntry& relocationEntry::operator=(const relocationEntry &ra) 
2555 {
2556    target_addr_ = ra.target_addr_;
2557    rel_addr_ = ra.rel_addr_;
2558    addend_ = ra.addend_;
2559    rtype_ = ra.rtype_;
2560    name_ = ra.name_; 
2561    dynref_ = ra.dynref_;
2562    relType_ = ra.relType_;
2563    return *this;
2564 }
2565
2566 SYMTAB_EXPORT void relocationEntry::setAddend(const Offset value) {
2567     addend_ = value;
2568 }
2569
2570 SYMTAB_EXPORT Offset relocationEntry::addend() const {
2571     return addend_;
2572 }
2573
2574 SYMTAB_EXPORT void relocationEntry::setRegionType(const Region::RegionType value) {
2575     rtype_ = value;
2576 }
2577
2578 SYMTAB_EXPORT Region::RegionType relocationEntry::regionType() const {
2579         return rtype_;
2580 }
2581
2582 void relocationEntry::serialize(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
2583 {
2584    try 
2585    {
2586       ifxml_start_element(sb, tag);
2587       gtranslate(sb, target_addr_, "targetAddress");
2588       gtranslate(sb, rel_addr_, "relocationAddress");
2589       gtranslate(sb, name_, "relocationName");
2590       gtranslate(sb, relType_, "relocationType");
2591       //  deserialize: Re-assign dynref_ symbol elsewhere (in Symtab class)
2592       ifxml_end_element(sb, tag);
2593    } SER_CATCH("relocationEntry");
2594 }
2595
2596
2597 const char *Symbol::symbolType2Str(SymbolType t) 
2598 {
2599    switch (t) 
2600    {
2601       CASE_RETURN_STR(ST_UNKNOWN);
2602       CASE_RETURN_STR(ST_FUNCTION);
2603       CASE_RETURN_STR(ST_OBJECT);
2604       CASE_RETURN_STR(ST_MODULE);
2605       CASE_RETURN_STR(ST_SECTION);
2606       CASE_RETURN_STR(ST_DELETED);
2607       CASE_RETURN_STR(ST_NOTYPE);
2608    };
2609
2610    return "invalid symbol type";
2611 }
2612
2613 const char *Symbol::symbolLinkage2Str(SymbolLinkage t) 
2614 {
2615    switch (t) 
2616    {
2617       CASE_RETURN_STR(SL_UNKNOWN);
2618       CASE_RETURN_STR(SL_GLOBAL);
2619       CASE_RETURN_STR(SL_LOCAL);
2620       CASE_RETURN_STR(SL_WEAK);
2621    };
2622
2623    return "invalid symbol linkage";
2624 }
2625
2626 const char *Symbol::symbolTag2Str(SymbolTag t) 
2627 {
2628    switch (t) 
2629    {
2630       CASE_RETURN_STR(TAG_UNKNOWN);
2631       CASE_RETURN_STR(TAG_USER);
2632       CASE_RETURN_STR(TAG_LIBRARY);
2633       CASE_RETURN_STR(TAG_INTERNAL);
2634    };
2635
2636    return "invalid symbol tag";
2637 }
2638
2639 const char *Symbol::symbolVisibility2Str(SymbolVisibility t) 
2640 {
2641    switch(t) {
2642       CASE_RETURN_STR(SV_UNKNOWN);
2643       CASE_RETURN_STR(SV_DEFAULT);
2644       CASE_RETURN_STR(SV_INTERNAL);
2645       CASE_RETURN_STR(SV_HIDDEN);
2646       CASE_RETURN_STR(SV_PROTECTED);
2647    }
2648    return "invalid symbol visibility";
2649 }
2650
2651 bool Symtab::hasStackwalkDebugInfo()
2652 {
2653    return getObject()->hasFrameDebugInfo();
2654 }
2655
2656 bool Symtab::getRegValueAtFrame(Address pc, 
2657                                 Dyninst::MachRegister reg, 
2658                                 Dyninst::MachRegisterVal &reg_result,
2659                                 MemRegReader *reader)
2660 {
2661    return getObject()->getRegValueAtFrame(pc, reg, reg_result, reader);
2662 }
2663
2664 Object *Symtab::getObject()
2665 {
2666    if (obj_private)
2667       return obj_private;
2668
2669    //TODO: This likely triggered because we serialized in an object
2670    // from cache, but now the user is requesting more information from
2671    // the on disk object.  We should create a new 'Object' from data
2672    // (likely a file path) serialized in.
2673    
2674    assert(0);
2675    //obj_private = new Object();
2676    return obj_private;
2677 }
2678
2679 void Symtab::parseTypesNow()
2680 {
2681    if (isTypeInfoValid_)
2682       return;
2683
2684    parseTypes();
2685 }
2686
2687 MemRegReader::~MemRegReader()
2688 {
2689 }
2690
2691 #if defined (cap_serialization)
2692 //  Not sure this is strictly necessary, problems only seem to exist with Module 
2693 // annotations when the file was split off, so there's probably something else that
2694 //  can be done to instantiate the relevant functions.
2695
2696 bool dummy_for_ser_instance(std::string file, SerializerBase *sb)
2697 {
2698    if (file == std::string("no_such_file")) 
2699    {
2700       if (!sb) 
2701       {
2702          fprintf(stderr, "%s[%d]:  really should not happen\n", FILE__, __LINE__);
2703          return false;
2704       }
2705 #if 0
2706 #else
2707       fprintf(stderr, "%s[%d]:  WARN:  disabled serializer init here\n", FILE__, __LINE__);
2708 #endif
2709    }
2710    return true;
2711 }
2712
2713 #endif
2714
2715 namespace Dyninst {
2716         namespace SymtabAPI {
2717
2718 SYMTAB_EXPORT SerializerBin<Symtab> st_static_instance(NULL);
2719
2720 SYMTAB_EXPORT SerializerBase *nonpublic_make_bin_symtab_serializer(Symtab *t, std::string file)
2721 {
2722         SerializerBin<Symtab> *ser;
2723         ser = new SerializerBin<Symtab>(t, "SerializerBin", file, sd_serialize, true);
2724         Symtab *test_st = ser->getScope();
2725         assert(test_st == t);
2726         return ser;
2727 }
2728
2729 SYMTAB_EXPORT SerializerBase *nonpublic_make_bin_symtab_deserializer(Symtab *t, std::string file)
2730 {
2731         SerializerBin<Symtab> *ser;
2732         ser = new SerializerBin<Symtab>(t, "DeserializerBin", file, sd_deserialize, true);
2733         Symtab *test_st = ser->getScope();
2734         assert(test_st == t);
2735         return ser;
2736 }
2737
2738 SYMTAB_EXPORT void nonpublic_free_bin_symtab_serializer(SerializerBase *sb)
2739 {
2740         SerializerBin<Symtab> *sbin = dynamic_cast<SerializerBin<Symtab> *>(sb);
2741         if (sbin)
2742         {
2743                 delete(sbin);
2744         }
2745         else
2746                 fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
2747
2748 }
2749 } // namespace SymtabAPI
2750 } // namespace Dyninst
2751