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