Update copyright to LGPL on all files
[dyninst.git] / common / src / Annotatable.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 // $Id: Annotatable.C,v 1.12 2008/11/03 15:19:23 jaw Exp $
33
34 #include "common/h/headers.h"
35 #include "dyntypes.h"
36 #include "Annotatable.h"
37 #include "Serialization.h"
38 #include "common/h/serialize.h"
39
40 using namespace Dyninst;
41
42 #if defined (NON_STATIC_SPARSE_MAP)
43 char buffer[1024];
44 //AnnotatableSparse::annos_t *AnnotatableSparse::annos = NULL;
45 AnnotatableSparse::annos_t *annos = NULL;
46 AnnotatableSparse::annos_t *AnnotatableSparse::getAnnos() const
47 {
48         if (!annos)
49         {
50                 sprintf(buffer, "booga_booga");
51                 annos = new annos_t();
52         }
53         return annos;
54 }
55 #else
56 AnnotatableSparse::annos_t AnnotatableSparse::annos;
57 AnnotatableSparse::annos_t *AnnotatableSparse::getAnnos() const
58 {
59         return &annos;
60 }
61 #endif
62
63 dyn_hash_map<void *, unsigned short> AnnotatableSparse::ser_ndx_map;
64
65 namespace Dyninst 
66 {
67
68 bool dyn_debug_annotations = false;
69 bool annotation_debug_flag()
70 {
71         return dyn_debug_annotations;
72 }
73
74 void annotations_debug_init()
75 {
76         if (dyn_debug_annotations) return;
77
78         char *p;
79         if ( (p=getenv("DYNINST_DEBUG_ANNOTATIONS"))) {
80                 fprintf(stderr, "Enabling DyninstAPI annotations debug\n");
81                 dyn_debug_annotations = true;
82         }
83         else if ( (p=getenv("DYNINST_DEBUG_ANNOTATION"))) {
84                 fprintf(stderr, "Enabling DyninstAPI annotations debug\n");
85                 dyn_debug_annotations = true;
86         }
87         else if ( (p=getenv("DYNINST_DEBUG_ANNOTATABLE"))) {
88                 fprintf(stderr, "Enabling DyninstAPI annotations debug\n");
89                 dyn_debug_annotations = true;
90         }
91 }
92
93 int annotatable_printf(const char *format, ...)
94 {
95         if (!dyn_debug_annotations) return 0;
96         if (NULL == format) return -1;
97
98         //debugPrintLock->_Lock(FILE__, __LINE__);
99
100         //  probably want to have basic thread-id routines in libcommon...
101         //  uh...  later....
102
103         //fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
104         va_list va;
105         va_start(va, format);
106         int ret = vfprintf(stderr, format, va);
107         va_end(va);
108
109         //debugPrintLock->_Unlock(FILE__, __LINE__);
110
111         return ret;
112 }
113
114 COMMON_EXPORT int AnnotationClass_nextId;
115
116 bool void_ptr_cmp_func(void *v1, void *v2)
117 {
118         return v1 == v2;
119 }
120 }
121
122 std::vector<AnnotationClassBase *> *AnnotationClassBase::annotation_types = NULL;
123 dyn_hash_map<std::string, AnnotationClassID> *AnnotationClassBase::annotation_ids_by_name = NULL;
124
125 AnnotationClassBase::AnnotationClassBase(std::string n, 
126                 anno_cmp_func_t cmp_func_, 
127                 ser_func_t sf_) :
128    name(n),
129    serialize_func(sf_)
130 {
131         annotations_debug_init();
132     // Using a static vector led to the following pattern on AIX:
133     //   dyninstAPI static initialization
134     //     ... add annotation types
135     //   common static initialization
136     //     ... vector constructor called, resetting size to 0.
137
138     if (annotation_types == NULL)
139         annotation_types = new std::vector<AnnotationClassBase *>;
140     if (annotation_ids_by_name == NULL)
141         annotation_ids_by_name = new dyn_hash_map<std::string, AnnotationClassID>;
142
143    if (NULL == cmp_func_)
144       cmp_func = void_ptr_cmp_func;
145    else
146       cmp_func = cmp_func_;
147
148    dyn_hash_map<std::string, AnnotationClassID>::iterator iter;
149    iter = annotation_ids_by_name->find(n);
150    if (iter == annotation_ids_by_name->end()) 
151    {
152       id = (AnnotationClassID) annotation_types->size();
153           annotatable_printf("%s[%d]:  New AnnotationClass %d: %s\n", 
154                           FILE__, __LINE__, id, n.c_str());
155       annotation_types->push_back(this);
156       (*annotation_ids_by_name)[name] = id;
157    }
158    else
159    {
160       id = iter->second;
161           annotatable_printf("%s[%d]:  Existing AnnotationClass %d\n", FILE__, __LINE__, id);
162    }
163
164    if (id >= annotation_types->size())
165            assert(0 && "bad anno id");
166 }
167
168 AnnotationClassBase::~AnnotationClassBase()
169 {
170         //  Still waffling...  maybe a bad idea
171 #if 0 
172         //  The general rule in dyninst/symtab etc is to use global/static
173         //  Annotation classes, so they never go away.  This is good.
174         //  But in the testsuite, we have a bunch of transient fly-by-night
175         //  AnnotationClasses for the purposes of testing.  
176         //
177         //  This may be a bit dangerous and might require a bit more thought,
178         //  but for now, if this AnnotationClass was the last one allocated
179         //  remove it from the static mapping so it can be reused.
180
181         if (!annotation_types)  return; //  should never happen
182         if (id >= annotation_types->size()) return; //  should never happen
183         if (id == (annotation_types->size() -1))
184         {
185                 annotatable_printf("%s[%d]:  removing annotation class %d: %s\n", 
186                                 FILE__, __LINE__, id, name.c_str());
187                 //  this is the special case where we can "undo" the existence of
188                 // the annotation type
189                 annotation_types->pop_back();
190                 assert((*annotation_types)[id] == this);
191                 dyn_hash_map<std::string, AnnotationClassID>::iterator iter;
192                 iter = annotation_ids_by_name->find(name);
193                 if (iter != annotation_ids_by_name->end()) 
194                 {
195                         annotation_ids_by_name->erase(iter);
196                 }
197         }
198 #endif
199 }
200
201 #if 0
202 void AnnotationClassBase::clearAnnotationIDMap()
203 {
204         if (!annotation_ids_by_name) return;
205         annotation_ids_by_name->clear();
206         delete annotation_ids_by_name;
207         annotation_ids_by_name = NULL;
208 }
209 #endif
210
211 Dyninst::AnnotationClassBase* AnnotationClassBase::findAnnotationClass(unsigned int id)
212 {
213         if(id > annotation_types->size())
214         {
215                 fprintf(stderr, "%s[%d]:  cannot find annotation class base for id %d, max is %ld\n", FILE__, __LINE__, id, annotation_types->size());
216                 return NULL;
217         }
218         if (NULL == (*annotation_types)[id])
219         {
220                 fprintf(stderr, "%s[%d]:  FIXME:  have NULL slot\n", FILE__, __LINE__);
221         }
222         if ((*annotation_types)[id]->getID() != id)
223         {
224                 fprintf(stderr, "%s[%d]:  FIXME:  have bad id in annotation class: %d, not %d\n", FILE__, __LINE__, (*annotation_types)[id]->getID(), id);
225                 return NULL;
226         }
227         return (*annotation_types)[id];
228 }
229 void AnnotationClassBase::dumpAnnotationClasses()
230 {
231         fprintf(stderr, "%s[%d]: have the following annotation classes:\n", FILE__, __LINE__);
232         for (unsigned int i = 0; i < annotation_types->size(); ++i)
233         {
234                 AnnotationClassBase *acb = (*annotation_types)[i];
235                 if (!acb)
236                 {
237                         fprintf(stderr, "\t<NULL>\n");
238                         continue;
239                 }
240                 fprintf(stderr, "\tid-%d\t%s, type %s\n", acb->getID(), acb->getName().c_str(), acb->getTypeName());
241         }
242 }
243
244 namespace Dyninst {
245 bool is_input(SerializerBase *sb)
246 {
247         return sb->isInput();
248 }
249 bool is_output(SerializerBase *sb)
250 {
251         return sb->isOutput();
252 }
253 bool serialize_annotation_list(void *id, std::vector<ser_rec_t> &sers, SerializerBase *sb, const char *tag)
254 {
255         if (sers.size())
256                 serialize_printf("%s[%d]:  welcome to serialize_annotation_list, size %lu, id = %p\n", FILE__, __LINE__, sers.size(), id);
257         assert(sb);
258         assert(id);
259         try {
260                 sb->serialize_annotations(id, sers, tag);
261         } 
262         catch (const SerializerError &err)
263         {
264                 fprintf(stderr, "%s[%d]:  serializer error translating annotations\n", FILE__, __LINE__);
265                 printSerErr(err);
266                 return false;
267         }
268         return true;
269 }
270
271 bool serialize_post_annotation(void *parent, void *anno, SerializerBase *sb, AnnotationClassBase *acb, sparse_or_dense_anno_t sod, const char *tag)
272 {
273         serialize_printf("%s[%d]:  welcome to serialize_post_annotation_list, id = %p\n", 
274                         FILE__, __LINE__, parent);
275         assert(parent);
276         assert(anno);
277         if (!sb)
278         {
279                 fprintf(stderr, "%s[%d]:  no existing output serializer\n", FILE__, __LINE__);
280                 return true;
281         }
282         try {
283                 sb->serialize_post_annotation(parent, anno, acb, sod, tag);
284         }
285         catch (const SerializerError &err)
286         {
287                 fprintf(stderr, "%s[%d]:  serializer error translating annotations\n", FILE__, __LINE__);
288                 printSerErr(err);
289                 return false;
290         }
291         return true;
292 }
293
294 bool add_annotations(SerializerBase *sb, AnnotatableSparse *an, std::vector<ser_rec_t> &sers)
295 {
296         if (sers.size())
297                 serialize_printf("%s[%d]:  welcome to addAnnotations: got %lu\n", FILE__, __LINE__, sers.size());
298         //  if we are not doing deserialization, there is nothing to do here, just return true
299         //  to keep from triggering error handling.
300         if (sb->isOutput())
301                 return true;
302         bool err = false;
303         for (unsigned int i = 0; i < sers.size(); ++i)
304         {
305                 ser_rec_t &sr = sers[i];
306                 if (!sr.data)
307                 {
308                         fprintf(stderr, "%s[%d]:  bad deserialize annotation record\n", FILE__, __LINE__);
309                         err = true;
310                         continue;
311                 }
312                 if (!sr.acb)
313                 {
314                         fprintf(stderr, "%s[%d]:  bad deserialize annotation record\n", FILE__, __LINE__);
315                         err = true;
316                         continue;
317                 }
318
319                 if (!an->addAnnotation(sr.data, sr.acb->getID()))
320                 {
321                         fprintf(stderr, "%s[%d]:  failed to add deserialized annotation here\n", FILE__, __LINE__);
322                         err = true;
323                 }
324         }
325         return (err == false);
326 }
327 bool add_annotations(SerializerBase *sb, AnnotatableDense *an, std::vector<ser_rec_t> &sers)
328 {
329         serialize_printf("%s[%d]:  welcome to addAnnotations: got %lu\n", FILE__, __LINE__, sers.size());
330         //  if we are not doing deserialization, there is nothing to do here, just return true
331         //  to keep from triggering error handling.
332         if (sb->isOutput())
333                 return true;
334         bool err = false;
335         for (unsigned int i = 0; i < sers.size(); ++i)
336         {
337                 ser_rec_t &sr = sers[i];
338                 if (!sr.data)
339                 {
340                         fprintf(stderr, "%s[%d]:  bad deserialize annotation record\n", FILE__, __LINE__);
341                         err = true;
342                         continue;
343                 }
344                 if (!sr.acb)
345                 {
346                         fprintf(stderr, "%s[%d]:  bad deserialize annotation record\n", FILE__, __LINE__);
347                         err = true;
348                         continue;
349                 }
350                 serialize_printf("%s[%d]:  adding pre annotation\n", FILE__, __LINE__);
351                 if (!an->addAnnotation(sr.data, sr.acb->getID()))
352                 {
353                         fprintf(stderr, "%s[%d]:  failed to add deserialized annotation here\n", FILE__, __LINE__);
354                         err = true;
355                 }
356         }
357         return (err == false);
358 }
359 }
360 bool dummy_bs()
361 {
362    fprintf(stderr, "%s[%d]:  \n", FILE__, __LINE__);
363    return true;
364 }