Compile fix after removing deprecated SymtabAPI methods.
[dyninst.git] / symtabAPI / src / Object.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 // $Id: Object.C,v 1.31 2008/11/03 15:19:25 jaw Exp $
32
33 #include "symutil.h"
34 #include "Annotatable.h"
35 #include "common/h/serialize.h"
36
37 #include "Symtab.h"
38 #include "Module.h"
39 #include "Region.h"
40 #include "Collections.h"
41 #include "annotations.h"
42 #include "Symbol.h"
43
44 #include "Aggregate.h"
45 #include "Function.h"
46 #include "Variable.h"
47
48 #include "symtabAPI/src/Object.h"
49
50 #include <iostream>
51
52 using namespace std;
53 using namespace Dyninst;
54 using namespace Dyninst::SymtabAPI;
55
56 string Symbol::emptyString("");
57
58
59 //#ifdef BINEDIT_DEBUG
60 bool ____sym_hdr_printed = false;
61 void print_symbols( std::vector< Symbol *>& allsymbols ) {
62     FILE* fd = stdout;
63     Symbol *sym;
64     std::string modname;
65     if (!____sym_hdr_printed) {
66         fprintf(fd, "%-20s  %-15s  %-10s  %5s  SEC  TYP  LN  VIS  INFO\n", 
67                 "SYMBOL", "MODULE", "ADDR", "SIZE");
68         ____sym_hdr_printed = true;
69     }
70     for (unsigned i=0; i<allsymbols.size(); i++) {
71         sym = allsymbols[i];
72         modname = (sym->getModule() ? sym->getModule()->fileName() : "");
73         //if (sym->getName() == "__gmon_start__") {
74         //if (modname == "libspecial.so" || modname == "libprofile.so") {
75         //if (sym->getLinkage() == Symbol::SL_WEAK) {
76         //if (sym->isInDynSymtab()) {
77         if (1) {
78             fprintf(fd, "%-20s  %-15s  0x%08x  %5u  %3u", 
79                     sym->getMangledName().substr(0,20).c_str(), 
80                 //modname.size() > 15 ? modname.substr(modname.size()-15,15).c_str() : modname.c_str(),
81                 "",
82                 (unsigned)sym->getOffset(),
83                 (unsigned)sym->getSize(),
84                     sym->getRegion() ? sym->getRegion()->getRegionNumber() : 0
85                 );
86             switch (sym->getType()) {
87                 case Symbol::ST_FUNCTION: fprintf(fd, "  FUN"); break;
88                 case Symbol::ST_TLS:      fprintf(fd, "  TLS"); break;
89                 case Symbol::ST_OBJECT:   fprintf(fd, "  OBJ"); break;
90                 case Symbol::ST_MODULE:   fprintf(fd, "  MOD"); break;
91                 case Symbol::ST_SECTION:  fprintf(fd, "  SEC"); break;
92                 case Symbol::ST_DELETED:  fprintf(fd, "  DEL"); break;
93                 case Symbol::ST_NOTYPE:   fprintf(fd, "   - "); break;
94                 default:
95                 case Symbol::ST_UNKNOWN:  fprintf(fd, "  ???"); break;                 
96             }
97             switch (sym->getLinkage()) {
98                 case Symbol::SL_UNKNOWN: fprintf(fd, "  ??"); break;
99                 case Symbol::SL_GLOBAL:  fprintf(fd, "  GL"); break;
100                 case Symbol::SL_LOCAL:   fprintf(fd, "  LO"); break;
101                 case Symbol::SL_WEAK:    fprintf(fd, "  WK"); break;
102             }
103             switch (sym->getVisibility()) {
104                 case Symbol::SV_UNKNOWN:   fprintf(fd, "  ???"); break;
105                 case Symbol::SV_DEFAULT:   fprintf(fd, "   - "); break;
106                 case Symbol::SV_INTERNAL:  fprintf(fd, "  INT"); break;
107                 case Symbol::SV_HIDDEN:    fprintf(fd, "  HID"); break;
108                 case Symbol::SV_PROTECTED: fprintf(fd, "  PRO"); break;
109             }
110             fprintf(fd, " ");
111             if (sym->isInSymtab())
112                 fprintf(fd, " STA");
113             if (sym->isInDynSymtab())
114                 fprintf(fd, " DYN");
115             if (sym->isAbsolute())
116                 fprintf(fd, " ABS");
117             std::string fileName;
118             std::vector<std::string> *vers;
119             if (sym->getVersionFileName(fileName))
120                 fprintf(fd, "  [%s]", fileName.c_str());
121             if (sym->getVersions(vers)) {
122                 fprintf(fd, " {");
123                 for (unsigned j=0; j < vers->size(); j++) {
124                     if (j > 0)
125                         fprintf(fd, ", ");
126                     fprintf(fd, "%s", (*vers)[j].c_str());
127                 }
128                 fprintf(fd, "}");
129             }
130             fprintf(fd,"\n");
131         }
132     }
133 }
134 void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols) {
135     dyn_hash_map< std::string, std::vector< Symbol *> >::iterator siter = symbols->begin();
136     int total_syms = 0;
137     while (siter != symbols->end()) {
138         print_symbols(siter->second);
139         total_syms += siter->second.size();
140         siter++;
141     }
142     printf("%d total symbol(s)\n", total_syms);
143 }
144 //#endif
145
146
147 const char *Dyninst::SymtabAPI::supportedLanguages2Str(supportedLanguages s)
148 {
149    switch(s) {
150       CASE_RETURN_STR(lang_Unknown);
151       CASE_RETURN_STR(lang_Assembly);
152       CASE_RETURN_STR(lang_C);
153       CASE_RETURN_STR(lang_CPlusPlus);
154       CASE_RETURN_STR(lang_GnuCPlusPlus);
155       CASE_RETURN_STR(lang_Fortran);
156       CASE_RETURN_STR(lang_Fortran_with_pretty_debug);
157       CASE_RETURN_STR(lang_CMFortran);
158    };
159    return "bad_language";
160 }
161
162
163 bool Dyninst::SymtabAPI::symbol_compare(const Symbol *s1, const Symbol *s2) 
164 {
165     // select the symbol with the lowest address
166     Offset s1_addr = s1->getOffset();
167     Offset s2_addr = s2->getOffset();
168     if (s1_addr > s2_addr)
169         return false;
170     if (s1_addr < s2_addr)
171         return true;
172
173     // symbols are co-located at the same address
174     // select the symbol which is not a function
175     if ((s1->getType() != Symbol::ST_FUNCTION) && (s2->getType() == Symbol::ST_FUNCTION))
176         return true;
177     if ((s2->getType() != Symbol::ST_FUNCTION) && (s1->getType() == Symbol::ST_FUNCTION))
178         return false;
179     
180     // symbols are both functions
181     // select the symbol which has GLOBAL linkage
182     if ((s1->getLinkage() == Symbol::SL_GLOBAL) && (s2->getLinkage() != Symbol::SL_GLOBAL))
183         return true;
184     if ((s2->getLinkage() == Symbol::SL_GLOBAL) && (s1->getLinkage() != Symbol::SL_GLOBAL))
185         return false;
186         
187     // neither function is GLOBAL
188     // select the symbol which has LOCAL linkage
189     if ((s1->getLinkage() == Symbol::SL_LOCAL) && (s2->getLinkage() != Symbol::SL_LOCAL))
190         return true;
191     if ((s2->getLinkage() == Symbol::SL_LOCAL) && (s1->getLinkage() != Symbol::SL_LOCAL))
192         return false;
193     
194     // both functions are WEAK
195     
196     // Apparently sort requires a strict weak ordering
197     // and fails for equality. our compare
198     // function behaviour should be as follows
199     // f(x,y) => !f(y,x)
200     // f(x,y),f(y,z) => f(x,z)
201     // f(x,x) = false. 
202     // So return which ever is first in the array. May be that would help.
203     return (s1 < s2);
204 }
205
206
207 bool AObject::needs_function_binding() const 
208 {
209     return false;
210 }
211
212 bool AObject::get_func_binding_table(std::vector<relocationEntry> &) const 
213 {
214     return false;
215 }
216
217 bool AObject::get_func_binding_table_ptr(const std::vector<relocationEntry> *&) const 
218 {
219     return false;
220 }
221
222 bool AObject::addRelocationEntry(relocationEntry &)
223 {
224     return true;
225 }
226
227 char *AObject::mem_image() const
228 {
229         return NULL;
230 }
231
232 SYMTAB_EXPORT ExceptionBlock::~ExceptionBlock() 
233 {
234 }
235
236 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock() : tryStart_(0), trySize_(0), 
237                                                                 catchStart_(0), hasTry_(false) 
238 {
239 }
240
241 SYMTAB_EXPORT Offset ExceptionBlock::catchStart() const 
242 {
243         return catchStart_;
244 }
245
246 #ifdef DEBUG 
247 ostream &operator<<(ostream &os, relocationEntry &q) {
248    return q.operator<<(os);
249 }
250 #endif
251
252 /**************************************************
253  *
254  *  Stream based debuggering output - for regreesion testing.
255  *  Dump info on state of object *this....
256  *
257  **************************************************/
258
259 SYMTAB_EXPORT unsigned AObject::nsymbols () const 
260
261     unsigned n = 0;
262     for (dyn_hash_map<std::string, std::vector<Symbol *> >::const_iterator i = symbols_.begin();
263          i != symbols_.end(); 
264          i++) {
265         n += i->second.size();
266     }
267     return n;
268 }
269
270 SYMTAB_EXPORT bool AObject::get_symbols(string & name, 
271       std::vector<Symbol *> &symbols ) 
272 {
273    if ( symbols_.find(name) == symbols_.end()) {
274       return false;
275    }
276
277    symbols = symbols_[name];
278    return true;
279 }
280
281 SYMTAB_EXPORT char* AObject::code_ptr () const 
282
283    return code_ptr_; 
284 }
285
286 SYMTAB_EXPORT Offset AObject::code_off () const 
287
288    return code_off_; 
289 }
290
291 SYMTAB_EXPORT Offset AObject::code_len () const 
292
293    return code_len_; 
294 }
295
296 SYMTAB_EXPORT char* AObject::data_ptr () const 
297
298    return data_ptr_; 
299 }
300
301 SYMTAB_EXPORT Offset AObject::data_off () const 
302
303    return data_off_; 
304 }
305
306 SYMTAB_EXPORT Offset AObject::data_len () const 
307
308    return data_len_; 
309 }
310
311 SYMTAB_EXPORT bool AObject::is_aout() const 
312 {
313    return is_aout_;  
314 }
315
316 SYMTAB_EXPORT bool AObject::isDynamic() const 
317 {
318    return is_dynamic_;  
319 }
320
321 SYMTAB_EXPORT unsigned AObject::no_of_sections() const 
322
323    return no_of_sections_; 
324 }
325
326 SYMTAB_EXPORT unsigned AObject::no_of_symbols() const 
327
328    return no_of_symbols_;  
329 }
330
331 SYMTAB_EXPORT bool AObject::getAllExceptions(std::vector<ExceptionBlock *>&excpBlocks) const
332 {
333    for (unsigned i=0;i<catch_addrs_.size();i++)
334       excpBlocks.push_back(new ExceptionBlock(catch_addrs_[i]));
335
336    return true;
337 }
338
339 SYMTAB_EXPORT std::vector<Region *> AObject::getAllRegions() const
340 {
341    return regions_;     
342 }
343
344 SYMTAB_EXPORT Offset AObject::loader_off() const 
345
346    return loader_off_; 
347 }
348
349 SYMTAB_EXPORT unsigned AObject::loader_len() const 
350
351    return loader_len_; 
352 }
353
354
355 SYMTAB_EXPORT int AObject::getAddressWidth() const 
356
357    return addressWidth_nbytes; 
358 }
359
360 SYMTAB_EXPORT bool AObject::have_deferred_parsing(void) const
361
362    return deferredParse;
363 }
364
365 SYMTAB_EXPORT void * AObject::getErrFunc() const 
366 {
367    return (void *) err_func_; 
368 }
369
370 SYMTAB_EXPORT dyn_hash_map< string, std::vector< Symbol *> > *AObject::getAllSymbols() 
371
372    return &(symbols_);
373 }
374
375 SYMTAB_EXPORT AObject::~AObject() 
376 {
377     using std::string;
378     using std::vector;
379
380     dyn_hash_map<string,vector<Symbol *> >::iterator it = symbols_.begin();
381     for( ; it != symbols_.end(); ++it) {
382         vector<Symbol *> & v = (*it).second;
383         for(unsigned i=0;i<v.size();++i)
384             delete v[i];
385         v.clear();
386     }
387 }
388
389 // explicitly protected
390 SYMTAB_EXPORT AObject::AObject(MappedFile *mf_, MappedFile *mfd, void (*err_func)(const char *)) 
391 : mf(mf_), mfForDebugInfo(mfd), code_ptr_(0), code_off_(0),
392    code_len_(0), data_ptr_(0), data_off_(0), data_len_(0),loader_off_(0),
393   loader_len_(0), is_dynamic_(false), has_error(false), is_static_binary_(false), deferredParse(false), err_func_(err_func),
394    addressWidth_nbytes(4) 
395 {
396 }
397
398 SYMTAB_EXPORT AObject::AObject(const AObject &obj)
399 : mf(obj.mf), mfForDebugInfo(obj.mfForDebugInfo), symbols_(obj.symbols_), 
400    code_ptr_(obj.code_ptr_), code_off_(obj.code_off_), 
401    code_len_(obj.code_len_), data_ptr_(obj.data_ptr_), 
402    data_off_(obj.data_off_), data_len_(obj.data_len_), 
403    loader_off_(obj.loader_off_), loader_len_(obj.loader_len_), is_dynamic_(obj.is_dynamic_),
404    has_error(obj.has_error), is_static_binary_(obj.is_static_binary_), 
405    deferredParse(false), err_func_(obj.err_func_), addressWidth_nbytes(4)
406 {
407
408
409 //  a helper routine that selects a language based on information from the symtab
410 supportedLanguages AObject::pickLanguage(string &working_module, char *working_options,
411       supportedLanguages working_lang)
412 {
413    supportedLanguages lang = lang_Unknown;
414    static int sticky_fortran_modifier_flag = 0;
415    // (2) -- check suffixes -- try to keep most common suffixes near the top of the checklist
416    string::size_type len = working_module.length();
417    if((len>2) && (working_module.substr(len-2,2) == string(".c"))) lang = lang_C;
418    else if ((len>2) && (working_module.substr(len-2,2) == string(".C"))) lang = lang_CPlusPlus;
419    else if ((len>4) && (working_module.substr(len-4,4) == string(".cpp"))) lang = lang_CPlusPlus;
420    else if ((len>2) && (working_module.substr(len-2,2) == string(".F"))) lang = lang_Fortran;
421    else if ((len>2) && (working_module.substr(len-2,2) == string(".f"))) lang = lang_Fortran;
422    else if ((len>3) && (working_module.substr(len-3,3) == string(".cc"))) lang = lang_C;
423    else if ((len>2) && (working_module.substr(len-2,2) == string(".a"))) lang = lang_Assembly; // is this right?
424    else if ((len>2) && (working_module.substr(len-2,2) == string(".S"))) lang = lang_Assembly;
425    else if ((len>2) && (working_module.substr(len-2,2) == string(".s"))) lang = lang_Assembly;
426    else
427    {
428       //(3) -- try to use options string -- if we have 'em
429       if (working_options)
430       {
431          //  NOTE:  a binary is labeled "gcc2_compiled" even if compiled w/g77 -- thus this is
432          //  quite inaccurate to make such assumptions
433          if (strstr(working_options, "gcc"))
434             lang = lang_C;
435          else if (strstr(working_options, "g++"))
436             lang = lang_CPlusPlus;
437       }
438    }
439    //  This next section tries to determine the version of the debug info generator for a
440    //  Sun fortran compiler.  Some leave the underscores on names in the debug info, and some
441    //  have the "pretty" names, we need to detect this in order to properly read the debug.
442    if (working_lang == lang_Fortran)
443    {
444       if (sticky_fortran_modifier_flag)
445       {
446          //cerr << FILE__ << __LINE__ << ": UPDATE: lang_Fortran->lang_Fortran_with_pretty_debug." << endl;
447          working_lang = lang_Fortran_with_pretty_debug;
448       }
449       else if (working_options)
450       {
451          char *dbg_gen = NULL;
452          //cerr << FILE__ << __LINE__ << ":  OPT: " << working_options << endl;                 
453          if (NULL != (dbg_gen = strstr(working_options, "DBG_GEN=")))
454          {
455             //cerr << __FILE__ << __LINE__ << ":  OPT: " << dbg_gen << endl;
456             // Sun fortran compiler (probably), need to examine version
457             char *dbg_gen_ver_maj = dbg_gen + strlen("DBG_GEN=");
458             //cerr << __FILE__ << __LINE__ << ":  OPT: " << dbg_gen_ver_maj << endl;
459             char *next_dot = strchr(dbg_gen_ver_maj, '.');
460             if (NULL != next_dot)
461             {
462                next_dot = '\0';  //terminate major version number string
463                int ver_maj = atoi(dbg_gen_ver_maj);
464                //cerr <<"Major Debug Ver. "<<ver_maj<< endl;
465                if (ver_maj < 3)
466                {
467                   working_lang = lang_Fortran_with_pretty_debug;
468                   sticky_fortran_modifier_flag = 1;
469                   //cerr << __FILE__ << __LINE__ << ": UPDATE: lang_Fortran->lang_Fortran_with_pretty_debug.  " << "Major Debug Ver. "<<ver_maj<<endl;
470                }
471             }
472          }
473       }
474    }
475    return lang;
476 }
477
478 SymbolIter::SymbolIter( Object & obj ) 
479 : symbols(obj.getAllSymbols()), currentPositionInVector(0) 
480 {
481    symbolIterator = obj.getAllSymbols()->begin();
482 }
483
484 SymbolIter::SymbolIter( const SymbolIter & src ) 
485 : symbols(src.symbols),currentPositionInVector(0),
486    symbolIterator( src.symbolIterator ) 
487 {
488 }
489
490 SymbolIter::~SymbolIter () 
491 {
492 }
493
494
495 void SymbolIter::reset () 
496 {
497    currentPositionInVector = 0;
498    symbolIterator = symbols->begin();
499 }
500
501 SymbolIter::operator bool() const
502 {
503    return (symbolIterator!=symbols->end());
504 }
505
506 void SymbolIter::operator++ ( int ) 
507 {
508    if ( currentPositionInVector + 1 < (symbolIterator->second).size())
509    {
510       currentPositionInVector++;
511       return;
512    }
513
514    /* Otherwise, we need a new std::vector. */
515    currentPositionInVector = 0;                 
516    symbolIterator++;
517 }
518
519 const string & SymbolIter::currkey() const 
520 {
521    return symbolIterator->first;
522 }
523
524 /* If it's important that this be const, we could try to initialize
525    currentVector to '& symbolIterator.currval()' in the constructor. */
526
527 Symbol *SymbolIter::currval() 
528 {
529         if (currentPositionInVector >= symbolIterator->second.size())
530         {
531                 fprintf(stderr, "%s[%d]:  OUT OF RANGE\n", FILE__, __LINE__);
532                 return NULL;
533         }
534    return ((symbolIterator->second)[ currentPositionInVector ]);
535 }
536
537 const std::string AObject::findModuleForSym(Symbol *sym) {
538     return symsToModules_[sym];
539 }
540
541 void AObject::clearSymsToMods() {
542     symsToModules_.clear();
543 }
544
545 bool AObject::hasError() const
546 {
547   return has_error;
548 }
549
550 void AObject::setTruncateLinePaths(bool)
551 {
552 }
553
554 bool AObject::getTruncateLinePaths()
555 {
556    return false;
557 }