windows build fixes and some more work on symtab serialization
[dyninst.git] / symtabAPI / src / Symbol.C
1 /*
2  * Copyright (c) 1996-2007 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
49 Symbol *Symbol::magicEmitElfSymbol() {
50     // I have no idea why this is the way it is,
51     // but emitElf needs it...
52     return new Symbol("",
53                       ST_NOTYPE,
54                       SL_LOCAL,
55                       SV_DEFAULT,
56                       0,
57                       NULL,
58                       NULL,
59                       0,
60                       false,
61                       false);
62 }
63     
64 SYMTAB_EXPORT const string& Symbol::getMangledName() const 
65 {
66     return mangledName_;
67 }
68
69 SYMTAB_EXPORT const string& Symbol::getPrettyName() const 
70 {
71     return prettyName_;
72 }
73
74 SYMTAB_EXPORT const string& Symbol::getTypedName() const 
75 {
76     return typedName_;
77 }
78
79 SYMTAB_EXPORT const string& Symbol::getModuleName() const 
80 {
81     if (module_)
82         return module_->fullName();
83     else
84         return emptyString;
85 }
86
87 bool Symbol::setOffset(Offset newOffset)
88 {
89     offset_ = newOffset;
90     return true;
91 }
92
93 bool Symbol::setPtrOffset(Offset newOffset)
94 {
95     ptr_offset_ = newOffset;
96     return true;
97 }
98
99 SYMTAB_EXPORT bool Symbol::setModule(Module *mod) 
100 {
101     module_ = mod; 
102     return true;
103 }
104
105 SYMTAB_EXPORT bool Symbol::isFunction() const
106 {
107     return (getFunction() != NULL);
108 }
109
110 SYMTAB_EXPORT bool Symbol::setFunction(Function *func)
111 {
112     aggregate_ = func;
113     return true;
114 }
115
116 SYMTAB_EXPORT Function * Symbol::getFunction() const
117 {
118     return dynamic_cast<Function *>(aggregate_);
119 }
120
121 SYMTAB_EXPORT bool Symbol::isVariable() const 
122 {
123     return (getVariable() != NULL);
124 }
125
126 SYMTAB_EXPORT bool Symbol::setVariable(Variable *var) 
127 {
128     aggregate_ = var;
129     return true;
130 }
131
132 SYMTAB_EXPORT Variable * Symbol::getVariable() const
133 {
134     return dynamic_cast<Variable *>(aggregate_);
135 }
136
137 SYMTAB_EXPORT bool      Symbol::setSize(unsigned ns)
138 {
139         size_ = ns;
140         return true;
141 }
142
143 SYMTAB_EXPORT Symbol::SymbolTag Symbol::tag() const 
144 {
145     return tag_;
146 }
147
148
149 SYMTAB_EXPORT bool Symbol::setSymbolType(SymbolType sType)
150 {
151     if ((sType != ST_UNKNOWN)&&
152         (sType != ST_FUNCTION)&&
153         (sType != ST_OBJECT)&&
154         (sType != ST_MODULE)&&
155         (sType != ST_NOTYPE))
156         return false;
157     
158     SymbolType oldType = type_; 
159     type_ = sType;
160     if (module_ && module_->exec())
161         module_->exec()->changeType(this, oldType);
162
163     // TODO: update aggregate with information
164     
165     return true;
166 }
167
168 SYMTAB_EXPORT bool Symbol::setVersionFileName(std::string &fileName)
169 {
170    std::string *fn_p = NULL;
171    if (getAnnotation(fn_p, SymbolFileNameAnno)) 
172    {
173       if (!fn_p) 
174       {
175          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
176       }
177       else
178       {
179          fprintf(stderr, "%s[%d]:  WARNING, already have filename set for symbol %s\n", 
180                  FILE__, __LINE__, getMangledName().c_str());
181       }
182       return false;
183    }
184    else
185    {
186       //  not sure if we need to copy here or not, so let's do it...
187       std::string *fn = new std::string(fileName);
188       if (!addAnnotation(fn, SymbolFileNameAnno)) 
189       {
190          fprintf(stderr, "%s[%d]:  failed to add anno here\n", FILE__, __LINE__);
191          return false;
192       }
193       return true;
194    }
195
196    return false;
197 }
198
199 SYMTAB_EXPORT bool Symbol::setVersions(std::vector<std::string> &vers)
200 {
201    std::vector<std::string> *vn_p = NULL;
202    if (getAnnotation(vn_p, SymbolVersionNamesAnno)) 
203    {
204       if (!vn_p) 
205       {
206          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
207       }
208       else
209          fprintf(stderr, "%s[%d]:  WARNING, already have versions set for symbol %s\n", FILE__, __LINE__, getMangledName().c_str());
210       return false;
211    }
212    else
213    {
214       if (!addAnnotation(&vers, SymbolVersionNamesAnno)) 
215       {
216          fprintf(stderr, "%s[%d]:  failed to add anno here\n", FILE__, __LINE__);
217       }
218    }
219
220    return true;
221 }
222
223 SYMTAB_EXPORT bool Symbol::getVersionFileName(std::string &fileName)
224 {
225    std::string *fn_p = NULL;
226
227    if (getAnnotation(fn_p, SymbolFileNameAnno)) 
228    {
229       if (!fn_p) 
230       {
231          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
232       }
233       else
234          fileName = *fn_p;
235
236       return true;
237    }
238
239    return false;
240
241 #if 0
242    Annotatable<std::string, symbol_file_name_a> &fn = *this;
243    if (!fn.size()) {
244       return false;
245    }
246    fileName = fn[0];
247    return true;
248 #endif
249 }
250
251 SYMTAB_EXPORT bool Symbol::getVersions(std::vector<std::string> *&vers)
252 {
253    std::vector<std::string> *vn_p = NULL;
254
255    if (getAnnotation(vn_p, SymbolVersionNamesAnno)) 
256    {
257       if (!vn_p) 
258       {
259          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
260       }
261       else
262       {
263          vers = vn_p;
264          return true;
265       } 
266    }
267
268    return false;
269
270 #if 0
271    Annotatable<std::vector<std::string>, symbol_version_names_a> &sv = *this;
272    if (!sv.size()) {
273       return false;
274    }
275    vers = &(sv[0]);
276    return true;
277 #endif
278 }
279
280 void Symbol::serialize(SerializerBase *s, const char *tag) THROW_SPEC (SerializerError)
281 {
282
283 #if 0
284         //  Need to serialize types before symbols
285         //  Use typeID as unique identifier
286         Type *t = retType_;
287         unsigned int t_id = t ? t->getID() : (unsigned int) 0xdeadbeef; 
288 #endif
289
290         //  Need to serialize regions before symbols
291         //  Use disk offset as unique identifier
292         Region *r = region_;
293         Offset r_off = r ? r->getDiskOffset() : (Offset) 0;
294         std::string modname = "";
295         if (!module_)
296                 fprintf(stderr, "%s[%d]:  WARN:  NULL module\n", FILE__, __LINE__);
297         else
298             modname = module_->fullName();
299
300         try {
301                 ifxml_start_element(s, tag);
302                 gtranslate(s, type_, symbolType2Str, "type");
303                 gtranslate(s, linkage_, symbolLinkage2Str, "linkage");
304                 gtranslate(s, tag_, symbolTag2Str, "tag");
305                 gtranslate(s, visibility_, symbolVisibility2Str, "visibility");
306                 gtranslate(s, offset_, "offset");
307                 gtranslate(s, size_, "size");
308                 gtranslate(s, index_, "index");
309                 gtranslate(s, isDynamic_, "isDynamic");
310                 gtranslate(s, isAbsolute_, "isAbsolute");
311                 gtranslate(s, prettyName_, "prettyName");
312                 gtranslate(s, mangledName_, "mangledName");
313                 gtranslate(s, typedName_, "typedName");
314                 gtranslate(s, r_off, "regionDiskOffset");
315                 gtranslate(s, modname, "moduleName");
316                 ifxml_end_element(s, "Symbol");
317
318                 //  Now, if we are doing binary deserialization, lookup type and region by unique ids
319                 if (s->isBin() && s->isInput())
320                         restore_module_and_region(s, modname, r_off);
321
322         } SER_CATCH("Symbol");
323 }
324
325 void Symbol::restore_module_and_region(SerializerBase *s, std::string &modname, Offset r_off) THROW_SPEC (SerializerError)
326 {
327         ScopedSerializerBase<Symtab> *ssb = dynamic_cast<ScopedSerializerBase<Symtab> *>(s);
328
329         if (!ssb)
330         {
331                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
332                 SER_ERR("FIXME");
333         }
334
335         Symtab *st = ssb->getScope();
336         if (!st)
337         {
338                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
339                 SER_ERR("FIXME");
340         }
341
342         module_ = NULL;
343
344         if (modname.length())
345         {
346                 //  All symbols should have an associated module
347                 if (!st->findModuleByName(module_, modname) || !module_)
348                 {
349                         //  This should throw...  but not quite ready for that yet
350                         fprintf(stderr, "%s[%d]:  WARNING:  No module '%s' for symbol\n", 
351                                         FILE__, __LINE__, modname.c_str());
352                 }
353         }
354
355         region_ = NULL;
356
357         //  All symbols should have an associated region 
358         if (!st->findRegionByEntry(region_, r_off) || !region_)
359         {
360                 //  This should throw...  but not quite ready for that yet
361                 fprintf(stderr, "%s[%d]:  WARNING:  No region for symbol\n", 
362                                 FILE__, __LINE__);
363         }
364
365 }
366
367 #if 0
368 void Symbol::serialize(SerializerBase *s, const char *tag) 
369 {
370         try {
371                 ifxml_start_element(s, tag);
372                 gtranslate(s, type_, symbolType2Str, "type");
373                 gtranslate(s, linkage_, symbolLinkage2Str, "linkage");
374                 gtranslate(s, tag_, symbolTag2Str, "tag");
375                 gtranslate(s, visibility_, symbolVisibility2Str, "visibility");
376                 gtranslate(s, offset_, "offset");
377                 gtranslate(s, ptr_offset_, "ptr_offset");
378                 gtranslate(s, size_, "size");
379                 gtranslate(s, isDynamic_, "isDynamic"); 
380                 gtranslate(s, isAbsolute_, "isAbsolute");
381                 gtranslate(s, prettyName_, "prettyName", "prettyName");
382                 gtranslate(s, mangledName_, "mangledName", "mangledName");
383                 gtranslate(s, typedName_, "typedName", "typedName");
384                 //  Note:  have to deal with retType_ here?? Probably use type id.
385                 ifxml_end_element(s, "Symbol");
386 #if 0
387                 symbol_start(param);
388                 translate(param.type_, "type");
389                 translate(param.linkage_, "linkage");
390                 translate(param.tag_, "tag");
391                 getSD().translate(param.offset_, "offset");
392                 getSD().translate(param.ptr_offste_, "ptr_offset");
393                 getSD().translate(param.size_, "size");
394                 getSD().translate(param.isInDynsymtab_, "isInDynsymtab");
395                 getSD().translate(param.isInSymtab_, "isInSymtab");
396                 getSD().translate(param.prettyName_, "prettyName", "prettyName");
397                 getSD().translate(param.mangledName_, "mangledName", "mangledName");
398                 getSD().translate(param.typedName_, "typedName", "typedName");
399                 getSD().translate(param.framePtrRegNum_, "framePtrRegNum");
400                 //  Note:  have to deal with retType_ here?? Probably use type id.
401                 symbol_end(param);
402 #endif
403         } SER_CATCH("Symbol");
404 }
405 #endif
406
407
408 ostream& Dyninst::SymtabAPI::operator<< (ostream &os, const Symbol &s) 
409 {
410         return os << "{"
411                 << " mangled=" << s.getMangledName()
412                 << " pretty="  << s.getPrettyName()
413               << " module="  << s.module_
414         //<< " type="    << (unsigned) s.type_
415               << " type="    << s.symbolType2Str(s.type_)
416         //<< " linkage=" << (unsigned) s.linkage_
417               << " linkage=" << s.symbolLinkage2Str(s.linkage_)
418               << " offset=0x"    << hex << s.offset_ << dec
419               << " ptr_offset=0x"    << hex << s.ptr_offset_ << dec
420         //<< " tag="     << (unsigned) s.tag_
421               << " tag="     << s.symbolTag2Str(s.tag_)
422               << " isAbs="   << s.isAbsolute_
423               << (s.isFunction() ? " [FUNC]" : "")
424               << (s.isVariable() ? " [VAR]" : "")
425               << (s.isInSymtab() ? "[STA]" : "[DYN]")
426               << " }" << endl;
427 }
428
429 ostream & Dyninst::SymtabAPI::operator<< (ostream &s, const relocationEntry &r) 
430 {
431         s << "target_addr=" << r.target_addr_ 
432                 << "rel_addr=" << r.rel_addr_ 
433                 << "addend=" << r.addend_ 
434                 << "rtype=" << r.rtype_ 
435                 << "name=" << r.name_ ;
436         return s; 
437 }
438      Offset tryStart_;
439                unsigned trySize_;
440                          Offset catchStart_;
441                                        bool hasTry_;
442
443 ostream & Dyninst::SymtabAPI::operator<< (ostream &s, const ExceptionBlock &eb) 
444 {
445         s << "tryStart=" << eb.tryStart_ 
446                 << "trySize=" << eb.trySize_ 
447                 << "catchStart=" << eb.catchStart_ 
448                 << "hasTry=" << eb.trySize_ ;
449         return s; 
450 }
451
452 bool Symbol::operator==(const Symbol& s) const
453 {
454         // explicitly ignore tags when comparing symbols
455
456         //  compare sections by offset, not pointer
457         if (!region_ && s.region_) return false;
458         if (region_ && !s.region_) return false;
459         if (region_)
460         {
461                 if (region_->getDiskOffset() != s.region_->getDiskOffset())
462                         return false;
463         }
464
465         // compare modules by name, not pointer
466         if (!module_ && s.module_) return false;
467         if (module_ && !s.module_) return false;
468         if (module_)
469         {
470                 if (module_->fullName() != s.module_->fullName())
471                         return false;
472         }
473
474         return (   (type_    == s.type_)
475                         && (linkage_ == s.linkage_)
476                         && (offset_    == s.offset_)
477                         && (size_    == s.size_)
478                         && (isDynamic_ == s.isDynamic_)
479                         && (isAbsolute_ == s.isAbsolute_)
480                         && (mangledName_ == s.mangledName_)
481                         && (prettyName_ == s.prettyName_)
482                         && (typedName_ == s.typedName_));
483 }
484
485 #if 0
486 inline
487 bool
488 Symbol::operator==(const Symbol& s) const 
489 {
490         return ((s.module_ == module_) && 
491                         (s.type_ == type_) &&
492                         (s.linkage_ == linkage_) &&
493             (s.visibility_ == visibility_) &&
494             (s.offset_ == offset_) &&
495             (s.region_ == region_) &&
496             (s.size_ == size_) &&
497             (s.isDynamic_ == isDynamic_) &&
498             (s.isAbsolute_ == isAbsolute_) &&
499             (s.mangledName_ == mangledName_));
500 }
501 #endif
502