export more serializer interface to allow for finer grain testing
[dyninst.git] / symtabAPI / src / Variable.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 // $Id: Object.C,v 1.31 2008/11/03 15:19:25 jaw Exp $
33
34 #include "Annotatable.h"
35 #include "common/h/serialize.h"
36
37 #include "Symtab.h"
38 #include "symutil.h"
39 #include "Module.h"
40 #include "Collections.h"
41 #include "Variable.h"
42 #include "Aggregate.h"
43
44 #include "symtabAPI/src/Object.h"
45
46 #include <iostream>
47
48 using namespace std;
49 using namespace Dyninst;
50 using namespace Dyninst::SymtabAPI;
51
52
53 Variable::Variable(Symbol *sym) :
54         Aggregate(sym),
55         type_(NULL)
56 {
57 }
58
59 Variable::Variable() :
60         Aggregate(),
61         type_(NULL)
62 {
63 }
64 void Variable::setType(Type *type)
65 {
66         //fprintf(stderr, "%s[%d]:  setting variable %s to type id %d\n", FILE__, __LINE__, prettyName.c_str(), type ? type->getID() : 0xdeadbeef);
67         type_ = type;
68 }
69
70 Type* Variable::getType()
71 {
72         module_->exec()->parseTypesNow();
73         return type_;
74 }
75
76 void Variable::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
77 {
78         //fprintf(stderr, "%s[%d]:  welcome to Variable::serialize\n", FILE__, __LINE__);
79         if (!sb)
80         {
81                 SER_ERR("bad paramater sb");
82         }
83
84         //  Use typeID as unique identifier
85         //  magic numbers stink, but we use both positive and negative numbers for type ids
86         unsigned int t_id = type_ ? type_->getID() : (unsigned int) 0xdeadbeef; 
87
88         try 
89         {
90                 ifxml_start_element(sb, tag);
91                 gtranslate(sb, t_id, "typeID");
92                 Aggregate::serialize_aggregate(sb);
93                 ifxml_end_element(sb, tag);
94                 if (sb->isInput())
95                 {
96                    if (t_id == 0xdeadbeef)
97                    {
98                            type_ = NULL;
99                    }
100                    else
101                    {
102                            restore_type_by_id(sb, type_, t_id);
103                    }
104                 } 
105                 else
106                 {
107                         Dyninst::ScopedSerializerBase<Dyninst::SymtabAPI::Symtab> *ssb = dynamic_cast<Dyninst::ScopedSerializerBase<Dyninst::SymtabAPI::Symtab> *>(sb);
108
109                         if (!ssb)
110                         {
111                                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME, sb is_bin = %s, sb = %p\n", FILE__, __LINE__, sb->isBin() ? "true" : "false", sb);
112                                 SerializerBin<Symtab> *sbst = dynamic_cast<SerializerBin<Symtab> *> (sb);
113                                 if (NULL == sbst)
114                                 {
115                                         fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
116                                 }
117                                 SER_ERR("FIXME");
118                         }
119
120                         Symtab *st = ssb->getScope();
121
122                         //  remove this check
123                         if ((t_id != 0xdeadbeef) && !st->findType(t_id))
124                         {
125                                 fprintf(stderr, "%s[%d]:  ERROR:  serialize bad type %s\n", FILE__, __LINE__, type_->getName().c_str());
126                         }
127                 }
128         }
129         SER_CATCH(tag);
130 }
131
132 std::ostream &operator<<(std::ostream &os, const Dyninst::SymtabAPI::Variable &v)
133 {
134         std::string tname(v.type_ ? v.type_->getName() : "no_type");
135         const Aggregate *ag = dynamic_cast<const Aggregate *>(&v);
136         assert(ag);
137
138         os  << "Variable{"        
139                 << " type=" 
140                 << tname
141             << " ";                                                
142         os  <<  *ag;                                       
143         os  <<  "}";
144         return os;      
145
146 }
147 bool Variable::operator==(const Variable &v)
148 {
149         if (type_ && !v.type_)
150                 return false;
151         if (!type_ && v.type_)
152                 return false;
153         if (type_)
154                 if (type_->getID() != v.type_->getID())
155                 {
156                         return false;
157                 }
158         return ((Aggregate &)(*this)) == ((Aggregate &)v);
159 }
160
161 bool Variable::removeSymbol(Symbol *sym) 
162 {
163     removeSymbolInt(sym);
164     if (symbols_.empty()) {
165         module_->exec()->deleteVariable(this);
166     }
167     return true;
168 }
169
170 namespace Dyninst {
171         namespace SymtabAPI {
172 const char *storageClass2Str(Dyninst::SymtabAPI::storageClass sc) 
173 {
174         switch(sc) {
175                 CASE_RETURN_STR(storageAddr);
176                 CASE_RETURN_STR(storageReg);
177                 CASE_RETURN_STR(storageRegOffset);
178         };
179         return "bad_storage_class";
180 }
181
182 const char *storageRefClass2Str(Dyninst::SymtabAPI::storageRefClass sc) 
183 {
184         switch(sc) {
185                 CASE_RETURN_STR(storageRef);
186                 CASE_RETURN_STR(storageNoRef);
187         };
188         return "bad_storage_class";
189 }
190 }
191 }
192
193 bool VariableLocation::operator==(const VariableLocation &f)
194 {
195         if (stClass != f.stClass) return false;
196         if (refClass != f.refClass) return false;
197         if (reg != f.reg) return false;
198         if (frameOffset != f.frameOffset) return false;
199         if (hiPC != f.hiPC) return false;
200         if (lowPC != f.lowPC) return false;
201         return true;
202 }
203 void VariableLocation::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
204 {
205         ifxml_start_element(sb, tag);
206         gtranslate(sb, (int &)stClass, "StorageClass");
207         gtranslate(sb, (int &)refClass, "StorageRefClass");
208         gtranslate(sb, reg, "register");
209         gtranslate(sb, frameOffset, "frameOffset");
210         gtranslate(sb, hiPC, "hiPC");
211         gtranslate(sb, lowPC, "lowPC");
212         ifxml_end_element(sb, tag);
213 }
214
215 localVar::localVar(std::string name,  Type *typ, std::string fileName, 
216                 int lineNum, std::vector<VariableLocation> *locs) :
217         Serializable(),
218         name_(name), 
219         type_(typ), 
220         fileName_(fileName), 
221         lineNum_(lineNum) 
222 {
223         type_->incrRefCount();
224
225         if (locs)
226         {
227                 for (unsigned int i = 0; i < locs->size(); ++i)
228                 {
229                         locs_.push_back((*locs)[i]);
230                 }
231         }
232 }
233
234 localVar::localVar(localVar &lvar) :
235         Serializable()
236 {
237         name_ = lvar.name_;
238         type_ = lvar.type_;
239         fileName_ = lvar.fileName_;
240         lineNum_ = lvar.lineNum_;
241
242         for (unsigned int i = 0; i < lvar.locs_.size(); ++i)
243         {
244                 locs_.push_back(lvar.locs_[i]);
245         }
246
247         if (type_ != NULL)
248         {
249                 type_->incrRefCount();
250         }
251 }
252
253 bool localVar::addLocation(VariableLocation &location)
254 {
255         locs_.push_back(location);
256
257         return true;
258 }
259
260 localVar::~localVar()
261 {
262         //XXX jdd 5/25/99 More to do later
263         type_->decrRefCount();
264 }
265
266 void localVar::fixupUnknown(Module *module) 
267 {
268         if (type_->getDataClass() == dataUnknownType) 
269         {
270                 Type *otype = type_;
271                 type_ = module->getModuleTypesPrivate()->findType(type_->getID());
272
273                 if (type_)
274                 {
275                         type_->incrRefCount();
276                         otype->decrRefCount();
277                 }
278                 else
279                         type_ = otype;
280         }
281 }
282
283 std::string &localVar::getName() 
284 {
285         return name_;
286 }
287
288 Type *localVar::getType() 
289 {
290         return type_;
291 }
292
293 bool localVar::setType(Type *newType) 
294 {
295         type_ = newType;
296         return true;
297 }
298
299 int localVar::getLineNum() 
300 {
301         return lineNum_;
302 }
303
304 std::string &localVar::getFileName() 
305 {
306         return fileName_;
307 }
308
309 std::vector<Dyninst::SymtabAPI::VariableLocation> &localVar::getLocationLists() 
310 {
311         return locs_;
312 }
313
314 bool localVar::operator==(const localVar &l)
315 {
316         if (type_ && !l.type_) return false;
317         if (!type_ && l.type_) return false;
318
319         if (type_)
320         {
321                 if (type_->getID() != l.type_->getID())
322                         return false;
323         }
324
325         if (name_ != l.name_) return false;
326         if (fileName_ != l.fileName_) return false;
327         if (lineNum_ != l.lineNum_) return false;
328
329         if (locs_.size() != l.locs_.size()) return false;
330
331         for (unsigned int i = 0; i < locs_.size(); ++i)
332         {
333                 if ( !(locs_[i] == l.locs_[i]) ) return false;
334         }
335
336         return true;
337 }
338
339 void localVar::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC(SerializerError)
340 {
341         //  Use typeID as unique identifier
342         //  magic numbers stink, but we use both positive and negative numbers for type ids
343         unsigned int t_id = type_ ? type_->getID() : (unsigned int) 0xdeadbeef; 
344
345         ifxml_start_element(sb, tag);
346         gtranslate(sb, name_, "Name");
347         gtranslate(sb, fileName_, "FileName");
348         gtranslate(sb, lineNum_, "LineNumber");
349         gtranslate(sb, t_id, "TypeID");
350         gtranslate(sb, locs_, "Locations", "Location");
351         ifxml_end_element(sb, tag);
352
353         if (sb->isInput())
354         {
355                 if (t_id == 0xdeadbeef)
356                 {
357                         type_ = NULL;
358                 }
359                 else 
360                 {
361                         ScopedSerializerBase<Symtab> *ssb = dynamic_cast<ScopedSerializerBase<Symtab> *>(sb);
362
363                         if (!ssb)
364                         {
365                                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
366                                 SER_ERR("FIXME");
367                         }
368
369                         Symtab *st = ssb->getScope();
370
371                         if (!st)
372                         {
373                                 fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
374                                 SER_ERR("FIXME");
375                         }
376
377                         type_ = st->findType(t_id);
378
379                         if (!type_)
380                         {
381                                 //  This should probably throw, but let's play nice for now
382                                 fprintf(stderr, "%s[%d]:  FIXME: cannot find type with id %d\n", FILE__, __LINE__, t_id);
383                         }
384                 }
385
386         }
387 }
388