Object.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 // $Id: Object.C,v 1.31 2008/11/03 15:19:25 jaw Exp $
00032 
00033 #include "symutil.h"
00034 #include "Annotatable.h"
00035 #include "common/h/serialize.h"
00036 
00037 #include "Symtab.h"
00038 #include "Module.h"
00039 #include "Region.h"
00040 #include "Collections.h"
00041 #include "annotations.h"
00042 #include "Symbol.h"
00043 
00044 #include "Aggregate.h"
00045 #include "Function.h"
00046 #include "Variable.h"
00047 
00048 #include "symtabAPI/src/Object.h"
00049 
00050 #include <iostream>
00051 
00052 using namespace std;
00053 using namespace Dyninst;
00054 using namespace Dyninst::SymtabAPI;
00055 
00056 string Symbol::emptyString("");
00057 
00058 
00059 //#ifdef BINEDIT_DEBUG
00060 bool ____sym_hdr_printed = false;
00061 void print_symbols( std::vector< Symbol *>& allsymbols ) {
00062     FILE* fd = stdout;
00063     Symbol *sym;
00064     std::string modname;
00065     if (!____sym_hdr_printed) {
00066         fprintf(fd, "%-20s  %-15s  %-10s  %5s  SEC  TYP  LN  VIS  INFO\n", 
00067                 "SYMBOL", "MODULE", "ADDR", "SIZE");
00068         ____sym_hdr_printed = true;
00069     }
00070     for (unsigned i=0; i<allsymbols.size(); i++) {
00071         sym = allsymbols[i];
00072         modname = (sym->getModule() ? sym->getModule()->fileName() : "");
00073         //if (sym->getName() == "__gmon_start__") {
00074         //if (modname == "libspecial.so" || modname == "libprofile.so") {
00075         //if (sym->getLinkage() == Symbol::SL_WEAK) {
00076         //if (sym->isInDynSymtab()) {
00077         if (1) {
00078             fprintf(fd, "%-20s  %-15s  0x%08x  %5u  %3u", 
00079                     sym->getMangledName().substr(0,20).c_str(), 
00080                 //modname.size() > 15 ? modname.substr(modname.size()-15,15).c_str() : modname.c_str(),
00081                 "",
00082                 (unsigned)sym->getOffset(),
00083                 (unsigned)sym->getSize(),
00084                     sym->getRegion() ? sym->getRegion()->getRegionNumber() : 0
00085                 );
00086             switch (sym->getType()) {
00087                 case Symbol::ST_FUNCTION: fprintf(fd, "  FUN"); break;
00088                 case Symbol::ST_TLS:      fprintf(fd, "  TLS"); break;
00089                 case Symbol::ST_OBJECT:   fprintf(fd, "  OBJ"); break;
00090                 case Symbol::ST_MODULE:   fprintf(fd, "  MOD"); break;
00091                 case Symbol::ST_SECTION:  fprintf(fd, "  SEC"); break;
00092                 case Symbol::ST_DELETED:  fprintf(fd, "  DEL"); break;
00093                 case Symbol::ST_NOTYPE:   fprintf(fd, "   - "); break;
00094                 default:
00095                 case Symbol::ST_UNKNOWN:  fprintf(fd, "  ???"); break;                 
00096             }
00097             switch (sym->getLinkage()) {
00098                 case Symbol::SL_UNKNOWN: fprintf(fd, "  ??"); break;
00099                 case Symbol::SL_GLOBAL:  fprintf(fd, "  GL"); break;
00100                 case Symbol::SL_LOCAL:   fprintf(fd, "  LO"); break;
00101                 case Symbol::SL_WEAK:    fprintf(fd, "  WK"); break;
00102             }
00103             switch (sym->getVisibility()) {
00104                 case Symbol::SV_UNKNOWN:   fprintf(fd, "  ???"); break;
00105                 case Symbol::SV_DEFAULT:   fprintf(fd, "   - "); break;
00106                 case Symbol::SV_INTERNAL:  fprintf(fd, "  INT"); break;
00107                 case Symbol::SV_HIDDEN:    fprintf(fd, "  HID"); break;
00108                 case Symbol::SV_PROTECTED: fprintf(fd, "  PRO"); break;
00109             }
00110             fprintf(fd, " ");
00111             if (sym->isInSymtab())
00112                 fprintf(fd, " STA");
00113             if (sym->isInDynSymtab())
00114                 fprintf(fd, " DYN");
00115             if (sym->isAbsolute())
00116                 fprintf(fd, " ABS");
00117             std::string fileName;
00118             std::vector<std::string> *vers;
00119             if (sym->getVersionFileName(fileName))
00120                 fprintf(fd, "  [%s]", fileName.c_str());
00121             if (sym->getVersions(vers)) {
00122                 fprintf(fd, " {");
00123                 for (unsigned j=0; j < vers->size(); j++) {
00124                     if (j > 0)
00125                         fprintf(fd, ", ");
00126                     fprintf(fd, "%s", (*vers)[j].c_str());
00127                 }
00128                 fprintf(fd, "}");
00129             }
00130             fprintf(fd,"\n");
00131         }
00132     }
00133 }
00134 void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols) {
00135     dyn_hash_map< std::string, std::vector< Symbol *> >::iterator siter = symbols->begin();
00136     int total_syms = 0;
00137     while (siter != symbols->end()) {
00138         print_symbols(siter->second);
00139         total_syms += siter->second.size();
00140         siter++;
00141     }
00142     printf("%d total symbol(s)\n", total_syms);
00143 }
00144 //#endif
00145 
00146 
00147 const char *Dyninst::SymtabAPI::supportedLanguages2Str(supportedLanguages s)
00148 {
00149    switch(s) {
00150       CASE_RETURN_STR(lang_Unknown);
00151       CASE_RETURN_STR(lang_Assembly);
00152       CASE_RETURN_STR(lang_C);
00153       CASE_RETURN_STR(lang_CPlusPlus);
00154       CASE_RETURN_STR(lang_GnuCPlusPlus);
00155       CASE_RETURN_STR(lang_Fortran);
00156       CASE_RETURN_STR(lang_Fortran_with_pretty_debug);
00157       CASE_RETURN_STR(lang_CMFortran);
00158    };
00159    return "bad_language";
00160 }
00161 
00162 
00163 bool Dyninst::SymtabAPI::symbol_compare(const Symbol *s1, const Symbol *s2) 
00164 {
00165     // select the symbol with the lowest address
00166     Offset s1_addr = s1->getOffset();
00167     Offset s2_addr = s2->getOffset();
00168     if (s1_addr > s2_addr)
00169         return false;
00170     if (s1_addr < s2_addr)
00171         return true;
00172 
00173     // symbols are co-located at the same address
00174     // select the symbol which is not a function
00175     if ((s1->getType() != Symbol::ST_FUNCTION) && (s2->getType() == Symbol::ST_FUNCTION))
00176         return true;
00177     if ((s2->getType() != Symbol::ST_FUNCTION) && (s1->getType() == Symbol::ST_FUNCTION))
00178         return false;
00179     
00180     // symbols are both functions
00181     // select the symbol which has GLOBAL linkage
00182     if ((s1->getLinkage() == Symbol::SL_GLOBAL) && (s2->getLinkage() != Symbol::SL_GLOBAL))
00183         return true;
00184     if ((s2->getLinkage() == Symbol::SL_GLOBAL) && (s1->getLinkage() != Symbol::SL_GLOBAL))
00185         return false;
00186     
00187     // neither function is GLOBAL
00188     // select the symbol which has LOCAL linkage
00189     if ((s1->getLinkage() == Symbol::SL_LOCAL) && (s2->getLinkage() != Symbol::SL_LOCAL))
00190         return true;
00191     if ((s2->getLinkage() == Symbol::SL_LOCAL) && (s1->getLinkage() != Symbol::SL_LOCAL))
00192         return false;
00193     
00194     // both functions are WEAK
00195     
00196     // Apparently sort requires a strict weak ordering
00197     // and fails for equality. our compare
00198     // function behaviour should be as follows
00199     // f(x,y) => !f(y,x)
00200     // f(x,y),f(y,z) => f(x,z)
00201     // f(x,x) = false. 
00202     // So return which ever is first in the array. May be that would help.
00203     return (s1 < s2);
00204 }
00205 
00206 
00207 bool AObject::needs_function_binding() const 
00208 {
00209     return false;
00210 }
00211 
00212 bool AObject::get_func_binding_table(std::vector<relocationEntry> &) const 
00213 {
00214     return false;
00215 }
00216 
00217 bool AObject::get_func_binding_table_ptr(const std::vector<relocationEntry> *&) const 
00218 {
00219     return false;
00220 }
00221 
00222 bool AObject::addRelocationEntry(relocationEntry &)
00223 {
00224     return true;
00225 }
00226 
00227 char *AObject::mem_image() const
00228 {
00229     return NULL;
00230 }
00231 
00232 SYMTAB_EXPORT ExceptionBlock::~ExceptionBlock() 
00233 {
00234 }
00235 
00236 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock() : tryStart_(0), trySize_(0), 
00237                                 catchStart_(0), hasTry_(false) 
00238 {
00239 }
00240 
00241 SYMTAB_EXPORT Offset ExceptionBlock::catchStart() const 
00242 {
00243     return catchStart_;
00244 }
00245 
00246 #ifdef DEBUG 
00247 ostream &operator<<(ostream &os, relocationEntry &q) {
00248    return q.operator<<(os);
00249 }
00250 #endif
00251 
00252 /**************************************************
00253  *
00254  *  Stream based debuggering output - for regreesion testing.
00255  *  Dump info on state of object *this....
00256  *
00257  **************************************************/
00258 
00259 SYMTAB_EXPORT unsigned AObject::nsymbols () const 
00260 { 
00261     unsigned n = 0;
00262     for (dyn_hash_map<std::string, std::vector<Symbol *> >::const_iterator i = symbols_.begin();
00263          i != symbols_.end(); 
00264          i++) {
00265         n += i->second.size();
00266     }
00267     return n;
00268 }
00269 
00270 SYMTAB_EXPORT bool AObject::get_symbols(string & name, 
00271       std::vector<Symbol *> &symbols ) 
00272 {
00273    if ( symbols_.find(name) == symbols_.end()) {
00274       return false;
00275    }
00276 
00277    symbols = symbols_[name];
00278    return true;
00279 }
00280 
00281 SYMTAB_EXPORT char* AObject::code_ptr () const 
00282 { 
00283    return code_ptr_; 
00284 }
00285 
00286 SYMTAB_EXPORT Offset AObject::code_off () const 
00287 { 
00288    return code_off_; 
00289 }
00290 
00291 SYMTAB_EXPORT Offset AObject::code_len () const 
00292 { 
00293    return code_len_; 
00294 }
00295 
00296 SYMTAB_EXPORT char* AObject::data_ptr () const 
00297 { 
00298    return data_ptr_; 
00299 }
00300 
00301 SYMTAB_EXPORT Offset AObject::data_off () const 
00302 { 
00303    return data_off_; 
00304 }
00305 
00306 SYMTAB_EXPORT Offset AObject::data_len () const 
00307 { 
00308    return data_len_; 
00309 }
00310 
00311 SYMTAB_EXPORT bool AObject::is_aout() const 
00312 {
00313    return is_aout_;  
00314 }
00315 
00316 SYMTAB_EXPORT bool AObject::isDynamic() const 
00317 {
00318    return is_dynamic_;  
00319 }
00320 
00321 SYMTAB_EXPORT unsigned AObject::no_of_sections() const 
00322 { 
00323    return no_of_sections_; 
00324 }
00325 
00326 SYMTAB_EXPORT unsigned AObject::no_of_symbols() const 
00327 { 
00328    return no_of_symbols_;  
00329 }
00330 
00331 SYMTAB_EXPORT bool AObject::getAllExceptions(std::vector<ExceptionBlock *>&excpBlocks) const
00332 {
00333    for (unsigned i=0;i<catch_addrs_.size();i++)
00334       excpBlocks.push_back(new ExceptionBlock(catch_addrs_[i]));
00335 
00336    return true;
00337 }
00338 
00339 SYMTAB_EXPORT std::vector<Region *> AObject::getAllRegions() const
00340 {
00341    return regions_; 
00342 }
00343 
00344 SYMTAB_EXPORT Offset AObject::loader_off() const 
00345 { 
00346    return loader_off_; 
00347 }
00348 
00349 SYMTAB_EXPORT unsigned AObject::loader_len() const 
00350 { 
00351    return loader_len_; 
00352 }
00353 
00354 
00355 SYMTAB_EXPORT int AObject::getAddressWidth() const 
00356 { 
00357    return addressWidth_nbytes; 
00358 }
00359 
00360 SYMTAB_EXPORT bool AObject::have_deferred_parsing(void) const
00361 { 
00362    return deferredParse;
00363 }
00364 
00365 SYMTAB_EXPORT void * AObject::getErrFunc() const 
00366 {
00367    return (void *) err_func_; 
00368 }
00369 
00370 SYMTAB_EXPORT dyn_hash_map< string, std::vector< Symbol *> > *AObject::getAllSymbols() 
00371 { 
00372    return &(symbols_);
00373 }
00374 
00375 SYMTAB_EXPORT AObject::~AObject() 
00376 {
00377     using std::string;
00378     using std::vector;
00379 
00380     dyn_hash_map<string,vector<Symbol *> >::iterator it = symbols_.begin();
00381     for( ; it != symbols_.end(); ++it) {
00382         vector<Symbol *> & v = (*it).second;
00383         for(unsigned i=0;i<v.size();++i)
00384             delete v[i];
00385         v.clear();
00386     }
00387 }
00388 
00389 // explicitly protected
00390 SYMTAB_EXPORT AObject::AObject(MappedFile *mf_, void (*err_func)(const char *)) 
00391 : mf(mf_), code_ptr_(0), code_off_(0),
00392    code_len_(0), data_ptr_(0), data_off_(0), data_len_(0),loader_off_(0),
00393   loader_len_(0), is_dynamic_(false), has_error(false), is_static_binary_(false), deferredParse(false), err_func_(err_func),
00394    addressWidth_nbytes(4) 
00395 {
00396 }
00397 
00398 SYMTAB_EXPORT AObject::AObject(const AObject &obj)
00399 : mf(obj.mf), symbols_(obj.symbols_), 
00400    code_ptr_(obj.code_ptr_), code_off_(obj.code_off_), 
00401    code_len_(obj.code_len_), data_ptr_(obj.data_ptr_), 
00402    data_off_(obj.data_off_), data_len_(obj.data_len_), 
00403    loader_off_(obj.loader_off_), loader_len_(obj.loader_len_), is_dynamic_(obj.is_dynamic_),
00404    has_error(obj.has_error), is_static_binary_(obj.is_static_binary_), 
00405    deferredParse(false), err_func_(obj.err_func_), addressWidth_nbytes(4)
00406 {
00407 } 
00408 
00409 //  a helper routine that selects a language based on information from the symtab
00410 supportedLanguages AObject::pickLanguage(string &working_module, char *working_options,
00411       supportedLanguages working_lang)
00412 {
00413    supportedLanguages lang = lang_Unknown;
00414    static int sticky_fortran_modifier_flag = 0;
00415    // (2) -- check suffixes -- try to keep most common suffixes near the top of the checklist
00416    string::size_type len = working_module.length();
00417    if((len>2) && (working_module.substr(len-2,2) == string(".c"))) lang = lang_C;
00418    else if ((len>2) && (working_module.substr(len-2,2) == string(".C"))) lang = lang_CPlusPlus;
00419    else if ((len>4) && (working_module.substr(len-4,4) == string(".cpp"))) lang = lang_CPlusPlus;
00420    else if ((len>2) && (working_module.substr(len-2,2) == string(".F"))) lang = lang_Fortran;
00421    else if ((len>2) && (working_module.substr(len-2,2) == string(".f"))) lang = lang_Fortran;
00422    else if ((len>3) && (working_module.substr(len-3,3) == string(".cc"))) lang = lang_C;
00423    else if ((len>2) && (working_module.substr(len-2,2) == string(".a"))) lang = lang_Assembly; // is this right?
00424    else if ((len>2) && (working_module.substr(len-2,2) == string(".S"))) lang = lang_Assembly;
00425    else if ((len>2) && (working_module.substr(len-2,2) == string(".s"))) lang = lang_Assembly;
00426    else
00427    {
00428       //(3) -- try to use options string -- if we have 'em
00429       if (working_options)
00430       {
00431          //  NOTE:  a binary is labeled "gcc2_compiled" even if compiled w/g77 -- thus this is
00432          //  quite inaccurate to make such assumptions
00433          if (strstr(working_options, "gcc"))
00434             lang = lang_C;
00435          else if (strstr(working_options, "g++"))
00436             lang = lang_CPlusPlus;
00437       }
00438    }
00439    //  This next section tries to determine the version of the debug info generator for a
00440    //  Sun fortran compiler.  Some leave the underscores on names in the debug info, and some
00441    //  have the "pretty" names, we need to detect this in order to properly read the debug.
00442    if (working_lang == lang_Fortran)
00443    {
00444       if (sticky_fortran_modifier_flag)
00445       {
00446          //cerr << FILE__ << __LINE__ << ": UPDATE: lang_Fortran->lang_Fortran_with_pretty_debug." << endl;
00447          working_lang = lang_Fortran_with_pretty_debug;
00448       }
00449       else if (working_options)
00450       {
00451          char *dbg_gen = NULL;
00452          //cerr << FILE__ << __LINE__ << ":  OPT: " << working_options << endl;         
00453          if (NULL != (dbg_gen = strstr(working_options, "DBG_GEN=")))
00454          {
00455             //cerr << __FILE__ << __LINE__ << ":  OPT: " << dbg_gen << endl;
00456             // Sun fortran compiler (probably), need to examine version
00457             char *dbg_gen_ver_maj = dbg_gen + strlen("DBG_GEN=");
00458             //cerr << __FILE__ << __LINE__ << ":  OPT: " << dbg_gen_ver_maj << endl;
00459             char *next_dot = strchr(dbg_gen_ver_maj, '.');
00460             if (NULL != next_dot)
00461             {
00462                next_dot = '\0';  //terminate major version number string
00463                int ver_maj = atoi(dbg_gen_ver_maj);
00464                //cerr <<"Major Debug Ver. "<<ver_maj<< endl;
00465                if (ver_maj < 3)
00466                {
00467                   working_lang = lang_Fortran_with_pretty_debug;
00468                   sticky_fortran_modifier_flag = 1;
00469                   //cerr << __FILE__ << __LINE__ << ": UPDATE: lang_Fortran->lang_Fortran_with_pretty_debug.  " << "Major Debug Ver. "<<ver_maj<<endl;
00470                }
00471             }
00472          }
00473       }
00474    }
00475    return lang;
00476 }
00477 
00478 SymbolIter::SymbolIter( Object & obj ) 
00479 : symbols(obj.getAllSymbols()), currentPositionInVector(0) 
00480 {
00481    symbolIterator = obj.getAllSymbols()->begin();
00482 }
00483 
00484 SymbolIter::SymbolIter( const SymbolIter & src ) 
00485 : symbols(src.symbols),currentPositionInVector(0),
00486    symbolIterator( src.symbolIterator ) 
00487 {
00488 }
00489 
00490 SymbolIter::~SymbolIter () 
00491 {
00492 }
00493 
00494 
00495 void SymbolIter::reset () 
00496 {
00497    currentPositionInVector = 0;
00498    symbolIterator = symbols->begin();
00499 }
00500 
00501 SymbolIter::operator bool() const
00502 {
00503    return (symbolIterator!=symbols->end());
00504 }
00505 
00506 void SymbolIter::operator++ ( int ) 
00507 {
00508    if ( currentPositionInVector + 1 < (symbolIterator->second).size())
00509    {
00510       currentPositionInVector++;
00511       return;
00512    }
00513 
00514    /* Otherwise, we need a new std::vector. */
00515    currentPositionInVector = 0;         
00516    symbolIterator++;
00517 }
00518 
00519 const string & SymbolIter::currkey() const 
00520 {
00521    return symbolIterator->first;
00522 }
00523 
00524 /* If it's important that this be const, we could try to initialize
00525    currentVector to '& symbolIterator.currval()' in the constructor. */
00526 
00527 Symbol *SymbolIter::currval() 
00528 {
00529     if (currentPositionInVector >= symbolIterator->second.size())
00530     {
00531         fprintf(stderr, "%s[%d]:  OUT OF RANGE\n", FILE__, __LINE__);
00532         return NULL;
00533     }
00534    return ((symbolIterator->second)[ currentPositionInVector ]);
00535 }
00536 
00537 const std::string AObject::findModuleForSym(Symbol *sym) {
00538     return symsToModules_[sym];
00539 }
00540 
00541 void AObject::clearSymsToMods() {
00542     symsToModules_.clear();
00543 }
00544 
00545 bool AObject::hasError() const
00546 {
00547   return has_error;
00548 }
00549 
00550 void AObject::setTruncateLinePaths(bool)
00551 {
00552 }
00553 
00554 bool AObject::getTruncateLinePaths()
00555 {
00556    return false;
00557 }
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1