Merge branch 'master' of legendre@git.dyninst.org:/pub/dyninst
[dyninst.git] / symtabAPI / src / Symbol.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include "symutil.h"
33 #include "Symbol.h"
34 #include "Module.h"
35 #include "Symtab.h"
36 #include "Aggregate.h"
37 #include "Function.h"
38 #include "Variable.h"
39 #include <string>
40 #include "annotations.h"
41
42 #include <iostream>
43
44
45 using namespace Dyninst;
46 using namespace SymtabAPI;
47
48 bool addSymID(SerializerBase *sb, Symbol *sym, Address id)
49 {
50         assert(id);
51         assert(sym);
52         assert(sb);
53
54         SerContextBase *scb = sb->getContext();
55         if (!scb)
56         {
57                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
58                 return false;
59         }
60
61         SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
62
63         if (!scs)
64         {
65                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
66                 return false;
67         }
68
69         Symtab *st = scs->getScope();
70
71         if (!st)
72         {
73                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
74                 return false;
75         }
76
77         dyn_hash_map<Address, Symbol *> *smap = NULL;
78
79         if (!st->getAnnotation(smap, IdToSymAnno))
80         {
81                 smap = new dyn_hash_map<Address, Symbol *>();
82
83                 if (!st->addAnnotation(smap, IdToSymAnno))
84                 {
85                         fprintf(stderr, "%s[%d]:  ERROR:  failed to add IdToSymMap anno to Symtab\n", 
86                                         FILE__, __LINE__);
87                         return false;
88                 }
89         }
90
91         assert(smap);
92
93         if (serializer_debug_flag())
94         {
95                 dyn_hash_map<Address, Symbol *>::iterator iter = smap->find(id);
96                 if (iter != smap->end())
97                 {
98                         fprintf(stderr, "%s[%d]:  WARNING:  already have mapping for IdToSym\n", 
99                                         FILE__, __LINE__);
100                 }
101         }
102
103         (*smap)[id] = sym;
104         return true;
105 }
106
107 Symbol * getSymForID(SerializerBase *sb, Address id)
108 {
109         assert(id);
110         assert(sb);
111
112         SerContextBase *scb = sb->getContext();
113         if (!scb)
114         {
115                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
116                 return NULL;
117         }
118
119         SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
120
121         if (!scs)
122         {
123                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
124                 return NULL;
125         }
126
127         Symtab *st = scs->getScope();
128
129         if (!st)
130         {
131                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
132                 return NULL;
133         }
134
135         dyn_hash_map<Address, Symbol *> *smap = NULL;
136         if (!st->getAnnotation(smap, IdToSymAnno))
137         {
138                 fprintf(stderr, "%s[%d]:  ERROR:  failed to find IdToSymMap anno on Symtab\n", 
139                                 FILE__, __LINE__);
140                 return NULL;
141         }
142         assert(smap);
143         dyn_hash_map<Address, Symbol *>::iterator iter = smap->find(id);
144         if (iter == smap->end())
145         {
146                 fprintf(stderr, "%s[%d]:  ERROR:  failed to find id %p in IdToSymMap\n", 
147                                 FILE__, __LINE__, (void *)id);
148                 return NULL;
149         }
150         return iter->second;
151 }
152
153 Symbol *Symbol::magicEmitElfSymbol() {
154         // I have no idea why this is the way it is,
155         // but emitElf needs it...
156         return new Symbol("",
157                         ST_NOTYPE,
158                       SL_LOCAL,
159                       SV_DEFAULT,
160                       0,
161                       NULL,
162                       NULL,
163                       0,
164                       false,
165                       false);
166 }
167     
168 SYMTAB_EXPORT const string& Symbol::getMangledName() const 
169 {
170     return mangledName_;
171 }
172
173 SYMTAB_EXPORT const string& Symbol::getPrettyName() const 
174 {
175     return prettyName_;
176 }
177
178 SYMTAB_EXPORT const string& Symbol::getTypedName() const 
179 {
180     return typedName_;
181 }
182
183 SYMTAB_EXPORT const string& Symbol::getModuleName() const 
184 {
185     if (module_)
186         return module_->fullName();
187     else
188         return emptyString;
189 }
190
191 bool Symbol::setOffset(Offset newOffset)
192 {
193     offset_ = newOffset;
194     return true;
195 }
196
197 bool Symbol::setPtrOffset(Offset newOffset)
198 {
199     ptr_offset_ = newOffset;
200     return true;
201 }
202
203 SYMTAB_EXPORT bool Symbol::setModule(Module *mod) 
204 {
205     module_ = mod; 
206     return true;
207 }
208
209 SYMTAB_EXPORT bool Symbol::isFunction() const
210 {
211     return (getFunction() != NULL);
212 }
213
214 SYMTAB_EXPORT bool Symbol::setFunction(Function *func)
215 {
216     aggregate_ = func;
217     return true;
218 }
219
220 SYMTAB_EXPORT Function * Symbol::getFunction() const
221 {
222         if (aggregate_ == NULL) 
223                 return NULL;
224     return dynamic_cast<Function *>(aggregate_);
225 }
226
227 SYMTAB_EXPORT bool Symbol::isVariable() const 
228 {
229     return (getVariable() != NULL);
230 }
231
232 SYMTAB_EXPORT bool Symbol::setVariable(Variable *var) 
233 {
234     aggregate_ = var;
235     return true;
236 }
237
238 SYMTAB_EXPORT Variable * Symbol::getVariable() const
239 {
240     return dynamic_cast<Variable *>(aggregate_);
241 }
242
243 SYMTAB_EXPORT bool      Symbol::setSize(unsigned ns)
244 {
245         size_ = ns;
246         return true;
247 }
248
249 SYMTAB_EXPORT Symbol::SymbolTag Symbol::tag() const 
250 {
251     return tag_;
252 }
253
254
255 SYMTAB_EXPORT bool Symbol::setSymbolType(SymbolType sType)
256 {
257     if ((sType != ST_UNKNOWN)&&
258         (sType != ST_FUNCTION)&&
259         (sType != ST_OBJECT)&&
260         (sType != ST_MODULE)&&
261         (sType != ST_NOTYPE))
262         return false;
263     
264     SymbolType oldType = type_; 
265     type_ = sType;
266     if (module_ && module_->exec())
267         module_->exec()->changeType(this, oldType);
268
269     // TODO: update aggregate with information
270     
271     return true;
272 }
273
274 SYMTAB_EXPORT bool Symbol::setVersionFileName(std::string &fileName)
275 {
276    std::string *fn_p = NULL;
277    if (getAnnotation(fn_p, SymbolFileNameAnno)) 
278    {
279       if (!fn_p) 
280       {
281          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
282       }
283       else
284       {
285          fprintf(stderr, "%s[%d]:  WARNING, already have filename set for symbol %s\n", 
286                  FILE__, __LINE__, getMangledName().c_str());
287       }
288       return false;
289    }
290    else
291    {
292       //  not sure if we need to copy here or not, so let's do it...
293       std::string *fn = new std::string(fileName);
294       if (!addAnnotation(fn, SymbolFileNameAnno)) 
295       {
296          fprintf(stderr, "%s[%d]:  failed to add anno here\n", FILE__, __LINE__);
297          return false;
298       }
299       return true;
300    }
301
302    return false;
303 }
304
305 SYMTAB_EXPORT bool Symbol::setVersions(std::vector<std::string> &vers)
306 {
307    std::vector<std::string> *vn_p = NULL;
308    if (getAnnotation(vn_p, SymbolVersionNamesAnno)) 
309    {
310       if (!vn_p) 
311       {
312          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
313       }
314       else
315          fprintf(stderr, "%s[%d]:  WARNING, already have versions set for symbol %s\n", FILE__, __LINE__, getMangledName().c_str());
316       return false;
317    }
318    else
319    {
320       if (!addAnnotation(&vers, SymbolVersionNamesAnno)) 
321       {
322          fprintf(stderr, "%s[%d]:  failed to add anno here\n", FILE__, __LINE__);
323       }
324    }
325
326    return true;
327 }
328
329 SYMTAB_EXPORT bool Symbol::getVersionFileName(std::string &fileName)
330 {
331    std::string *fn_p = NULL;
332
333    if (getAnnotation(fn_p, SymbolFileNameAnno)) 
334    {
335       if (!fn_p) 
336       {
337          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
338       }
339       else
340          fileName = *fn_p;
341
342       return true;
343    }
344
345    return false;
346 }
347
348 SYMTAB_EXPORT bool Symbol::getVersions(std::vector<std::string> *&vers)
349 {
350    std::vector<std::string> *vn_p = NULL;
351
352    if (getAnnotation(vn_p, SymbolVersionNamesAnno)) 
353    {
354       if (!vn_p) 
355       {
356          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
357       }
358       else
359       {
360          vers = vn_p;
361          return true;
362       } 
363    }
364
365    return false;
366 }
367
368 Serializable *Symbol::serialize_impl(SerializerBase *s, const char *tag) THROW_SPEC (SerializerError)
369 {
370         //  Need to serialize regions before symbols
371         //  Use disk offset as unique identifier
372         Address symid = (Address) this;
373         Region *r = region_;
374         Offset r_off = r ? r->getDiskOffset() : (Offset) 0;
375         std::string modname = "";
376         if (!module_) {
377                 //fprintf(stderr, "%s[%d]:  WARN:  NULL module\n", FILE__, __LINE__);
378    }
379         else
380             modname = module_->fullName();
381
382                 ifxml_start_element(s, tag);
383                 gtranslate(s, type_, symbolType2Str, "type");
384                 gtranslate(s, linkage_, symbolLinkage2Str, "linkage");
385                 gtranslate(s, tag_, symbolTag2Str, "tag");
386                 gtranslate(s, visibility_, symbolVisibility2Str, "visibility");
387                 gtranslate(s, offset_, "offset");
388                 gtranslate(s, size_, "size");
389                 gtranslate(s, index_, "index");
390                 gtranslate(s, isDynamic_, "isDynamic");
391                 gtranslate(s, isAbsolute_, "isAbsolute");
392                 gtranslate(s, isCommonStorage_, "isCommonStorage");
393                 gtranslate(s, prettyName_, "prettyName");
394                 gtranslate(s, mangledName_, "mangledName");
395                 gtranslate(s, typedName_, "typedName");
396                 gtranslate(s, r_off, "regionDiskOffset");
397                 gtranslate(s, modname, "moduleName");
398                 gtranslate(s, symid, "symbolID");
399                 ifxml_end_element(s, "Symbol");
400
401                 //  Now, if we are doing binary deserialization, lookup type and region by unique ids
402                 if (s->isBin() && s->isInput())
403                 {
404                         restore_module_and_region(s, modname, r_off);
405                         addSymID(s, this, symid);
406                         //serialize_printf("%s[%d]:  added sym ID mapping: %p--%p\n", FILE__, __LINE__, this, symid);
407                 }
408
409                 return NULL;
410 }
411
412 void Symbol::restore_module_and_region(SerializerBase *s, std::string &modname, Offset r_off) THROW_SPEC (SerializerError)
413 {
414 #if 0
415         ScopedSerializerBase<Symtab> *ssb = dynamic_cast<ScopedSerializerBase<Symtab> *>(s);
416
417         if (!ssb)
418         {
419                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
420                 SER_ERR("FIXME");
421         }
422
423         Symtab *st = ssb->getScope();
424 #endif
425         SerContextBase *scb = s->getContext();
426         if (!scb)
427         {
428                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
429                 SER_ERR("FIXME");
430         }
431
432         SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
433
434         if (!scs)
435         {
436                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
437                 SER_ERR("FIXME");
438         }
439
440         Symtab *st = scs->getScope();
441
442         if (!st)
443         {
444                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
445                 SER_ERR("FIXME");
446         }
447
448         module_ = NULL;
449
450         if (modname.length())
451         {
452                 //  All symbols should have an associated module
453                 if (!st->findModuleByName(module_, modname) || !module_)
454                 {
455                         //  This should throw...  but not quite ready for that yet
456                         fprintf(stderr, "%s[%d]:  WARNING:  No module '%s' for symbol\n", 
457                                         FILE__, __LINE__, modname.c_str());
458                 }
459         }
460
461         region_ = NULL;
462
463         //  All symbols should have an associated region 
464         if (!st->findRegionByEntry(region_, r_off) || !region_)
465         {
466                 //  This should throw...  but not quite ready for that yet
467                 fprintf(stderr, "%s[%d]:  WARNING:  No region for symbol\n", 
468                                 FILE__, __LINE__);
469         }
470
471 }
472
473 std::ostream& Dyninst::SymtabAPI::operator<< (ostream &os, const Symbol &s) 
474 {
475         return os << "{"
476                 << " mangled=" << s.getMangledName()
477                 << " pretty="  << s.getPrettyName()
478               << " module="  << s.module_
479         //<< " type="    << (unsigned) s.type_
480               << " type="    << s.symbolType2Str(s.type_)
481         //<< " linkage=" << (unsigned) s.linkage_
482               << " linkage=" << s.symbolLinkage2Str(s.linkage_)
483               << " offset=0x"    << hex << s.offset_ << dec
484               << " ptr_offset=0x"    << hex << s.ptr_offset_ << dec
485         //<< " tag="     << (unsigned) s.tag_
486               << " tag="     << s.symbolTag2Str(s.tag_)
487               << " isAbs="   << s.isAbsolute_
488               << " isCommon=" << s.isCommonStorage_
489               << (s.isFunction() ? " [FUNC]" : "")
490               << (s.isVariable() ? " [VAR]" : "")
491               << (s.isInSymtab() ? "[STA]" : "[DYN]")
492               << " }" << endl;
493 }
494
495      Offset tryStart_;
496                unsigned trySize_;
497                          Offset catchStart_;
498                                        bool hasTry_;
499
500 ostream & Dyninst::SymtabAPI::operator<< (ostream &s, const ExceptionBlock &eb) 
501 {
502         s << "tryStart=" << eb.tryStart_ 
503                 << "trySize=" << eb.trySize_ 
504                 << "catchStart=" << eb.catchStart_ 
505                 << "hasTry=" << eb.trySize_ ;
506         return s; 
507 }
508
509 bool Symbol::operator==(const Symbol& s) const
510 {
511         // explicitly ignore tags when comparing symbols
512
513         //  compare sections by offset, not pointer
514         if (!region_ && s.region_) return false;
515         if (region_ && !s.region_) return false;
516         if (region_)
517         {
518                 if (region_->getDiskOffset() != s.region_->getDiskOffset())
519                         return false;
520         }
521
522         // compare modules by name, not pointer
523         if (!module_ && s.module_) return false;
524         if (module_ && !s.module_) return false;
525         if (module_)
526         {
527                 if (module_->fullName() != s.module_->fullName())
528                         return false;
529         }
530
531         return (   (type_    == s.type_)
532                         && (linkage_ == s.linkage_)
533                         && (offset_    == s.offset_)
534                         && (size_    == s.size_)
535                         && (isDynamic_ == s.isDynamic_)
536                         && (isAbsolute_ == s.isAbsolute_)
537                         && (isCommonStorage_ == s.isCommonStorage_)
538                         && (mangledName_ == s.mangledName_)
539                         && (prettyName_ == s.prettyName_)
540                         && (typedName_ == s.typedName_));
541 }
542
543 Symtab *Symbol::getSymtab() const { 
544    return module_->exec(); 
545 }
546
547 Symbol::Symbol () :
548   module_(NULL),
549   type_(ST_NOTYPE),
550   internal_type_(0),
551   linkage_(SL_UNKNOWN),
552   visibility_(SV_UNKNOWN),
553   offset_(0),
554   ptr_offset_(0),
555   region_(NULL),
556   referring_(NULL),
557   size_(0),
558   isDynamic_(false),
559   isAbsolute_(false),
560   aggregate_(NULL),
561   mangledName_(Symbol::emptyString),
562   prettyName_(Symbol::emptyString),
563   typedName_(Symbol::emptyString),
564   tag_(TAG_UNKNOWN) ,
565   index_(-1),
566   strindex_(-1),
567   isCommonStorage_(false)
568 {
569 }
570
571 Symbol::Symbol(const std::string name,
572                SymbolType t,
573                SymbolLinkage l,
574                SymbolVisibility v,
575                Offset o,
576                Module *module,
577                Region *r,
578                unsigned s,
579                bool d,
580                bool a,
581                int index,
582                int strindex,
583                bool cs):
584   module_(module),
585   type_(t),
586   internal_type_(0),
587   linkage_(l),
588   visibility_(v),
589   offset_(o),
590   ptr_offset_(0),
591   region_(r),
592   referring_(NULL),
593   size_(s),
594   isDynamic_(d),
595   isAbsolute_(a),
596   aggregate_(NULL),
597   mangledName_(name),
598   prettyName_(name),
599   typedName_(name),
600   tag_(TAG_UNKNOWN),
601   index_(index),
602   strindex_(strindex),
603   isCommonStorage_(cs)
604 {
605 }
606
607 Symbol::~Symbol ()
608 {
609         std::string *sfa_p = NULL;
610
611         if (getAnnotation(sfa_p, SymbolFileNameAnno))
612         {
613                 if (!removeAnnotation(SymbolFileNameAnno))
614                 {
615                         fprintf(stderr, "%s[%d]:  failed to remove file name anno\n", 
616                                         FILE__, __LINE__);
617                 }
618                 delete (sfa_p);
619         }
620
621         std::vector<std::string> *vn_p = NULL;
622         if (getAnnotation(vn_p, SymbolVersionNamesAnno))
623         {
624                 if (!removeAnnotation(SymbolVersionNamesAnno))
625                 {
626                         fprintf(stderr, "%s[%d]:  failed to remove version names anno\n", 
627                                         FILE__, __LINE__);
628                 }
629                 delete (vn_p);
630         }
631
632 }
633
634 void Symbol::setReferringSymbol(Symbol* referringSymbol) 
635 {
636         referring_= referringSymbol;
637 }
638
639 Symbol* Symbol::getReferringSymbol() {
640         return referring_;
641 }