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