2 * Copyright (c) 1996-2009 Barton P. Miller
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.
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.
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.
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.
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
38 #include "common/h/Timer.h"
39 #include "common/h/debugOstream.h"
40 #include "common/h/serialize.h"
41 #include "common/h/pathName.h"
43 #include "Serialization.h"
46 #include "Collections.h"
50 #include "annotations.h"
54 #include "symtabAPI/src/Object.h"
56 #if !defined(os_windows)
65 using namespace Dyninst;
66 using namespace Dyninst::SymtabAPI;
69 static std::string errMsg;
70 extern bool parseCompilerType(Object *);
72 void symtab_log_perror(const char *msg)
74 errMsg = std::string(msg);
80 std::vector<Symtab *> Symtab::allSymtabs;
81 builtInTypeCollection *Symtab::builtInTypes = NULL;
82 typeCollection *Symtab::stdTypes = NULL;
84 SymtabError Symtab::getLastSymtabError()
89 void setSymtabError(SymtabError new_err)
94 std::string Symtab::printError(SymtabError serr)
99 return "Failed to parse the Object"+errMsg;
100 case Syms_To_Functions:
101 return "Failed to convert Symbols to Functions";
102 case No_Such_Function:
103 return "Function does not exist";
104 case No_Such_Variable:
105 return "Variable does not exist";
107 return "Module does not exist";
109 return "Region does not exist";
111 return "Symbol does not exist";
113 return "Not a File. Call openArchive()";
115 return "Not an Archive. Call openFile()";
117 return "Error Constructing XML"+errMsg;
119 return "Flags passed are invalid.";
121 return "No previous Error.";
123 return "Unknown Error";
127 Type *Symtab::type_Error = NULL;
128 Type *Symtab::type_Untyped = NULL;
130 void Symtab::setupTypes()
133 * Create the "error" and "untyped" types.
135 std::string name = "<error>";
136 if (NULL == type_Error) type_Error = new Type(name, 0, dataUnknownType);
137 name = std::string("<no type>");
138 if (NULL == type_Untyped) type_Untyped = new Type(name, 0, dataUnknownType);
142 void Symtab::setupStdTypes()
147 builtInTypes = new builtInTypeCollection;
150 // NOTE: integral type mean twos-complement
151 // -1 int, 32 bit signed integral type
152 // in stab document, size specified in bits, system size is in bytes
153 builtInTypes->addBuiltInType(newType = new typeScalar(-1, 4, "int", true));
154 newType->decrRefCount();
155 // -2 char, 8 bit type holding a character. GDB & dbx(AIX) treat as signed
156 builtInTypes->addBuiltInType(newType = new typeScalar(-2, 1, "char", true));
157 newType->decrRefCount();
158 // -3 short, 16 bit signed integral type
159 builtInTypes->addBuiltInType(newType = new typeScalar(-3, 2, "short", true));
160 newType->decrRefCount();
161 // -4 long, 32/64 bit signed integral type
162 builtInTypes->addBuiltInType(newType = new typeScalar(-4, sizeof(long), "long", true));
163 newType->decrRefCount();
164 // -5 unsigned char, 8 bit unsigned integral type
165 builtInTypes->addBuiltInType(newType = new typeScalar(-5, 1, "unsigned char"));
166 newType->decrRefCount();
167 // -6 signed char, 8 bit signed integral type
168 builtInTypes->addBuiltInType(newType = new typeScalar(-6, 1, "signed char", true));
169 newType->decrRefCount();
170 // -7 unsigned short, 16 bit unsigned integral type
171 builtInTypes->addBuiltInType(newType = new typeScalar(-7, 2, "unsigned short"));
172 newType->decrRefCount();
173 // -8 unsigned int, 32 bit unsigned integral type
174 builtInTypes->addBuiltInType(newType = new typeScalar(-8, 4, "unsigned int"));
175 newType->decrRefCount();
176 // -9 unsigned, 32 bit unsigned integral type
177 builtInTypes->addBuiltInType(newType = new typeScalar(-9, 4, "unsigned"));
178 newType->decrRefCount();
179 // -10 unsigned long, 32 bit unsigned integral type
180 builtInTypes->addBuiltInType(newType = new typeScalar(-10, sizeof(unsigned long), "unsigned long"));
181 newType->decrRefCount();
182 // -11 void, type indicating the lack of a value
183 // XXX-size may not be correct jdd 4/22/99
184 builtInTypes->addBuiltInType(newType = new typeScalar(-11, 0, "void", false));
185 newType->decrRefCount();
186 // -12 float, IEEE single precision
187 builtInTypes->addBuiltInType(newType = new typeScalar(-12, sizeof(float), "float", true));
188 newType->decrRefCount();
189 // -13 double, IEEE double precision
190 builtInTypes->addBuiltInType(newType = new typeScalar(-13, sizeof(double), "double", true));
191 newType->decrRefCount();
192 // -14 long double, IEEE double precision, size may increase in future
193 builtInTypes->addBuiltInType(newType = new typeScalar(-14, sizeof(long double), "long double", true));
194 newType->decrRefCount();
195 // -15 integer, 32 bit signed integral type
196 builtInTypes->addBuiltInType(newType = new typeScalar(-15, 4, "integer", true));
197 newType->decrRefCount();
198 // -16 boolean, 32 bit type. GDB/GCC 0=False, 1=True, all other values
199 // have unspecified meaning
200 builtInTypes->addBuiltInType(newType = new typeScalar(-16, sizeof(bool), "boolean"));
201 newType->decrRefCount();
202 // -17 short real, IEEE single precision
203 // XXX-size may not be correct jdd 4/22/99
204 builtInTypes->addBuiltInType(newType = new typeScalar(-17, sizeof(float), "short real", true));
205 newType->decrRefCount();
206 // -18 real, IEEE double precision XXX-size may not be correct jdd 4/22/99
207 builtInTypes->addBuiltInType(newType = new typeScalar(-18, sizeof(double), "real", true));
208 newType->decrRefCount();
209 // -19 stringptr XXX- size of void * -- jdd 4/22/99
210 builtInTypes->addBuiltInType(newType = new typeScalar(-19, sizeof(void *), "stringptr"));
211 newType->decrRefCount();
212 // -20 character, 8 bit unsigned character type
213 builtInTypes->addBuiltInType(newType = new typeScalar(-20, 1, "character"));
214 newType->decrRefCount();
215 // -21 logical*1, 8 bit type (Fortran, used for boolean or unsigned int)
216 builtInTypes->addBuiltInType(newType = new typeScalar(-21, 1, "logical*1"));
217 newType->decrRefCount();
218 // -22 logical*2, 16 bit type (Fortran, some for boolean or unsigned int)
219 builtInTypes->addBuiltInType(newType = new typeScalar(-22, 2, "logical*2"));
220 newType->decrRefCount();
221 // -23 logical*4, 32 bit type (Fortran, some for boolean or unsigned int)
222 builtInTypes->addBuiltInType(newType = new typeScalar(-23, 4, "logical*4"));
223 newType->decrRefCount();
224 // -24 logical, 32 bit type (Fortran, some for boolean or unsigned int)
225 builtInTypes->addBuiltInType(newType = new typeScalar(-24, 4, "logical"));
226 newType->decrRefCount();
227 // -25 complex, consists of 2 IEEE single-precision floating point values
228 builtInTypes->addBuiltInType(newType = new typeScalar(-25, sizeof(float)*2, "complex", true));
229 newType->decrRefCount();
230 // -26 complex, consists of 2 IEEE double-precision floating point values
231 builtInTypes->addBuiltInType(newType = new typeScalar(-26, sizeof(double)*2, "complex*16", true));
232 newType->decrRefCount();
233 // -27 integer*1, 8 bit signed integral type
234 builtInTypes->addBuiltInType(newType = new typeScalar(-27, 1, "integer*1", true));
235 newType->decrRefCount();
236 // -28 integer*2, 16 bit signed integral type
237 builtInTypes->addBuiltInType(newType = new typeScalar(-28, 2, "integer*2", true));
238 newType->decrRefCount();
240 /* Quick hack to make integer*4 compatible with int for Fortran
242 // This seems questionable - let's try removing that hack - jmo 05/21/04
244 builtInTypes->addBuiltInType(newType = new type("int",-29,
246 newType->decrRefCount();
248 // -29 integer*4, 32 bit signed integral type
249 builtInTypes->addBuiltInType(newType = new typeScalar(-29, 4, "integer*4", true));
250 newType->decrRefCount();
251 // -30 wchar, Wide character, 16 bits wide, unsigned (unknown format)
252 builtInTypes->addBuiltInType(newType = new typeScalar(-30, 2, "wchar"));
253 newType->decrRefCount();
254 #if defined(os_windows)
255 // -31 long long, 64 bit signed integral type
256 builtInTypes->addBuiltInType(newType = new typeScalar(-31, sizeof(LONGLONG), "long long", true));
257 newType->decrRefCount();
258 // -32 unsigned long long, 64 bit unsigned integral type
259 builtInTypes->addBuiltInType(newType = new typeScalar(-32, sizeof(ULONGLONG), "unsigned long long"));
260 newType->decrRefCount();
262 // -31 long long, 64 bit signed integral type
263 builtInTypes->addBuiltInType(newType = new typeScalar(-31, sizeof(long long), "long long", true));
264 newType->decrRefCount();
265 // -32 unsigned long long, 64 bit unsigned integral type
266 builtInTypes->addBuiltInType(newType = new typeScalar(-32, sizeof(unsigned long long), "unsigned long long"));
267 newType->decrRefCount();
269 // -33 logical*8, 64 bit unsigned integral type
270 builtInTypes->addBuiltInType(newType = new typeScalar(-33, 8, "logical*8"));
271 newType->decrRefCount();
272 // -34 integer*8, 64 bit signed integral type
273 builtInTypes->addBuiltInType(newType = new typeScalar(-34, 8, "integer*8", true));
274 newType->decrRefCount();
277 * Initialize hash table of standard types.
282 stdTypes = new typeCollection();
283 stdTypes->addType(newType = new typeScalar(-1, sizeof(int), "int"));
284 newType->decrRefCount();
286 Type *charType = new typeScalar(-2, sizeof(char), "char");
287 stdTypes->addType(charType);
289 std::string tName = "char *";
290 typePointer *newPtrType;
291 stdTypes->addType(newPtrType = new typePointer(-3, charType, tName));
292 charType->decrRefCount();
293 newPtrType->decrRefCount();
295 Type *voidType = new typeScalar(-11, 0, "void", false);
296 stdTypes->addType(voidType);
299 stdTypes->addType(newPtrType = new typePointer(-4, voidType, tName));
300 voidType->decrRefCount();
301 newPtrType->decrRefCount();
303 stdTypes->addType(newType = new typeScalar(-12, sizeof(float), "float"));
304 newType->decrRefCount();
306 #if defined(i386_unknown_nt4_0)
307 stdTypes->addType(newType = new typeScalar(-31, sizeof(LONGLONG), "long long"));
309 stdTypes->addType(newType = new typeScalar(-31, sizeof(long long), "long long"));
312 newType->decrRefCount();
317 SYMTAB_EXPORT unsigned Symtab::getAddressWidth() const
319 return address_width_;
322 SYMTAB_EXPORT bool Symtab::isNativeCompiler() const
324 return nativeCompiler;
328 SYMTAB_EXPORT Symtab::Symtab(MappedFile *mf_) :
334 init_debug_symtabAPI();
338 SYMTAB_EXPORT Symtab::Symtab() :
341 init_debug_symtabAPI();
342 create_printf("%s[%d]: Created symtab via default constructor\n", FILE__, __LINE__);
343 defaultNamespacePrefix = "";
346 SYMTAB_EXPORT bool Symtab::isExec() const
351 SYMTAB_EXPORT bool Symtab::isStripped()
353 #if defined(os_linux) || defined(os_solaris)
355 return !findRegion(sec,".symtab");
357 return (no_of_symbols==0);
361 SYMTAB_EXPORT Offset Symtab::imageOffset() const
366 SYMTAB_EXPORT Offset Symtab::dataOffset() const
371 SYMTAB_EXPORT Offset Symtab::dataLength() const
376 SYMTAB_EXPORT Offset Symtab::imageLength() const
381 SYMTAB_EXPORT void Symtab::fixup_code_and_data(Offset newImageOffset,
382 Offset newImageLength,
383 Offset newDataOffset,
384 Offset newDataLength)
386 imageOffset_ = newImageOffset;
387 imageLen_ = newImageLength;
388 dataOffset_ = newDataOffset;
389 dataLen_ = newDataLength;
391 // Should we update the underlying Object?
395 SYMTAB_EXPORT char* Symtab::image_ptr () const
400 SYMTAB_EXPORT char* Symtab::data_ptr () const
405 SYMTAB_EXPORT const char* Symtab::getInterpreterName() const
407 if (interpreter_name_.length())
408 return interpreter_name_.c_str();
412 SYMTAB_EXPORT Offset Symtab::getEntryOffset() const
414 return entry_address_;
417 SYMTAB_EXPORT Offset Symtab::getBaseOffset() const
419 return base_address_;
422 SYMTAB_EXPORT Offset Symtab::getLoadOffset() const
424 return load_address_;
427 SYMTAB_EXPORT Offset Symtab::getTOCoffset() const
432 SYMTAB_EXPORT string Symtab::getDefaultNamespacePrefix() const
434 return defaultNamespacePrefix;
438 // TODO -- is this g++ specific
439 bool Symtab::buildDemangledName( const std::string &mangled,
443 supportedLanguages lang )
445 /* The C++ demangling function demangles MPI__Allgather (and other MPI__
446 * functions with start with A) into the MPI constructor. In order to
447 * prevent this a hack needed to be made, and this seemed the cleanest
451 if ((mangled.length()>5) && (mangled.substr(0,5)==std::string("MPI__")))
456 /* If it's Fortran, eliminate the trailing underscores, if any. */
457 if (lang == lang_Fortran
458 || lang == lang_CMFortran
459 || lang == lang_Fortran_with_pretty_debug )
461 if ( mangled[ mangled.length() - 1 ] == '_' )
463 char * demangled = P_strdup( mangled.c_str() );
464 demangled[ mangled.length() - 1 ] = '\0';
465 pretty = std::string( demangled );
472 /* No trailing underscores, do nothing */
475 } /* end if it's Fortran. */
477 // Check to see if we have a gnu versioned symbol on our hands.
478 // These are of the form <symbol>@<version> or <symbol>@@<version>
480 // If we do, we want to create a "demangled" name for the one that
481 // is of the form <symbol>@@<version> since this is, by definition,
482 // the default. The "demangled" name will just be <symbol>
484 // NOTE: this is just a 0th order approach to dealing with versioned
485 // symbols. We may need to do something more sophisticated
486 // in the future. JAW 10/03
488 #if !defined(os_windows)
492 if (NULL != (atat = strstr(mangled.c_str(), "@@")))
494 pretty = mangled.substr(0 /*start pos*/,
495 (int)(atat - mangled.c_str())/*len*/);
497 //sprintf(msg, "%s[%d]: 'demangling' versioned symbol: %s, to %s",
498 // __FILE__, __LINE__, mangled.c_str(), pretty.c_str());
500 //cerr << msg << endl;
510 /* Try demangling it. */
511 char * demangled = P_cplus_demangle( mangled.c_str(), nativeCompiler, false);
514 pretty = std::string( demangled );
518 char *t_demangled = P_cplus_demangle(mangled.c_str(), nativeCompiler, true);
519 if (t_demangled && (strcmp(t_demangled, demangled) != 0))
521 typed = std::string(t_demangled);
531 } /* end buildDemangledName() */
535 * extractSymbolsFromFile
537 * Create a Symtab-level list of symbols by pulling out data
538 * from the low-level parse (linkedFile).
539 * Technically this causes a duplication of symbols; however,
540 * we will be rewriting these symbols and so we need our own
543 * TODO: delete the linkedFile once we're done?
546 bool Symtab::extractSymbolsFromFile(Object *linkedFile, std::vector<Symbol *> &raw_syms)
548 for (SymbolIter symIter(*linkedFile); symIter; symIter++)
550 Symbol *sym = symIter.currval();
553 fprintf(stderr, "%s[%d]: range error, stopping now\n", FILE__, __LINE__);
557 // If a symbol starts with "." we want to skip it. These indicate labels in the
560 // removed 1/09: this should be done in Dyninst, not Symtab
562 // check for undefined dynamic symbols. Used when rewriting relocation section.
563 // relocation entries have references to these undefined dynamic symbols.
564 // We also have undefined symbols for the static binary case.
566 #if !defined(os_vxworks)
567 if (sym->getSec() == NULL && !sym->isAbsolute() && !sym->isCommonStorage()) {
568 undefDynSyms[sym->getMangledName()].push_back(sym);
573 // Check whether this symbol has a valid offset. If they do not we have a
574 // consistency issue. This should be a null check.
576 // Symbols can have an offset of 0 if they don't refer to things within a file.
578 raw_syms.push_back(sym);
587 * Add Module information to all symbols.
590 bool Symtab::fixSymModules(std::vector<Symbol *> &raw_syms)
592 for (unsigned i = 0; i < raw_syms.size(); i++) {
593 fixSymModule(raw_syms[i]);
595 Object *obj = getObject();
598 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
601 const std::vector<std::pair<std::string, Offset> > &mods = obj->modules_;
602 for (unsigned i=0; i< mods.size(); i++) {
603 getOrCreateModule(mods[i].first, mods[i].second);
612 * Perform name demangling on all symbols.
615 bool Symtab::demangleSymbols(std::vector<Symbol *> &raw_syms)
617 for (unsigned i = 0; i < raw_syms.size(); i++) {
618 demangleSymbol(raw_syms[i]);
626 * We index symbols by various attributes for quick lookup. Build those
630 bool Symtab::createIndices(std::vector<Symbol *> &raw_syms) {
631 for (unsigned i = 0; i < raw_syms.size(); i++) {
632 addSymbolToIndices(raw_syms[i]);
640 * Frequently there will be multiple Symbols that refer to a single
641 * code object (e.g., function or variable). We use separate objects
642 * to refer to these aggregates, and build those objects here.
645 bool Symtab::createAggregates()
647 #if !defined(os_vxworks)
648 // In VxWorks, symbol offsets are not complete until object is loaded.
650 for (unsigned i = 0; i < everyDefinedSymbol.size(); i++)
652 addSymbolToAggregates(everyDefinedSymbol[i]);
659 bool Symtab::fixSymModule(Symbol *&sym)
665 // It has been decided that all libraries shall have only one
666 // module named after the library. The a.out has one module
667 // per (reported) source file, plus DEFAULT_MODULE for everything
668 // else. This is enforced here, although the Object-* files might
671 if (getObjectType() == obj_SharedLib) {
672 mod = getDefaultModule();
675 Object *obj = getObject();
678 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
681 std::string modName = obj->findModuleForSym(sym);
682 if (modName.length() == 0) {
683 mod = getDefaultModule();
686 mod = getOrCreateModule(modName, sym->getOffset());
696 bool Symtab::demangleSymbol(Symbol *&sym) {
697 switch (sym->getType()) {
698 case Symbol::ST_FUNCTION: {
699 Module *rawmod = sym->getModule();
702 // At this point we need to generate the following information:
704 // A pretty (demangled) name.
705 // The symtab name goes in the global list as well as the module list.
706 // Same for the pretty name.
707 // Finally, check addresses to find aliases.
709 std::string mangled_name = sym->getMangledName();
710 std::string working_name = mangled_name;
712 #if !defined(os_windows)
713 //Remove extra stabs information
714 const char *p = strchr(working_name.c_str(), ':');
716 unsigned nchars = p - mangled_name.c_str();
717 working_name = std::string(mangled_name.c_str(), nchars);
721 std::string pretty_name = working_name;
722 std::string typed_name = working_name;
724 if (!buildDemangledName(working_name, pretty_name, typed_name,
725 nativeCompiler, rawmod->language())) {
726 pretty_name = working_name;
729 sym->prettyName_ = pretty_name;
730 sym->typedName_ = typed_name;
735 // All cases where there really shouldn't be a mangled
736 // name, since mangling is for functions.
738 char *prettyName = P_cplus_demangle(sym->getMangledName().c_str(), nativeCompiler, false);
740 sym->prettyName_ = prettyName;
748 bool Symtab::addSymbolToIndices(Symbol *&sym)
751 // sym->index_ = everyDefinedSymbol.size();
753 everyDefinedSymbol.push_back(sym);
755 #if !defined(os_vxworks)
756 // VxWorks doesn't know symbol addresses until object is loaded.
757 symsByOffset[sym->getAddr()].push_back(sym);
760 symsByMangledName[sym->getMangledName()].push_back(sym);
762 symsByPrettyName[sym->getPrettyName()].push_back(sym);
764 symsByTypedName[sym->getTypedName()].push_back(sym);
769 bool Symtab::addSymbolToAggregates(Symbol *&sym)
771 switch(sym->getType()) {
772 case Symbol::ST_FUNCTION: {
773 // We want to do the following:
774 // If no function exists, create and add.
775 // Combine this information
776 // Add this symbol's names to the function.
777 // Keep module information
779 Function *func = NULL;
780 findFuncByEntryOffset(func, sym->getAddr());
782 // Create a new function
783 // Also, update the symbol to point to this function.
785 func = new Function(sym);
787 everyFunction.push_back(func);
788 sorted_everyFunction = false;
789 funcsByOffset[sym->getAddr()] = func;
793 * For relocatable files, the offset of a symbol is relative to the
794 * beginning of a Region. Therefore, a symbol in a relocatable file
795 * is not uniquely identifiable by its offset, but it is uniquely
796 * identifiable by its Region and its offset.
798 * For now, do not add these functions to funcsByOffset collection.
801 if( func->getRegion() != sym->getRegion() ) {
802 func = new Function(sym);
803 everyFunction.push_back(func);
804 sorted_everyFunction = false;
806 func->addSymbol(sym);
808 sym->setFunction(func);
813 case Symbol::ST_OBJECT: {
814 // The same as the above, but with variables.
815 Variable *var = NULL;
816 findVariableByOffset(var, sym->getAddr());
818 // Create a new function
819 // Also, update the symbol to point to this function.
820 var = new Variable(sym);
822 everyVariable.push_back(var);
823 varsByOffset[sym->getAddr()] = var;
827 * For relocatable files, the offset is not a unique identifier for
828 * a Symbol. With functions, the Region and offset could be used to
829 * identify the symbol. With variables, the Region and offset may
830 * not uniquely identify the symbol. The only case were this occurs
831 * is with COMMON symbols -- their offset is their memory alignment
832 * and their Region is undefined. In this case, always create a
835 if( obj_RelocatableFile == getObjectType() &&
836 ( var->getRegion() != sym->getRegion() ||
837 NULL == sym->getRegion() ) )
839 var = new Variable(sym);
840 everyVariable.push_back(var);
845 sym->setVariable(var);
855 /* Add the new name to the appropriate symbol index */
857 bool Symtab::updateIndices(Symbol *sym, std::string newName, NameType nameType) {
858 if (nameType & mangledName) {
859 // Add this symbol under the given name (as mangled)
860 symsByMangledName[newName].push_back(sym);
862 if (nameType & prettyName) {
863 // Add this symbol under the given name (as pretty)
864 symsByPrettyName[newName].push_back(sym);
866 if (nameType & typedName) {
867 // Add this symbol under the given name (as typed)
868 symsByTypedName[newName].push_back(sym);
874 /* checkPPC64DescriptorSymbols() is no longer needed. 3-word descriptor
875 * symbols are properly taken care of during symbol parsing. See
876 * parse_symbols() in Object-elf.C for details.
879 #if defined(ppc64_linux)
880 /* Special case for ppc64 ELF binaries. Sometimes a function has a 3-byte descriptor symbol
881 * along with it in the symbol table and "." preceding its original pretty name for the correct
882 * function symbol. This checks to see if we have a corresponding 3-byte descriptor symbol existing
883 * and if it does we remove the preceding "." from the name of the symbol
886 void Symtab::checkPPC64DescriptorSymbols(Object *linkedFile)
888 // find the real functions -- those with the correct type in the symbol table
889 for(SymbolIter symIter(*linkedFile); symIter;symIter++)
891 Symbol *lookUp = symIter.currval();
892 const char *np = lookUp->getMangledName().c_str();
896 if(np[0] == '.' && (lookUp->getType() == Symbol::ST_FUNCTION))
898 std::vector<Symbol *>syms;
899 std::string newName = np+1;
900 if(linkedFile->get_symbols(newName, syms) && (syms[0]->getSize() == 24 || syms[0]->getSize() == 0))
902 //Remove the "." from the name
903 lookUp->mangledNames[0] = newName;
905 //Change the type of the descriptor symbol
906 syms[0]->type_ = Symbol::ST_NOTYPE;
916 // setModuleLanguages is only called after modules have been defined.
917 // it attempts to set each module's language, information which is needed
918 // before names can be demangled.
919 void Symtab::setModuleLanguages(dyn_hash_map<std::string, supportedLanguages> *mod_langs)
921 if (!mod_langs->size())
922 return; // cannot do anything here
923 // this case will arise on non-stabs platforms until language parsing can be introduced at this level
924 std::vector<Module *> *modlist;
925 Module *currmod = NULL;
929 for (unsigned int i = 0; i < modlist->size(); ++i)
931 currmod = (*modlist)[i];
932 supportedLanguages currLang;
933 if (currmod->isShared()) {
934 continue; // need to find some way to get shared object languages?
937 const std::string fn = currmod->fileName();
938 if (mod_langs->find(currmod->fileName()) != mod_langs->end())
940 currLang = (*mod_langs)[fn];
942 else if (fn.rfind(".s") != std::string::npos ||
943 fn.rfind(".asm") != std::string::npos)
945 currLang = lang_Assembly;
947 else if (fn.rfind(".c") != std::string::npos)
951 else if (fn.rfind(".cpp") != std::string::npos ||
952 fn.rfind(".cc") != std::string::npos ||
953 fn.rfind(".C") != std::string::npos)
955 currLang = lang_CPlusPlus;
961 currmod->setLanguage(currLang);
965 void Symtab::createDefaultModule() {
967 if (getObjectType() == obj_SharedLib) {
968 mod = new Module(lang_Unknown,
974 mod = new Module(lang_Unknown,
979 modsByFileName[mod->fileName()] = mod;
980 modsByFullName[mod->fullName()] = mod;
981 _mods.push_back(mod);
986 Module *Symtab::getOrCreateModule(const std::string &modName,
987 const Offset modAddr)
989 std::string nameToUse;
990 if (modName.length() > 0)
993 nameToUse = "DEFAULT_MODULE";
996 if (findModuleByName(fm, nameToUse))
1001 const char *str = nameToUse.c_str();
1002 int len = nameToUse.length();
1005 // TODO ignore directory definitions for now
1006 if (str[len-1] == '/')
1009 return (newModule(nameToUse, modAddr, lang_Unknown));
1012 Module *Symtab::newModule(const std::string &name, const Offset addr, supportedLanguages lang)
1015 // modules can be defined several times in C++ due to templates and
1016 // in-line member functions.
1018 if (findModuleByName(ret, name))
1023 //parsing_printf("=== image, creating new pdmodule %s, addr 0x%x\n",
1024 // name.c_str(), addr);
1026 std::string fileNm, fullNm;
1028 fileNm = extract_pathname_tail(name);
1030 // /* DEBUG */ fprintf( stderr, "%s[%d]: In %p: Creating new pdmodule '%s'/'%s'\n", FILE__, __LINE__, this, fileNm.c_str(), fullNm.c_str() );
1031 create_printf("%s[%d]: In %p: Creating new module '%s'/'%s'\n", FILE__, __LINE__, this, fileNm.c_str(), fullNm.c_str());
1033 ret = new Module(lang, addr, fullNm, this);
1039 * There are cases where the fileName can be the same, but the full name is
1040 * different and the modules are actually different. This is an inherent
1041 * problem with how modules are processed.
1043 if (modsByFileName.end() != modsByFileName.find(ret->fileName()))
1045 create_printf("%s[%d]: WARN: LEAK? already have module with name %s\n",
1046 FILE__, __LINE__, ret->fileName().c_str());
1049 if (modsByFullName.end() != modsByFullName.find(ret->fullName()))
1051 create_printf("%s[%d]: WARN: LEAK? already have module with name %s\n",
1052 FILE__, __LINE__, ret->fullName().c_str());
1055 modsByFileName[ret->fileName()] = ret;
1056 modsByFullName[ret->fullName()] = ret;
1057 _mods.push_back(ret);
1062 Symtab::Symtab(std::string filename,bool &err) :
1066 nativeCompiler(false),
1067 isLineInfoValid_(false),
1068 isTypeInfoValid_(false),
1071 init_debug_symtabAPI();
1072 // Initialize error parameter
1075 create_printf("%s[%d]: created symtab for %s\n", FILE__, __LINE__, filename.c_str());
1077 #if defined (os_windows)
1078 extern void fixup_filename(std::string &);
1079 fixup_filename(filename);
1082 // createMappedFile handles reference counting
1083 mf = MappedFile::createMappedFile(filename);
1085 create_printf("%s[%d]: WARNING: creating symtab for %s, "
1086 "createMappedFile() failed\n", FILE__, __LINE__,
1092 obj_private = new Object(mf, mfForDebugInfo, symtab_log_perror, true);
1093 if (obj_private->hasError()) {
1098 if (!extractInfo(obj_private))
1100 create_printf("%s[%d]: WARNING: creating symtab for %s, extractInfo() "
1101 "failed\n", FILE__, __LINE__, filename.c_str());
1105 member_name_ = mf->filename();
1107 defaultNamespacePrefix = "";
1110 Symtab::Symtab(char *mem_image, size_t image_size, bool &err) :
1114 nativeCompiler(false),
1115 isLineInfoValid_(false),
1116 isTypeInfoValid_(false),
1119 // Initialize error parameter
1122 create_printf("%s[%d]: created symtab for memory image at addr %u\n",
1123 FILE__, __LINE__, mem_image);
1125 // createMappedFile handles reference counting
1126 mf = MappedFile::createMappedFile(mem_image, image_size);
1128 create_printf("%s[%d]: WARNING: creating symtab for memory image at "
1129 "addr %u, createMappedFile() failed\n", FILE__, __LINE__,
1135 obj_private = new Object(mf, mfForDebugInfo, symtab_log_perror, true);
1136 if (obj_private->hasError()) {
1141 if (!extractInfo(obj_private))
1143 create_printf("%s[%d]: WARNING: creating symtab for memory image at addr"
1144 "%u, extractInfo() failed\n", FILE__, __LINE__, mem_image);
1148 member_name_ = mf->filename();
1150 defaultNamespacePrefix = "";
1153 // Symtab constructor for archive members
1155 Symtab::Symtab(std::string filename, std::string member_name, Offset offset,
1156 bool &err, void *base) :
1157 member_name_(member_name),
1158 member_offset_(offset),
1161 nativeCompiler(false),
1162 isLineInfoValid_(false),
1163 isTypeInfoValid_(false),
1166 mf = MappedFile::createMappedFile(filename);
1168 obj_private = new Object(mf, mfForDebugInfo, member_name, offset, symtab_log_perror, base);
1169 if (obj_private->hasError()) {
1173 err = !extractInfo(obj_private);
1174 defaultNamespacePrefix = "";
1176 create_printf("%s[%d]: created symtab for %s(%s)\n", FILE__, __LINE__, filename.c_str(),
1177 member_name.c_str());
1180 Symtab::Symtab(std::string, std::string, Offset, bool &, void *)
1187 Symtab::Symtab(char *mem_image, size_t image_size, std::string member_name,
1188 Offset offset, bool &err, void *base) :
1189 member_name_(member_name),
1190 member_offset_(offset),
1193 nativeCompiler(false),
1194 isLineInfoValid_(false),
1195 isTypeInfoValid_(false)
1197 mf = MappedFile::createMappedFile(mem_image, image_size);
1199 obj_private = new Object(mf, mf, member_name, offset, symtab_log_perror, base);
1200 if (obj_private->hasError()) {
1204 err = !extractInfo(obj_private);
1205 defaultNamespacePrefix = "";
1208 Symtab::Symtab(char *, size_t, std::string , Offset, bool &, void *)
1214 bool sort_reg_by_addr(const Region* a, const Region* b)
1216 if (a->getRegionAddr() == b->getRegionAddr())
1217 return a->getMemSize() < b->getMemSize();
1218 return a->getRegionAddr() < b->getRegionAddr();
1221 extern void print_symbols( std::vector< Symbol *>& allsymbols );
1222 extern void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols);
1224 bool Symtab::extractInfo(Object *linkedFile)
1226 #if defined(TIMED_PARSE)
1227 struct timeval starttime;
1228 gettimeofday(&starttime, NULL);
1230 mfForDebugInfo = linkedFile->getMappedFileForDebugInfo();
1234 * Some ELF .o's don't have contiguous code and data Regions so these data
1235 * members are imprecise. These members should probably be deprecated in
1236 * favor of the getCodeRegions and getDataRegions functions.
1240 imageOffset_ = linkedFile->code_off();
1241 dataOffset_ = linkedFile->data_off();
1243 imageLen_ = linkedFile->code_len();
1244 dataLen_ = linkedFile->data_len();
1246 if (0 == imageLen_ || 0 == linkedFile->code_ptr())
1248 // for AIX, code_ptr()==NULL is normal behavior
1249 #if !defined(os_aix)
1250 if (0 == linkedFile->code_ptr()) {
1251 //fprintf(stderr, "[%s][%d]WARNING: null code pointer in Symtab for"
1252 //" file %s, possibly due to a missing .text section.\n",
1253 //__FILE__,__LINE__, file().c_str());
1254 linkedFile->code_ptr_ = (char *) linkedFile->code_off();
1259 if( object_type_ != obj_RelocatableFile ||
1260 linkedFile->code_ptr() == 0)
1268 // if (!imageLen_ || !linkedFile->code_ptr()) {
1269 // serr = Obj_Parsing;
1273 no_of_sections = linkedFile->no_of_sections();
1274 newSectionInsertPoint = no_of_sections;
1275 no_of_symbols = linkedFile->no_of_symbols();
1277 isStaticBinary_ = linkedFile->isStaticBinary();
1282 hasReladyn_ = false;
1284 hasRelaplt_ = false;
1285 regions_ = linkedFile->getAllRegions();
1287 for (unsigned index=0;index<regions_.size();index++)
1289 if ( regions_[index]->isLoadable() )
1291 if ( (regions_[index]->getRegionPermissions() == Region::RP_RX)
1292 || (regions_[index]->getRegionPermissions() == Region::RP_RWX))
1294 codeRegions_.push_back(regions_[index]);
1298 dataRegions_.push_back(regions_[index]);
1302 regionsByEntryAddr[regions_[index]->getRegionAddr()] = regions_[index];
1304 if (regions_[index]->getRegionType() == Region::RT_REL)
1309 if (regions_[index]->getRegionType() == Region::RT_RELA)
1314 #if defined(os_linux) || defined(os_solaris)
1315 hasReldyn_ = linkedFile->hasReldyn();
1316 hasReladyn_ = linkedFile->hasReladyn();
1317 hasRelplt_ = linkedFile->hasRelplt();
1318 hasRelaplt_ = linkedFile->hasRelaplt();
1322 // sort regions_ & codeRegions_ vectors
1324 std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
1325 std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
1326 std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
1328 /* insert error check here. check if parsed */
1329 address_width_ = linkedFile->getAddressWidth();
1330 is_a_out = linkedFile->is_aout();
1331 code_ptr_ = linkedFile->code_ptr();
1332 data_ptr_ = linkedFile->data_ptr();
1334 if (linkedFile->interpreter_name())
1335 interpreter_name_ = std::string(linkedFile->interpreter_name());
1337 entry_address_ = linkedFile->getEntryAddress();
1338 base_address_ = linkedFile->getBaseAddress();
1339 load_address_ = linkedFile->getLoadAddress();
1340 toc_offset_ = linkedFile->getTOCoffset();
1341 object_type_ = linkedFile->objType();
1342 is_eel_ = linkedFile->isEEL();
1343 linkedFile->getSegments(segments_);
1345 #if !defined(os_aix) && !defined(os_windows)
1346 linkedFile->getDependencies(deps_);
1349 #if defined (os_aix)
1350 // These should go away
1351 linkedFile->get_stab_info(stabstr_, nstabs_, stabs_, stringpool_);
1352 linkedFile->get_line_info(nlines_, lines_, fdptr_);
1355 #if defined(os_solaris) || defined(os_aix) || defined(os_linux)
1356 // make sure we're using the right demangler
1358 nativeCompiler = parseCompilerType(linkedFile);
1359 //parsing_printf("isNativeCompiler: %d\n", nativeCompiler);
1362 // define all of the functions
1363 //statusLine("winnowing functions");
1365 #if defined(ppc64_linux)
1366 //checkPPC64DescriptorSymbols(linkedFile);
1369 // a vector to hold all created symbols until they are properly classified
1370 std::vector<Symbol *> raw_syms;
1372 #ifdef BINEDIT_DEBUG
1373 printf("== from linkedFile...\n");
1374 print_symbol_map(linkedFile->getAllSymbols());
1377 if (!extractSymbolsFromFile(linkedFile, raw_syms))
1380 serr = Syms_To_Functions;
1384 #ifdef BINEDIT_DEBUG
1385 printf("== in Symtab now...\n");
1386 //print_symbols(raw_syms);
1387 std::vector<Symbol *> undefsyms;
1388 std::map<std::string, std::vector<Symbol *> >::iterator iter;
1389 std::vector<Symbol *>::iterator siter;
1390 for (iter = undefDynSyms.begin(); iter != undefDynSyms.end(); iter++)
1391 for (siter = iter->second.begin(); siter != iter->second.end(); siter++)
1392 undefsyms.push_back(*siter);
1393 //print_symbols(undefsyms);
1394 printf("%d total symbol(s)\n", raw_syms.size() + undefsyms.size());
1397 // don't sort the symbols--preserve the original ordering
1398 //sort(raw_syms.begin(),raw_syms.end(),symbol_compare);
1400 createDefaultModule();
1402 if (!fixSymModules(raw_syms))
1405 serr = Syms_To_Functions;
1408 Object *obj = getObject();
1411 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
1414 obj->clearSymsToMods();
1416 // wait until all modules are defined before applying languages to
1417 // them we want to do it this way so that module information comes
1418 // from the function symbols, first and foremost, to avoid any
1419 // internal module-function mismatching.
1421 // get Information on the language each modules is written in
1422 // (prior to making modules)
1424 dyn_hash_map<std::string, supportedLanguages> mod_langs;
1425 linkedFile->getModuleLanguageInfo(&mod_langs);
1426 setModuleLanguages(&mod_langs);
1428 // Be sure that module languages are set before demangling, or
1429 // we won't get very far.
1431 if (!demangleSymbols(raw_syms))
1434 serr = Syms_To_Functions;
1438 if (!createIndices(raw_syms))
1441 serr = Syms_To_Functions;
1445 if (!createAggregates())
1448 serr = Syms_To_Functions;
1452 // Once languages are assigned, we can build demangled names (in
1453 // the wider sense of demangling which includes stripping _'s from
1454 // fortran names -- this is why language information must be
1455 // determined before this step).
1457 // Also identifies aliases (multiple names with equal addresses)
1459 //addSymtabVariables();
1460 linkedFile->getAllExceptions(excpBlocks);
1462 vector<relocationEntry >fbt;
1463 linkedFile->get_func_binding_table(fbt);
1464 for(unsigned i=0; i<fbt.size();i++)
1465 relocation_table_.push_back(fbt[i]);
1469 Symtab::Symtab(const Symtab& obj) :
1474 create_printf("%s[%d]: Creating symtab 0x%p from symtab 0x%p\n", FILE__, __LINE__, this, &obj);
1476 member_name_ = obj.member_name_;
1477 member_offset_ = obj.member_offset_;
1478 imageOffset_ = obj.imageOffset_;
1479 imageLen_ = obj.imageLen_;
1480 dataOffset_ = obj.dataOffset_;
1481 dataLen_ = obj.dataLen_;
1483 isLineInfoValid_ = obj.isLineInfoValid_;
1484 isTypeInfoValid_ = obj.isTypeInfoValid_;
1486 is_a_out = obj.is_a_out;
1487 main_call_addr_ = obj.main_call_addr_; // address of call to main()
1489 nativeCompiler = obj.nativeCompiler;
1490 defaultNamespacePrefix = obj.defaultNamespacePrefix;
1493 no_of_sections = obj.no_of_sections;
1496 for (i=0;i<obj.regions_.size();i++)
1497 regions_.push_back(new Region(*(obj.regions_[i])));
1499 for (i=0;i<regions_.size();i++)
1500 regionsByEntryAddr[regions_[i]->getRegionAddr()] = regions_[i];
1502 // TODO FIXME: copying symbols/Functions/Variables
1504 for (i=0;i<obj._mods.size();i++)
1506 Module *m = new Module(*(obj._mods[i]));
1508 modsByFileName[m->fileName()] = m;
1509 modsByFullName[m->fullName()] = m;
1510 fprintf(stderr, "%s[%d]: copy ctor creating new module %s\n",
1511 FILE__, __LINE__, m->fileName().c_str());
1514 for (i=0; i<relocation_table_.size();i++)
1516 relocation_table_.push_back(relocationEntry(obj.relocation_table_[i]));
1517 //undefDynSyms[obj.relocation_table_[i].name()] = relocation_table_[i].getDynSym();
1518 undefDynSyms[obj.relocation_table_[i].name()].push_back(relocation_table_[i].getDynSym());
1522 for (i=0;i<excpBlocks.size();i++)
1524 excpBlocks.push_back(new ExceptionBlock(*(obj.excpBlocks[i])));
1531 // Address must be in code or data range since some code may end up
1532 // in the data segment
1533 bool Symtab::isValidOffset(const Offset where) const
1535 return isCode(where) || isData(where);
1538 /* Performs a binary search on the codeRegions_ vector, which must
1539 * be kept in sorted order
1541 bool Symtab::isCode(const Offset where) const
1543 #if defined(os_vxworks)
1544 // All memory is valid in the kernel. Kinda.
1548 if (!codeRegions_.size())
1550 fprintf(stderr, "%s[%d] No code regions in %s \n",
1551 __FILE__, __LINE__, mf->filename().c_str());
1555 // search for "where" in codeRegions_ (code regions must not overlap)
1557 int last = codeRegions_.size() - 1;
1559 while (last >= first)
1561 Region *curreg = codeRegions_[(first + last) / 2];
1562 if (where >= curreg->getRegionAddr()
1563 && where < (curreg->getRegionAddr()
1564 + curreg->getDiskSize()))
1566 if (curreg->getRegionType() == Region::RT_BSS)
1570 else if (where < curreg->getRegionAddr())
1572 last = ((first + last) / 2) - 1;
1574 else if (where >= (curreg->getRegionAddr() + curreg->getMemSize()))
1576 first = ((first + last) / 2) + 1;
1579 { // "where" is in the range:
1580 // [memOffset + diskSize , memOffset + memSize)
1581 // meaning that it's in an uninitialized data region
1589 /* Performs a binary search on the dataRegions_ vector, which must
1590 * be kept in sorted order */
1591 bool Symtab::isData(const Offset where) const
1593 if (!dataRegions_.size())
1595 fprintf(stderr, "%s[%d] No data regions in %s \n",
1596 __FILE__,__LINE__,mf->filename().c_str());
1601 int last = dataRegions_.size() - 1;
1603 while (last >= first)
1605 Region *curreg = dataRegions_[(first + last) / 2];
1607 if ( (where >= curreg->getRegionAddr())
1608 && (where < (curreg->getRegionAddr() + curreg->getRegionSize())))
1612 else if (where < curreg->getRegionAddr())
1614 last = ((first + last) / 2) - 1;
1618 first = ((first + last) / 2) + 1;
1625 SYMTAB_EXPORT bool Symtab::getFuncBindingTable(std::vector<relocationEntry> &fbt) const
1627 fbt = relocation_table_;
1631 SYMTAB_EXPORT bool Symtab::updateFuncBindingTable(Offset stub_addr, Offset plt_addr)
1633 int stub_idx = -1, plt_idx = -1;
1635 for (unsigned i = 0; i < relocation_table_.size(); ++i) {
1636 if (stub_addr == relocation_table_[i].target_addr())
1638 if (plt_addr == relocation_table_[i].target_addr())
1640 if (stub_idx >= 0 && plt_idx >= 0)
1643 if (stub_idx >= 0 && plt_idx >= 0) {
1644 relocation_table_[stub_idx] = relocation_table_[plt_idx];
1645 relocation_table_[stub_idx].setTargetAddr(stub_addr);
1651 SYMTAB_EXPORT std::vector<std::string> &Symtab::getDependencies(){
1655 SYMTAB_EXPORT Archive *Symtab::getParentArchive() const {
1656 return parentArchive_;
1661 // Doesn't do anything yet, moved here so we don't mess with symtab.h
1662 // Only called if we fail to create a process.
1663 // Or delete the a.out...
1667 for (unsigned i = 0; i < regions_.size(); i++)
1673 codeRegions_.clear();
1674 dataRegions_.clear();
1675 regionsByEntryAddr.clear();
1677 std::vector<Region *> *user_regions = NULL;
1678 getAnnotation(user_regions, UserRegionsAnno);
1682 for (unsigned i = 0; i < user_regions->size(); ++i)
1683 delete (*user_regions)[i];
1684 user_regions->clear();
1687 // Symbols are copied from linkedFile, and NOT deleted
1688 everyDefinedSymbol.clear();
1689 undefDynSyms.clear();
1691 // TODO make annotation
1692 userAddedSymbols.clear();
1693 symsByOffset.clear();
1694 symsByMangledName.clear();
1695 symsByPrettyName.clear();
1696 symsByTypedName.clear();
1698 for (unsigned i = 0; i < everyFunction.size(); i++)
1700 delete everyFunction[i];
1703 everyFunction.clear();
1704 funcsByOffset.clear();
1706 for (unsigned i = 0; i < everyVariable.size(); i++)
1708 delete everyVariable[i];
1711 everyVariable.clear();
1712 varsByOffset.clear();
1714 for (unsigned i = 0; i < _mods.size(); i++)
1719 modsByFileName.clear();
1720 modsByFullName.clear();
1722 for (unsigned i=0;i<excpBlocks.size();i++)
1723 delete excpBlocks[i];
1725 create_printf("%s[%d]: Symtab::~Symtab removing %p from allSymtabs\n",
1726 FILE__, __LINE__, this);
1730 for (unsigned i = 0; i < allSymtabs.size(); i++)
1732 if (allSymtabs[i] == this)
1733 allSymtabs.erase(allSymtabs.begin()+i);
1736 // Make sure to free the underlying Object as it doesn't have a factory
1738 if( obj_private ) delete obj_private;
1740 //fprintf(stderr, "%s[%d]: symtab DTOR, mf = %p: %s\n", FILE__, __LINE__, mf, mf->filename().c_str());
1741 if (mf) MappedFile::closeMappedFile(mf);
1742 //if (mfForDebugInfo) MappedFile::closeMappedFile(mfForDebugInfo);
1746 bool Symtab::exportXML(string file)
1748 #if defined (cap_serialization)
1751 SerContext<Symtab> *scs = new SerContext<Symtab>(this, file);
1752 serialize(file, scs, ser_xml);
1754 SerContext<Symtab> *scs = new SerContext<Symtab>(this);
1755 SerializerXML *ser = new SerializerXML(scs, "XMLTranslator", file, sd_serialize, true);
1756 serialize(ser, "Symtab");
1759 SerializerXML sb("XMLTranslator", file, sd_serialize, true);
1760 serialize(&sb, "Symtab");
1763 catch (const SerializerError &err)
1765 fprintf(stderr, "%s[%d]: error serializing xml: %s\n", FILE__, __LINE__, err.what());
1771 fprintf(stderr, "%s[%d]: WARNING: cannot produce %s, serialization not available\n", FILE__, __LINE__, file.c_str());
1776 #if defined (cap_serialization)
1777 bool Symtab::exportBin(string file)
1781 SerContext<Symtab> *scs = new SerContext<Symtab>(this, file);
1782 serialize(file, scs, ser_bin);
1783 //fprintf(stderr, "%s[%d]: did serialize\n", FILE__, __LINE__);
1787 catch (const SerializerError &err)
1789 if (err.code() == SerializerError::ser_err_disabled)
1791 fprintf(stderr, "%s[%d]: WARN: serialization is disabled for file %s\n",
1792 FILE__, __LINE__, file.c_str());
1796 fprintf(stderr, "%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
1797 err.what(), err.file().c_str(), err.line());
1800 fprintf(stderr, "%s[%d]: error doing binary serialization\n", __FILE__, __LINE__);
1804 bool Symtab::exportBin(string)
1806 fprintf(stderr, "%s[%d]: WARNING: serialization not available\n", FILE__, __LINE__);
1811 Symtab *Symtab::importBin(std::string file)
1813 #if defined (cap_serialization)
1814 MappedFile *mf= MappedFile::createMappedFile(file);
1817 fprintf(stderr, "%s[%d]: failed to map file %s\n", FILE__, __LINE__, file.c_str());
1821 Symtab *st = new Symtab(mf);
1825 SerContext<Symtab> *scs = new SerContext<Symtab>(st, file);
1826 if (!st->deserialize(file, scs))
1835 catch (const SerializerError &err)
1837 if (err.code() == SerializerError::ser_err_disabled)
1839 serialize_printf("%s[%d]: WARN: serialization is disabled for file %s\n",
1840 FILE__, __LINE__, file.c_str());
1841 fprintf(stderr, "%s[%d]: WARN: serialization is disabled for file %s\n",
1842 FILE__, __LINE__, file.c_str());
1846 serialize_printf("%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
1847 err.what(), err.file().c_str(), err.line());
1848 fprintf(stderr, "%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
1849 err.what(), err.file().c_str(), err.line());
1853 serialize_printf("%s[%d]: error doing binary deserialization\n", __FILE__, __LINE__);
1857 serialize_printf("%s[%d]: WARNING: cannot produce %s, serialization not available\n", FILE__, __LINE__, file.c_str());
1863 bool Symtab::openFile(Symtab *&obj, char *mem_image, size_t size)
1866 #if defined(TIMED_PARSE)
1867 struct timeval starttime;
1868 gettimeofday(&starttime, NULL);
1871 obj = new Symtab(mem_image, size, err);
1873 #if defined(TIMED_PARSE)
1874 struct timeval endtime;
1875 gettimeofday(&endtime, NULL);
1876 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1877 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1878 unsigned long difftime = lendtime - lstarttime;
1879 double dursecs = difftime/(1000 );
1880 cout << __FILE__ << ":" << __LINE__ <<": openFile "<< filename<< " took "<<dursecs <<" msecs" << endl;
1884 allSymtabs.push_back(obj);
1892 // returns true on success (not an error)
1896 bool Symtab::closeSymtab(Symtab *st)
1899 if (!st) return false;
1901 std::vector<Symtab *>::reverse_iterator iter;
1902 for (iter = allSymtabs.rbegin(); iter != allSymtabs.rend() ; iter++)
1906 allSymtabs.erase(iter.base() -1);
1914 Symtab *Symtab::findOpenSymtab(std::string filename)
1916 unsigned numSymtabs = allSymtabs.size();
1917 for (unsigned u=0; u<numSymtabs; u++)
1919 assert(allSymtabs[u]);
1920 if (filename == allSymtabs[u]->file() &&
1921 allSymtabs[u]->mf->canBeShared())
1924 return allSymtabs[u];
1930 bool Symtab::openFile(Symtab *&obj, std::string filename)
1933 #if defined(TIMED_PARSE)
1934 struct timeval starttime;
1935 gettimeofday(&starttime, NULL);
1938 // AIX: it's possible that we're reparsing a file with better information
1939 // about it. If so, yank the old one out of the allSymtabs std::vector -- replace
1941 if ( filename.find("/proc") == std::string::npos)
1943 obj = findOpenSymtab(filename);
1946 //fprintf(stderr, "%s[%d]: have existing symtab obj for %s\n", FILE__, __LINE__, filename.c_str());
1952 #if defined (cap_serialization)
1954 obj = importBin(filename);
1958 if (deserializeEnforced<Symtab>(filename))
1960 serialize_printf("%s[%d]: aborting new symtab, expected deserialize failed\n",
1962 fprintf(stderr, "%s[%d]: aborting new symtab, expected deserialize failed\n",
1966 //fprintf(stderr, "%s[%d]: deserialize failed, but not enforced for %s\n", FILE__, __LINE__, filename.c_str());
1970 //fprintf(stderr, "%s[%d]: deserialize success\n", FILE__, __LINE__);
1976 obj = new Symtab(filename, err);
1977 #if defined(TIMED_PARSE)
1978 struct timeval endtime;
1979 gettimeofday(&endtime, NULL);
1980 unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1981 unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1982 unsigned long difftime = lendtime - lstarttime;
1983 double dursecs = difftime/(1000 );
1984 cout << __FILE__ << ":" << __LINE__ <<": openFile "<< filename<< " took "<<dursecs <<" msecs" << endl;
1989 if (filename.find("/proc") == std::string::npos)
1990 allSymtabs.push_back(obj);
1994 #if defined (cap_serialization)
1996 serialize_printf("%s[%d]: doing bin-serialize for %s\n",
1997 FILE__, __LINE__, filename.c_str());
1999 if (!obj->exportBin(filename))
2001 serialize_printf("%s[%d]: failed to export symtab\n", FILE__, __LINE__);
2004 serialize_printf("%s[%d]: did bin-serialize for %s\n",
2005 FILE__, __LINE__, filename.c_str());
2012 create_printf("%s[%d]: WARNING: failed to open symtab for %s\n",
2013 FILE__, __LINE__, filename.c_str());
2018 // returns true on success (not an error)
2022 bool Symtab::addRegion(Offset vaddr, void *data, unsigned int dataSize, std::string name,
2023 Region::RegionType rType_, bool loadable, unsigned long memAlign, bool tls)
2029 sec = new Region(newSectionInsertPoint, name, vaddr, dataSize, vaddr,
2030 dataSize, (char *)data, Region::RP_R, rType_, true, tls, memAlign);
2032 regions_.insert(regions_.begin()+newSectionInsertPoint, sec);
2034 for (i = newSectionInsertPoint+1; i < regions_.size(); i++)
2036 regions_[i]->setRegionNumber(regions_[i]->getRegionNumber() + 1);
2039 if ( (sec->getRegionType() == Region::RT_TEXT)
2040 || (sec->getRegionType() == Region::RT_TEXTDATA))
2042 codeRegions_.push_back(sec);
2043 std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
2046 if ( (sec->getRegionType() == Region::RT_DATA)
2047 || (sec->getRegionType() == Region::RT_TEXTDATA))
2049 dataRegions_.push_back(sec);
2050 std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
2055 sec = new Region(regions_.size()+1, name, vaddr, dataSize, 0, 0,
2056 (char *)data, Region::RP_R, rType_, loadable, tls, memAlign);
2057 regions_.push_back(sec);
2061 std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
2065 bool Symtab::addUserRegion(Region *reg)
2067 std::vector<Region *> *user_regions = NULL;
2069 if (!getAnnotation(user_regions, UserRegionsAnno))
2071 user_regions = new std::vector<Region *>();
2072 if (!addAnnotation(user_regions, UserRegionsAnno))
2074 fprintf(stderr, "%s[%d]: failed to addAnnotation here\n", FILE__, __LINE__);
2081 fprintf(stderr, "%s[%d]: failed to addAnnotation here\n", FILE__, __LINE__);
2085 user_regions->push_back(reg);
2090 bool Symtab::addUserType(Type *t)
2092 std::vector<Type *> *user_types = NULL;
2094 // need to change this to something based on AnnotationContainer
2095 // for it to work with serialization
2096 if (!getAnnotation(user_types, UserTypesAnno))
2098 user_types = new std::vector<Type *>();
2099 if (!addAnnotation(user_types, UserTypesAnno))
2101 fprintf(stderr, "%s[%d]: failed to addAnnotation here\n", FILE__, __LINE__);
2107 fprintf(stderr, "%s[%d]: failed to addAnnotation here\n", FILE__, __LINE__);
2111 user_types->push_back(t);
2116 bool Symtab::addRegion(Region *sec)
2118 regions_.push_back(sec);
2119 std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
2124 void Symtab::parseLineInformation()
2126 dyn_hash_map<std::string, LineInformation> *lineInfo = new dyn_hash_map <std::string, LineInformation>;
2129 Object *linkedFile = getObject();
2132 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
2135 linkedFile->parseFileLineInfo(this, *lineInfo);
2137 isLineInfoValid_ = true;
2138 dyn_hash_map <std::string, LineInformation>::iterator iter;
2140 for (iter = lineInfo->begin(); iter!=lineInfo->end(); iter++)
2143 bool result = findModuleByName(mod, iter->first);
2145 mod = getDefaultModule();
2148 LineInformation *lineInformation = mod->getLineInformation();
2149 if (!lineInformation)
2151 mod->setLineInfo(&(iter->second));
2155 lineInformation->addLineInfo(&(iter->second));
2156 mod->setLineInfo(lineInformation);
2161 SYMTAB_EXPORT bool Symtab::getAddressRanges(std::vector<pair<Offset, Offset> >&ranges,
2162 std::string lineSource, unsigned int lineNo)
2164 unsigned int originalSize = ranges.size();
2166 /* Iteratate over the modules, looking for ranges in each. */
2168 for ( unsigned int i = 0; i < _mods.size(); i++ )
2170 LineInformation *lineInformation = _mods[i]->getLineInformation();
2172 if (lineInformation)
2173 lineInformation->getAddressRanges( lineSource.c_str(), lineNo, ranges );
2175 } /* end iteration over modules */
2177 if ( ranges.size() != originalSize )
2180 fprintf(stderr, "%s[%d]: failing to getAdressRanges for %s[%d]\n", FILE__, __LINE__, lineSource.c_str(), lineNo);
2184 SYMTAB_EXPORT bool Symtab::getSourceLines(std::vector<Statement *> &lines, Offset addressInRange)
2186 unsigned int originalSize = lines.size();
2188 /* Iteratate over the modules, looking for ranges in each. */
2189 for ( unsigned int i = 0; i < _mods.size(); i++ )
2191 LineInformation *lineInformation = _mods[i]->getLineInformation();
2193 if (lineInformation)
2194 lineInformation->getSourceLines( addressInRange, lines );
2196 } /* end iteration over modules */
2198 if ( lines.size() != originalSize )
2205 SYMTAB_EXPORT bool Symtab::addLine(std::string lineSource, unsigned int lineNo,
2206 unsigned int lineOffset, Offset lowInclAddr,
2207 Offset highExclAddr)
2211 if (!findModuleByName(mod, lineSource))
2213 std::string fileNm = extract_pathname_tail(lineSource);
2215 if (!findModuleByName(mod, fileNm))
2217 if (!findModuleByName(mod, mf->pathname()))
2222 LineInformation *lineInfo = mod->getLineInformation();
2227 return (lineInfo->addLine(lineSource.c_str(), lineNo, lineOffset,
2228 lowInclAddr, highExclAddr));
2231 SYMTAB_EXPORT bool Symtab::addAddressRange( Offset lowInclusiveAddr, Offset highExclusiveAddr,
2232 std::string lineSource, unsigned int lineNo,
2233 unsigned int lineOffset)
2237 if (!findModuleByName(mod, lineSource))
2239 std::string fileNm = extract_pathname_tail(lineSource);
2241 if (!findModuleByName(mod, fileNm))
2245 LineInformation *lineInfo = mod->getLineInformation();
2250 return (lineInfo->addAddressRange(lowInclusiveAddr, highExclusiveAddr,
2251 lineSource.c_str(), lineNo, lineOffset));
2255 void Symtab::parseTypes()
2257 Object *linkedFile = getObject();
2260 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
2263 linkedFile->parseTypeInfo(this);
2264 isTypeInfoValid_ = true;
2266 for (unsigned int i = 0; i < _mods.size(); ++i)
2268 typeCollection *tc = typeCollection::getModTypeCollection(_mods[i]);
2270 if (!_mods[i]->addAnnotation(tc, ModuleTypeInfoAnno))
2272 fprintf(stderr, "%s[%d]: failed to addAnnotation here\n", FILE__, __LINE__);
2276 // optionally we might want to clear the static data struct in typeCollection
2277 // here.... the parsing is over, and we have added all typeCollections as
2278 // annotations proper.
2280 typeCollection::fileToTypesMap.clear();
2284 bool Symtab::addType(Type *type)
2286 bool result = addUserType(type);
2293 SYMTAB_EXPORT vector<Type *> *Symtab::getAllstdTypes()
2296 return stdTypes->getAllTypes();
2299 SYMTAB_EXPORT vector<Type *> *Symtab::getAllbuiltInTypes()
2302 return builtInTypes->getAllBuiltInTypes();
2305 SYMTAB_EXPORT bool Symtab::findType(Type *&type, std::string name)
2312 for (unsigned int i = 0; i < _mods.size(); ++i)
2314 typeCollection *tc = _mods[i]->getModuleTypes();
2316 type = tc->findType(name);
2317 if (type) return true;
2326 SYMTAB_EXPORT Type *Symtab::findType(unsigned type_id)
2333 //fprintf(stderr, "%s[%d]: findType failing due to lack of modules\n", FILE__, __LINE__);
2337 for (unsigned int i = 0; i < _mods.size(); ++i)
2339 typeCollection *tc = _mods[i]->getModuleTypes();
2341 t = tc->findType(type_id);
2349 t = builtInTypes->findBuiltInType(type_id);
2354 //fprintf(stderr, "%s[%d]: no built in types!\n", FILE__, __LINE__);
2359 t = stdTypes->findType(type_id);
2364 //fprintf(stderr, "%s[%d]: no std types!\n", FILE__, __LINE__);
2373 SYMTAB_EXPORT bool Symtab::findVariableType(Type *&type, std::string name)
2381 for (unsigned int i = 0; i < _mods.size(); ++i)
2383 typeCollection *tc = _mods[i]->getModuleTypes();
2385 type = tc->findVariableType(name);
2395 SYMTAB_EXPORT bool Symtab::findLocalVariable(std::vector<localVar *>&vars, std::string name)
2398 unsigned origSize = vars.size();
2400 for (unsigned i = 0; i < everyFunction.size(); i++)
2402 everyFunction[i]->findLocalVariable(vars, name);
2405 if (vars.size()>origSize)
2411 SYMTAB_EXPORT bool Symtab::hasRel() const
2416 SYMTAB_EXPORT bool Symtab::hasRela() const
2421 SYMTAB_EXPORT bool Symtab::hasReldyn() const
2426 SYMTAB_EXPORT bool Symtab::hasReladyn() const
2431 SYMTAB_EXPORT bool Symtab::hasRelplt() const
2436 SYMTAB_EXPORT bool Symtab::hasRelaplt() const
2441 SYMTAB_EXPORT bool Symtab::isStaticBinary() const
2443 return isStaticBinary_;
2446 bool Symtab::setDefaultNamespacePrefix(string &str)
2448 defaultNamespacePrefix = str;
2452 SYMTAB_EXPORT bool Symtab::emitSymbols(Object *linkedFile,std::string filename, unsigned flag)
2454 // Start with all the defined symbols
2455 std::vector<Symbol *> allSyms;
2456 for (unsigned i = 0; i < everyDefinedSymbol.size(); i++) {
2457 allSyms.push_back(everyDefinedSymbol[i]);
2460 // Add the undefined dynamic symbols
2461 map<string, std::vector<Symbol *> >::iterator iter;
2462 std::vector<Symbol *>::iterator siter;
2464 for (iter = undefDynSyms.begin(); iter != undefDynSyms.end(); iter++)
2465 for (siter=iter->second.begin(); siter != iter->second.end(); siter++)
2466 allSyms.push_back(*siter);
2468 // Write the new file
2469 return linkedFile->emitDriver(this, filename, allSyms, flag);
2472 SYMTAB_EXPORT bool Symtab::emit(std::string filename, unsigned flag)
2474 Object *obj = getObject();
2477 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
2480 obj->mf->setSharing(false);
2481 return emitSymbols(obj, filename, flag);
2484 SYMTAB_EXPORT void Symtab::addDynLibSubstitution(std::string oldName, std::string newName)
2486 dynLibSubs[oldName] = newName;
2489 SYMTAB_EXPORT std::string Symtab::getDynLibSubstitution(std::string name)
2491 #ifdef BINEDIT_DEBUG
2492 map<std::string, std::string>::iterator iter = dynLibSubs.begin();
2494 printf ("substitutions for %s:\n", mf->filename().c_str());
2496 while (iter != dynLibSubs.end())
2498 printf(" \"%s\" => \"%s\"\n", iter->first.c_str(), iter->second.c_str());
2503 map<std::string, std::string>::iterator loc = dynLibSubs.find(name);
2505 if (loc == dynLibSubs.end())
2511 SYMTAB_EXPORT bool Symtab::getSegments(vector<Segment> &segs) const
2515 if (!segments_.size())
2521 SYMTAB_EXPORT bool Symtab::getMappedRegions(std::vector<Region *> &mappedRegs) const
2523 unsigned origSize = mappedRegs.size();
2525 for (unsigned i = 0; i < regions_.size(); i++)
2527 if (regions_[i]->isLoadable())
2528 mappedRegs.push_back(regions_[i]);
2531 if (mappedRegs.size() > origSize)
2537 SYMTAB_EXPORT bool Symtab::fixup_RegionAddr(const char* name, Offset memOffset, long memSize)
2541 if (!findRegion(sec, name)) {
2542 fprintf(stderr, "Couldn't find region %s\n", name);
2547 if (!strcmp(name, ".text")) {
2548 vector<relocationEntry> relocs;
2550 // Fix relocation table with correct memory address
2551 getObject()->get_func_binding_table(relocs);
2552 // fprintf(stderr, "There are %d relocs in this symtab.\n", relocs.size());
2553 for (unsigned i=0; i < relocs.size(); i++) {
2554 Offset value = relocs[i].rel_addr();
2555 relocs[i].setRelAddr(memOffset + value);
2556 // fprintf(stderr, "Fixing relocation from 0x%x to 0x%x\n", value, memOffset + value);
2559 relocation_table_ = relocs;
2562 #if defined(_MSC_VER)
2563 regionsByEntryAddr.erase(sec->getRegionAddr());
2566 sec->setMemOffset(memOffset);
2567 sec->setMemSize(memSize);
2569 #if defined(_MSC_VER)
2570 regionsByEntryAddr[sec->getRegionAddr()] = sec;
2573 std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
2574 std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
2575 std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
2579 SYMTAB_EXPORT bool Symtab::fixup_SymbolAddr(const char* name, Offset newOffset)
2584 for (i = 0; i < everyDefinedSymbol.size(); ++i)
2585 if (everyDefinedSymbol[i]->getMangledName() == name) {
2586 sym = everyDefinedSymbol[i];
2590 fprintf(stderr, "VxWorks found symbol %s that we didn't know about. Skipping...\n", name);
2596 Offset oldOffset = sym->getOffset();
2597 sym->setOffset(newOffset);
2598 //fprintf(stderr, "Fixing symbol %s from 0x%x to 0x%x\n", name, oldOffset, newOffset);
2601 if (symsByOffset.count(oldOffset)) {
2602 std::vector<Symbol *>::iterator iter = symsByOffset[oldOffset].begin();
2603 while (iter != symsByOffset[oldOffset].end()) {
2605 symsByOffset[oldOffset].erase(iter);
2606 iter = symsByOffset[oldOffset].begin();
2611 if (!findSymbolByOffset(newOffset))
2612 symsByOffset[newOffset].push_back(sym);
2614 // Update aggregates.
2615 addSymbolToAggregates(sym);
2618 if (funcsByOffset.count(oldOffset) > 0) {
2619 Function *func = funcsByOffset[oldOffset];
2621 func->changeSymbolOffset(sym);
2622 funcsByOffset.erase(oldOffset);
2623 funcsByOffset[newOffset] = func;
2625 // DEBUG fprintf(stderr, "Symbol was a function\n");
2628 if (varsByOffset.count(oldOffset) > 0) {
2629 Variable *var = varsByOffset[oldOffset];
2631 var->changeSymbolOffset(sym);
2632 varsByOffset.erase(oldOffset);
2633 varsByOffset[newOffset] = var;
2634 // DEBUG fprintf(stderr, "Symbol was a variable\n");
2641 SYMTAB_EXPORT bool Symtab::updateRegion(const char* name, void *buffer, unsigned size)
2645 if (!findRegion(sec, name))
2648 sec->setPtrToRawData(buffer, size);
2653 SYMTAB_EXPORT bool Symtab::updateCode(void *buffer, unsigned size)
2655 return updateRegion(".text", buffer, size);
2658 SYMTAB_EXPORT bool Symtab::updateData(void *buffer, unsigned size)
2660 return updateRegion(".data", buffer, size);
2663 SYMTAB_EXPORT Offset Symtab::getFreeOffset(unsigned size)
2665 // Look through sections until we find a gap with
2666 // sufficient space.
2667 Offset highWaterMark = 0;
2668 Offset secoffset = 0;
2669 Offset prevSecoffset = 0;
2670 Object *linkedFile = getObject();
2673 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
2677 for (unsigned i = 0; i < regions_.size(); i++)
2679 //Offset end = regions_[i]->getRegionAddr() + regions_[i]->getDiskSize();
2680 Offset end = regions_[i]->getRegionAddr() + regions_[i]->getRegionSize();
2681 if (regions_[i]->getRegionAddr() == 0)
2684 prevSecoffset = secoffset;
2686 unsigned region_offset = (unsigned)((char *)(regions_[i]->getPtrToRawData())
2687 - linkedFile->mem_image());
2689 if (region_offset < (unsigned)prevSecoffset)
2691 //secoffset += regions_[i]->getDiskSize();
2692 secoffset += regions_[i]->getRegionSize();
2696 secoffset = (char *)(regions_[i]->getPtrToRawData()) - linkedFile->mem_image();
2697 //secoffset += regions_[i]->getDiskSize();
2698 secoffset += regions_[i]->getRegionSize();
2701 /*fprintf(stderr, "%d: secAddr 0x%lx, size %d, end 0x%lx, looking for %d\n",
2702 i, regions_[i]->getSecAddr(), regions_[i]->getSecSize(),
2705 if (end > highWaterMark)
2707 //fprintf(stderr, "Increasing highWaterMark...\n");
2708 newSectionInsertPoint = i+1;
2709 highWaterMark = end;
2712 if ( (i < (regions_.size()-2))
2713 && ((end + size) < regions_[i+1]->getRegionAddr()))
2715 /* fprintf(stderr, "Found a hole between sections %d and %d\n",
2717 fprintf(stderr, "End at 0x%lx, next one at 0x%lx\n",
2718 end, regions_[i+1]->getSecAddr());
2720 newSectionInsertPoint = i+1;
2721 highWaterMark = end;
2726 // return highWaterMark;
2727 #if defined (os_windows)
2728 Object *obj = getObject();
2731 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
2734 unsigned pgSize = obj->getSecAlign();
2735 //printf("pgSize:0x%x\n", pgSize);
2736 Offset newaddr = highWaterMark - (highWaterMark & (pgSize-1));
2737 while(newaddr < highWaterMark)
2739 //printf("getfreeoffset:%lu\n", newaddr);
2743 unsigned pgSize = P_getpagesize();
2744 Offset newaddr = highWaterMark - (highWaterMark & (pgSize-1));
2745 if(newaddr < highWaterMark)
2752 SYMTAB_EXPORT ObjectType Symtab::getObjectType() const
2754 return object_type_;
2757 SYMTAB_EXPORT char *Symtab::mem_image() const
2759 return (char *)mf->base_addr();
2762 SYMTAB_EXPORT std::string Symtab::file() const
2765 return mf->pathname();
2768 SYMTAB_EXPORT std::string Symtab::name() const
2770 return mf->filename();
2773 SYMTAB_EXPORT std::string Symtab::memberName() const
2775 return member_name_;
2778 SYMTAB_EXPORT unsigned Symtab::getNumberofRegions() const
2780 return no_of_sections;
2783 SYMTAB_EXPORT unsigned Symtab::getNumberofSymbols() const
2785 return no_of_symbols;
2788 bool Symtab::setup_module_up_ptrs(SerializerBase *, Symtab *st)
2790 std::vector<Module *> &mods = st->_mods;
2792 for (unsigned int i = 0; i < mods.size(); ++i)
2794 Module *m = mods[i];
2801 bool Symtab::fixup_relocation_symbols(SerializerBase *, Symtab *st)
2803 std::vector<Module *> &mods = st->_mods;
2805 for (unsigned int i = 0; i < mods.size(); ++i)
2807 Module *m = mods[i];
2814 void Symtab::rebuild_symbol_hashes(SerializerBase *sb)
2819 for (unsigned long i = 0; i < everyDefinedSymbol.size(); ++i)
2821 Symbol *s = everyDefinedSymbol[i];
2823 const std::string &pn = s->getPrettyName();
2824 const std::string &mn = s->getMangledName();
2825 const std::string tn = s->getTypedName();
2827 symsByPrettyName[pn].push_back(s);
2828 symsByMangledName[mn].push_back(s);
2829 symsByTypedName[tn].push_back(s);
2830 symsByOffset[s->getOffset()].push_back(s);
2834 void Symtab::rebuild_funcvar_hashes(SerializerBase *sb)
2838 for (unsigned int i = 0; i < everyFunction.size(); ++i)
2840 Function *f = everyFunction[i];
2841 funcsByOffset[f->getOffset()] = f;
2843 for (unsigned int i = 0; i < everyVariable.size(); ++i)
2845 Variable *v = everyVariable[i];
2846 varsByOffset[v->getOffset()] = v;
2849 void Symtab::rebuild_module_hashes(SerializerBase *sb)
2853 for (unsigned int i = 0; i < _mods.size(); ++i)
2855 Module *m = _mods[i];
2856 modsByFileName[m->fileName()] = m;
2857 modsByFullName[m->fullName()] = m;
2860 void Symtab::rebuild_region_indexes(SerializerBase *sb) THROW_SPEC (SerializerError)
2865 for (unsigned int i = 0; i < regions_.size(); ++i)
2867 Region *r = regions_[i];
2869 if (!r) SER_ERR("FIXME: NULL REGION");
2871 if ( r->isLoadable() )
2873 if ((r->getRegionPermissions() == Region::RP_RX)
2874 || (r->getRegionPermissions() == Region::RP_RWX))
2875 codeRegions_.push_back(r);
2877 dataRegions_.push_back(r);
2880 // entry addr might require some special attn on windows, since it
2881 // is not the disk offset but the actual mem addr, which is going to be
2882 // different after deserialize. Probably have to look it up again.
2883 regionsByEntryAddr[r->getRegionAddr()] = r;
2886 std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
2887 std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
2892 Serializable *Symtab::serialize_impl(SerializerBase *sb,
2893 const char *tag) THROW_SPEC (SerializerError)
2895 serialize_printf("%s[%d]: welcome to Symtab::serialize_impl\n",
2899 // don't bother with serializing standard and builtin types.
2903 ifxml_start_element(sb, tag);
2904 gtranslate(sb, imageOffset_, "imageOffset");
2905 gtranslate(sb, imageLen_, "imageLen");
2906 gtranslate(sb, dataOffset_, "dataOff");
2907 gtranslate(sb, dataLen_, "dataLen");
2908 gtranslate(sb, is_a_out, "isExec");
2909 gtranslate(sb, _mods, "Modules", "Module");
2910 rebuild_module_hashes(sb);
2913 // problem: if isTypeInfoValid_ is not true, we can trigger type parsing
2914 // for an object class that does not exist. Need to introduce logic to
2915 // recreate the object in this case
2916 isTypeInfoValid_ = true;
2917 isLineInfoValid_ = true; // NOTE: set this to true after deserializing at least one lineInformaton object
2919 gtranslate(sb, regions_, "Regions", "Region");
2920 rebuild_region_indexes(sb);
2921 gtranslate(sb, everyDefinedSymbol, "EveryDefinedSymbol", "Symbol");
2922 rebuild_symbol_hashes(sb);
2923 gtranslate(sb, relocation_table_, "RelocationTable", "RelocationTableEntry");
2924 gtranslate(sb, everyFunction, "EveryFunction", "Function");
2925 gtranslate(sb, everyVariable, "EveryVariable", "Variable");
2926 rebuild_funcvar_hashes(sb);
2928 //gtranslate(sb, everyUniqueVariable, "EveryUniqueVariable", "UniqueVariable");
2929 //gtranslate(sb, modSyms, "ModuleSymbols", "ModuleSymbol");
2931 gtranslate(sb, excpBlocks, "ExceptionBlocks", "ExceptionBlock");
2932 ifxml_end_element(sb, tag);
2934 sb->magic_check(FILE__, __LINE__);
2936 ifinput(Symtab::setup_module_up_ptrs, sb, this);
2937 ifinput(fixup_relocation_symbols, sb, this);
2942 dyn_hash_map<Address, Symbol *> *map_p = NULL;
2943 if (getAnnotation(map_p, IdToSymAnno) && (NULL != map_p))
2945 if (!removeAnnotation(IdToSymAnno))
2947 fprintf(stderr, "%s[%d]: failed to remove id-to-sym map\n",
2953 serialize_printf("%s[%d]: leaving Symtab::serialize_impl\n", FILE__, __LINE__);
2957 SYMTAB_EXPORT LookupInterface::LookupInterface()
2961 SYMTAB_EXPORT LookupInterface::~LookupInterface()
2966 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(Offset tStart,
2969 : tryStart_(tStart), trySize_(tSize), catchStart_(cStart), hasTry_(true)
2973 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(Offset cStart)
2974 : tryStart_(0), trySize_(0), catchStart_(cStart), hasTry_(false)
2978 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(const ExceptionBlock &eb) :
2980 tryStart_(eb.tryStart_), trySize_(eb.trySize_),
2981 catchStart_(eb.catchStart_), hasTry_(eb.hasTry_)
2984 SYMTAB_EXPORT bool ExceptionBlock::hasTry() const
2989 SYMTAB_EXPORT Offset ExceptionBlock::tryStart() const
2994 SYMTAB_EXPORT Offset ExceptionBlock::tryEnd() const
2996 return tryStart_ + trySize_;
2999 SYMTAB_EXPORT Offset ExceptionBlock::trySize() const
3004 SYMTAB_EXPORT bool ExceptionBlock::contains(Offset a) const
3006 return (a >= tryStart_ && a < tryStart_ + trySize_);
3009 Serializable * ExceptionBlock::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
3011 ifxml_start_element(sb, tag);
3012 gtranslate(sb, tryStart_, "tryStart");
3013 gtranslate(sb, trySize_, "trySize");
3014 gtranslate(sb, catchStart_, "catchStart");
3015 gtranslate(sb, hasTry_, "hasTry");
3016 ifxml_end_element(sb, tag);
3021 SYMTAB_EXPORT relocationEntry::relocationEntry() :
3025 rtype_(Region::RT_REL),
3032 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, std::string n,
3033 Symbol *dynref, unsigned long relType) :
3037 rtype_(Region::RT_REL),
3044 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, Offset add,
3045 std::string n, Symbol *dynref, unsigned long relType) :
3049 rtype_(Region::RT_REL),
3056 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ra, std::string n,
3057 Symbol *dynref, unsigned long relType, Region::RegionType rtype) :
3068 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, Offset add,
3069 std::string n, Symbol *dynref, unsigned long relType,
3070 Region::RegionType rtype) :
3080 SYMTAB_EXPORT const relocationEntry& relocationEntry::operator=(const relocationEntry &ra)
3082 target_addr_ = ra.target_addr_;
3083 rel_addr_ = ra.rel_addr_;
3084 addend_ = ra.addend_;
3087 dynref_ = ra.dynref_;
3088 relType_ = ra.relType_;
3092 SYMTAB_EXPORT Offset relocationEntry::target_addr() const
3094 return target_addr_;
3097 SYMTAB_EXPORT void relocationEntry::setTargetAddr(const Offset off)
3102 SYMTAB_EXPORT Offset relocationEntry::rel_addr() const
3107 SYMTAB_EXPORT void relocationEntry::setRelAddr(const Offset value)
3112 SYMTAB_EXPORT const string &relocationEntry::name() const
3117 SYMTAB_EXPORT Symbol *relocationEntry::getDynSym() const
3122 SYMTAB_EXPORT bool relocationEntry::addDynSym(Symbol *dynref)
3128 SYMTAB_EXPORT Region::RegionType relocationEntry::regionType() const
3133 SYMTAB_EXPORT unsigned long relocationEntry::getRelType() const
3138 SYMTAB_EXPORT Offset relocationEntry::addend() const
3143 SYMTAB_EXPORT void relocationEntry::setAddend(const Offset value)
3148 SYMTAB_EXPORT void relocationEntry::setRegionType(const Region::RegionType value)
3153 SYMTAB_EXPORT void relocationEntry::setName(const std::string &newName) {
3157 bool relocationEntry::operator==(const relocationEntry &r) const
3159 if (target_addr_ != r.target_addr_) return false;
3160 if (rel_addr_ != r.rel_addr_) return false;
3161 if (addend_ != r.addend_) return false;
3162 if (rtype_ != r.rtype_) return false;
3163 if (name_ != r.name_) return false;
3164 if (relType_ != r.relType_) return false;
3165 if (dynref_ && !r.dynref_) return false;
3166 if (!dynref_ && r.dynref_) return false;
3169 if (dynref_->getName() != r.dynref_->getName()) return false;
3170 if (dynref_->getOffset() != r.dynref_->getOffset()) return false;
3176 Serializable *relocationEntry::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
3178 // on deserialize need to rebuild symtab::undefDynSyms before deserializing relocations
3180 std::string symname = dynref_ ? dynref_->getName() : std::string("");
3181 Offset symoff = dynref_ ? dynref_->getOffset() : (Offset) -1;
3183 ifxml_start_element(sb, tag);
3184 gtranslate(sb, target_addr_, "targetAddress");
3185 gtranslate(sb, rel_addr_, "relocationAddress");
3186 gtranslate(sb, addend_, "Addend");
3187 gtranslate(sb, name_, "relocationName");
3188 gtranslate(sb, rtype_, Region::regionType2Str, "regionType");
3189 gtranslate(sb, relType_, "relocationType");
3190 gtranslate(sb, symname, "SymbolName");
3191 gtranslate(sb, symoff, "SymbolOffset");
3192 ifxml_end_element(sb, tag);
3197 if (symname != std::string(""))
3199 // if we have a name for this symbol, the offset should not be -1;
3200 if (symoff == (Offset) -1)
3202 fprintf(stderr, "%s[%d]: inconsistent symname and offset combo!\n",
3206 SerContextBase *scb = sb->getContext();
3209 fprintf(stderr, "%s[%d]: SERIOUS: FIXME\n", FILE__, __LINE__);
3213 SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
3217 fprintf(stderr, "%s[%d]: SERIOUS: FIXME\n", FILE__, __LINE__);
3221 Symtab *st = scs->getScope();
3225 fprintf(stderr, "%s[%d]: SERIOUS: FIXME\n", FILE__, __LINE__);
3229 std::vector<Symbol *> *syms = st->findSymbolByOffset(symoff);
3230 if (!syms || !syms->size())
3232 serialize_printf("%s[%d]: cannot find symbol by offset %p\n",
3233 FILE__, __LINE__, (void *)symoff);
3237 // Might want to try to select the "best" symbol here if there is
3238 // more than one. Or Maybe just returning the first is sufficient.
3240 dynref_ = (*syms)[0];
3246 ostream & Dyninst::SymtabAPI::operator<< (ostream &os, const relocationEntry &r)
3248 if( r.getDynSym() != NULL ) {
3249 os << "Name: " << setw(20) << ( "'" + r.getDynSym()->getName() + "'" );
3251 os << "Name: " << setw(20) << r.name();
3253 os << " Offset: " << std::hex << std::setfill('0') << setw(8) << r.rel_addr()
3254 << std::dec << std::setfill(' ')
3255 << " Offset: " << std::hex << std::setfill('0') << setw(8) << r.target_addr()
3256 << std::dec << std::setfill(' ')
3257 << " Addend: " << r.addend()
3258 << " Region: " << Region::regionType2Str(r.regionType())
3259 << " Type: " << setw(15) << relocationEntry::relType2Str(r.getRelType())
3260 << "(" << r.getRelType() << ")";
3261 if( r.getDynSym() != NULL ) {
3262 os << " Symbol Offset: " << std::hex << std::setfill('0') << setw(8) << r.getDynSym()->getOffset();
3263 os << std::setfill(' ');
3264 if( r.getDynSym()->isCommonStorage() ) {
3266 }else if( r.getDynSym()->getRegion() == NULL ) {
3273 const char *Symbol::symbolType2Str(SymbolType t)
3277 CASE_RETURN_STR(ST_UNKNOWN);
3278 CASE_RETURN_STR(ST_FUNCTION);
3279 CASE_RETURN_STR(ST_OBJECT);
3280 CASE_RETURN_STR(ST_MODULE);
3281 CASE_RETURN_STR(ST_SECTION);
3282 CASE_RETURN_STR(ST_TLS);
3283 CASE_RETURN_STR(ST_DELETED);
3284 CASE_RETURN_STR(ST_NOTYPE);
3287 return "invalid symbol type";
3290 const char *Symbol::symbolLinkage2Str(SymbolLinkage t)
3294 CASE_RETURN_STR(SL_UNKNOWN);
3295 CASE_RETURN_STR(SL_GLOBAL);
3296 CASE_RETURN_STR(SL_LOCAL);
3297 CASE_RETURN_STR(SL_WEAK);
3300 return "invalid symbol linkage";
3303 const char *Symbol::symbolTag2Str(SymbolTag t)
3307 CASE_RETURN_STR(TAG_UNKNOWN);
3308 CASE_RETURN_STR(TAG_USER);
3309 CASE_RETURN_STR(TAG_LIBRARY);
3310 CASE_RETURN_STR(TAG_INTERNAL);
3313 return "invalid symbol tag";
3316 const char *Symbol::symbolVisibility2Str(SymbolVisibility t)
3319 CASE_RETURN_STR(SV_UNKNOWN);
3320 CASE_RETURN_STR(SV_DEFAULT);
3321 CASE_RETURN_STR(SV_INTERNAL);
3322 CASE_RETURN_STR(SV_HIDDEN);
3323 CASE_RETURN_STR(SV_PROTECTED);
3325 return "invalid symbol visibility";
3328 bool Symtab::hasStackwalkDebugInfo()
3331 Object *obj = getObject();
3334 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
3337 return obj->hasFrameDebugInfo();
3340 bool Symtab::getRegValueAtFrame(Address pc,
3341 Dyninst::MachRegister reg,
3342 Dyninst::MachRegisterVal ®_result,
3343 MemRegReader *reader)
3345 Object *obj = getObject();
3348 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
3351 return obj->getRegValueAtFrame(pc, reg, reg_result, reader);
3354 Object *Symtab::getObject()
3359 //TODO: This likely triggered because we serialized in an object
3360 // from cache, but now the user is requesting more information from
3361 // the on disk object. We should create a new 'Object' from data
3362 // (likely a file path) serialized in.
3364 fprintf(stderr, "%s[%d]: FIXME: request for object that does not exist!\n", FILE__, __LINE__);
3366 //obj_private = new Object();
3367 //return obj_private;
3370 void Symtab::parseTypesNow()
3372 if (isTypeInfoValid_)
3378 #if defined (cap_serialization)
3379 // Not sure this is strictly necessary, problems only seem to exist with Module
3380 // annotations when the file was split off, so there's probably something else that
3381 // can be done to instantiate the relevant functions.
3383 bool dummy_for_ser_instance(std::string file, SerializerBase *sb)
3385 if (file == std::string("no_such_file"))
3389 fprintf(stderr, "%s[%d]: really should not happen\n", FILE__, __LINE__);
3392 fprintf(stderr, "%s[%d]: WARN: disabled serializer init here\n", FILE__, __LINE__);
3400 namespace SymtabAPI {
3404 SYMTAB_EXPORT SerializerBase *nonpublic_make_bin_symtab_serializer(Symtab *t, std::string file)
3407 SerContext<Symtab> *scs = new SerContext<Symtab>(t, file);
3408 ser = new SerializerBin(scs, "SerializerBin", file, sd_serialize, false);
3412 SYMTAB_EXPORT SerializerBase *nonpublic_make_bin_symtab_deserializer(Symtab *t, std::string file)
3415 SerContext<Symtab> *scs = new SerContext<Symtab>(t, file);
3416 ser = new SerializerBin(scs, "DeserializerBin", file, sd_deserialize, false);
3420 SYMTAB_EXPORT void nonpublic_free_bin_symtab_serializer(SerializerBase *sb)
3422 SerializerBin *sbin = dynamic_cast<SerializerBin *>(sb);
3428 fprintf(stderr, "%s[%d]: FIXME\n", FILE__, __LINE__);
3433 SYMTAB_EXPORT Offset Symtab::getElfDynamicOffset()
3435 #if defined(os_linux)
3436 Object *obj = getObject();
3439 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
3442 return obj->getDynamicAddr();
3448 SYMTAB_EXPORT bool Symtab::addLibraryPrereq(std::string name)
3450 #if defined(os_linux)
3451 Object *obj = getObject();
3454 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
3457 obj->insertPrereqLibrary(name);
3464 SYMTAB_EXPORT bool Symtab::addSysVDynamic(long name, long value)
3466 #if defined(os_linux)
3467 Object *obj = getObject();
3470 fprintf(stderr, "%s[%d]: getObject failed here\n", FILE__, __LINE__);
3473 obj->insertDynamicEntry(name, value);
3480 SYMTAB_EXPORT bool Symtab::addExternalSymbolReference(Symbol *externalSym, Region *localRegion,
3481 relocationEntry localRel)
3483 // Create placeholder Symbol for external Symbol reference
3484 Symbol *symRef = new Symbol(externalSym->getName(),
3485 externalSym->getType(),
3491 externalSym->getSize(),
3495 if( !addSymbol(symRef, externalSym) ) return false;
3497 localRegion->addRelocationEntry(localRel);
3499 // Make sure the Symtab holding the external symbol gets linked
3501 explicitSymtabRefs_.insert(externalSym->getSymtab());
3506 bool Symtab::getExplicitSymtabRefs(std::set<Symtab *> &refs) {
3507 refs = explicitSymtabRefs_;
3508 return (refs.size() != 0);
3511 SYMTAB_EXPORT bool Symtab::addLinkingResource(Archive *library) {
3512 linkingResources_.push_back(library);
3517 SYMTAB_EXPORT bool Symtab::getLinkingResources(std::vector<Archive *> &libs) {
3518 libs = linkingResources_;
3519 return (linkingResources_.size() != 0);
3522 SYMTAB_EXPORT Address Symtab::getLoadAddress()
3524 #if defined(os_linux) || defined(os_aix)
3525 return getObject()->getLoadAddress();
3531 SYMTAB_EXPORT bool Symtab::canBeShared()
3533 return mf->canBeShared();
3536 SYMTAB_EXPORT Offset Symtab::getInitOffset()
3538 #if defined(os_linux) || defined(os_solaris)
3539 return getObject()->getInitAddr();
3546 SYMTAB_EXPORT Offset Symtab::getFiniOffset()
3548 #if defined(os_linux) || defined(os_solaris)
3549 return getObject()->getFiniAddr();
3556 } // namespace SymtabAPI
3557 } // namespace Dyninst