Function wrapping implementation and Symtab extensions for undefined symbols
[dyninst.git] / symtabAPI / src / Symbol.C
1 /*
2  * Copyright (c) 1996-2011 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 bool Symbol::setLocalTOC(Offset toc)
204 {
205     localTOC_ = toc;
206     return true;
207 }
208
209 SYMTAB_EXPORT bool Symbol::setModule(Module *mod) 
210 {
211     module_ = mod; 
212     return true;
213 }
214
215 SYMTAB_EXPORT bool Symbol::isFunction() const
216 {
217     return (getFunction() != NULL);
218 }
219
220 SYMTAB_EXPORT bool Symbol::setFunction(Function *func)
221 {
222     aggregate_ = func;
223     return true;
224 }
225
226 SYMTAB_EXPORT Function * Symbol::getFunction() const
227 {
228         if (aggregate_ == NULL) 
229                 return NULL;
230     return dynamic_cast<Function *>(aggregate_);
231 }
232
233 SYMTAB_EXPORT bool Symbol::isVariable() const 
234 {
235     return (getVariable() != NULL);
236 }
237
238 SYMTAB_EXPORT bool Symbol::setVariable(Variable *var) 
239 {
240     aggregate_ = var;
241     return true;
242 }
243
244 SYMTAB_EXPORT Variable * Symbol::getVariable() const
245 {
246     return dynamic_cast<Variable *>(aggregate_);
247 }
248
249 SYMTAB_EXPORT bool Symbol::setSize(unsigned ns)
250 {
251         size_ = ns;
252         return true;
253 }
254
255 SYMTAB_EXPORT bool Symbol::setRegion(Region *r)
256 {
257         region_ = r;
258         return true;
259 }
260
261 SYMTAB_EXPORT Symbol::SymbolTag Symbol::tag() const 
262 {
263     return tag_;
264 }
265
266
267 SYMTAB_EXPORT bool Symbol::setSymbolType(SymbolType sType)
268 {
269     if ((sType != ST_UNKNOWN)&&
270         (sType != ST_FUNCTION)&&
271         (sType != ST_OBJECT)&&
272         (sType != ST_MODULE)&&
273         (sType != ST_NOTYPE))
274         return false;
275     
276     SymbolType oldType = type_; 
277     type_ = sType;
278     if (module_ && module_->exec())
279         module_->exec()->changeType(this, oldType);
280
281     // TODO: update aggregate with information
282     
283     return true;
284 }
285
286 SYMTAB_EXPORT bool Symbol::setVersionFileName(std::string &fileName)
287 {
288    std::string *fn_p = NULL;
289    if (getAnnotation(fn_p, SymbolFileNameAnno)) 
290    {
291       if (!fn_p) 
292       {
293          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
294       }
295       else
296       {
297          fprintf(stderr, "%s[%d]:  WARNING, already have filename set for symbol %s\n", 
298                  FILE__, __LINE__, getMangledName().c_str());
299       }
300       return false;
301    }
302    else
303    {
304       //  not sure if we need to copy here or not, so let's do it...
305       std::string *fn = new std::string(fileName);
306       if (!addAnnotation(fn, SymbolFileNameAnno)) 
307       {
308          fprintf(stderr, "%s[%d]:  failed to add anno here\n", FILE__, __LINE__);
309          return false;
310       }
311       return true;
312    }
313
314    return false;
315 }
316
317 SYMTAB_EXPORT bool Symbol::setVersions(std::vector<std::string> &vers)
318 {
319    std::vector<std::string> *vn_p = NULL;
320    if (getAnnotation(vn_p, SymbolVersionNamesAnno)) 
321    {
322       if (!vn_p) 
323       {
324          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
325       }
326       else
327          fprintf(stderr, "%s[%d]:  WARNING, already have versions set for symbol %s\n", FILE__, __LINE__, getMangledName().c_str());
328       return false;
329    }
330    else
331    {
332       if (!addAnnotation(&vers, SymbolVersionNamesAnno)) 
333       {
334          fprintf(stderr, "%s[%d]:  failed to add anno here\n", FILE__, __LINE__);
335       }
336    }
337
338    return true;
339 }
340
341 SYMTAB_EXPORT bool Symbol::getVersionFileName(std::string &fileName)
342 {
343    std::string *fn_p = NULL;
344
345    if (getAnnotation(fn_p, SymbolFileNameAnno)) 
346    {
347       if (!fn_p) 
348       {
349          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
350       }
351       else
352          fileName = *fn_p;
353
354       return true;
355    }
356
357    return false;
358 }
359
360 SYMTAB_EXPORT bool Symbol::getVersions(std::vector<std::string> *&vers)
361 {
362    std::vector<std::string> *vn_p = NULL;
363
364    if (getAnnotation(vn_p, SymbolVersionNamesAnno)) 
365    {
366       if (!vn_p) 
367       {
368          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
369       }
370       else
371       {
372          vers = vn_p;
373          return true;
374       } 
375    }
376
377    return false;
378 }
379
380 Serializable *Symbol::serialize_impl(SerializerBase *s, const char *tag) THROW_SPEC (SerializerError)
381 {
382         //  Need to serialize regions before symbols
383         //  Use disk offset as unique identifier
384         Address symid = (Address) this;
385         Region *r = region_;
386         Offset r_off = r ? r->getDiskOffset() : (Offset) 0;
387         std::string modname = "";
388         if (!module_) {
389                 //fprintf(stderr, "%s[%d]:  WARN:  NULL module\n", FILE__, __LINE__);
390         }
391         else
392             modname = module_->fullName();
393
394                 ifxml_start_element(s, tag);
395                 gtranslate(s, type_, symbolType2Str, "type");
396                 gtranslate(s, linkage_, symbolLinkage2Str, "linkage");
397                 gtranslate(s, tag_, symbolTag2Str, "tag");
398                 gtranslate(s, visibility_, symbolVisibility2Str, "visibility");
399                 gtranslate(s, offset_, "offset");
400                 gtranslate(s, ptr_offset_, "ptr_offset");
401                 gtranslate(s, localTOC_, "localTOC");
402                 gtranslate(s, size_, "size");
403                 gtranslate(s, index_, "index");
404                 gtranslate(s, isDynamic_, "isDynamic");
405                 gtranslate(s, isAbsolute_, "isAbsolute");
406                 gtranslate(s, isCommonStorage_, "isCommonStorage");
407                 gtranslate(s, versionHidden_, "versionHidden");
408                 gtranslate(s, prettyName_, "prettyName");
409                 gtranslate(s, mangledName_, "mangledName");
410                 gtranslate(s, typedName_, "typedName");
411                 gtranslate(s, r_off, "regionDiskOffset");
412                 gtranslate(s, modname, "moduleName");
413                 gtranslate(s, symid, "symbolID");
414                 ifxml_end_element(s, "Symbol");
415
416                 //  Now, if we are doing binary deserialization, lookup type and region by unique ids
417                 if (s->isBin() && s->isInput())
418                 {
419                         restore_module_and_region(s, modname, r_off);
420                         addSymID(s, this, symid);
421                         //serialize_printf("%s[%d]:  added sym ID mapping: %p--%p\n", FILE__, __LINE__, this, symid);
422                 }
423
424                 return NULL;
425 }
426
427 void Symbol::restore_module_and_region(SerializerBase *s, std::string &modname, Offset r_off) THROW_SPEC (SerializerError)
428 {
429 #if 0
430         ScopedSerializerBase<Symtab> *ssb = dynamic_cast<ScopedSerializerBase<Symtab> *>(s);
431
432         if (!ssb)
433         {
434                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
435                 SER_ERR("FIXME");
436         }
437
438         Symtab *st = ssb->getScope();
439 #endif
440         SerContextBase *scb = s->getContext();
441         if (!scb)
442         {
443                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
444                 SER_ERR("FIXME");
445         }
446
447         SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
448
449         if (!scs)
450         {
451                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
452                 SER_ERR("FIXME");
453         }
454
455         Symtab *st = scs->getScope();
456
457         if (!st)
458         {
459                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
460                 SER_ERR("FIXME");
461         }
462
463         module_ = NULL;
464
465         if (modname.length())
466         {
467                 //  All symbols should have an associated module
468                 if (!st->findModuleByName(module_, modname) || !module_)
469                 {
470                         //  This should throw...  but not quite ready for that yet
471                         fprintf(stderr, "%s[%d]:  WARNING:  No module '%s' for symbol\n", 
472                                         FILE__, __LINE__, modname.c_str());
473                 }
474         }
475
476         region_ = NULL;
477
478         //  All symbols should have an associated region 
479         if (!st->findRegionByEntry(region_, r_off) || !region_)
480         {
481                 //  This should throw...  but not quite ready for that yet
482                 fprintf(stderr, "%s[%d]:  WARNING:  No region for symbol\n", 
483                                 FILE__, __LINE__);
484         }
485
486 }
487
488 std::ostream& Dyninst::SymtabAPI::operator<< (ostream &os, const Symbol &s) 
489 {
490         return os << "{"
491                 << " mangled=" << s.getMangledName()
492                 << " pretty="  << s.getPrettyName()
493               << " module="  << s.module_
494         //<< " type="    << (unsigned) s.type_
495               << " type="    << s.symbolType2Str(s.type_)
496         //<< " linkage=" << (unsigned) s.linkage_
497               << " linkage=" << s.symbolLinkage2Str(s.linkage_)
498               << " offset=0x"    << hex << s.offset_ << dec
499               << " ptr_offset=0x"    << hex << s.ptr_offset_ << dec
500               << " localTOC=0x"    << hex << s.localTOC_ << dec
501         //<< " tag="     << (unsigned) s.tag_
502               << " tag="     << s.symbolTag2Str(s.tag_)
503               << " isAbs="   << s.isAbsolute_
504               << " isCommon=" << s.isCommonStorage_
505               << (s.isFunction() ? " [FUNC]" : "")
506               << (s.isVariable() ? " [VAR]" : "")
507               << (s.isInSymtab() ? "[STA]" : "[DYN]")
508               << " }";
509 }
510
511      Offset tryStart_;
512                unsigned trySize_;
513                          Offset catchStart_;
514                                        bool hasTry_;
515
516 ostream & Dyninst::SymtabAPI::operator<< (ostream &s, const ExceptionBlock &eb) 
517 {
518         s << "tryStart=" << eb.tryStart_ 
519                 << "trySize=" << eb.trySize_ 
520                 << "catchStart=" << eb.catchStart_ 
521                 << "hasTry=" << eb.trySize_ ;
522         return s; 
523 }
524
525 bool Symbol::operator==(const Symbol& s) const
526 {
527         // explicitly ignore tags when comparing symbols
528
529         //  compare sections by offset, not pointer
530         if (!region_ && s.region_) return false;
531         if (region_ && !s.region_) return false;
532         if (region_)
533         {
534                 if (region_->getDiskOffset() != s.region_->getDiskOffset())
535                         return false;
536         }
537
538         // compare modules by name, not pointer
539         if (!module_ && s.module_) return false;
540         if (module_ && !s.module_) return false;
541         if (module_)
542         {
543                 if (module_->fullName() != s.module_->fullName())
544                         return false;
545         }
546
547         return (   (type_    == s.type_)
548                         && (linkage_ == s.linkage_)
549                         && (offset_    == s.offset_)
550                         && (size_    == s.size_)
551                         && (isDynamic_ == s.isDynamic_)
552                         && (isAbsolute_ == s.isAbsolute_)
553                         && (isCommonStorage_ == s.isCommonStorage_)
554                    && (versionHidden_ == s.versionHidden_)
555                         && (mangledName_ == s.mangledName_)
556                         && (prettyName_ == s.prettyName_)
557                         && (typedName_ == s.typedName_));
558 }
559
560 Symtab *Symbol::getSymtab() const { 
561    return module_->exec(); 
562 }
563
564 Symbol::Symbol () :
565   module_(NULL),
566   type_(ST_NOTYPE),
567   internal_type_(0),
568   linkage_(SL_UNKNOWN),
569   visibility_(SV_UNKNOWN),
570   offset_(0),
571   ptr_offset_(0),
572   localTOC_(0),
573   region_(NULL),
574   referring_(NULL),
575   size_(0),
576   isDynamic_(false),
577   isAbsolute_(false),
578   aggregate_(NULL),
579   mangledName_(Symbol::emptyString),
580   prettyName_(Symbol::emptyString),
581   typedName_(Symbol::emptyString),
582   tag_(TAG_UNKNOWN) ,
583   index_(-1),
584   strindex_(-1),
585   isCommonStorage_(false),
586   versionHidden_(false)
587 {
588 }
589
590 Symbol::Symbol(const std::string& name,
591                SymbolType t,
592                SymbolLinkage l,
593                SymbolVisibility v,
594                Offset o,
595                Module *module,
596                Region *r,
597                unsigned s,
598                bool d,
599                bool a,
600                int index,
601                int strindex,
602                bool cs):
603   module_(module),
604   type_(t),
605   internal_type_(0),
606   linkage_(l),
607   visibility_(v),
608   offset_(o),
609   ptr_offset_(0),
610   localTOC_(0),
611   region_(r),
612   referring_(NULL),
613   size_(s),
614   isDynamic_(d),
615   isAbsolute_(a),
616   aggregate_(NULL),
617   mangledName_(name),
618   prettyName_(name),
619   typedName_(name),
620   tag_(TAG_UNKNOWN),
621   index_(index),
622   strindex_(strindex),
623   isCommonStorage_(cs),
624   versionHidden_(false)
625 {
626 }
627
628 Symbol::~Symbol ()
629 {
630         std::string *sfa_p = NULL;
631
632         if (getAnnotation(sfa_p, SymbolFileNameAnno))
633         {
634                 if (!removeAnnotation(SymbolFileNameAnno))
635                 {
636                         fprintf(stderr, "%s[%d]:  failed to remove file name anno\n", 
637                                         FILE__, __LINE__);
638                 }
639                 delete (sfa_p);
640         }
641
642         std::vector<std::string> *vn_p = NULL;
643         if (getAnnotation(vn_p, SymbolVersionNamesAnno))
644         {
645                 if (!removeAnnotation(SymbolVersionNamesAnno))
646                 {
647                         fprintf(stderr, "%s[%d]:  failed to remove version names anno\n", 
648                                         FILE__, __LINE__);
649                 }
650                 delete (vn_p);
651         }
652
653 }
654
655 void Symbol::setReferringSymbol(Symbol* referringSymbol) 
656 {
657         referring_= referringSymbol;
658 }
659
660 Symbol* Symbol::getReferringSymbol() {
661         return referring_;
662 }