Warning cleanup. Applying RH's Dyninst patches to 8.1, this one originally by Willia...
[dyninst.git] / common / src / Annotatable.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 // $Id: Annotatable.C,v 1.12 2008/11/03 15:19:23 jaw Exp $
32
33 #include "common/h/headers.h"
34 #include "dyntypes.h"
35 #include "Annotatable.h"
36 #include "Serialization.h"
37 #include "common/h/serialize.h"
38
39 using namespace Dyninst;
40
41 #if defined (NON_STATIC_SPARSE_MAP)
42 char buffer[1024];
43 //AnnotatableSparse::annos_t *AnnotatableSparse::annos = NULL;
44 AnnotatableSparse::annos_t *annos = NULL;
45 AnnotatableSparse::annos_t *AnnotatableSparse::getAnnos() const
46 {
47         if (!annos)
48         {
49                 sprintf(buffer, "booga_booga");
50                 annos = new annos_t();
51         }
52         return annos;
53 }
54 #else
55 AnnotatableSparse::annos_t AnnotatableSparse::annos;
56 AnnotatableSparse::annos_t *AnnotatableSparse::getAnnos() const
57 {
58         return &annos;
59 }
60 #endif
61
62 dyn_hash_map<void *, unsigned short> AnnotatableSparse::ser_ndx_map;
63
64 namespace Dyninst 
65 {
66
67 bool dyn_debug_annotations = false;
68 bool annotation_debug_flag()
69 {
70         return dyn_debug_annotations;
71 }
72
73 void annotations_debug_init()
74 {
75         if (dyn_debug_annotations) return;
76
77         if (getenv("DYNINST_DEBUG_ANNOTATIONS")) {
78                 fprintf(stderr, "Enabling DyninstAPI annotations debug\n");
79                 dyn_debug_annotations = true;
80         }
81         else if (getenv("DYNINST_DEBUG_ANNOTATION")) {
82                 fprintf(stderr, "Enabling DyninstAPI annotations debug\n");
83                 dyn_debug_annotations = true;
84         }
85         else if (getenv("DYNINST_DEBUG_ANNOTATABLE")) {
86                 fprintf(stderr, "Enabling DyninstAPI annotations debug\n");
87                 dyn_debug_annotations = true;
88         }
89 }
90
91 int annotatable_printf(const char *format, ...)
92 {
93         if (!dyn_debug_annotations) return 0;
94         if (NULL == format) return -1;
95
96         //debugPrintLock->_Lock(FILE__, __LINE__);
97
98         //  probably want to have basic thread-id routines in libcommon...
99         //  uh...  later....
100
101         //fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
102         va_list va;
103         va_start(va, format);
104         int ret = vfprintf(stderr, format, va);
105         va_end(va);
106
107         //debugPrintLock->_Unlock(FILE__, __LINE__);
108
109         return ret;
110 }
111
112 COMMON_EXPORT int AnnotationClass_nextId;
113
114 bool void_ptr_cmp_func(void *v1, void *v2)
115 {
116         return v1 == v2;
117 }
118 }
119
120 std::vector<AnnotationClassBase *> *AnnotationClassBase::annotation_types = NULL;
121 dyn_hash_map<std::string, AnnotationClassID> *AnnotationClassBase::annotation_ids_by_name = NULL;
122
123 AnnotationClassBase::AnnotationClassBase(std::string n, 
124                 anno_cmp_func_t cmp_func_, 
125                 ser_func_t sf_) :
126    name(n),
127    serialize_func(sf_)
128 {
129         annotations_debug_init();
130     // Using a static vector led to the following pattern on AIX:
131     //   dyninstAPI static initialization
132     //     ... add annotation types
133     //   common static initialization
134     //     ... vector constructor called, resetting size to 0.
135
136     if (annotation_types == NULL)
137         annotation_types = new std::vector<AnnotationClassBase *>;
138     if (annotation_ids_by_name == NULL)
139         annotation_ids_by_name = new dyn_hash_map<std::string, AnnotationClassID>;
140
141    if (NULL == cmp_func_)
142       cmp_func = void_ptr_cmp_func;
143    else
144       cmp_func = cmp_func_;
145
146    dyn_hash_map<std::string, AnnotationClassID>::iterator iter;
147    iter = annotation_ids_by_name->find(n);
148    if (iter == annotation_ids_by_name->end()) 
149    {
150       id = (AnnotationClassID) annotation_types->size();
151           annotatable_printf("%s[%d]:  New AnnotationClass %d: %s\n", 
152                           FILE__, __LINE__, id, n.c_str());
153       annotation_types->push_back(this);
154       (*annotation_ids_by_name)[name] = id;
155    }
156    else
157    {
158       id = iter->second;
159           annotatable_printf("%s[%d]:  Existing AnnotationClass %d\n", FILE__, __LINE__, id);
160    }
161
162    if (id >= annotation_types->size())
163            assert(0 && "bad anno id");
164 }
165
166 AnnotationClassBase::~AnnotationClassBase()
167 {
168         //  Still waffling...  maybe a bad idea
169 #if 0 
170         //  The general rule in dyninst/symtab etc is to use global/static
171         //  Annotation classes, so they never go away.  This is good.
172         //  But in the testsuite, we have a bunch of transient fly-by-night
173         //  AnnotationClasses for the purposes of testing.  
174         //
175         //  This may be a bit dangerous and might require a bit more thought,
176         //  but for now, if this AnnotationClass was the last one allocated
177         //  remove it from the static mapping so it can be reused.
178
179         if (!annotation_types)  return; //  should never happen
180         if (id >= annotation_types->size()) return; //  should never happen
181         if (id == (annotation_types->size() -1))
182         {
183                 annotatable_printf("%s[%d]:  removing annotation class %d: %s\n", 
184                                 FILE__, __LINE__, id, name.c_str());
185                 //  this is the special case where we can "undo" the existence of
186                 // the annotation type
187                 annotation_types->pop_back();
188                 assert((*annotation_types)[id] == this);
189                 dyn_hash_map<std::string, AnnotationClassID>::iterator iter;
190                 iter = annotation_ids_by_name->find(name);
191                 if (iter != annotation_ids_by_name->end()) 
192                 {
193                         annotation_ids_by_name->erase(iter);
194                 }
195         }
196 #endif
197 }
198
199 #if 0
200 void AnnotationClassBase::clearAnnotationIDMap()
201 {
202         if (!annotation_ids_by_name) return;
203         annotation_ids_by_name->clear();
204         delete annotation_ids_by_name;
205         annotation_ids_by_name = NULL;
206 }
207 #endif
208
209 Dyninst::AnnotationClassBase* AnnotationClassBase::findAnnotationClass(unsigned int id)
210 {
211         if(id > annotation_types->size())
212         {
213                 fprintf(stderr, "%s[%d]:  cannot find annotation class base for id %d, max is %ld\n", FILE__, __LINE__, id, (long int) annotation_types->size());
214                 return NULL;
215         }
216         if (NULL == (*annotation_types)[id])
217         {
218                 fprintf(stderr, "%s[%d]:  FIXME:  have NULL slot\n", FILE__, __LINE__);
219         }
220         if ((*annotation_types)[id]->getID() != id)
221         {
222                 fprintf(stderr, "%s[%d]:  FIXME:  have bad id in annotation class: %d, not %d\n", FILE__, __LINE__, (*annotation_types)[id]->getID(), id);
223                 return NULL;
224         }
225         return (*annotation_types)[id];
226 }
227 void AnnotationClassBase::dumpAnnotationClasses()
228 {
229         fprintf(stderr, "%s[%d]: have the following annotation classes:\n", FILE__, __LINE__);
230         for (unsigned int i = 0; i < annotation_types->size(); ++i)
231         {
232                 AnnotationClassBase *acb = (*annotation_types)[i];
233                 if (!acb)
234                 {
235                         fprintf(stderr, "\t<NULL>\n");
236                         continue;
237                 }
238                 fprintf(stderr, "\tid-%d\t%s, type %s\n", acb->getID(), acb->getName().c_str(), acb->getTypeName());
239         }
240 }
241
242 namespace Dyninst {
243
244 #if !defined(SERIALIZATION_DISABLED)
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
328 bool add_annotations(SerializerBase *sb, AnnotatableDense *an, std::vector<ser_rec_t> &sers)
329 {
330         serialize_printf("%s[%d]:  welcome to addAnnotations: got %lu\n", FILE__, __LINE__, sers.size());
331         //  if we are not doing deserialization, there is nothing to do here, just return true
332         //  to keep from triggering error handling.
333         if (sb->isOutput())
334                 return true;
335         bool err = false;
336         for (unsigned int i = 0; i < sers.size(); ++i)
337         {
338                 ser_rec_t &sr = sers[i];
339                 if (!sr.data)
340                 {
341                         fprintf(stderr, "%s[%d]:  bad deserialize annotation record\n", FILE__, __LINE__);
342                         err = true;
343                         continue;
344                 }
345                 if (!sr.acb)
346                 {
347                         fprintf(stderr, "%s[%d]:  bad deserialize annotation record\n", FILE__, __LINE__);
348                         err = true;
349                         continue;
350                 }
351                 serialize_printf("%s[%d]:  adding pre annotation\n", FILE__, __LINE__);
352                 if (!an->addAnnotation(sr.data, sr.acb->getID()))
353                 {
354                         fprintf(stderr, "%s[%d]:  failed to add deserialized annotation here\n", FILE__, __LINE__);
355                         err = true;
356                 }
357         }
358         return (err == false);
359 }
360
361 #else
362 bool is_input(SerializerBase *)
363 {
364    return false;
365 }
366
367 bool is_output(SerializerBase *) {
368    return false;
369 }
370
371 bool serialize_annotation_list(void *, std::vector<ser_rec_t> &, SerializerBase *, const char *) {
372    return false;
373 }
374
375 bool serialize_post_annotation(void *, void *, SerializerBase *, AnnotationClassBase *, sparse_or_dense_anno_t, const char *) {
376    return false;
377 }
378
379 bool add_annotations(SerializerBase *, AnnotatableSparse *, std::vector<ser_rec_t> &) {
380    return false;
381 }
382
383 bool add_annotations(SerializerBase *, AnnotatableDense *, std::vector<ser_rec_t> &) {
384    return false;
385 }
386 #endif
387
388 }
389 bool dummy_bs()
390 {
391    fprintf(stderr, "%s[%d]:  \n", FILE__, __LINE__);
392    return true;
393 }