Correct static initialization for built in & standard types in Symtab
[dyninst.git] / symtabAPI / src / Symtab.C
1 /*
2  * Copyright (c) 1996-2011 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <assert.h>
35 #include <string.h>
36 #include <algorithm>
37 #include <iostream>
38 #include <iomanip>
39 #include <sstream>
40
41 #include "common/h/Timer.h"
42 #include "common/h/debugOstream.h"
43 #include "common/h/serialize.h"
44 #include "common/h/pathName.h"
45
46 #include "dyn_detail/boost/make_shared.hpp"
47
48 #include "Serialization.h"
49 #include "Symtab.h"
50 #include "Module.h"
51 #include "Collections.h"
52 #include "Function.h"
53 #include "Variable.h"
54
55 #include "annotations.h"
56
57 #include "debug.h"
58
59 #include "symtabAPI/src/Object.h"
60
61 #if !defined(os_windows)
62 #include <dlfcn.h>
63 #else
64 #include <windows.h>
65 #endif
66
67 #include <iomanip>
68 #include <stdarg.h>
69
70 using namespace Dyninst;
71 using namespace Dyninst::SymtabAPI;
72 using namespace std;
73
74 static std::string errMsg;
75 extern bool parseCompilerType(Object *);
76
77 static const int Symtab_major_version = 7;
78 static const int Symtab_minor_version = 0;
79 static const int Symtab_maintenance_version = 0;
80
81 void Symtab::version(int& major, int& minor, int& maintenance)
82 {
83     major = Symtab_major_version;
84     minor = Symtab_minor_version;
85     maintenance = Symtab_maintenance_version;
86 }
87
88
89 void symtab_log_perror(const char *msg)
90 {
91    errMsg = std::string(msg);
92 };
93
94
95 SymtabError serr;
96
97 std::vector<Symtab *> Symtab::allSymtabs;
98
99  
100 SymtabError Symtab::getLastSymtabError()
101 {
102     return serr;
103 }
104
105 void setSymtabError(SymtabError new_err)
106 {
107    serr = new_err;
108 }
109
110 std::string Symtab::printError(SymtabError serr)
111 {
112     switch (serr)
113     {
114        case Obj_Parsing:
115            return "Failed to parse the Object"+errMsg;
116        case Syms_To_Functions:
117            return "Failed to convert Symbols to Functions";
118        case No_Such_Function:
119            return "Function does not exist";
120        case No_Such_Variable:
121            return "Variable does not exist";
122        case No_Such_Module:
123           return "Module does not exist";
124        case No_Such_Region:
125            return "Region does not exist";
126        case No_Such_Symbol:
127            return "Symbol does not exist";
128        case Not_A_File:
129            return "Not a File. Call openArchive()";
130        case Not_An_Archive:
131            return "Not an Archive. Call openFile()";
132        case Export_Error:
133            return "Error Constructing XML"+errMsg;
134        case Emit_Error:
135            return "Error rewriting binary: " + errMsg;
136        case Invalid_Flags:
137           return "Flags passed are invalid.";
138        case No_Error:
139           return "No previous Error.";
140        default:
141           return "Unknown Error";
142     }           
143 }
144
145 dyn_detail::boost::shared_ptr<Type> Symtab::type_Error()
146 {
147     static dyn_detail::boost::shared_ptr<Type> store =
148         dyn_detail::boost::make_shared<Type>( 
149             std::string("<error>"), 0, dataUnknownType);
150     return store;
151 }
152 dyn_detail::boost::shared_ptr<Type> Symtab::type_Untyped()
153 {
154     static dyn_detail::boost::shared_ptr<Type> store =
155         dyn_detail::boost::make_shared<Type>(
156             std::string("<no type>"), 0, dataUnknownType);
157     return store;
158 }
159
160 dyn_detail::boost::shared_ptr<builtInTypeCollection> Symtab::builtInTypes()
161 {
162     static dyn_detail::boost::shared_ptr<builtInTypeCollection> store =
163         setupBuiltinTypes();
164     return store;
165 }
166 dyn_detail::boost::shared_ptr<typeCollection> Symtab::stdTypes()
167 {
168     static dyn_detail::boost::shared_ptr<typeCollection> store =
169         setupStdTypes();
170     return store;
171 }
172
173 dyn_detail::boost::shared_ptr<builtInTypeCollection> Symtab::setupBuiltinTypes()
174 {
175     dyn_detail::boost::shared_ptr<builtInTypeCollection> builtInTypes =
176         dyn_detail::boost::make_shared<builtInTypeCollection>(); 
177
178    typeScalar *newType;
179
180    // NOTE: integral type  mean twos-complement
181    // -1  int, 32 bit signed integral type
182    // in stab document, size specified in bits, system size is in bytes
183    builtInTypes->addBuiltInType(newType = new typeScalar(-1, 4, "int", true));
184    newType->decrRefCount();
185    // -2  char, 8 bit type holding a character. GDB & dbx(AIX) treat as signed
186    builtInTypes->addBuiltInType(newType = new typeScalar(-2, 1, "char", true));
187    newType->decrRefCount();
188    // -3  short, 16 bit signed integral type
189    builtInTypes->addBuiltInType(newType = new typeScalar(-3, 2, "short", true));
190    newType->decrRefCount();
191    // -4  long, 32/64 bit signed integral type
192    builtInTypes->addBuiltInType(newType = new typeScalar(-4, sizeof(long), "long", true));
193    newType->decrRefCount();
194    // -5  unsigned char, 8 bit unsigned integral type
195    builtInTypes->addBuiltInType(newType = new typeScalar(-5, 1, "unsigned char"));
196    newType->decrRefCount();
197    // -6  signed char, 8 bit signed integral type
198    builtInTypes->addBuiltInType(newType = new typeScalar(-6, 1, "signed char", true));
199    newType->decrRefCount();
200    // -7  unsigned short, 16 bit unsigned integral type
201    builtInTypes->addBuiltInType(newType = new typeScalar(-7, 2, "unsigned short"));
202    newType->decrRefCount();
203    // -8  unsigned int, 32 bit unsigned integral type
204    builtInTypes->addBuiltInType(newType = new typeScalar(-8, 4, "unsigned int"));
205    newType->decrRefCount();
206    // -9  unsigned, 32 bit unsigned integral type
207    builtInTypes->addBuiltInType(newType = new typeScalar(-9, 4, "unsigned"));
208    newType->decrRefCount();
209    // -10 unsigned long, 32 bit unsigned integral type
210    builtInTypes->addBuiltInType(newType = new typeScalar(-10, sizeof(unsigned long), "unsigned long"));
211    newType->decrRefCount();
212    // -11 void, type indicating the lack of a value
213    //  XXX-size may not be correct jdd 4/22/99
214    builtInTypes->addBuiltInType(newType = new typeScalar(-11, 0, "void", false));
215    newType->decrRefCount();
216    // -12 float, IEEE single precision
217    builtInTypes->addBuiltInType(newType = new typeScalar(-12, sizeof(float), "float", true));
218    newType->decrRefCount();
219    // -13 double, IEEE double precision
220    builtInTypes->addBuiltInType(newType = new typeScalar(-13, sizeof(double), "double", true));
221    newType->decrRefCount();
222    // -14 long double, IEEE double precision, size may increase in future
223    builtInTypes->addBuiltInType(newType = new typeScalar(-14, sizeof(long double), "long double", true));
224    newType->decrRefCount();
225    // -15 integer, 32 bit signed integral type
226    builtInTypes->addBuiltInType(newType = new typeScalar(-15, 4, "integer", true));
227    newType->decrRefCount();
228    // -16 boolean, 32 bit type. GDB/GCC 0=False, 1=True, all other values
229    //  have unspecified meaning
230    builtInTypes->addBuiltInType(newType = new typeScalar(-16, sizeof(bool), "boolean"));
231    newType->decrRefCount();
232    // -17 short real, IEEE single precision
233    //  XXX-size may not be correct jdd 4/22/99
234    builtInTypes->addBuiltInType(newType = new typeScalar(-17, sizeof(float), "short real", true));
235    newType->decrRefCount();
236    // -18 real, IEEE double precision XXX-size may not be correct jdd 4/22/99
237    builtInTypes->addBuiltInType(newType = new typeScalar(-18, sizeof(double), "real", true));
238    newType->decrRefCount();
239    // -19 stringptr XXX- size of void * -- jdd 4/22/99
240    builtInTypes->addBuiltInType(newType = new typeScalar(-19, sizeof(void *), "stringptr"));
241    newType->decrRefCount();
242    // -20 character, 8 bit unsigned character type
243    builtInTypes->addBuiltInType(newType = new typeScalar(-20, 1, "character"));
244    newType->decrRefCount();
245    // -21 logical*1, 8 bit type (Fortran, used for boolean or unsigned int)
246    builtInTypes->addBuiltInType(newType = new typeScalar(-21, 1, "logical*1"));
247    newType->decrRefCount();
248    // -22 logical*2, 16 bit type (Fortran, some for boolean or unsigned int)
249    builtInTypes->addBuiltInType(newType = new typeScalar(-22, 2, "logical*2"));
250    newType->decrRefCount();
251    // -23 logical*4, 32 bit type (Fortran, some for boolean or unsigned int)
252    builtInTypes->addBuiltInType(newType = new typeScalar(-23, 4, "logical*4"));
253    newType->decrRefCount();
254    // -24 logical, 32 bit type (Fortran, some for boolean or unsigned int)
255    builtInTypes->addBuiltInType(newType = new typeScalar(-24, 4, "logical"));
256    newType->decrRefCount();
257    // -25 complex, consists of 2 IEEE single-precision floating point values
258    builtInTypes->addBuiltInType(newType = new typeScalar(-25, sizeof(float)*2, "complex", true));
259    newType->decrRefCount();
260    // -26 complex, consists of 2 IEEE double-precision floating point values
261    builtInTypes->addBuiltInType(newType = new typeScalar(-26, sizeof(double)*2, "complex*16", true));
262    newType->decrRefCount();
263    // -27 integer*1, 8 bit signed integral type
264    builtInTypes->addBuiltInType(newType = new typeScalar(-27, 1, "integer*1", true));
265    newType->decrRefCount();
266    // -28 integer*2, 16 bit signed integral type
267    builtInTypes->addBuiltInType(newType = new typeScalar(-28, 2, "integer*2", true));
268    newType->decrRefCount();
269
270    /* Quick hack to make integer*4 compatible with int for Fortran
271       jnb 6/20/01 */
272    // This seems questionable - let's try removing that hack - jmo 05/21/04
273    /*
274      builtInTypes->addBuiltInType(newType = new type("int",-29,
275      built_inType, 4));
276      newType->decrRefCount();
277    */
278    // -29 integer*4, 32 bit signed integral type
279    builtInTypes->addBuiltInType(newType = new typeScalar(-29, 4, "integer*4", true));
280    newType->decrRefCount();
281    // -30 wchar, Wide character, 16 bits wide, unsigned (unknown format)
282    builtInTypes->addBuiltInType(newType = new typeScalar(-30, 2, "wchar"));
283    newType->decrRefCount();
284 #if defined(os_windows)
285    // -31 long long, 64 bit signed integral type
286    builtInTypes->addBuiltInType(newType = new typeScalar(-31, sizeof(LONGLONG), "long long", true));
287    newType->decrRefCount();
288    // -32 unsigned long long, 64 bit unsigned integral type
289    builtInTypes->addBuiltInType(newType = new typeScalar(-32, sizeof(ULONGLONG), "unsigned long long"));
290    newType->decrRefCount();
291 #else
292    // -31 long long, 64 bit signed integral type
293    builtInTypes->addBuiltInType(newType = new typeScalar(-31, sizeof(long long), "long long", true));
294    newType->decrRefCount();
295    // -32 unsigned long long, 64 bit unsigned integral type
296    builtInTypes->addBuiltInType(newType = new typeScalar(-32, sizeof(unsigned long long), "unsigned long long"));
297    newType->decrRefCount();
298 #endif
299    // -33 logical*8, 64 bit unsigned integral type
300    builtInTypes->addBuiltInType(newType = new typeScalar(-33, 8, "logical*8"));
301    newType->decrRefCount();
302    // -34 integer*8, 64 bit signed integral type
303    builtInTypes->addBuiltInType(newType = new typeScalar(-34, 8, "integer*8", true));
304    newType->decrRefCount();
305
306    return builtInTypes;
307 }
308
309
310 dyn_detail::boost::shared_ptr<typeCollection> Symtab::setupStdTypes() 
311 {
312     dyn_detail::boost::shared_ptr<typeCollection> stdTypes =
313         dyn_detail::boost::make_shared<typeCollection>();
314
315    typeScalar *newType;
316
317    stdTypes->addType(newType = new typeScalar(-1, sizeof(int), "int"));
318    newType->decrRefCount();
319
320    Type *charType = new typeScalar(-2, sizeof(char), "char");
321    stdTypes->addType(charType);
322
323         std::string tName = "char *";
324         typePointer *newPtrType;
325    stdTypes->addType(newPtrType = new typePointer(-3, charType, tName));
326    charType->decrRefCount();
327    newPtrType->decrRefCount();
328
329    Type *voidType = new typeScalar(-11, 0, "void", false);
330    stdTypes->addType(voidType);
331
332         tName = "void *";
333    stdTypes->addType(newPtrType = new typePointer(-4, voidType, tName));
334    voidType->decrRefCount();
335    newPtrType->decrRefCount();
336
337    stdTypes->addType(newType = new typeScalar(-12, sizeof(float), "float"));
338    newType->decrRefCount();
339
340 #if defined(i386_unknown_nt4_0)
341    stdTypes->addType(newType = new typeScalar(-31, sizeof(LONGLONG), "long long"));    
342 #else
343    stdTypes->addType(newType = new typeScalar(-31, sizeof(long long), "long long"));
344 #endif
345
346         newType->decrRefCount();
347
348    return stdTypes;
349 }
350
351 SYMTAB_EXPORT unsigned Symtab::getAddressWidth() const 
352 {
353    return address_width_;
354 }
355  
356 SYMTAB_EXPORT bool Symtab::isNativeCompiler() const 
357 {
358     return nativeCompiler; 
359 }
360
361 SYMTAB_EXPORT Symtab::Symtab(MappedFile *mf_) :
362    AnnotatableSparse(),
363    mf(mf_), 
364    mfForDebugInfo(mf_),
365    imageOffset_(0),   
366    address_width_(sizeof(int)),
367    object_type_(obj_Unknown),
368    defaultNamespacePrefix(""),
369    no_of_sections(0),
370    newSectionInsertPoint(0),
371    no_of_symbols(0),
372    obj_private(NULL),
373    _ref_cnt(1)
374 {
375     init_debug_symtabAPI();
376
377 #if defined(os_vxworks)
378     // This is how we initialize objects from WTX information alone.
379     // Basically replaces extractInfo().
380     object_type_ = obj_RelocatableFile;
381     mfForDebugInfo = NULL;
382     imageOffset_ = 0;
383     dataOffset_ = 0;
384     imageLen_ = 0;
385     dataLen_ = 0;
386     isStaticBinary_ = false;
387     hasRel_ = false;
388     hasRela_ = false;
389     hasReldyn_ = false;
390     hasReladyn_ = false;
391     hasRelplt_ = false;
392     hasRelaplt_ = false;
393     is_a_out = false;
394     code_ptr_ = NULL;
395     data_ptr_ = NULL;
396     entry_address_ = 0;
397     base_address_ = 0;
398     load_address_ = 0;
399     toc_offset_ = 0;
400     is_eel_ = false;
401 #endif
402
403     createDefaultModule();
404 }
405
406 SYMTAB_EXPORT Symtab::Symtab() :
407    imageOffset_(0),
408    address_width_(sizeof(int)),
409    object_type_(obj_Unknown),
410    defaultNamespacePrefix(""),
411    no_of_sections(0),
412    newSectionInsertPoint(0),
413    no_of_symbols(0),
414    obj_private(NULL),
415    _ref_cnt(1)
416 {
417     init_debug_symtabAPI();
418     create_printf("%s[%d]: Created symtab via default constructor\n", FILE__, __LINE__);
419     createDefaultModule();
420 }
421
422 SYMTAB_EXPORT bool Symtab::isExec() const 
423 {
424     return is_a_out; 
425 }
426
427 SYMTAB_EXPORT bool Symtab::isStripped() 
428 {
429 #if defined(os_linux) || defined(os_freebsd)
430     Region *sec;
431     return !findRegion(sec,".symtab");
432 #else
433     return (no_of_symbols==0);
434 #endif
435 }
436
437 SYMTAB_EXPORT Offset Symtab::imageOffset() const 
438 {
439     return imageOffset_;
440 }
441
442 SYMTAB_EXPORT Offset Symtab::dataOffset() const 
443
444     return dataOffset_;
445 }
446
447 SYMTAB_EXPORT Offset Symtab::dataLength() const 
448 {
449     return dataLen_;
450
451
452 SYMTAB_EXPORT Offset Symtab::imageLength() const 
453 {
454     return imageLen_;
455 }
456
457 SYMTAB_EXPORT void Symtab::fixup_code_and_data(Offset newImageOffset,
458                                                Offset newImageLength,
459                                                Offset newDataOffset,
460                                                Offset newDataLength)
461 {
462     imageOffset_ = newImageOffset;
463     imageLen_ = newImageLength;
464     dataOffset_ = newDataOffset;
465     dataLen_ = newDataLength;
466
467     // Should we update the underlying Object?
468 }
469
470 /*
471 SYMTAB_EXPORT char* Symtab::image_ptr ()  const 
472 {
473    return code_ptr_;
474 }
475
476 SYMTAB_EXPORT char* Symtab::data_ptr ()  const 
477
478    return data_ptr_;
479 }
480 */
481 SYMTAB_EXPORT const char*  Symtab::getInterpreterName() const 
482 {
483    if (interpreter_name_.length())
484       return interpreter_name_.c_str();
485    return NULL;
486 }
487  
488 SYMTAB_EXPORT Offset Symtab::getEntryOffset() const 
489
490    return entry_address_;
491 }
492
493 SYMTAB_EXPORT Offset Symtab::getBaseOffset() const 
494 {
495    return base_address_;
496 }
497
498 SYMTAB_EXPORT Offset Symtab::getLoadOffset() const 
499
500    return load_address_;
501 }
502
503 SYMTAB_EXPORT Offset Symtab::getTOCoffset() const 
504 {
505    return toc_offset_;
506 }
507
508 SYMTAB_EXPORT string Symtab::getDefaultNamespacePrefix() const
509 {
510     return defaultNamespacePrefix;
511 }
512         
513         
514 // TODO -- is this g++ specific
515 bool Symtab::buildDemangledName( const std::string &mangled, 
516       std::string &pretty,
517       std::string &typed,
518       bool nativeCompiler, 
519       supportedLanguages lang )
520 {
521    /* The C++ demangling function demangles MPI__Allgather (and other MPI__
522     * functions with start with A) into the MPI constructor.  In order to
523     * prevent this a hack needed to be made, and this seemed the cleanest
524     * approach.
525     */
526
527    if ((mangled.length()>5) && (mangled.substr(0,5)==std::string("MPI__"))) 
528    {
529       return false;
530    }      
531
532    /* If it's Fortran, eliminate the trailing underscores, if any. */
533    if (lang == lang_Fortran 
534          || lang == lang_CMFortran 
535          || lang == lang_Fortran_with_pretty_debug )
536    {
537       if ( mangled[ mangled.length() - 1 ] == '_' ) 
538       {
539          char * demangled = P_strdup( mangled.c_str() );
540          demangled[ mangled.length() - 1 ] = '\0';
541          pretty = std::string( demangled );
542
543          free ( demangled );
544          return true;
545       }
546       else 
547       {
548          /* No trailing underscores, do nothing */
549          return false;
550       }
551    } /* end if it's Fortran. */
552
553    //  Check to see if we have a gnu versioned symbol on our hands.
554    //  These are of the form <symbol>@<version> or <symbol>@@<version>
555    //
556    //  If we do, we want to create a "demangled" name for the one that
557    //  is of the form <symbol>@@<version> since this is, by definition,
558    //  the default.  The "demangled" name will just be <symbol>
559
560    //  NOTE:  this is just a 0th order approach to dealing with versioned
561    //         symbols.  We may need to do something more sophisticated
562    //         in the future.  JAW 10/03
563
564 #if !defined(os_windows)
565
566    const char *atat;
567
568    if (NULL != (atat = strstr(mangled.c_str(), "@@"))) 
569    {
570         pretty = mangled.substr(0 /*start pos*/, 
571                         (int)(atat - mangled.c_str())/*len*/);
572         //char msg[256];
573         //sprintf(msg, "%s[%d]: 'demangling' versioned symbol: %s, to %s",
574         //          __FILE__, __LINE__, mangled.c_str(), pretty.c_str());
575
576         //cerr << msg << endl;
577         //logLine(msg);
578       
579         return true;
580     }
581
582 #endif
583
584     bool retval = false;
585   
586     /* Try demangling it. */
587     char * demangled = P_cplus_demangle( mangled.c_str(), nativeCompiler, false);
588     if (demangled) 
589     {
590         pretty = std::string( demangled );
591         retval = true;
592     }
593   
594     char *t_demangled = P_cplus_demangle(mangled.c_str(), nativeCompiler, true);
595     if (t_demangled && (strcmp(t_demangled, demangled) != 0)) 
596     {
597         typed = std::string(t_demangled);
598         retval = true;
599     }
600
601     if (demangled)
602         free(demangled);
603     if (t_demangled)
604         free(t_demangled);
605
606     return retval;
607 } /* end buildDemangledName() */
608
609
610 /*
611  * extractSymbolsFromFile
612  *
613  * Create a Symtab-level list of symbols by pulling out data
614  * from the low-level parse (linkedFile).
615  * Technically this causes a duplication of symbols; however,
616  * we will be rewriting these symbols and so we need our own
617  * copy. 
618  *
619  * TODO: delete the linkedFile once we're done?
620  */
621
622 bool Symtab::extractSymbolsFromFile(Object *linkedFile, std::vector<Symbol *> &raw_syms) 
623 {
624     for (SymbolIter symIter(*linkedFile); symIter; symIter++) 
625         {
626         Symbol *sym = symIter.currval();
627                 if (!sym) 
628                 {
629                         fprintf(stderr, "%s[%d]:  range error, stopping now\n", FILE__, __LINE__);
630                         return true;
631                 }
632
633         // If a symbol starts with "." we want to skip it. These indicate labels in the
634         // code. 
635         
636         // removed 1/09: this should be done in Dyninst, not Symtab
637
638         // check for undefined dynamic symbols. Used when rewriting relocation section.
639         // relocation entries have references to these undefined dynamic symbols.
640         // We also have undefined symbols for the static binary case.
641
642 #if !defined(os_vxworks)
643         if (sym->getSec() == NULL && !sym->isAbsolute() && !sym->isCommonStorage()) {
644            undefDynSyms.push_back(sym);
645            continue;
646         }
647 #endif
648
649         // Check whether this symbol has a valid offset. If they do not we have a
650         // consistency issue. This should be a null check.
651
652         // Symbols can have an offset of 0 if they don't refer to things within a file.
653
654         raw_syms.push_back(sym);
655     }
656
657     return true;
658 }
659
660 /*
661  * fixSymModules
662  * 
663  * Add Module information to all symbols. 
664  */
665
666 bool Symtab::fixSymModules(std::vector<Symbol *> &raw_syms) 
667 {
668     for (unsigned i = 0; i < raw_syms.size(); i++) {
669         fixSymModule(raw_syms[i]);
670     }
671         Object *obj = getObject();
672         if (!obj)
673         {
674 #if !defined(os_vxworks)
675                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
676 #endif
677                 return false;
678         }
679     const std::vector<std::pair<std::string, Offset> > &mods = obj->modules_;
680     for (unsigned i=0; i< mods.size(); i++) {
681        getOrCreateModule(mods[i].first, mods[i].second);
682     }
683        
684     return true;
685 }
686
687 /*
688  * demangleSymbols
689  *
690  * Perform name demangling on all symbols.
691  */
692
693 bool Symtab::demangleSymbols(std::vector<Symbol *> &raw_syms) 
694 {
695     for (unsigned i = 0; i < raw_syms.size(); i++) {
696         demangleSymbol(raw_syms[i]);
697     }
698     return true;
699 }
700
701 /*
702  * createIndices
703  *
704  * We index symbols by various attributes for quick lookup. Build those
705  * indices here. 
706  */
707
708 bool Symtab::createIndices(std::vector<Symbol *> &raw_syms, bool undefined) {
709     for (unsigned i = 0; i < raw_syms.size(); i++) {
710        addSymbolToIndices(raw_syms[i], undefined);
711     }
712     return true;
713 }
714
715 /*
716  * createAggregates
717  *
718  * Frequently there will be multiple Symbols that refer to a single 
719  * code object (e.g., function or variable). We use separate objects
720  * to refer to these aggregates, and build those objects here. 
721  */
722
723 bool Symtab::createAggregates() 
724 {
725 #if !defined(os_vxworks)
726     // In VxWorks, symbol offsets are not complete until object is loaded.
727
728     for (unsigned i = 0; i < everyDefinedSymbol.size(); i++) 
729       {
730         if (!doNotAggregate(everyDefinedSymbol[i])) {
731           addSymbolToAggregates(everyDefinedSymbol[i]);
732         }
733       }
734 #endif
735
736     return true;
737 }
738  
739 bool Symtab::fixSymModule(Symbol *&sym) 
740 {
741     //////////
742     //////////
743     //////////
744     //
745     // It has been decided that all libraries shall have only one
746     // module named after the library. The a.out has one module
747     // per (reported) source file, plus DEFAULT_MODULE for everything
748     // else. This is enforced here, although the Object-* files might
749     // do it as well.
750     Module *mod = NULL;
751     if (getObjectType() == obj_SharedLib) {
752        mod = getDefaultModule();
753     }
754     else {
755        Object *obj = getObject();
756        if (!obj)
757        {
758 #if !defined(os_vxworks)
759           fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
760 #endif
761           return false;
762        }
763        std::string modName = obj->findModuleForSym(sym);
764        if (modName.length() == 0) {
765           mod = getDefaultModule();
766        }
767        else {
768           mod = getOrCreateModule(modName, sym->getOffset());
769        }
770     }
771
772
773     if (!mod)
774        return false;
775     
776     sym->setModule(mod);
777     return true;
778 }
779
780 bool Symtab::demangleSymbol(Symbol *&sym) {
781    bool typed_demangle = false;
782    if (sym->getType() == Symbol::ST_FUNCTION) typed_demangle = true;
783
784    // This is a bit of a hack; we're trying to demangle undefined symbols which don't necessarily
785    // have a ST_FUNCTION type. 
786    if (sym->getSec() == NULL && !sym->isAbsolute() && !sym->isCommonStorage())
787       typed_demangle = true;
788
789    if (typed_demangle) {
790       Module *rawmod = sym->getModule();
791
792       // At this point we need to generate the following information:
793       // A symtab name.
794       // A pretty (demangled) name.
795       // The symtab name goes in the global list as well as the module list.
796       // Same for the pretty name.
797       // Finally, check addresses to find aliases.
798       
799       std::string mangled_name = sym->getMangledName();
800       std::string working_name = mangled_name;
801       
802 #if !defined(os_windows)        
803       //Remove extra stabs information
804       const char *p = strchr(working_name.c_str(), ':');
805       if( p ) {
806          unsigned nchars = p - mangled_name.c_str();
807          working_name = std::string(mangled_name.c_str(), nchars);
808       }
809 #endif        
810       
811       std::string pretty_name = working_name;
812       std::string typed_name = working_name;
813       
814       if (!buildDemangledName(working_name, pretty_name, typed_name,
815                               nativeCompiler, (rawmod ? rawmod->language() : lang_Unknown))) {
816          pretty_name = working_name;
817       }
818       
819       sym->prettyName_ = pretty_name;
820       sym->typedName_ = typed_name;
821    }
822    else {
823        // All cases where there really shouldn't be a mangled
824       // name, since mangling is for functions.
825       
826       char *prettyName = P_cplus_demangle(sym->getMangledName().c_str(), nativeCompiler, false);
827       if (prettyName) {
828          sym->prettyName_ = prettyName;
829       }
830    }
831
832    return true;
833 }
834
835 bool Symtab::addSymbolToIndices(Symbol *&sym, bool undefined) 
836 {
837    assert(sym);
838    if (!undefined) {
839       everyDefinedSymbol.push_back(sym);
840       symsByMangledName[sym->getMangledName()].push_back(sym);
841       symsByPrettyName[sym->getPrettyName()].push_back(sym);
842       symsByTypedName[sym->getTypedName()].push_back(sym);
843 #if !defined(os_vxworks)    
844       // VxWorks doesn't know symbol addresses until object is loaded.
845       symsByOffset[sym->getAddr()].push_back(sym);
846 #endif
847    }
848    else {
849       // We keep a different index for undefined symbols
850       undefDynSymsByMangledName[sym->getMangledName()].push_back(sym);
851       undefDynSymsByPrettyName[sym->getPrettyName()].push_back(sym);
852       undefDynSymsByTypedName[sym->getTypedName()].push_back(sym);
853       // And undefDynSyms is already filled in
854    }
855     return true;
856 }
857
858 bool Symtab::addSymbolToAggregates(Symbol *&sym) 
859 {
860
861     switch(sym->getType()) {
862     case Symbol::ST_FUNCTION: {
863         // We want to do the following:
864         // If no function exists, create and add. 
865         // Combine this information
866         //   Add this symbol's names to the function.
867         //   Keep module information 
868
869         Function *func = NULL;
870         findFuncByEntryOffset(func, sym->getAddr());
871         if (!func) {
872             // Create a new function
873             // Also, update the symbol to point to this function.
874
875             func = new Function(sym);
876
877             everyFunction.push_back(func);
878             sorted_everyFunction = false;
879             funcsByOffset[sym->getAddr()] = func;
880         }
881         else {
882             /* XXX 
883              * For relocatable files, the offset of a symbol is relative to the
884              * beginning of a Region. Therefore, a symbol in a relocatable file
885              * is not uniquely identifiable by its offset, but it is uniquely
886              * identifiable by its Region and its offset.
887              *
888              * For now, do not add these functions to funcsByOffset collection.
889              */
890
891             if( func->getRegion() != sym->getRegion() ) {
892                 func = new Function(sym);
893                 everyFunction.push_back(func);
894                 sorted_everyFunction = false;
895             }
896             func->addSymbol(sym);
897         } 
898         sym->setFunction(func);
899
900         break;
901     }
902     case Symbol::ST_TLS:
903     case Symbol::ST_OBJECT: {
904         // The same as the above, but with variables.
905         Variable *var = NULL;
906         findVariableByOffset(var, sym->getAddr());
907         if (!var) {
908             // Create a new function
909             // Also, update the symbol to point to this function.
910             var = new Variable(sym);
911             
912             everyVariable.push_back(var);
913             varsByOffset[sym->getAddr()] = var;
914         }
915         else {
916             /* XXX
917              * For relocatable files, the offset is not a unique identifier for
918              * a Symbol. With functions, the Region and offset could be used to
919              * identify the symbol. With variables, the Region and offset may 
920              * not uniquely identify the symbol. The only case were this occurs
921              * is with COMMON symbols -- their offset is their memory alignment
922              * and their Region is undefined. In this case, always create a 
923              * new variable.
924              */
925             if( obj_RelocatableFile == getObjectType() &&
926                 ( var->getRegion() != sym->getRegion() ||
927                   NULL == sym->getRegion() ) )
928             {
929                 var = new Variable(sym);
930                 everyVariable.push_back(var);
931             }else{
932                 var->addSymbol(sym);
933             }
934         }
935         sym->setVariable(var);
936         break;
937     }
938     default: {
939         break;
940     }
941     }
942     return true;
943 }
944
945 // A hacky override for specially treating symbols that appear
946 // to be functions or variables but aren't.
947 //
948 // Example: IA-32/AMD-64 libc (and others compiled with libc headers)
949 // uses outlined locking primitives. These are named _L_lock_<num>
950 // and _L_unlock_<num> and labelled as functions. We explicitly do
951 // not include them in function scope.
952 bool Symtab::doNotAggregate(Symbol *&sym) {
953   if (sym->getMangledName().compare(0, strlen("_L_lock_"), "_L_lock_") == 0) {
954     return true;
955   }
956   if (sym->getMangledName().compare(0, strlen("_L_unlock_"), "_L_unlock_") == 0) {
957     return true;
958   }
959
960   // PPC64 Linux symbols in the .opd section appear to be functions,
961   // but are not.
962   if (sym->getRegion() && sym->getRegion()->getRegionName() == ".opd") {
963       return true;
964   }
965
966   return false;
967 }
968
969 /* Add the new name to the appropriate symbol index */
970
971 bool Symtab::updateIndices(Symbol *sym, std::string newName, NameType nameType) {
972     if (nameType & mangledName) {
973         // Add this symbol under the given name (as mangled)
974         symsByMangledName[newName].push_back(sym);
975     }
976     if (nameType & prettyName) {
977         // Add this symbol under the given name (as pretty)
978         symsByPrettyName[newName].push_back(sym);
979     }
980     if (nameType & typedName) {
981         // Add this symbol under the given name (as typed)
982         symsByTypedName[newName].push_back(sym);
983     }
984     return true;
985 }
986
987 #if 0
988 /* checkPPC64DescriptorSymbols() is no longer needed.  3-word descriptor
989  * symbols are properly taken care of during symbol parsing.  See
990  * parse_symbols() in Object-elf.C for details.
991  */
992
993 #if defined(ppc64_linux)
994 /* Special case for ppc64 ELF binaries. Sometimes a function has a 3-byte descriptor symbol
995  * along with it in the symbol table and "." preceding its original pretty name for the correct
996  * function symbol. This checks to see if we have a corresponding 3-byte descriptor symbol existing
997  * and if it does we remove the preceding "." from the name of the symbol
998  */
999
1000 void Symtab::checkPPC64DescriptorSymbols(Object *linkedFile)
1001 {
1002    // find the real functions -- those with the correct type in the symbol table
1003    for(SymbolIter symIter(*linkedFile); symIter;symIter++)
1004    {
1005       Symbol *lookUp = symIter.currval();
1006       const char *np = lookUp->getMangledName().c_str();
1007       if(!np)
1008          continue;
1009
1010       if(np[0] == '.' && (lookUp->getType() == Symbol::ST_FUNCTION))
1011       {
1012          std::vector<Symbol *>syms;
1013          std::string newName = np+1;
1014          if(linkedFile->get_symbols(newName, syms) && (syms[0]->getSize() == 24 || syms[0]->getSize() == 0))
1015          {
1016             //Remove the "." from the name
1017             lookUp->mangledNames[0] = newName;
1018
1019             //Change the type of the descriptor symbol
1020             syms[0]->type_ = Symbol::ST_NOTYPE;
1021          }
1022       }
1023    }
1024
1025 }
1026
1027 #endif
1028 #endif
1029
1030 //  setModuleLanguages is only called after modules have been defined.
1031 //  it attempts to set each module's language, information which is needed
1032 //  before names can be demangled.
1033 void Symtab::setModuleLanguages(dyn_hash_map<std::string, supportedLanguages> *mod_langs)
1034 {
1035    if (!mod_langs->size())
1036       return;  // cannot do anything here
1037    //  this case will arise on non-stabs platforms until language parsing can be introduced at this level
1038    std::vector<Module *> *modlist;
1039    Module *currmod = NULL;
1040    modlist = &_mods;
1041    //int dump = 0;
1042
1043    for (unsigned int i = 0;  i < modlist->size(); ++i)
1044    {
1045       currmod = (*modlist)[i];
1046       supportedLanguages currLang;
1047       if (currmod->isShared()) {
1048          continue;  // need to find some way to get shared object languages?
1049       }
1050
1051       const std::string fn = currmod->fileName();
1052       if (mod_langs->find(currmod->fileName()) != mod_langs->end())
1053       {
1054          currLang = (*mod_langs)[fn];
1055       }
1056       else if (fn.rfind(".s") != std::string::npos ||
1057             fn.rfind(".asm") != std::string::npos)
1058       {
1059          currLang = lang_Assembly;
1060       }
1061       else if (fn.rfind(".c") != std::string::npos)
1062       {
1063          currLang = lang_C;
1064       }
1065       else if (fn.rfind(".cpp") != std::string::npos ||
1066             fn.rfind(".cc") != std::string::npos ||
1067             fn.rfind(".C") != std::string::npos)
1068       {
1069          currLang = lang_CPlusPlus;
1070       }
1071       else
1072       {
1073          continue;
1074       }
1075       currmod->setLanguage(currLang);
1076    }
1077 }
1078
1079 void Symtab::createDefaultModule() {
1080     Module *mod = NULL;
1081     if (getObjectType() == obj_SharedLib) {
1082         mod = new Module(lang_Unknown, 
1083                          imageOffset_,
1084                          name(),
1085                          this);
1086     }
1087     else {
1088         mod = new Module(lang_Unknown, 
1089                          imageOffset_,
1090 #if defined(os_vxworks)
1091                          // VxWorks' kernel objects should
1092                          // have their own module.
1093                          name(),
1094 #else
1095                          "DEFAULT_MODULE",
1096 #endif
1097                          this);
1098     }
1099     modsByFileName[mod->fileName()] = mod;
1100     modsByFullName[mod->fullName()] = mod;
1101     _mods.push_back(mod);
1102 }
1103
1104
1105
1106 Module *Symtab::getOrCreateModule(const std::string &modName, 
1107                                   const Offset modAddr)
1108 {
1109    std::string nameToUse;
1110    if (modName.length() > 0)
1111       nameToUse = modName;
1112    else
1113       nameToUse = "DEFAULT_MODULE";
1114
1115    Module *fm = NULL;
1116    if (findModuleByName(fm, nameToUse)) 
1117    {
1118       return fm;
1119    }
1120
1121     const char *str = nameToUse.c_str();
1122     int len = nameToUse.length();
1123     assert(len>0);
1124
1125     // TODO ignore directory definitions for now
1126     if (str[len-1] == '/') 
1127         return NULL;
1128
1129     return (newModule(nameToUse, modAddr, lang_Unknown));
1130 }
1131  
1132 Module *Symtab::newModule(const std::string &name, const Offset addr, supportedLanguages lang)
1133 {
1134     Module *ret = NULL;
1135     // modules can be defined several times in C++ due to templates and
1136     //   in-line member functions.
1137
1138     if (findModuleByName(ret, name)) 
1139     {
1140         return(ret);
1141     }
1142
1143     //parsing_printf("=== image, creating new pdmodule %s, addr 0x%x\n",
1144     //                          name.c_str(), addr);
1145     
1146     std::string fileNm, fullNm;
1147     fullNm = name;
1148     fileNm = extract_pathname_tail(name);
1149
1150     // /* DEBUG */ fprintf( stderr, "%s[%d]: In %p: Creating new pdmodule '%s'/'%s'\n", FILE__, __LINE__, this, fileNm.c_str(), fullNm.c_str() );
1151     create_printf("%s[%d]: In %p: Creating new module '%s'/'%s'\n", FILE__, __LINE__, this, fileNm.c_str(), fullNm.c_str());
1152
1153     ret = new Module(lang, addr, fullNm, this);
1154     assert(ret);
1155
1156     /*
1157      * FIXME
1158      *
1159      * There are cases where the fileName can be the same, but the full name is
1160      * different and the modules are actually different. This is an inherent
1161      * problem with how modules are processed.
1162      */
1163     if (modsByFileName.end() != modsByFileName.find(ret->fileName()))
1164     {
1165        create_printf("%s[%d]:  WARN:  LEAK?  already have module with name %s\n", 
1166              FILE__, __LINE__, ret->fileName().c_str());
1167     }
1168
1169     if (modsByFullName.end() != modsByFullName.find(ret->fullName()))
1170     {
1171        create_printf("%s[%d]:  WARN:  LEAK?  already have module with name %s\n", 
1172                      FILE__, __LINE__, ret->fullName().c_str());
1173     }
1174
1175     modsByFileName[ret->fileName()] = ret;
1176     modsByFullName[ret->fullName()] = ret;
1177     _mods.push_back(ret);
1178     
1179     return (ret);
1180 }
1181
1182 Symtab::Symtab(std::string filename, bool defensive_bin, bool &err) :
1183    member_offset_(0),
1184    is_a_out(false), 
1185    main_call_addr_(0),
1186    nativeCompiler(false), 
1187    isLineInfoValid_(false), 
1188    isTypeInfoValid_(false),
1189    isDefensiveBinary_(defensive_bin),
1190    obj_private(NULL),
1191    _ref_cnt(1)
1192 {
1193     init_debug_symtabAPI();
1194    // Initialize error parameter
1195    err = false;
1196    
1197    create_printf("%s[%d]: created symtab for %s\n", FILE__, __LINE__, filename.c_str());
1198
1199 #if defined (os_windows)
1200    extern void fixup_filename(std::string &);
1201    fixup_filename(filename);
1202 #endif
1203
1204    //  createMappedFile handles reference counting
1205    mf = MappedFile::createMappedFile(filename);
1206    if (!mf) {
1207       create_printf("%s[%d]: WARNING: creating symtab for %s, " 
1208                     "createMappedFile() failed\n", FILE__, __LINE__, 
1209                     filename.c_str());
1210       err = true;
1211       return;
1212    }
1213
1214    obj_private = new Object(mf, mfForDebugInfo, defensive_bin, 
1215                             symtab_log_perror, true);
1216    if (obj_private->hasError()) {
1217      err = true;
1218      return;
1219    }
1220
1221    if (!extractInfo(obj_private))
1222    {
1223       create_printf("%s[%d]: WARNING: creating symtab for %s, extractInfo() " 
1224                     "failed\n", FILE__, __LINE__, filename.c_str());
1225       err = true;
1226    }
1227
1228    member_name_ = mf->filename();
1229
1230    defaultNamespacePrefix = "";
1231 }
1232
1233 Symtab::Symtab(unsigned char *mem_image, size_t image_size, 
1234                const std::string &name, bool defensive_bin, bool &err) :
1235    member_offset_(0),
1236    is_a_out(false), 
1237    main_call_addr_(0),
1238    nativeCompiler(false),
1239    isLineInfoValid_(false),
1240    isTypeInfoValid_(false),
1241    isDefensiveBinary_(defensive_bin),
1242    obj_private(NULL),
1243    _ref_cnt(1)
1244 {
1245    // Initialize error parameter
1246    err = false;
1247   
1248    create_printf("%s[%d]: created symtab for memory image at addr %u\n", 
1249                  FILE__, __LINE__, mem_image);
1250
1251    //  createMappedFile handles reference counting
1252    mf = MappedFile::createMappedFile(mem_image, image_size, name);
1253    if (!mf) {
1254       create_printf("%s[%d]: WARNING: creating symtab for memory image at " 
1255                     "addr %u, createMappedFile() failed\n", FILE__, __LINE__, 
1256                     mem_image);
1257       err = true;
1258       return;
1259    }
1260
1261    obj_private = new Object(mf, mfForDebugInfo, defensive_bin, 
1262                             symtab_log_perror, true);
1263    if (obj_private->hasError()) {
1264      err = true;
1265      return;
1266    }
1267
1268    if (!extractInfo(obj_private))
1269    {
1270       create_printf("%s[%d]: WARNING: creating symtab for memory image at addr" 
1271                     "%u, extractInfo() failed\n", FILE__, __LINE__, mem_image);
1272       err = true;
1273    }
1274
1275    member_name_ = mf->filename();
1276
1277    defaultNamespacePrefix = "";
1278 }
1279
1280 // Symtab constructor for archive members
1281 #if defined(os_aix)
1282 Symtab::Symtab(std::string filename, std::string member_name, Offset offset, 
1283                bool &err, void *base) :
1284    member_name_(member_name), 
1285    member_offset_(offset),
1286    is_a_out(false),
1287    main_call_addr_(0), 
1288    nativeCompiler(false), 
1289    isLineInfoValid_(false),
1290    isTypeInfoValid_(false), 
1291    obj_private(NULL),
1292    _ref_cnt(1)
1293 {
1294    mf = MappedFile::createMappedFile(filename);
1295    assert(mf);
1296    obj_private = new Object(mf, mfForDebugInfo, member_name, offset, symtab_log_perror, base);
1297    if (obj_private->hasError()) {
1298      err = true;
1299      return;
1300    }
1301    err = !extractInfo(obj_private);
1302    defaultNamespacePrefix = "";
1303
1304    create_printf("%s[%d]: created symtab for %s(%s)\n", FILE__, __LINE__, filename.c_str(),
1305            member_name.c_str());
1306 }
1307 #else
1308 Symtab::Symtab(std::string, std::string, Offset, bool &, void *)
1309 {
1310     assert(0);
1311 }
1312 #endif
1313
1314 #if defined(os_aix) // is this ever used on AIX? 
1315 Symtab::Symtab(char *mem_image, size_t image_size, std::string member_name,
1316                        Offset offset, bool &err, void *base) :
1317    member_name_(member_name), 
1318    member_offset_(offset),
1319    is_a_out(false), 
1320    main_call_addr_(0),
1321    nativeCompiler(false), 
1322    isLineInfoValid_(false), 
1323    isTypeInfoValid_(false),
1324    _ref_cnt(1)
1325 {
1326    mf = MappedFile::createMappedFile(mem_image, image_size);
1327    assert(mf);
1328    obj_private = new Object(mf, mf, member_name, offset, symtab_log_perror, base);
1329    if (obj_private->hasError()) {
1330      err = true;
1331      return;
1332    }
1333    err = !extractInfo(obj_private);
1334    defaultNamespacePrefix = "";
1335 }
1336 #else 
1337 Symtab::Symtab(char *, size_t, std::string , Offset, bool &, void *)
1338 {
1339     assert(0);
1340 }
1341 #endif
1342
1343 bool sort_reg_by_addr(const Region* a, const Region* b)
1344 {
1345   if (a->getRegionAddr() == b->getRegionAddr())
1346     return a->getMemSize() < b->getMemSize();
1347   return a->getRegionAddr() < b->getRegionAddr();
1348 }
1349
1350 extern void print_symbols( std::vector< Symbol *>& allsymbols );
1351 extern void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols);
1352
1353 bool Symtab::extractInfo(Object *linkedFile)
1354 {
1355 #if defined(TIMED_PARSE)
1356     struct timeval starttime;
1357     gettimeofday(&starttime, NULL);
1358 #endif
1359     mfForDebugInfo = linkedFile->getMappedFileForDebugInfo();
1360
1361     /* FIXME 
1362      *
1363      * Some ELF .o's don't have contiguous code and data Regions so these data
1364      * members are imprecise. These members should probably be deprecated in
1365      * favor of the getCodeRegions and getDataRegions functions.
1366      */
1367
1368     bool err = true;
1369     imageOffset_ = linkedFile->code_off();
1370     dataOffset_ = linkedFile->data_off();
1371
1372     imageLen_ = linkedFile->code_len();
1373     dataLen_ = linkedFile->data_len();
1374     
1375     if (0 == imageLen_ || 0 == linkedFile->code_ptr()) 
1376     {
1377         // for AIX, code_ptr()==NULL is normal behavior
1378 #if !defined(os_aix)
1379        if (0 == linkedFile->code_ptr()) {
1380           //fprintf(stderr, "[%s][%d]WARNING: null code pointer in Symtab for"
1381           //" file %s, possibly due to a missing .text section.\n",
1382           //__FILE__,__LINE__, file().c_str());
1383           linkedFile->code_ptr_ = (char *) linkedFile->code_off();
1384        }
1385        else 
1386 #endif
1387        {
1388            if( object_type_ != obj_RelocatableFile ||
1389                linkedFile->code_ptr() == 0)
1390            {
1391                 serr = Obj_Parsing;
1392                 return false;
1393            }
1394        }
1395    }
1396         
1397   //  if (!imageLen_ || !linkedFile->code_ptr()) {
1398   //      serr = Obj_Parsing; 
1399   //      return false; 
1400    // }
1401
1402     no_of_sections = linkedFile->no_of_sections();
1403     newSectionInsertPoint = no_of_sections;
1404     no_of_symbols = linkedFile->no_of_symbols();
1405     
1406     isStaticBinary_ = linkedFile->isStaticBinary();
1407
1408     hasRel_ = false;
1409     hasRela_ = false;
1410     hasReldyn_ = false;
1411     hasReladyn_ = false;
1412     hasRelplt_ = false;
1413     hasRelaplt_ = false;
1414     regions_ = linkedFile->getAllRegions();
1415
1416     for (unsigned index=0;index<regions_.size();index++)
1417     {
1418         if ( regions_[index]->isLoadable() ) 
1419         {
1420            if (     (regions_[index]->getRegionPermissions() == Region::RP_RX) 
1421                  || (isDefensiveBinary_ && 
1422                      regions_[index]->getRegionPermissions() == Region::RP_RW)
1423                  || (regions_[index]->getRegionPermissions() == Region::RP_RWX)) 
1424            {
1425               codeRegions_.push_back(regions_[index]);
1426            }
1427            else 
1428            {
1429               dataRegions_.push_back(regions_[index]);
1430            }
1431         }
1432
1433         regionsByEntryAddr[regions_[index]->getRegionAddr()] = regions_[index];
1434
1435         if (regions_[index]->getRegionType() == Region::RT_REL) 
1436         {
1437             hasRel_ = true;
1438         }
1439
1440         if (regions_[index]->getRegionType() == Region::RT_RELA) 
1441         {
1442             hasRela_ = true;
1443         }
1444
1445 #if defined(os_linux) || defined(os_freebsd)
1446         hasReldyn_ = linkedFile->hasReldyn();
1447         hasReladyn_ = linkedFile->hasReladyn();
1448         hasRelplt_ = linkedFile->hasRelplt();
1449         hasRelaplt_ = linkedFile->hasRelaplt();
1450 #endif  
1451
1452     }
1453     // sort regions_ & codeRegions_ vectors
1454
1455     std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
1456     std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
1457     std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
1458
1459     /* insert error check here. check if parsed */
1460     address_width_ = linkedFile->getAddressWidth();
1461     is_a_out = linkedFile->is_aout();
1462     code_ptr_ = linkedFile->code_ptr();
1463     data_ptr_ = linkedFile->data_ptr();
1464
1465     if (linkedFile->interpreter_name())
1466        interpreter_name_ = std::string(linkedFile->interpreter_name());
1467
1468     entry_address_ = linkedFile->getEntryAddress();
1469     base_address_ = linkedFile->getBaseAddress();
1470     load_address_ = linkedFile->getLoadAddress();
1471     toc_offset_ = linkedFile->getTOCoffset();
1472     object_type_  = linkedFile->objType();
1473     is_eel_ = linkedFile->isEEL();
1474     linkedFile->getSegments(segments_);
1475
1476 #if !defined(os_aix) && !defined(os_windows)
1477     linkedFile->getDependencies(deps_);
1478 #endif
1479
1480 #if defined (os_aix)
1481     //  These should go away
1482     linkedFile->get_stab_info(stabstr_, nstabs_, stabs_, stringpool_);
1483     linkedFile->get_line_info(nlines_, lines_, fdptr_);
1484 #endif
1485
1486 #if defined(os_aix) || defined(os_linux) || defined(os_freebsd)
1487     // make sure we're using the right demangler
1488     
1489     nativeCompiler = parseCompilerType(linkedFile);
1490     //parsing_printf("isNativeCompiler: %d\n", nativeCompiler);
1491 #endif
1492     
1493     // define all of the functions
1494     //statusLine("winnowing functions");
1495
1496     // a vector to hold all created symbols until they are properly classified
1497     std::vector<Symbol *> raw_syms;
1498
1499 #ifdef BINEDIT_DEBUG
1500     printf("== from linkedFile...\n");
1501     print_symbol_map(linkedFile->getAllSymbols());
1502 #endif
1503
1504     if (!extractSymbolsFromFile(linkedFile, raw_syms)) 
1505     {
1506         err = false;
1507         serr = Syms_To_Functions;
1508         return false;
1509     }
1510
1511     // don't sort the symbols--preserve the original ordering
1512     //sort(raw_syms.begin(),raw_syms.end(),symbol_compare);
1513
1514     createDefaultModule();
1515
1516     if (!fixSymModules(raw_syms)) 
1517     {
1518         err = false;
1519         serr = Syms_To_Functions;
1520         return false;
1521     }
1522         Object *obj = getObject();
1523         if (!obj)
1524         {
1525 #if !defined(os_vxworks)
1526                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
1527 #endif
1528                 return false;
1529         }
1530     obj->clearSymsToMods();
1531
1532     // wait until all modules are defined before applying languages to
1533     // them we want to do it this way so that module information comes
1534     // from the function symbols, first and foremost, to avoid any
1535     // internal module-function mismatching.
1536             
1537     // get Information on the language each modules is written in
1538     // (prior to making modules)
1539
1540     dyn_hash_map<std::string, supportedLanguages> mod_langs;
1541     linkedFile->getModuleLanguageInfo(&mod_langs);
1542     setModuleLanguages(&mod_langs);
1543         
1544     // Be sure that module languages are set before demangling, or
1545     // we won't get very far.
1546
1547     if (!demangleSymbols(raw_syms)) 
1548     {
1549         err = false;
1550         serr = Syms_To_Functions;
1551         return false;
1552     }
1553     
1554     if (!demangleSymbols(undefDynSyms)) {
1555        err = false;
1556        serr = Syms_To_Functions;
1557        return false;
1558     }
1559
1560     if (!createIndices(raw_syms, false)) 
1561     {
1562         err = false;
1563         serr = Syms_To_Functions;
1564         return false;
1565     }
1566
1567     if (!createIndices(undefDynSyms, true)) 
1568     {
1569         err = false;
1570         serr = Syms_To_Functions;
1571         return false;
1572     }
1573
1574     if (!createAggregates()) 
1575     {
1576         err = false;
1577         serr = Syms_To_Functions;
1578         return false;
1579     }
1580         
1581     // Once languages are assigned, we can build demangled names (in
1582     // the wider sense of demangling which includes stripping _'s from
1583     // fortran names -- this is why language information must be
1584     // determined before this step).
1585     
1586     // Also identifies aliases (multiple names with equal addresses)
1587     
1588     //addSymtabVariables();
1589     linkedFile->getAllExceptions(excpBlocks);
1590
1591     vector<relocationEntry >fbt;
1592     linkedFile->get_func_binding_table(fbt);
1593     for(unsigned i=0; i<fbt.size();i++)
1594         relocation_table_.push_back(fbt[i]);
1595     return true;
1596 }
1597
1598 Symtab::Symtab(const Symtab& obj) :
1599    LookupInterface(),
1600    Serializable(),
1601    AnnotatableSparse(),
1602    _ref_cnt(1)
1603 {
1604     create_printf("%s[%d]: Creating symtab 0x%p from symtab 0x%p\n", FILE__, __LINE__, this, &obj);
1605   
1606     member_name_ = obj.member_name_;
1607     member_offset_ = obj.member_offset_;
1608     imageOffset_ = obj.imageOffset_;
1609     imageLen_ = obj.imageLen_;
1610     dataOffset_ = obj.dataOffset_;
1611     dataLen_ = obj.dataLen_;
1612     isDefensiveBinary_ = obj.isDefensiveBinary_;
1613
1614    isLineInfoValid_ = obj.isLineInfoValid_;
1615    isTypeInfoValid_ = obj.isTypeInfoValid_;
1616
1617    is_a_out = obj.is_a_out;
1618    main_call_addr_ = obj.main_call_addr_; // address of call to main()
1619
1620    nativeCompiler = obj.nativeCompiler;
1621    defaultNamespacePrefix = obj.defaultNamespacePrefix;
1622
1623    //sections
1624    no_of_sections = obj.no_of_sections;
1625    unsigned i;
1626
1627    for (i=0;i<obj.regions_.size();i++)
1628       regions_.push_back(new Region(*(obj.regions_[i])));
1629
1630    for (i=0;i<regions_.size();i++)
1631       regionsByEntryAddr[regions_[i]->getRegionAddr()] = regions_[i];
1632
1633    // TODO FIXME: copying symbols/Functions/Variables
1634
1635    for (i=0;i<obj._mods.size();i++)
1636    {
1637       Module *m = new Module(*(obj._mods[i]));
1638       _mods.push_back(m);
1639       modsByFileName[m->fileName()] = m;
1640       modsByFullName[m->fullName()] = m;
1641       fprintf(stderr, "%s[%d]:  copy ctor creating new module %s\n", 
1642             FILE__, __LINE__, m->fileName().c_str());
1643    }
1644
1645    for (i=0; i<relocation_table_.size();i++) 
1646    {
1647       relocation_table_.push_back(relocationEntry(obj.relocation_table_[i]));
1648    }
1649
1650    for (i=0;i<excpBlocks.size();i++)
1651    {
1652       excpBlocks.push_back(new ExceptionBlock(*(obj.excpBlocks[i])));
1653    }
1654
1655    deps_ = obj.deps_;
1656 }
1657
1658 // Address must be in code or data range since some code may end up
1659 // in the data segment
1660 bool Symtab::isValidOffset(const Offset where) const
1661 {
1662    return isCode(where) || isData(where);
1663 }
1664
1665 /* Performs a binary search on the codeRegions_ vector, which must
1666  * be kept in sorted order
1667  */
1668 bool Symtab::isCode(const Offset where)  const
1669 {
1670 #if defined(os_vxworks)
1671     // All memory is valid in the kernel.  Kinda.
1672     //return true;
1673 #endif
1674
1675    if (!codeRegions_.size()) 
1676    {
1677       fprintf(stderr, "%s[%d] No code regions in %s \n",
1678             __FILE__, __LINE__, mf->filename().c_str());
1679       return false;
1680    }
1681
1682    // search for "where" in codeRegions_ (code regions must not overlap)
1683    int first = 0; 
1684    int last = codeRegions_.size() - 1;
1685
1686    while (last >= first) 
1687    {
1688       Region *curreg = codeRegions_[(first + last) / 2];
1689       if (where >= curreg->getRegionAddr()
1690             && where < (curreg->getRegionAddr()
1691                + curreg->getDiskSize())) 
1692       {
1693          if (curreg->getRegionType() == Region::RT_BSS)
1694             return false;
1695          return true;
1696       }
1697       else if (where < curreg->getRegionAddr()) 
1698       {
1699          last = ((first + last) / 2) - 1;
1700       }
1701       else if (where >= (curreg->getRegionAddr() + curreg->getMemSize()))
1702       {
1703          first = ((first + last) / 2) + 1;
1704       }
1705       else 
1706       {  // "where" is in the range: 
1707          // [memOffset + diskSize , memOffset + memSize)
1708          // meaning that it's in an uninitialized data region 
1709          return false;
1710       }
1711    }
1712
1713    return false;
1714 }
1715
1716 /* Performs a binary search on the dataRegions_ vector, which must
1717  * be kept in sorted order */
1718 bool Symtab::isData(const Offset where)  const
1719 {
1720    if (!dataRegions_.size()) 
1721    {
1722       fprintf(stderr, "%s[%d] No data regions in %s \n",
1723             __FILE__,__LINE__,mf->filename().c_str());
1724       return false;
1725    }
1726
1727    int first = 0; 
1728    int last = dataRegions_.size() - 1;
1729
1730    while (last >= first) 
1731    {
1732       Region *curreg = dataRegions_[(first + last) / 2];
1733
1734       if (     (where >= curreg->getRegionAddr())
1735             && (where < (curreg->getRegionAddr() + curreg->getRegionSize())))
1736       {
1737          return true;
1738       }
1739       else if (where < curreg->getRegionAddr()) 
1740       {
1741          last = ((first + last) / 2) - 1;
1742       }
1743       else 
1744       {
1745          first = ((first + last) / 2) + 1;
1746       }
1747    }
1748
1749    return false;
1750 }
1751
1752 SYMTAB_EXPORT bool Symtab::getFuncBindingTable(std::vector<relocationEntry> &fbt) const
1753 {
1754    fbt = relocation_table_;
1755    return true;
1756 }
1757
1758 SYMTAB_EXPORT bool Symtab::updateFuncBindingTable(Offset stub_addr, Offset plt_addr)
1759 {
1760     int stub_idx = -1, plt_idx = -1;
1761
1762     for (unsigned i = 0; i < relocation_table_.size(); ++i) {
1763         if (stub_addr == relocation_table_[i].target_addr())
1764             stub_idx = i;
1765         if (plt_addr  == relocation_table_[i].target_addr())
1766             plt_idx = i;
1767         if (stub_idx >= 0 && plt_idx >= 0)
1768             break;
1769     }
1770     if (stub_idx >= 0 && plt_idx >= 0) {
1771         relocation_table_[stub_idx] = relocation_table_[plt_idx];
1772         relocation_table_[stub_idx].setTargetAddr(stub_addr);
1773         return true;
1774     }
1775     return false;
1776 }
1777
1778 SYMTAB_EXPORT std::vector<std::string> &Symtab::getDependencies(){
1779     return deps_;
1780 }
1781
1782 SYMTAB_EXPORT Archive *Symtab::getParentArchive() const {
1783     return parentArchive_;
1784 }
1785
1786 Symtab::~Symtab()
1787 {
1788    // Doesn't do anything yet, moved here so we don't mess with symtab.h
1789    // Only called if we fail to create a process.
1790    // Or delete the a.out...
1791
1792 #if 1 
1793
1794    for (unsigned i = 0; i < regions_.size(); i++) 
1795    {
1796       delete regions_[i];
1797    }
1798
1799    regions_.clear();
1800    codeRegions_.clear();
1801    dataRegions_.clear();
1802    regionsByEntryAddr.clear();
1803
1804    std::vector<Region *> *user_regions = NULL;
1805    getAnnotation(user_regions, UserRegionsAnno);
1806
1807    if (user_regions)
1808    {
1809       for (unsigned i = 0; i < user_regions->size(); ++i) 
1810          delete (*user_regions)[i];
1811       user_regions->clear();
1812    }
1813
1814    // Symbols are copied from linkedFile, and NOT deleted
1815    everyDefinedSymbol.clear();
1816    undefDynSyms.clear();
1817    undefDynSymsByMangledName.clear();
1818    undefDynSymsByPrettyName.clear();
1819    undefDynSymsByTypedName.clear();
1820
1821    // TODO make annotation
1822    userAddedSymbols.clear();
1823    symsByOffset.clear();
1824    symsByMangledName.clear();
1825    symsByPrettyName.clear();
1826    symsByTypedName.clear();
1827
1828    for (unsigned i = 0; i < everyFunction.size(); i++) 
1829    {
1830       delete everyFunction[i];
1831    }
1832
1833    everyFunction.clear();
1834    funcsByOffset.clear();
1835
1836    for (unsigned i = 0; i < everyVariable.size(); i++) 
1837    {
1838       delete everyVariable[i];
1839    }
1840
1841    everyVariable.clear();
1842    varsByOffset.clear();
1843
1844    for (unsigned i = 0; i < _mods.size(); i++) 
1845    {
1846       delete _mods[i];
1847    }
1848    _mods.clear();
1849    modsByFileName.clear();
1850    modsByFullName.clear();
1851
1852    for (unsigned i=0;i<excpBlocks.size();i++)
1853       delete excpBlocks[i];
1854
1855    create_printf("%s[%d]: Symtab::~Symtab removing %p from allSymtabs\n", 
1856          FILE__, __LINE__, this);
1857
1858    deps_.clear();
1859
1860    for (unsigned i = 0; i < allSymtabs.size(); i++) 
1861    {
1862       if (allSymtabs[i] == this)
1863          allSymtabs.erase(allSymtabs.begin()+i);
1864    }
1865
1866    // Make sure to free the underlying Object as it doesn't have a factory
1867    // open method
1868    if( obj_private ) delete obj_private;
1869
1870    //fprintf(stderr, "%s[%d]:  symtab DTOR, mf = %p: %s\n", FILE__, __LINE__, mf, mf->filename().c_str());
1871    if (mf) MappedFile::closeMappedFile(mf);
1872    //if (mfForDebugInfo) MappedFile::closeMappedFile(mfForDebugInfo);
1873 #endif
1874 }       
1875
1876 bool Symtab::exportXML(string file)
1877 {
1878 #if defined (cap_serialization)
1879    try 
1880    {
1881            SerContext<Symtab> *scs = new SerContext<Symtab>(this, file);
1882            serialize(file, scs, ser_xml);
1883 #if 0
1884            SerContext<Symtab> *scs = new SerContext<Symtab>(this);
1885            SerializerXML *ser = new SerializerXML(scs, "XMLTranslator", file, sd_serialize, true);
1886            serialize(ser, "Symtab");
1887 #endif
1888 #if 0
1889       SerializerXML sb("XMLTranslator", file, sd_serialize, true);
1890       serialize(&sb, "Symtab");
1891 #endif
1892    } 
1893    catch (const SerializerError &err) 
1894    {
1895       fprintf(stderr, "%s[%d]: error serializing xml: %s\n", FILE__, __LINE__, err.what());
1896       return false;
1897    }
1898
1899    return false;
1900 #else
1901    fprintf(stderr, "%s[%d]:  WARNING:  cannot produce %s, serialization not available\n", FILE__, __LINE__, file.c_str());
1902    return false;
1903 #endif
1904 }
1905
1906 #if defined (cap_serialization)
1907 bool Symtab::exportBin(string file)
1908 {
1909    try
1910    {
1911            SerContext<Symtab> *scs = new SerContext<Symtab>(this, file);
1912            serialize(file, scs, ser_bin);
1913            //fprintf(stderr, "%s[%d]:  did serialize\n", FILE__, __LINE__);
1914            return true;
1915    }
1916
1917    catch (const SerializerError &err)
1918    {
1919       if (err.code() == SerializerError::ser_err_disabled) 
1920       {
1921          fprintf(stderr, "%s[%d]:  WARN:  serialization is disabled for file %s\n",
1922                FILE__, __LINE__, file.c_str());
1923          return false;
1924       }
1925
1926       fprintf(stderr, "%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
1927             err.what(), err.file().c_str(), err.line());
1928    }
1929
1930    fprintf(stderr, "%s[%d]:  error doing binary serialization\n", __FILE__, __LINE__);
1931    return false;
1932 }
1933 #else
1934 bool Symtab::exportBin(string) 
1935 {
1936    fprintf(stderr, "%s[%d]:  WARNING:  serialization not available\n", FILE__, __LINE__);
1937    return false;
1938 }
1939 #endif
1940
1941 Symtab *Symtab::importBin(std::string file)
1942 {
1943 #if defined (cap_serialization)
1944    MappedFile *mf= MappedFile::createMappedFile(file);
1945    if (!mf) 
1946    {
1947       fprintf(stderr, "%s[%d]:  failed to map file %s\n", FILE__, __LINE__, file.c_str());
1948       return NULL;
1949    }
1950
1951    Symtab *st = new Symtab(mf);
1952
1953    try
1954    {
1955            SerContext<Symtab> *scs = new SerContext<Symtab>(st, file);
1956            if (!st->deserialize(file, scs))
1957            {
1958                    delete st;
1959                    return NULL;
1960            }
1961
1962            return st;
1963    }
1964
1965    catch (const SerializerError &err)
1966    {
1967       if (err.code() == SerializerError::ser_err_disabled) 
1968       {
1969          serialize_printf("%s[%d]:  WARN:  serialization is disabled for file %s\n",
1970                FILE__, __LINE__, file.c_str());
1971          fprintf(stderr, "%s[%d]:  WARN:  serialization is disabled for file %s\n",
1972                FILE__, __LINE__, file.c_str());
1973          return NULL;
1974       }
1975
1976       serialize_printf("%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
1977             err.what(), err.file().c_str(), err.line());
1978       fprintf(stderr, "%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
1979             err.what(), err.file().c_str(), err.line());
1980    }
1981
1982
1983    serialize_printf("%s[%d]:  error doing binary deserialization\n", __FILE__, __LINE__);
1984    delete st;
1985    return NULL;
1986 #else
1987    serialize_printf("%s[%d]:  WARNING:  cannot produce %s, serialization not available\n", FILE__, __LINE__, file.c_str());
1988    return NULL;
1989 #endif
1990 }
1991
1992 bool Symtab::openFile(Symtab *&obj, void *mem_image, size_t size, 
1993                       std::string name, def_t def_bin)
1994 {
1995    bool err = false;
1996 #if defined(TIMED_PARSE)
1997    struct timeval starttime;
1998    gettimeofday(&starttime, NULL);
1999 #endif
2000
2001    obj = new Symtab((unsigned char *) mem_image, size, name, (def_bin == Defensive), err);
2002
2003 #if defined(TIMED_PARSE)
2004     struct timeval endtime;
2005     gettimeofday(&endtime, NULL);
2006     unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
2007     unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
2008     unsigned long difftime = lendtime - lstarttime;
2009     double dursecs = difftime/(1000 );
2010     cout << __FILE__ << ":" << __LINE__ <<": openFile "<< filename<< " took "<<dursecs <<" msecs" << endl;
2011 #endif
2012     if(!err)
2013     {
2014        allSymtabs.push_back(obj);
2015     }
2016     else
2017     {
2018         delete obj;
2019        obj = NULL;
2020     }
2021     // returns true on success (not an error)
2022     return !err;
2023 }
2024
2025 bool Symtab::closeSymtab(Symtab *st)
2026 {
2027         bool found = false;
2028         if (!st) return false;
2029
2030     --(st->_ref_cnt);
2031
2032         std::vector<Symtab *>::reverse_iterator iter;
2033         for (iter = allSymtabs.rbegin(); iter != allSymtabs.rend() ; iter++)
2034         {
2035                 if (*iter == st)
2036                 {
2037             if(0 == st->_ref_cnt)
2038                             allSymtabs.erase(iter.base() -1);
2039                         found = true;
2040                 }
2041         }
2042     if(0 == st->_ref_cnt)
2043             delete(st);
2044         return found;
2045 }
2046
2047 Symtab *Symtab::findOpenSymtab(std::string filename)
2048 {
2049    unsigned numSymtabs = allSymtabs.size();
2050         for (unsigned u=0; u<numSymtabs; u++) 
2051         {
2052                 assert(allSymtabs[u]);
2053                 if (filename == allSymtabs[u]->file() && 
2054           allSymtabs[u]->mf->canBeShared()) 
2055                 {
2056             allSymtabs[u]->_ref_cnt++;
2057                         // return it
2058                         return allSymtabs[u];
2059                 }
2060         }   
2061         return NULL;
2062 }
2063
2064 bool Symtab::openFile(Symtab *&obj, std::string filename, def_t def_binary)
2065 {
2066    bool err = false;
2067 #if defined(TIMED_PARSE)
2068    struct timeval starttime;
2069    gettimeofday(&starttime, NULL);
2070 #endif
2071
2072    // AIX: it's possible that we're reparsing a file with better information
2073    // about it. If so, yank the old one out of the allSymtabs std::vector -- replace
2074    // it, basically.
2075    if ( filename.find("/proc") == std::string::npos)
2076    {
2077            obj = findOpenSymtab(filename);
2078            if (obj)
2079            {
2080                    //fprintf(stderr, "%s[%d]:  have existing symtab obj for %s\n", FILE__, __LINE__, filename.c_str());
2081                    return true;
2082    }
2083    }
2084
2085
2086 #if defined (cap_serialization)
2087 #if 0
2088    obj = importBin(filename);
2089
2090    if (NULL == obj) 
2091    {
2092            if (deserializeEnforced<Symtab>(filename))
2093           {
2094                           serialize_printf("%s[%d]: aborting new symtab, expected deserialize failed\n",
2095                                           FILE__, __LINE__);
2096                           fprintf(stderr, "%s[%d]: aborting new symtab, expected deserialize failed\n",
2097                                           FILE__, __LINE__);
2098                           return false;
2099           }
2100            //fprintf(stderr, "%s[%d]:  deserialize failed, but not enforced for %s\n", FILE__, __LINE__, filename.c_str());
2101    }
2102    else 
2103    {
2104           //fprintf(stderr, "%s[%d]:  deserialize success\n", FILE__, __LINE__);
2105       return true;
2106    }
2107 #endif
2108 #endif
2109
2110    obj = new Symtab(filename, (def_binary == Defensive), err);
2111
2112 #if defined(TIMED_PARSE)
2113    struct timeval endtime;
2114    gettimeofday(&endtime, NULL);
2115    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
2116    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
2117    unsigned long difftime = lendtime - lstarttime;
2118    double dursecs = difftime/(1000 );
2119    cout << __FILE__ << ":" << __LINE__ <<": openFile "<< filename<< " took "<<dursecs <<" msecs" << endl;
2120 #endif
2121
2122    if (!err)
2123    {
2124       if (filename.find("/proc") == std::string::npos)
2125          allSymtabs.push_back(obj);
2126
2127
2128 #if defined (cap_serialization)
2129 #if 0
2130       serialize_printf("%s[%d]:  doing bin-serialize for %s\n", 
2131             FILE__, __LINE__, filename.c_str());
2132
2133       if (!obj->exportBin(filename))
2134       {
2135          serialize_printf("%s[%d]:  failed to export symtab\n", FILE__, __LINE__);
2136       }
2137       else
2138          serialize_printf("%s[%d]:  did bin-serialize for %s\n", 
2139                           FILE__, __LINE__, filename.c_str());
2140 #endif
2141 #endif
2142
2143     }
2144     else
2145     {
2146        create_printf("%s[%d]: WARNING: failed to open symtab for %s\n", 
2147              FILE__, __LINE__, filename.c_str());
2148        delete obj;
2149        obj = NULL;
2150     }
2151
2152    // returns true on success (not an error)
2153    return !err;
2154 }
2155
2156 bool Symtab::addRegion(Offset vaddr, void *data, unsigned int dataSize, std::string name, 
2157         Region::RegionType rType_, bool loadable, unsigned long memAlign, bool tls)
2158 {
2159    Region *sec;
2160    unsigned i;
2161    if (loadable)
2162    {
2163       sec = new Region(newSectionInsertPoint, name, vaddr, dataSize, vaddr, 
2164             dataSize, (char *)data, Region::RP_R, rType_, true, tls, memAlign);
2165
2166       regions_.insert(regions_.begin()+newSectionInsertPoint, sec);
2167
2168       for (i = newSectionInsertPoint+1; i < regions_.size(); i++)
2169       {
2170          regions_[i]->setRegionNumber(regions_[i]->getRegionNumber() + 1);
2171       }
2172
2173       if (    (sec->getRegionType() == Region::RT_TEXT) 
2174             || (sec->getRegionType() == Region::RT_TEXTDATA))
2175       {
2176          codeRegions_.push_back(sec);
2177          std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
2178       }
2179
2180       if (    (sec->getRegionType() == Region::RT_DATA) 
2181             || (sec->getRegionType() == Region::RT_TEXTDATA))
2182       {
2183          dataRegions_.push_back(sec);
2184          std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
2185       }
2186    }
2187    else
2188    {
2189       sec = new Region(regions_.size()+1, name, vaddr, dataSize, 0, 0, 
2190             (char *)data, Region::RP_R, rType_, loadable, tls, memAlign);
2191       regions_.push_back(sec);
2192    }
2193
2194    addUserRegion(sec);
2195    std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
2196    return true;
2197 }
2198
2199 bool Symtab::addUserRegion(Region *reg)
2200 {
2201    std::vector<Region *> *user_regions = NULL;
2202
2203    if (!getAnnotation(user_regions, UserRegionsAnno))
2204    {
2205       user_regions = new std::vector<Region *>();
2206       if (!addAnnotation(user_regions, UserRegionsAnno))
2207       {
2208          fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
2209          return false;
2210       }
2211    }
2212
2213    if (!user_regions)
2214    {
2215       fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
2216       return false;
2217    }
2218
2219    user_regions->push_back(reg);
2220
2221    return true;
2222 }
2223
2224 bool Symtab::addUserType(Type *t)
2225 {
2226    std::vector<Type *> *user_types = NULL;
2227
2228    //  need to change this to something based on AnnotationContainer
2229    //  for it to work with serialization
2230    if (!getAnnotation(user_types, UserTypesAnno))
2231    {
2232       user_types = new std::vector<Type *>();
2233       if (!addAnnotation(user_types, UserTypesAnno))
2234       {
2235          fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
2236          return false;
2237       }
2238    }
2239    if (!user_types)
2240    {
2241       fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
2242       return false;
2243    }
2244
2245    user_types->push_back(t);
2246
2247    return true;
2248 }
2249
2250 bool Symtab::addRegion(Region *sec)
2251 {
2252    regions_.push_back(sec);
2253    std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
2254    addUserRegion(sec);
2255    return true;
2256 }
2257
2258 void Symtab::parseLineInformation()
2259 {
2260    dyn_hash_map<std::string, LineInformation> *lineInfo = new dyn_hash_map <std::string, LineInformation>;
2261
2262
2263    Object *linkedFile = getObject();
2264         if (!linkedFile)
2265         {
2266 #if !defined(os_vxworks)
2267                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
2268 #endif
2269                 return;
2270         }
2271    linkedFile->parseFileLineInfo(this, *lineInfo);
2272
2273    isLineInfoValid_ = true;     
2274    dyn_hash_map <std::string, LineInformation>::iterator iter;
2275
2276    for (iter = lineInfo->begin(); iter!=lineInfo->end(); iter++)
2277    {
2278       Module *mod = NULL;
2279       bool result = findModuleByName(mod, iter->first);
2280       if (!result) {
2281          mod = getDefaultModule();
2282       }
2283
2284          LineInformation *lineInformation = mod->getLineInformation();
2285          if (!lineInformation) 
2286          {
2287             mod->setLineInfo(&(iter->second));
2288          } 
2289          else 
2290          {
2291             lineInformation->addLineInfo(&(iter->second));
2292             mod->setLineInfo(lineInformation);
2293          }
2294       }
2295 }
2296
2297 SYMTAB_EXPORT bool Symtab::getAddressRanges(std::vector<pair<Offset, Offset> >&ranges,
2298       std::string lineSource, unsigned int lineNo)
2299 {
2300    unsigned int originalSize = ranges.size();
2301
2302    /* Iteratate over the modules, looking for ranges in each. */
2303
2304    for ( unsigned int i = 0; i < _mods.size(); i++ ) 
2305    {
2306       LineInformation *lineInformation = _mods[i]->getLineInformation();
2307
2308       if (lineInformation)
2309          lineInformation->getAddressRanges( lineSource.c_str(), lineNo, ranges );
2310
2311    } /* end iteration over modules */
2312
2313    if ( ranges.size() != originalSize )
2314       return true;
2315
2316    fprintf(stderr, "%s[%d]:  failing to getAdressRanges for %s[%d]\n", FILE__, __LINE__, lineSource.c_str(), lineNo);
2317    return false;
2318 }
2319
2320 SYMTAB_EXPORT bool Symtab::getSourceLines(std::vector<Statement *> &lines, Offset addressInRange)
2321 {
2322    unsigned int originalSize = lines.size();
2323
2324    /* Iteratate over the modules, looking for ranges in each. */
2325    for ( unsigned int i = 0; i < _mods.size(); i++ ) 
2326    {
2327       LineInformation *lineInformation = _mods[i]->getLineInformation();
2328
2329       if (lineInformation)
2330          lineInformation->getSourceLines( addressInRange, lines );
2331
2332    } /* end iteration over modules */
2333
2334    if ( lines.size() != originalSize )
2335       return true;
2336
2337    return false;
2338
2339 }
2340
2341 SYMTAB_EXPORT bool Symtab::getSourceLines(std::vector<LineNoTuple> &lines, Offset addressInRange)
2342 {
2343    unsigned int originalSize = lines.size();
2344    
2345    /* Iteratate over the modules, looking for ranges in each. */
2346    for ( unsigned int i = 0; i < _mods.size(); i++ ) 
2347    {
2348       LineInformation *lineInformation = _mods[i]->getLineInformation();
2349       
2350       if (lineInformation)
2351          lineInformation->getSourceLines( addressInRange, lines );
2352       
2353    } /* end iteration over modules */
2354    
2355    if ( lines.size() != originalSize )
2356       return true;
2357    
2358    return false;
2359 }
2360
2361 SYMTAB_EXPORT bool Symtab::addLine(std::string lineSource, unsigned int lineNo,
2362       unsigned int lineOffset, Offset lowInclAddr,
2363       Offset highExclAddr)
2364 {
2365    Module *mod;
2366
2367    if (!findModuleByName(mod, lineSource))
2368    {
2369       std::string fileNm = extract_pathname_tail(lineSource);
2370
2371       if (!findModuleByName(mod, fileNm))
2372       {
2373          if (!findModuleByName(mod, mf->pathname()))
2374             return false;
2375       }    
2376    }
2377
2378    LineInformation *lineInfo = mod->getLineInformation();
2379
2380    if (!lineInfo)
2381       return false;
2382
2383    return (lineInfo->addLine(lineSource.c_str(), lineNo, lineOffset, 
2384             lowInclAddr, highExclAddr));
2385 }
2386
2387 SYMTAB_EXPORT bool Symtab::addAddressRange( Offset lowInclusiveAddr, Offset highExclusiveAddr,
2388       std::string lineSource, unsigned int lineNo,
2389       unsigned int lineOffset)
2390 {
2391    Module *mod;
2392
2393    if (!findModuleByName(mod, lineSource))
2394    {
2395       std::string fileNm = extract_pathname_tail(lineSource);
2396
2397       if (!findModuleByName(mod, fileNm))
2398          return false;
2399    }
2400
2401    LineInformation *lineInfo = mod->getLineInformation();
2402
2403    if (!lineInfo)
2404       return false;
2405
2406    return (lineInfo->addAddressRange(lowInclusiveAddr, highExclusiveAddr, 
2407             lineSource.c_str(), lineNo, lineOffset));
2408 }
2409
2410 void Symtab::setTruncateLinePaths(bool value)
2411 {
2412    getObject()->setTruncateLinePaths(value);
2413 }
2414
2415 bool Symtab::getTruncateLinePaths()
2416 {
2417    return getObject()->getTruncateLinePaths();
2418 }
2419
2420 void Symtab::parseTypes()
2421 {
2422    Object *linkedFile = getObject();
2423         if (!linkedFile)
2424         {
2425 #if !defined(os_vxworks)
2426                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
2427 #endif
2428                 return;
2429         }
2430    linkedFile->parseTypeInfo(this);
2431    isTypeInfoValid_ = true;
2432
2433    for (unsigned int i = 0; i < _mods.size(); ++i)
2434    {
2435            typeCollection *tc = typeCollection::getModTypeCollection(_mods[i]);
2436
2437            if (!_mods[i]->addAnnotation(tc, ModuleTypeInfoAnno))
2438            {
2439                    fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
2440            }
2441    }
2442
2443    //  optionally we might want to clear the static data struct in typeCollection
2444    //  here....  the parsing is over, and we have added all typeCollections as
2445    //  annotations proper.
2446
2447    typeCollection::fileToTypesMap.clear();
2448
2449 }
2450
2451 bool Symtab::addType(Type *type)
2452 {
2453   bool result = addUserType(type);
2454   if (!result)
2455     return false;
2456
2457   return true;
2458 }
2459
2460 SYMTAB_EXPORT vector<Type *> *Symtab::getAllstdTypes()
2461 {
2462    return stdTypes()->getAllTypes();    
2463 }
2464
2465 SYMTAB_EXPORT vector<Type *> *Symtab::getAllbuiltInTypes()
2466 {
2467    return builtInTypes()->getAllBuiltInTypes();
2468 }
2469
2470 SYMTAB_EXPORT bool Symtab::findType(Type *&type, std::string name)
2471 {
2472    parseTypesNow();
2473
2474    if (!_mods.size())
2475       return false;
2476
2477    for (unsigned int i = 0; i < _mods.size(); ++i)
2478    {
2479            typeCollection *tc = _mods[i]->getModuleTypes();
2480            if (!tc) continue;
2481            type = tc->findType(name);
2482            if (type) return true;
2483    }
2484
2485    if (type == NULL)
2486       return false;
2487
2488    return true; 
2489 }
2490
2491 SYMTAB_EXPORT Type *Symtab::findType(unsigned type_id)
2492 {
2493         Type *t = NULL;
2494    parseTypesNow();
2495
2496    if (!_mods.size())
2497    {
2498            //fprintf(stderr, "%s[%d]:  findType failing due to lack of modules\n", FILE__, __LINE__);
2499       return NULL;
2500    }
2501
2502    for (unsigned int i = 0; i < _mods.size(); ++i)
2503    {
2504            typeCollection *tc = _mods[i]->getModuleTypes();
2505            if (!tc) continue;
2506            t = tc->findType(type_id);
2507            if (t)  break;
2508    }
2509
2510    if (t == NULL)
2511    {
2512            if (builtInTypes())
2513            {
2514                    t = builtInTypes()->findBuiltInType(type_id);
2515                    if (t) return t;
2516            }
2517            else
2518            {
2519                    //fprintf(stderr, "%s[%d]:  no built in types!\n", FILE__, __LINE__);
2520            }
2521
2522            if (stdTypes())
2523            {
2524                    t = stdTypes()->findType(type_id);
2525                    if (t) return t;
2526            }
2527            else
2528            {
2529                    //fprintf(stderr, "%s[%d]:  no std types!\n", FILE__, __LINE__);
2530            }
2531
2532            return NULL;
2533    }
2534
2535    return t;    
2536 }
2537
2538 SYMTAB_EXPORT bool Symtab::findVariableType(Type *&type, std::string name)
2539 {
2540    parseTypesNow();
2541
2542    if (!_mods.size())
2543       return false;
2544
2545
2546    for (unsigned int i = 0; i < _mods.size(); ++i)
2547    {
2548            typeCollection *tc = _mods[i]->getModuleTypes();
2549            if (!tc) continue;
2550            type = tc->findVariableType(name);
2551            if (type) break;
2552    }
2553
2554    if (type == NULL)
2555       return false;
2556
2557    return true; 
2558 }
2559
2560 SYMTAB_EXPORT bool Symtab::findLocalVariable(std::vector<localVar *>&vars, std::string name)
2561 {
2562    parseTypesNow();
2563    unsigned origSize = vars.size();
2564
2565    for (unsigned i = 0; i < everyFunction.size(); i++)
2566    {
2567       everyFunction[i]->findLocalVariable(vars, name);
2568    }
2569
2570    if (vars.size()>origSize)
2571       return true;
2572
2573    return false;        
2574 }
2575
2576 SYMTAB_EXPORT bool Symtab::hasRel() const
2577 {
2578    return hasRel_;
2579 }
2580
2581 SYMTAB_EXPORT bool Symtab::hasRela() const
2582 {
2583    return hasRela_;
2584 }
2585
2586 SYMTAB_EXPORT bool Symtab::hasReldyn() const
2587 {
2588    return hasReldyn_;
2589 }
2590
2591 SYMTAB_EXPORT bool Symtab::hasReladyn() const
2592 {
2593    return hasReladyn_;
2594 }
2595
2596 SYMTAB_EXPORT bool Symtab::hasRelplt() const
2597 {
2598    return hasRelplt_;
2599 }
2600
2601 SYMTAB_EXPORT bool Symtab::hasRelaplt() const
2602 {
2603    return hasRelaplt_;
2604 }
2605
2606 SYMTAB_EXPORT bool Symtab::isStaticBinary() const
2607 {
2608    return isStaticBinary_;
2609 }
2610
2611 bool Symtab::setDefaultNamespacePrefix(string &str)
2612 {
2613    defaultNamespacePrefix = str;
2614    return true;
2615 }
2616
2617 SYMTAB_EXPORT bool Symtab::emitSymbols(Object *linkedFile,std::string filename, unsigned flag)
2618 {
2619     // Start with all the defined symbols
2620     std::vector<Symbol *> allSyms;
2621     allSyms.insert(allSyms.end(), everyDefinedSymbol.begin(), everyDefinedSymbol.end());
2622
2623     // Add the undefined dynamic symbols
2624     map<string, std::vector<Symbol *> >::iterator iter;
2625     std::vector<Symbol *>::iterator siter;
2626
2627     allSyms.insert(allSyms.end(), undefDynSyms.begin(), undefDynSyms.end());
2628
2629     // Write the new file
2630     return linkedFile->emitDriver(this, filename, allSyms, flag);
2631 }
2632
2633 SYMTAB_EXPORT bool Symtab::emit(std::string filename, unsigned flag)
2634 {
2635         Object *obj = getObject();
2636         if (!obj)
2637         {
2638 #if !defined(os_vxworks)
2639                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
2640 #endif
2641                 return false;
2642         }
2643    obj->mf->setSharing(false);
2644    return emitSymbols(obj, filename, flag);
2645 }
2646
2647 SYMTAB_EXPORT void Symtab::addDynLibSubstitution(std::string oldName, std::string newName)
2648 {
2649    dynLibSubs[oldName] = newName;
2650 }
2651
2652 SYMTAB_EXPORT std::string Symtab::getDynLibSubstitution(std::string name)
2653 {
2654 #ifdef BINEDIT_DEBUG
2655    map<std::string, std::string>::iterator iter = dynLibSubs.begin();
2656
2657    printf ("substitutions for %s:\n", mf->filename().c_str());
2658
2659    while (iter != dynLibSubs.end()) 
2660    {
2661       printf("  \"%s\" => \"%s\"\n", iter->first.c_str(), iter->second.c_str());
2662       iter++;
2663    }
2664 #endif
2665
2666    map<std::string, std::string>::iterator loc = dynLibSubs.find(name);
2667
2668    if (loc == dynLibSubs.end())
2669       return name;
2670    else
2671       return loc->second;
2672 }
2673
2674 SYMTAB_EXPORT bool Symtab::getSegments(vector<Segment> &segs) const
2675 {
2676    segs = segments_;
2677
2678    if (!segments_.size()) 
2679       return false;
2680
2681    return true;
2682 }
2683
2684 SYMTAB_EXPORT bool Symtab::getMappedRegions(std::vector<Region *> &mappedRegs) const
2685 {
2686    unsigned origSize = mappedRegs.size();
2687
2688    for (unsigned i = 0; i < regions_.size(); i++)
2689    {
2690       if (regions_[i]->isLoadable())
2691          mappedRegs.push_back(regions_[i]);
2692    }
2693
2694    if (mappedRegs.size() > origSize)
2695       return true;
2696
2697    return false;
2698 }
2699
2700 SYMTAB_EXPORT bool Symtab::fixup_RegionAddr(const char* name, Offset memOffset, long memSize)
2701 {
2702     Region *sec;
2703
2704     if (!findRegion(sec, name)) {
2705         return false;
2706     }
2707
2708     vector<relocationEntry> relocs;
2709     Object *obj = getObject();
2710
2711     // Fix relocation table with correct memory address
2712     if (obj) {
2713         obj->get_func_binding_table(relocs);
2714         /* DEBUG
2715         fprintf(stderr, "There are %d relocs in this symtab.\n",
2716                 relocs.size()); // */
2717
2718         for (unsigned i=0; i < relocs.size(); i++) {
2719             Offset value = relocs[i].rel_addr();
2720             relocs[i].setRelAddr(memOffset + value);
2721             /* DEBUG
2722             fprintf(stderr, "Fixing reloc from 0x%x to 0x%x\n",
2723                     value, memOffset + value); // */
2724         }
2725     }
2726     relocation_table_ = relocs;
2727
2728     vector<relocationEntry> &relref = sec->getRelocations();
2729     for (unsigned i=0; i < relref.size(); i++) {
2730         Offset value = relref[i].rel_addr();
2731         relref[i].setRelAddr(memOffset + value);
2732         /* DEBUG
2733         fprintf(stderr, "Fixing region reloc from 0x%x to 0x%x\n",
2734                 value, memOffset + value); // */
2735     }
2736
2737 #if defined(_MSC_VER)
2738     regionsByEntryAddr.erase(sec->getRegionAddr());
2739 #endif
2740
2741     /* DEBUG
2742     fprintf(stderr, "Fixing region %s from 0x%x [0x%x] to 0x%x [0x%x]\n",
2743             name, sec->getRegionAddr(), sec->getRegionSize(), memOffset,
2744             memSize); // */
2745     sec->setMemOffset(memOffset);
2746     sec->setMemSize(memSize);
2747
2748 #if defined(_MSC_VER)
2749     regionsByEntryAddr[sec->getRegionAddr()] = sec;
2750 #endif
2751
2752     std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
2753     std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
2754     std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
2755     return true;
2756 }
2757
2758 SYMTAB_EXPORT bool Symtab::fixup_SymbolAddr(const char* name, Offset newOffset)
2759 {
2760     // Find the symbol.
2761     if (symsByMangledName.count(name) == 0) return false;
2762     // /* DEBUG
2763     if (symsByMangledName[name].size() != 1)
2764         fprintf(stderr, "*** Found %zu symbols with name %s.  Expecting 1.\n",
2765                 symsByMangledName[name].size(), name); // */
2766     Symbol *sym = symsByMangledName[name][0];
2767
2768     // Update symbol.
2769     Offset oldOffset = sym->getOffset();
2770     sym->setOffset(newOffset);
2771
2772     /* DEBUG
2773     fprintf(stderr, "Fixing symbol %s from 0x%x to 0x%x\n",
2774             name, oldOffset, newOffset); // */
2775
2776     // Update hashes.
2777     if (symsByOffset.count(oldOffset)) {
2778         std::vector<Symbol *>::iterator iter = symsByOffset[oldOffset].begin();
2779         while (iter != symsByOffset[oldOffset].end()) {
2780             if (*iter == sym) {
2781                 symsByOffset[oldOffset].erase(iter);
2782                 iter = symsByOffset[oldOffset].begin();
2783
2784             } else iter++;
2785         }
2786     }
2787     if (!findSymbolByOffset(newOffset))
2788         symsByOffset[newOffset].push_back(sym);
2789
2790     // Update aggregates.
2791     if (!doNotAggregate(sym)) {
2792       addSymbolToAggregates(sym);
2793     }
2794
2795     return true;
2796 }
2797
2798 SYMTAB_EXPORT bool Symtab::updateRegion(const char* name, void *buffer, unsigned size)
2799 {
2800    Region *sec;
2801
2802    if (!findRegion(sec, name))
2803       return false;
2804
2805    sec->setPtrToRawData(buffer, size);
2806
2807    return true;
2808 }
2809
2810 SYMTAB_EXPORT bool Symtab::updateCode(void *buffer, unsigned size)
2811 {
2812   return updateRegion(".text", buffer, size);
2813 }
2814
2815 SYMTAB_EXPORT bool Symtab::updateData(void *buffer, unsigned size)
2816 {
2817   return updateRegion(".data", buffer, size);
2818 }
2819
2820 SYMTAB_EXPORT Offset Symtab::getFreeOffset(unsigned size) 
2821 {
2822    // Look through sections until we find a gap with
2823    // sufficient space.
2824    Offset highWaterMark = 0;
2825    Offset secoffset = 0;
2826    Offset prevSecoffset = 0;
2827    Object *linkedFile = getObject();
2828         if (!linkedFile)
2829         {
2830 #if !defined(os_vxworks)
2831                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
2832 #endif
2833                 return 0;
2834         }
2835
2836    for (unsigned i = 0; i < regions_.size(); i++) 
2837    {
2838       //Offset end = regions_[i]->getRegionAddr() + regions_[i]->getDiskSize();
2839       Offset end = regions_[i]->getRegionAddr() + regions_[i]->getRegionSize();
2840       if (regions_[i]->getRegionAddr() == 0) 
2841          continue;
2842
2843       prevSecoffset = secoffset;
2844
2845       unsigned region_offset = (unsigned)((char *)(regions_[i]->getPtrToRawData())
2846                                           - linkedFile->mem_image());
2847
2848       if (region_offset < (unsigned)prevSecoffset)
2849       {
2850          //secoffset += regions_[i]->getDiskSize();
2851          secoffset += regions_[i]->getRegionSize();
2852       }
2853       else 
2854       {
2855          secoffset = (char *)(regions_[i]->getPtrToRawData()) - linkedFile->mem_image();
2856          //secoffset += regions_[i]->getDiskSize();
2857          secoffset += regions_[i]->getRegionSize();
2858       }
2859
2860       /*fprintf(stderr, "%d: secAddr 0x%lx, size %d, end 0x%lx, looking for %d\n",
2861         i, regions_[i]->getSecAddr(), regions_[i]->getSecSize(),
2862         end,size);*/
2863
2864       if (end > highWaterMark) 
2865       {
2866          //fprintf(stderr, "Increasing highWaterMark...\n");
2867          newSectionInsertPoint = i+1;
2868          highWaterMark = end;
2869       }
2870
2871       if (     (i < (regions_.size()-2)) 
2872                && ((end + size) < regions_[i+1]->getRegionAddr())) 
2873       {
2874          /*      fprintf(stderr, "Found a hole between sections %d and %d\n",
2875                  i, i+1);
2876                  fprintf(stderr, "End at 0x%lx, next one at 0x%lx\n",
2877                  end, regions_[i+1]->getSecAddr());
2878          */   
2879          newSectionInsertPoint = i+1;
2880          highWaterMark = end;
2881          break;
2882       }
2883    }
2884
2885    //   return highWaterMark;
2886 #if defined (os_windows)
2887         Object *obj = getObject();
2888         if (!obj)
2889         {
2890                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
2891                 return 0;
2892         }
2893         unsigned pgSize = obj->getSecAlign();
2894         //printf("pgSize:0x%x\n", pgSize);
2895         Offset newaddr = highWaterMark  - (highWaterMark & (pgSize-1));
2896         while(newaddr < highWaterMark)
2897       newaddr += pgSize;
2898         //printf("getfreeoffset:%lu\n", newaddr);
2899         return newaddr;
2900
2901 #else
2902         unsigned pgSize = P_getpagesize();
2903
2904 #if defined(os_linux)
2905         // Bluegene compute nodes have a 1MB alignment restructions on PT_LOAD section
2906         Object *obj = getObject();
2907         if (!obj)
2908         {
2909                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
2910                 return 0;
2911         }
2912         bool isBlueGeneQ = obj->isBlueGeneP();
2913         bool isBlueGeneP = obj->isBlueGeneQ();
2914         bool hasNoteSection = obj->hasNoteSection();
2915         if (isBlueGeneQ || (isBlueGeneP && hasNoteSection))
2916                 pgSize = 0x100000; 
2917 #endif  
2918         Offset newaddr = highWaterMark  - (highWaterMark & (pgSize-1));
2919         if(newaddr < highWaterMark)
2920                 newaddr += pgSize;
2921
2922    return newaddr;
2923 #endif  
2924 }
2925
2926 SYMTAB_EXPORT ObjectType Symtab::getObjectType() const 
2927 {
2928    return object_type_;
2929 }
2930
2931 SYMTAB_EXPORT Dyninst::Architecture Symtab::getArchitecture()
2932 {
2933    return getObject()->getArch();
2934 }
2935
2936 SYMTAB_EXPORT char *Symtab::mem_image() const 
2937 {
2938    return (char *)mf->base_addr();
2939 }
2940
2941 SYMTAB_EXPORT std::string Symtab::file() const 
2942 {
2943    assert(mf);
2944    return mf->pathname();
2945 }
2946
2947 SYMTAB_EXPORT std::string Symtab::name() const 
2948 {
2949    return mf->filename();
2950 }
2951
2952 SYMTAB_EXPORT std::string Symtab::memberName() const 
2953 {
2954     return member_name_;
2955 }
2956
2957 SYMTAB_EXPORT unsigned Symtab::getNumberofRegions() const 
2958 {
2959    return no_of_sections; 
2960 }
2961
2962 SYMTAB_EXPORT unsigned Symtab::getNumberofSymbols() const 
2963 {
2964    return no_of_symbols; 
2965 }
2966
2967 bool Symtab::setup_module_up_ptrs(SerializerBase *, Symtab *st)
2968 {
2969    std::vector<Module *> &mods = st->_mods;
2970
2971    for (unsigned int i = 0; i < mods.size(); ++i) 
2972    {
2973       Module *m = mods[i];
2974       m->exec_ = st;
2975    }
2976
2977    return true;
2978 }
2979
2980 bool Symtab::fixup_relocation_symbols(SerializerBase *, Symtab *st)
2981 {
2982    std::vector<Module *> &mods = st->_mods;
2983
2984    for (unsigned int i = 0; i < mods.size(); ++i) 
2985    {
2986       Module *m = mods[i];
2987       m->exec_ = st;
2988    }
2989
2990    return true;
2991 }
2992
2993 void Symtab::rebuild_symbol_hashes(SerializerBase *sb)
2994 {
2995         if (!is_input(sb))
2996                 return;
2997
2998         for (unsigned long i = 0; i < everyDefinedSymbol.size(); ++i)
2999         {
3000                 Symbol *s = everyDefinedSymbol[i];
3001                 assert(s);
3002                 const std::string &pn = s->getPrettyName();
3003                 const std::string &mn = s->getMangledName();
3004                 const std::string tn = s->getTypedName();
3005
3006                 symsByPrettyName[pn].push_back(s);
3007                 symsByMangledName[mn].push_back(s);
3008                 symsByTypedName[tn].push_back(s);
3009                 symsByOffset[s->getOffset()].push_back(s);
3010         }
3011 }
3012
3013 void Symtab::rebuild_funcvar_hashes(SerializerBase *sb)
3014 {
3015         if (!is_input(sb))
3016                 return;
3017         for (unsigned int i = 0; i < everyFunction.size(); ++i)
3018         {
3019                 Function *f = everyFunction[i];
3020                 funcsByOffset[f->getOffset()] = f;
3021         }
3022         for (unsigned int i = 0; i < everyVariable.size(); ++i)
3023         {
3024                 Variable *v = everyVariable[i];
3025                 varsByOffset[v->getOffset()] = v;
3026         }
3027 }
3028 void Symtab::rebuild_module_hashes(SerializerBase *sb)
3029 {
3030         if (!is_input(sb))
3031                 return;
3032         for (unsigned int i = 0; i < _mods.size(); ++i)
3033         {
3034                 Module *m = _mods[i];
3035                 modsByFileName[m->fileName()] = m;
3036                 modsByFullName[m->fullName()] = m;
3037         }
3038 }
3039 void Symtab::rebuild_region_indexes(SerializerBase *sb) THROW_SPEC (SerializerError)
3040 {
3041         if (!is_input(sb))
3042                 return;
3043
3044         for (unsigned int i = 0; i < regions_.size(); ++i)
3045         {
3046                 Region *r = regions_[i];
3047
3048                 if (!r) SER_ERR("FIXME:  NULL REGION");
3049
3050                 if ( r->isLoadable() )
3051                 {
3052                         if ((r->getRegionPermissions() == Region::RP_RX)
3053                                         || (r->getRegionPermissions() == Region::RP_RWX))
3054                                 codeRegions_.push_back(r);
3055                         else
3056                                 dataRegions_.push_back(r);
3057                 }
3058
3059                 //  entry addr might require some special attn on windows, since it
3060                 //  is not the disk offset but the actual mem addr, which is going to be
3061                 //  different after deserialize.  Probably have to look it up again.
3062                 regionsByEntryAddr[r->getRegionAddr()] = r;
3063         }
3064
3065         std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
3066         std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
3067
3068
3069 }
3070
3071 Serializable *Symtab::serialize_impl(SerializerBase *sb, 
3072                 const char *tag) THROW_SPEC (SerializerError)
3073 {
3074         serialize_printf("%s[%d]:  welcome to Symtab::serialize_impl\n", 
3075                         FILE__, __LINE__);
3076         if (is_input(sb))
3077         {
3078                 //  don't bother with serializing standard and builtin types.
3079         /* XXX Change to use safe static allocation and initialization
3080                of standard and builtin types changes serialization behavior:
3081                these types are initialized on first access to the types
3082                structures (no explicit initialization). I think this code
3083                is dead anyway, though, so it probably doesn't matter.
3084         */
3085                 //setupTypes();
3086         }
3087
3088         ifxml_start_element(sb, tag);
3089         gtranslate(sb, imageOffset_, "imageOffset");
3090         gtranslate(sb, imageLen_, "imageLen");
3091         gtranslate(sb, dataOffset_, "dataOff");
3092         gtranslate(sb, dataLen_, "dataLen");
3093         gtranslate(sb, is_a_out, "isExec");
3094         gtranslate(sb, _mods, "Modules", "Module");
3095         rebuild_module_hashes(sb);
3096         if (is_input(sb))
3097         {
3098                 //  problem:  if isTypeInfoValid_ is not true, we can trigger type parsing
3099                 //  for an object class that does not exist.  Need to introduce logic to 
3100                 //  recreate the object in this case
3101                 isTypeInfoValid_ = true;
3102                 isLineInfoValid_ = true; //  NOTE:  set this to true after deserializing at least one lineInformaton object
3103         }
3104         gtranslate(sb, regions_, "Regions", "Region");
3105         rebuild_region_indexes(sb);
3106         gtranslate(sb, everyDefinedSymbol, "EveryDefinedSymbol", "Symbol");
3107         rebuild_symbol_hashes(sb);
3108         gtranslate(sb, relocation_table_, "RelocationTable", "RelocationTableEntry");
3109         gtranslate(sb, everyFunction, "EveryFunction", "Function");
3110         gtranslate(sb, everyVariable, "EveryVariable", "Variable");
3111         rebuild_funcvar_hashes(sb);
3112
3113         //gtranslate(sb, everyUniqueVariable, "EveryUniqueVariable", "UniqueVariable");
3114         //gtranslate(sb, modSyms, "ModuleSymbols", "ModuleSymbol");
3115
3116         gtranslate(sb, excpBlocks, "ExceptionBlocks", "ExceptionBlock");
3117         ifxml_end_element(sb, tag);
3118
3119         sb->magic_check(FILE__, __LINE__);
3120 #if 0
3121         ifinput(Symtab::setup_module_up_ptrs, sb, this);
3122         ifinput(fixup_relocation_symbols, sb, this);
3123 #endif
3124
3125         if (is_input(sb))
3126         {
3127                 dyn_hash_map<Address, Symbol *> *map_p = NULL;
3128                 if (getAnnotation(map_p, IdToSymAnno) && (NULL != map_p))
3129                 {
3130                         if (!removeAnnotation(IdToSymAnno))
3131                         {
3132                                 fprintf(stderr, "%s[%d]:  failed to remove id-to-sym map\n", 
3133                                                 FILE__, __LINE__);
3134                         }
3135                         delete map_p;
3136                 }
3137         }
3138         serialize_printf("%s[%d]:  leaving Symtab::serialize_impl\n", FILE__, __LINE__);
3139         return NULL;
3140 }
3141
3142 SYMTAB_EXPORT LookupInterface::LookupInterface() 
3143 {
3144 }
3145
3146 SYMTAB_EXPORT LookupInterface::~LookupInterface()
3147 {
3148 }
3149
3150
3151 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(Offset tStart, 
3152       unsigned tSize, 
3153       Offset cStart) 
3154 : tryStart_(tStart), trySize_(tSize), catchStart_(cStart), hasTry_(true) 
3155 {
3156 }
3157
3158    SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(Offset cStart) 
3159 : tryStart_(0), trySize_(0), catchStart_(cStart), hasTry_(false) 
3160 {
3161 }
3162
3163 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(const ExceptionBlock &eb) :
3164    Serializable(),
3165    tryStart_(eb.tryStart_), trySize_(eb.trySize_), 
3166    catchStart_(eb.catchStart_), hasTry_(eb.hasTry_) 
3167 {
3168 }
3169 SYMTAB_EXPORT bool ExceptionBlock::hasTry() const
3170
3171    return hasTry_; 
3172 }
3173
3174 SYMTAB_EXPORT Offset ExceptionBlock::tryStart() const
3175
3176    return tryStart_; 
3177 }
3178
3179 SYMTAB_EXPORT Offset ExceptionBlock::tryEnd() const
3180
3181    return tryStart_ + trySize_; 
3182 }
3183
3184 SYMTAB_EXPORT Offset ExceptionBlock::trySize() const
3185 {
3186    return trySize_; 
3187 }
3188
3189 SYMTAB_EXPORT bool ExceptionBlock::contains(Offset a) const
3190
3191    return (a >= tryStart_ && a < tryStart_ + trySize_); 
3192 }
3193
3194 Serializable * ExceptionBlock::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
3195 {
3196         ifxml_start_element(sb, tag);
3197         gtranslate(sb, tryStart_, "tryStart");
3198         gtranslate(sb, trySize_, "trySize");
3199         gtranslate(sb, catchStart_, "catchStart");
3200         gtranslate(sb, hasTry_, "hasTry");
3201         ifxml_end_element(sb, tag);
3202         return NULL;
3203 }
3204
3205 SYMTAB_EXPORT relocationEntry::relocationEntry() :
3206    target_addr_(0), 
3207    rel_addr_(0), 
3208    addend_(0), 
3209    rtype_(Region::RT_REL), 
3210    name_(""), 
3211    dynref_(NULL), 
3212    relType_(0)
3213 {
3214 }   
3215
3216 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, std::string n, 
3217       Symbol *dynref, unsigned long relType) :
3218    target_addr_(ta), 
3219    rel_addr_(ra), 
3220    addend_(0), 
3221    rtype_(Region::RT_REL), 
3222    name_(n), 
3223    dynref_(dynref), 
3224    relType_(relType)
3225 {
3226 }   
3227
3228 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, Offset add, 
3229       std::string n, Symbol *dynref, unsigned long relType) :
3230    target_addr_(ta), 
3231    rel_addr_(ra), 
3232    addend_(add), 
3233    rtype_(Region::RT_REL), 
3234    name_(n), 
3235    dynref_(dynref), 
3236    relType_(relType)
3237 {
3238 }
3239
3240 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ra, std::string n, 
3241       Symbol *dynref, unsigned long relType, Region::RegionType rtype) :
3242    target_addr_(0), 
3243    rel_addr_(ra), 
3244    addend_(0), 
3245    rtype_(rtype), 
3246    name_(n), 
3247    dynref_(dynref), 
3248    relType_(relType)
3249 {
3250 }
3251
3252 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, Offset add,
3253         std::string n, Symbol *dynref, unsigned long relType,
3254         Region::RegionType rtype) :
3255     target_addr_(ta),
3256     rel_addr_(ra),
3257     addend_(add),
3258     rtype_(rtype),
3259     name_(n),
3260     dynref_(dynref),
3261     relType_(relType)
3262 {}
3263
3264 SYMTAB_EXPORT const relocationEntry& relocationEntry::operator=(const relocationEntry &ra) 
3265 {
3266    target_addr_ = ra.target_addr_;
3267    rel_addr_ = ra.rel_addr_;
3268    addend_ = ra.addend_;
3269    rtype_ = ra.rtype_;
3270    name_ = ra.name_; 
3271    dynref_ = ra.dynref_;
3272    relType_ = ra.relType_;
3273    return *this;
3274 }
3275
3276 SYMTAB_EXPORT Offset relocationEntry::target_addr() const 
3277 {
3278     return target_addr_;
3279 }
3280
3281 SYMTAB_EXPORT void relocationEntry::setTargetAddr(const Offset off)
3282 {
3283     target_addr_ = off;
3284 }
3285
3286 SYMTAB_EXPORT Offset relocationEntry::rel_addr() const 
3287 {
3288     return rel_addr_;
3289 }
3290
3291 SYMTAB_EXPORT void relocationEntry::setRelAddr(const Offset value)
3292 {
3293     rel_addr_ = value;
3294 }
3295
3296 SYMTAB_EXPORT const string &relocationEntry::name() const 
3297 {
3298     return name_;
3299 }
3300
3301 SYMTAB_EXPORT Symbol *relocationEntry::getDynSym() const 
3302 {
3303     return dynref_;
3304 }
3305
3306 SYMTAB_EXPORT bool relocationEntry::addDynSym(Symbol *dynref) 
3307 {
3308     dynref_ = dynref;
3309     return true;
3310 }
3311
3312 SYMTAB_EXPORT Region::RegionType relocationEntry::regionType() const
3313 {
3314         return rtype_;
3315 }
3316
3317 SYMTAB_EXPORT unsigned long relocationEntry::getRelType() const 
3318 {
3319     return relType_;
3320 }
3321
3322 SYMTAB_EXPORT Offset relocationEntry::addend() const
3323 {
3324         return addend_;
3325 }
3326
3327 SYMTAB_EXPORT void relocationEntry::setAddend(const Offset value)
3328 {
3329         addend_ = value;
3330 }
3331
3332 SYMTAB_EXPORT void relocationEntry::setRegionType(const Region::RegionType value)
3333 {
3334         rtype_ = value;
3335 }
3336
3337 SYMTAB_EXPORT void relocationEntry::setName(const std::string &newName) {
3338     name_ = newName;
3339 }
3340
3341 bool relocationEntry::operator==(const relocationEntry &r) const
3342 {
3343         if (target_addr_ != r.target_addr_) return false;
3344         if (rel_addr_ != r.rel_addr_) return false;
3345         if (addend_ != r.addend_) return false;
3346         if (rtype_ != r.rtype_) return false;
3347         if (name_ != r.name_) return false;
3348         if (relType_ != r.relType_) return false;
3349         if (dynref_ && !r.dynref_) return false;
3350         if (!dynref_ && r.dynref_) return false;
3351         if (dynref_)
3352         {
3353                 if (dynref_->getName() != r.dynref_->getName()) return false;
3354                 if (dynref_->getOffset() != r.dynref_->getOffset()) return false;
3355         }
3356
3357         return true;
3358 }
3359
3360 Serializable *relocationEntry::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
3361 {
3362         //  on deserialize need to rebuild symtab::undefDynSyms before deserializing relocations
3363
3364         std::string symname = dynref_ ? dynref_->getName() : std::string("");
3365         Offset symoff = dynref_ ? dynref_->getOffset() : (Offset) -1;
3366
3367       ifxml_start_element(sb, tag);
3368       gtranslate(sb, target_addr_, "targetAddress");
3369       gtranslate(sb, rel_addr_, "relocationAddress");
3370       gtranslate(sb, addend_, "Addend");
3371       gtranslate(sb, name_, "relocationName");
3372       gtranslate(sb,  rtype_, Region::regionType2Str, "regionType");
3373       gtranslate(sb, relType_, "relocationType");
3374       gtranslate(sb, symname, "SymbolName");
3375       gtranslate(sb, symoff, "SymbolOffset");
3376       ifxml_end_element(sb, tag);
3377
3378           if (sb->isInput())
3379           {
3380                   dynref_ = NULL;
3381                   if (symname != std::string(""))
3382                   {
3383                           //  if we have a name for this symbol, the offset should not be -1;
3384                           if (symoff == (Offset) -1)
3385                           {
3386                                   fprintf(stderr, "%s[%d]:  inconsistent symname and offset combo!\n", 
3387                                                   FILE__, __LINE__);
3388                           }
3389
3390                           SerContextBase *scb = sb->getContext();
3391                           if (!scb)
3392                           {
3393                                   fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
3394                                   SER_ERR("FIXME");
3395                           }
3396
3397                           SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
3398
3399                           if (!scs)
3400                           {
3401                                   fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
3402                                   SER_ERR("FIXME");
3403                           }
3404
3405                           Symtab *st = scs->getScope();
3406
3407                           if (!st)
3408                           {
3409                                   fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
3410                                   SER_ERR("FIXME");
3411                           }
3412
3413                           std::vector<Symbol *> *syms = st->findSymbolByOffset(symoff);
3414                           if (!syms || !syms->size())
3415                           {
3416                                   serialize_printf("%s[%d]:  cannot find symbol by offset %p\n", 
3417                                                   FILE__, __LINE__, (void *)symoff);
3418                                   return NULL;
3419                           }
3420
3421                           //  Might want to try to select the "best" symbol here if there is
3422                           //  more than one.  Or Maybe just returning the first is sufficient.
3423
3424                           dynref_ = (*syms)[0];
3425                   }
3426           }
3427           return NULL;
3428 }
3429
3430 ostream & Dyninst::SymtabAPI::operator<< (ostream &os, const relocationEntry &r) 
3431 {
3432     if( r.getDynSym() != NULL ) {
3433         os << "Name: " << setw(20) << ( "'" + r.getDynSym()->getName() + "'" );
3434     }else{
3435         os << "Name: " << setw(20) << r.name();
3436     }
3437     os << " Offset: " << std::hex << std::setfill('0') << setw(8) << r.rel_addr() 
3438        << std::dec << std::setfill(' ')
3439        << " Offset: " << std::hex << std::setfill('0') << setw(8) << r.target_addr() 
3440        << std::dec << std::setfill(' ')
3441        << " Addend: " << r.addend()
3442        << " Region: " << Region::regionType2Str(r.regionType())
3443        << " Type: " << setw(15) << relocationEntry::relType2Str(r.getRelType())
3444        << "(" << r.getRelType() << ")";
3445     if( r.getDynSym() != NULL ) {
3446         os << " Symbol Offset: " << std::hex << std::setfill('0') << setw(8) << r.getDynSym()->getOffset();
3447         os << std::setfill(' ');
3448         if( r.getDynSym()->isCommonStorage() ) {
3449             os << " COM";
3450         }else if( r.getDynSym()->getRegion() == NULL ) {
3451             os << " UND";
3452         }
3453     }
3454     return os;
3455 }
3456
3457 const char *Symbol::symbolType2Str(SymbolType t) 
3458 {
3459    switch (t) 
3460    {
3461       CASE_RETURN_STR(ST_UNKNOWN);
3462       CASE_RETURN_STR(ST_FUNCTION);
3463       CASE_RETURN_STR(ST_OBJECT);
3464       CASE_RETURN_STR(ST_MODULE);
3465       CASE_RETURN_STR(ST_SECTION);
3466       CASE_RETURN_STR(ST_TLS);
3467       CASE_RETURN_STR(ST_DELETED);
3468       CASE_RETURN_STR(ST_NOTYPE);
3469    };
3470
3471    return "invalid symbol type";
3472 }
3473
3474 const char *Symbol::symbolLinkage2Str(SymbolLinkage t) 
3475 {
3476    switch (t) 
3477    {
3478       CASE_RETURN_STR(SL_UNKNOWN);
3479       CASE_RETURN_STR(SL_GLOBAL);
3480       CASE_RETURN_STR(SL_LOCAL);
3481       CASE_RETURN_STR(SL_WEAK);
3482    };
3483
3484    return "invalid symbol linkage";
3485 }
3486
3487 const char *Symbol::symbolTag2Str(SymbolTag t) 
3488 {
3489    switch (t) 
3490    {
3491       CASE_RETURN_STR(TAG_UNKNOWN);
3492       CASE_RETURN_STR(TAG_USER);
3493       CASE_RETURN_STR(TAG_LIBRARY);
3494       CASE_RETURN_STR(TAG_INTERNAL);
3495    };
3496
3497    return "invalid symbol tag";
3498 }
3499
3500 const char *Symbol::symbolVisibility2Str(SymbolVisibility t) 
3501 {
3502    switch(t) {
3503       CASE_RETURN_STR(SV_UNKNOWN);
3504       CASE_RETURN_STR(SV_DEFAULT);
3505       CASE_RETURN_STR(SV_INTERNAL);
3506       CASE_RETURN_STR(SV_HIDDEN);
3507       CASE_RETURN_STR(SV_PROTECTED);
3508    }
3509    return "invalid symbol visibility";
3510 }
3511
3512 bool Symtab::hasStackwalkDebugInfo()
3513 {
3514
3515         Object *obj = getObject();
3516         if (!obj)
3517         {
3518                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
3519                 return false;
3520         }
3521    return obj->hasFrameDebugInfo();
3522 }
3523
3524 bool Symtab::getRegValueAtFrame(Address pc, 
3525                                 Dyninst::MachRegister reg, 
3526                                 Dyninst::MachRegisterVal &reg_result,
3527                                 MemRegReader *reader)
3528 {
3529         Object *obj = getObject();
3530         if (!obj)
3531         {
3532                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
3533                 return false;
3534         }
3535    return obj->getRegValueAtFrame(pc, reg, reg_result, reader);
3536 }
3537
3538 Object *Symtab::getObject()
3539 {
3540    if (obj_private)
3541       return obj_private;
3542
3543    //TODO: This likely triggered because we serialized in an object
3544    // from cache, but now the user is requesting more information from
3545    // the on disk object.  We should create a new 'Object' from data
3546    // (likely a file path) serialized in.
3547    
3548    fprintf(stderr, "%s[%d]:  FIXME:  request for object that does not exist!\n", FILE__, __LINE__);
3549    return NULL;
3550    //obj_private = new Object();
3551    //return obj_private;
3552 }
3553
3554 void Symtab::parseTypesNow()
3555 {
3556    if (isTypeInfoValid_)
3557       return;
3558
3559    parseTypes();
3560 }
3561
3562 #if defined (cap_serialization)
3563 //  Not sure this is strictly necessary, problems only seem to exist with Module 
3564 // annotations when the file was split off, so there's probably something else that
3565 //  can be done to instantiate the relevant functions.
3566
3567 bool dummy_for_ser_instance(std::string file, SerializerBase *sb)
3568 {
3569    if (file == std::string("no_such_file")) 
3570    {
3571       if (!sb) 
3572       {
3573          fprintf(stderr, "%s[%d]:  really should not happen\n", FILE__, __LINE__);
3574          return false;
3575       }
3576       fprintf(stderr, "%s[%d]:  WARN:  disabled serializer init here\n", FILE__, __LINE__);
3577    }
3578    return true;
3579 }
3580
3581 #endif
3582
3583 namespace Dyninst {
3584         namespace SymtabAPI {
3585
3586
3587 #if 1
3588 SYMTAB_EXPORT SerializerBase *nonpublic_make_bin_symtab_serializer(Symtab *t, std::string file)
3589 {
3590         SerializerBin *ser;
3591         SerContext<Symtab> *scs = new SerContext<Symtab>(t, file);
3592         ser = new SerializerBin(scs, "SerializerBin", file, sd_serialize, false);
3593         return ser;
3594 }
3595
3596 SYMTAB_EXPORT SerializerBase *nonpublic_make_bin_symtab_deserializer(Symtab *t, std::string file)
3597 {
3598         SerializerBin *ser;
3599         SerContext<Symtab> *scs = new SerContext<Symtab>(t, file);
3600         ser = new SerializerBin(scs, "DeserializerBin", file, sd_deserialize, false);
3601         return ser;
3602 }
3603
3604 SYMTAB_EXPORT void nonpublic_free_bin_symtab_serializer(SerializerBase *sb)
3605 {
3606         SerializerBin *sbin = dynamic_cast<SerializerBin *>(sb);
3607         if (sbin)
3608         {
3609                 delete(sbin);
3610         }
3611         else
3612                 fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
3613
3614 }
3615 #endif
3616
3617 SYMTAB_EXPORT Offset Symtab::getElfDynamicOffset()
3618 {
3619 #if defined(os_linux) || defined(os_freebsd)
3620         Object *obj = getObject();
3621         if (!obj)
3622         {
3623                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
3624                 return 0;
3625         }
3626    return obj->getDynamicAddr();
3627 #else
3628    return 0;
3629 #endif
3630 }
3631
3632 SYMTAB_EXPORT bool Symtab::addLibraryPrereq(std::string name)
3633 {
3634 #if defined(os_aix)
3635    return false;
3636 #endif
3637
3638    Object *obj = getObject();
3639         if (!obj)
3640         {
3641                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
3642                 return false;
3643         }
3644    // remove forward slashes and back slashes
3645    size_t size = name.find_last_of("/");
3646    size_t lastBS = name.find_last_of("\\");
3647    if (lastBS > size) {
3648       size = lastBS;
3649    }
3650
3651    string filename = name.substr(size+1);
3652
3653 #if ! defined(os_windows) 
3654    obj->insertPrereqLibrary(filename);
3655 #else 
3656    // must add a symbol for an exported function belonging to the library 
3657    // to get the Windows loader to load the library
3658
3659    Symtab *symtab = Symtab::findOpenSymtab(name);
3660    if (!symtab) {
3661       if (!Symtab::openFile(symtab, name)) {
3662          return false;
3663       }
3664    }
3665    
3666    // find an exported function
3667    vector<Symbol*> funcs;
3668    symtab->getAllSymbolsByType(funcs, Symbol::ST_FUNCTION);
3669    vector<Symbol*>::iterator fit = funcs.begin(); 
3670    for (; fit != funcs.end() && !(*fit)->isInDynSymtab(); fit++);
3671    if (fit == funcs.end()) {
3672       return false;
3673    }
3674    
3675    string funcName = string((*fit)->getPrettyName());
3676    if (funcName.empty()) {
3677       funcName = string((*fit)->getMangledName());
3678       if (funcName.empty()) {
3679          assert(0);
3680          return false;
3681       }
3682    }
3683    symtab->getObject()->addReference((*fit)->getOffset(), 
3684                                      name, 
3685                                      funcName);
3686    obj->addReference((*fit)->getOffset(), filename, funcName);
3687 #endif
3688    return true;
3689 }
3690
3691 SYMTAB_EXPORT bool Symtab::addSysVDynamic(long name, long value)
3692 {
3693 #if defined(os_linux) || defined(os_freebsd)
3694         Object *obj = getObject();
3695         if (!obj)
3696         {
3697                 fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
3698                 return false;
3699         }
3700   obj->insertDynamicEntry(name, value);
3701    return true;
3702 #else
3703    return false;
3704 #endif
3705 }
3706
3707 SYMTAB_EXPORT bool Symtab::addExternalSymbolReference(Symbol *externalSym, Region *localRegion,
3708         relocationEntry localRel)
3709 {
3710     // Adjust this to the correct value
3711     localRel.setRegionType(getObject()->getRelType());
3712
3713     // Create placeholder Symbol for external Symbol reference
3714     // Bernat, 7SEP2010 - according to Matt, these symbols should have
3715     // type "undefined", which means a region of NULL. Changing
3716     // from "localRegion" to NULL. 
3717     Symbol *symRef = new Symbol(externalSym->getName(),
3718                                 externalSym->getType(),
3719                                 Symbol::SL_GLOBAL,
3720                                 Symbol::SV_DEFAULT,
3721                                 (Address)0,
3722                                 getDefaultModule(),
3723                                 NULL, // localRegion,
3724                                 externalSym->getSize(),
3725                                 true,
3726                                 false);
3727
3728    if( !addSymbol(symRef, externalSym) ) return false;
3729
3730    localRegion->addRelocationEntry(localRel);
3731
3732    // Make sure the Symtab holding the external symbol gets linked
3733    // with this Symtab
3734    explicitSymtabRefs_.insert(externalSym->getSymtab());
3735
3736    return true;
3737 }
3738
3739 // on windows we can't specify the trap table's location by adding a dynamic
3740 // symbol as we don on windows
3741 SYMTAB_EXPORT bool Symtab::addTrapHeader_win(Address ptr)
3742 {
3743 #if defined(os_windows)
3744    getObject()->setTrapHeader(ptr);
3745    return true;
3746 #else
3747    ptr = ptr; //keep compiler happy
3748    assert(0);
3749    return false;
3750 #endif
3751 }
3752
3753 bool Symtab::getExplicitSymtabRefs(std::set<Symtab *> &refs) {
3754     refs = explicitSymtabRefs_;
3755     return (refs.size() != 0);
3756 }
3757
3758 SYMTAB_EXPORT bool Symtab::addLinkingResource(Archive *library) {
3759     linkingResources_.push_back(library);
3760
3761     return true;
3762 }
3763
3764 SYMTAB_EXPORT bool Symtab::getLinkingResources(std::vector<Archive *> &libs) {
3765     libs = linkingResources_;
3766     return (linkingResources_.size() != 0);
3767 }
3768
3769 SYMTAB_EXPORT Address Symtab::getLoadAddress()
3770 {
3771 #if defined(os_linux) || defined(os_freebsd) || defined(os_aix)
3772    return getObject()->getLoadAddress();
3773 #else
3774    return 0x0;
3775 #endif
3776 }
3777
3778 SYMTAB_EXPORT bool Symtab::isDefensiveBinary() const
3779 {
3780     return isDefensiveBinary_;
3781 }
3782
3783 SYMTAB_EXPORT bool Symtab::canBeShared()
3784 {
3785    return mf->canBeShared();
3786 }
3787
3788 SYMTAB_EXPORT Offset Symtab::getInitOffset()
3789 {
3790 #if defined(os_linux) || defined(os_freebsd)
3791    return getObject()->getInitAddr();
3792 #else
3793    return 0x0;
3794 #endif
3795
3796 }
3797
3798 SYMTAB_EXPORT Offset Symtab::getFiniOffset()
3799 {
3800 #if defined(os_linux) || defined(os_freebsd)
3801    return getObject()->getFiniAddr();
3802 #else
3803    return 0x0;
3804 #endif
3805
3806 }
3807
3808 } // namespace SymtabAPI
3809 } // namespace Dyninst
3810