Update copyright to LGPL on all files
[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, prettyName_, "prettyName");
393                 gtranslate(s, mangledName_, "mangledName");
394                 gtranslate(s, typedName_, "typedName");
395                 gtranslate(s, r_off, "regionDiskOffset");
396                 gtranslate(s, modname, "moduleName");
397                 gtranslate(s, symid, "symbolID");
398                 ifxml_end_element(s, "Symbol");
399
400                 //  Now, if we are doing binary deserialization, lookup type and region by unique ids
401                 if (s->isBin() && s->isInput())
402                 {
403                         restore_module_and_region(s, modname, r_off);
404                         addSymID(s, this, symid);
405                         //serialize_printf("%s[%d]:  added sym ID mapping: %p--%p\n", FILE__, __LINE__, this, symid);
406                 }
407
408                 return NULL;
409 }
410
411 void Symbol::restore_module_and_region(SerializerBase *s, std::string &modname, Offset r_off) THROW_SPEC (SerializerError)
412 {
413 #if 0
414         ScopedSerializerBase<Symtab> *ssb = dynamic_cast<ScopedSerializerBase<Symtab> *>(s);
415
416         if (!ssb)
417         {
418                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
419                 SER_ERR("FIXME");
420         }
421
422         Symtab *st = ssb->getScope();
423 #endif
424         SerContextBase *scb = s->getContext();
425         if (!scb)
426         {
427                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
428                 SER_ERR("FIXME");
429         }
430
431         SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
432
433         if (!scs)
434         {
435                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
436                 SER_ERR("FIXME");
437         }
438
439         Symtab *st = scs->getScope();
440
441         if (!st)
442         {
443                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
444                 SER_ERR("FIXME");
445         }
446
447         module_ = NULL;
448
449         if (modname.length())
450         {
451                 //  All symbols should have an associated module
452                 if (!st->findModuleByName(module_, modname) || !module_)
453                 {
454                         //  This should throw...  but not quite ready for that yet
455                         fprintf(stderr, "%s[%d]:  WARNING:  No module '%s' for symbol\n", 
456                                         FILE__, __LINE__, modname.c_str());
457                 }
458         }
459
460         region_ = NULL;
461
462         //  All symbols should have an associated region 
463         if (!st->findRegionByEntry(region_, r_off) || !region_)
464         {
465                 //  This should throw...  but not quite ready for that yet
466                 fprintf(stderr, "%s[%d]:  WARNING:  No region for symbol\n", 
467                                 FILE__, __LINE__);
468         }
469
470 }
471
472 ostream& Dyninst::SymtabAPI::operator<< (ostream &os, const Symbol &s) 
473 {
474         return os << "{"
475                 << " mangled=" << s.getMangledName()
476                 << " pretty="  << s.getPrettyName()
477               << " module="  << s.module_
478         //<< " type="    << (unsigned) s.type_
479               << " type="    << s.symbolType2Str(s.type_)
480         //<< " linkage=" << (unsigned) s.linkage_
481               << " linkage=" << s.symbolLinkage2Str(s.linkage_)
482               << " offset=0x"    << hex << s.offset_ << dec
483               << " ptr_offset=0x"    << hex << s.ptr_offset_ << dec
484         //<< " tag="     << (unsigned) s.tag_
485               << " tag="     << s.symbolTag2Str(s.tag_)
486               << " isAbs="   << s.isAbsolute_
487               << (s.isFunction() ? " [FUNC]" : "")
488               << (s.isVariable() ? " [VAR]" : "")
489               << (s.isInSymtab() ? "[STA]" : "[DYN]")
490               << " }" << endl;
491 }
492
493 ostream & Dyninst::SymtabAPI::operator<< (ostream &s, const relocationEntry &r) 
494 {
495         s << "target_addr=" << r.target_addr_ 
496                 << "rel_addr=" << r.rel_addr_ 
497                 << "addend=" << r.addend_ 
498                 << "rtype=" << r.rtype_ 
499                 << "name=" << r.name_ ;
500         return s; 
501 }
502      Offset tryStart_;
503                unsigned trySize_;
504                          Offset catchStart_;
505                                        bool hasTry_;
506
507 ostream & Dyninst::SymtabAPI::operator<< (ostream &s, const ExceptionBlock &eb) 
508 {
509         s << "tryStart=" << eb.tryStart_ 
510                 << "trySize=" << eb.trySize_ 
511                 << "catchStart=" << eb.catchStart_ 
512                 << "hasTry=" << eb.trySize_ ;
513         return s; 
514 }
515
516 bool Symbol::operator==(const Symbol& s) const
517 {
518         // explicitly ignore tags when comparing symbols
519
520         //  compare sections by offset, not pointer
521         if (!region_ && s.region_) return false;
522         if (region_ && !s.region_) return false;
523         if (region_)
524         {
525                 if (region_->getDiskOffset() != s.region_->getDiskOffset())
526                         return false;
527         }
528
529         // compare modules by name, not pointer
530         if (!module_ && s.module_) return false;
531         if (module_ && !s.module_) return false;
532         if (module_)
533         {
534                 if (module_->fullName() != s.module_->fullName())
535                         return false;
536         }
537
538         return (   (type_    == s.type_)
539                         && (linkage_ == s.linkage_)
540                         && (offset_    == s.offset_)
541                         && (size_    == s.size_)
542                         && (isDynamic_ == s.isDynamic_)
543                         && (isAbsolute_ == s.isAbsolute_)
544                         && (mangledName_ == s.mangledName_)
545                         && (prettyName_ == s.prettyName_)
546                         && (typedName_ == s.typedName_));
547 }
548
549 Symtab *Symbol::getSymtab() const { 
550    return module_->exec(); 
551 }
552
553 Symbol::Symbol () :
554   module_(NULL),
555   type_(ST_NOTYPE),
556   linkage_(SL_UNKNOWN),
557   visibility_(SV_UNKNOWN),
558   offset_(0),
559   ptr_offset_(0),
560   region_(NULL),
561   referring_(NULL),
562   size_(0),
563   isDynamic_(false),
564   isAbsolute_(false),
565   aggregate_(NULL),
566   mangledName_(Symbol::emptyString),
567   prettyName_(Symbol::emptyString),
568   typedName_(Symbol::emptyString),
569   tag_(TAG_UNKNOWN) ,
570   index_(-1),
571   strindex_(-1) 
572 {
573 }
574
575 Symbol::Symbol(const std::string name,
576                SymbolType t,
577                SymbolLinkage l,
578                SymbolVisibility v,
579                Offset o,
580                Module *module,
581                Region *r,
582                unsigned s,
583                bool d,
584                bool a,
585                int index,
586                int strindex):
587   module_(module),
588   type_(t),
589   linkage_(l),
590   visibility_(v),
591   offset_(o),
592   ptr_offset_(0),
593   region_(r),
594   referring_(NULL),
595   size_(s),
596   isDynamic_(d),
597   isAbsolute_(a),
598   aggregate_(NULL),
599   mangledName_(name),
600   prettyName_(name),
601   typedName_(name),
602   tag_(TAG_UNKNOWN),
603   index_(index),
604   strindex_(strindex)
605 {
606 }
607
608 Symbol::~Symbol ()
609 {
610         std::string *sfa_p = NULL;
611
612         if (getAnnotation(sfa_p, SymbolFileNameAnno))
613         {
614                 if (!removeAnnotation(SymbolFileNameAnno))
615                 {
616                         fprintf(stderr, "%s[%d]:  failed to remove file name anno\n", 
617                                         FILE__, __LINE__);
618                 }
619                 delete (sfa_p);
620         }
621
622         std::vector<std::string> *vn_p = NULL;
623         if (getAnnotation(vn_p, SymbolVersionNamesAnno))
624         {
625                 if (!removeAnnotation(SymbolVersionNamesAnno))
626                 {
627                         fprintf(stderr, "%s[%d]:  failed to remove version names anno\n", 
628                                         FILE__, __LINE__);
629                 }
630                 delete (vn_p);
631         }
632
633 }
634
635 void Symbol::setReferringSymbol(Symbol* referringSymbol) 
636 {
637         referring_= referringSymbol;
638 }
639
640 Symbol* Symbol::getReferringSymbol() {
641         return referring_;
642 }