export more serializer interface to allow for finer grain testing
[dyninst.git] / common / src / serialize-bin.C
1
2 /*
3  * Copyright (c) 1996-2007 Barton P. Miller
4  * 
5  * We provide the Paradyn Parallel Performance Tools (below
6  * described as "Paradyn") on an AS IS basis, and do not warrant its
7  * validity or performance.  We reserve the right to update, modify,
8  * or discontinue this software at any time.  We shall have no
9  * obligation to supply such updates or modifications or any other
10  * form of support to you.
11  * 
12  * By your use of Paradyn, you understand and agree that we (or any
13  * other person or entity with proprietary rights in Paradyn) are
14  * under no obligation to provide either maintenance services,
15  * update services, notices of latent defects, or correction of
16  * defects for Paradyn.
17  * 
18  * This library is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU Lesser General Public
20  * License as published by the Free Software Foundation; either
21  * version 2.1 of the License, or (at your option) any later version.
22  * 
23  * This library is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26  * Lesser General Public License for more details.
27  * 
28  * You should have received a copy of the GNU Lesser General Public
29  * License along with this library; if not, write to the Free Software
30  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
31  */
32
33 #include <stdio.h>
34 #include <vector>
35
36 #include "dynutil/h/dyntypes.h"
37 #include "dynutil/h/Annotatable.h"
38 #include "common/h/serialize.h"
39 #include "common/h/Types.h"
40 #include "common/h/headers.h"
41
42 using namespace Dyninst;
43
44 //COMMON_EXPORT dyn_hash_map<Address, AnnotatableBase *> SerDesBin::annotatable_id_map;
45
46
47 COMMON_EXPORT dyn_hash_map<std::string, SerializerBase::subsystem_serializers_t> SerializerBase::all_serializers;
48
49
50 namespace Dyninst {
51 bool dyn_debug_serializer = false;
52 bool &serializer_debug_flag()
53 {
54    //  This function exists to get around problems with exporting the variable
55    //  across library boundaries on windows...   there's probably a better way to do this...
56    return dyn_debug_serializer;
57 }
58
59 void ser_func_wrapper(void *it, SerializerBase *sb, 
60                 const char *tag)
61 {   
62         assert(it);
63         assert(sb);
64         Serializable *s = (Serializable *) (it);
65         s->serialize(sb, tag);
66 }   
67
68
69 void serialize_debug_init()
70 {
71    char *p;
72    if ( (p=getenv("DYNINST_DEBUG_SERIALIZER"))) {
73       fprintf(stderr, "Enabling DyninstAPI serializer debug\n");
74       dyn_debug_serializer = true;
75    }
76 }
77
78
79 int serializer_printf(const char *format, ...) 
80 {   
81    if (!dyn_debug_serializer) return 0;
82    if (NULL == format) return -1;
83
84    //debugPrintLock->_Lock(FILE__, __LINE__);
85
86    //  probably want to have basic thread-id routines in libcommon...
87    //  uh...  later....
88
89    //fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
90    va_list va;
91    va_start(va, format);
92    int ret = vfprintf(stderr, format, va);
93    va_end(va);
94
95    //debugPrintLock->_Unlock(FILE__, __LINE__);
96
97    return ret;
98
99
100 void Serializable::serialize(SerializerBase *sb, const char *tag) THROW_SPEC(SerializerError)
101 {
102         //  do base serialization for this class
103         serialize_impl(sb, tag);
104
105         //  then serialize all Annotations for which a serialization function has been provided
106         AnnotatableSparse *as = dynamic_cast<AnnotatableSparse *> (this);
107         if (as)
108                 as->serializeAnnotations(sb, tag);
109         AnnotatableDense *ad = dynamic_cast<AnnotatableDense *> (this);
110         if (ad)
111                 ad->serializeAnnotations(sb, tag);
112
113
114         
115 }
116
117 dyn_hash_map<const char*, deserialize_and_annotate_t> annotation_deserializers;
118
119 bool addDeserializeFuncForType(deserialize_and_annotate_t f, const std::type_info *ti)
120 {
121    dyn_hash_map<const char *, deserialize_and_annotate_t>::iterator iter;
122    iter = annotation_deserializers.find(ti->name());
123
124    if (iter != annotation_deserializers.end())
125    {
126       fprintf(stderr, "%s[%d]:  WARN:  already have deserialization function for type %s\n", 
127             FILE__, __LINE__, ti->name());
128       return false;
129    }
130
131    annotation_deserializers[ti->name()] = f;
132    return true;
133 }
134
135 deserialize_and_annotate_t getDeserializeFuncForType(const std::type_info *ti)
136 {
137    dyn_hash_map<const char *, deserialize_and_annotate_t>::iterator iter;
138    iter = annotation_deserializers.find(ti->name());
139
140    if (iter == annotation_deserializers.end())
141    {
142       fprintf(stderr, "%s[%d]:  WARN:  no deserialization function for type %s\n", 
143             FILE__, __LINE__, ti->name());
144       return NULL;
145    }
146
147    return iter->second;
148 }
149
150 void printSerErr(const SerializerError &err) 
151 {
152    fprintf(stderr, "\tserializer exception %s from \n\t%s[%d]\n", 
153          err.what(), err.file().c_str(), err.line());
154 }
155
156
157 bool isOutput(Dyninst::SerializerBase *ser)
158 {
159    return (ser->iomode() == sd_serialize);
160 }
161
162 bool isBinary(Dyninst::SerializerBase *ser)
163 {
164 #if 0
165    SerializerBin *sb = dynamic_cast<SerializerBin *>(ser);
166    return (sb != NULL);
167 #endif
168    return ser->isBin();
169 }
170
171 void trans_adapt(SerializerBase *ser, Serializable &it, const char *tag)
172 {
173    it.serialize(ser, tag);
174 }
175
176 void trans_adapt(SerializerBase *ser, Serializable  *itp, const char *tag)
177 {
178    assert(itp);
179    trans_adapt(ser, *itp, tag);
180 }
181
182 void trans_adapt(SerializerBase *ser, bool &it, const char *tag)
183 {
184    assert(ser);
185    ser->translate_base(it, tag);
186 }
187
188 void trans_adapt(SerializerBase *ser, int &it, const char *tag)
189 {
190    assert(ser);
191    ser->translate_base(it, tag);
192 }
193
194 void trans_adapt(SerializerBase *ser, unsigned int &it, const char *tag)
195 {
196    assert(ser);
197    ser->translate_base(it, tag);
198 }
199
200 void trans_adapt(SerializerBase *ser, long &it, const char *tag)
201 {
202    assert(ser);
203    ser->translate_base(it, tag);
204 }
205
206 void trans_adapt(SerializerBase *ser, unsigned long &it, const char *tag)
207 {
208    assert(ser);
209    ser->translate_base(it, tag);
210 }
211
212 void trans_adapt(SerializerBase *ser, char &it, const char *tag)
213 {
214    assert(ser);
215    ser->translate_base(it, tag);
216 }
217
218 void trans_adapt(SerializerBase *ser, char *&it, const char *tag)
219 {
220    assert(ser);
221    assert(it);
222    int s_len = strlen(it);
223    ser->translate_base(const_cast<const char *&>(it), s_len, tag);
224 }
225
226 void trans_adapt(SerializerBase *ser, std::string &it, const char *tag)
227 {
228    assert(ser);
229    ser->translate_base(it, tag);
230 }
231
232 void trans_adapt(SerializerBase *ser, float &it, const char *tag)
233 {
234    assert(ser);
235    ser->translate_base(it, tag);
236 }
237
238 void trans_adapt(SerializerBase *ser, double  &it, const char *tag)
239 {
240    assert(ser);
241    ser->translate_base(it, tag);
242 }
243
244 #if 0
245 COMMON_EXPORT bool ifxml_start_element(SerializerBase *sb, const char *tag)
246 {
247    SerializerXML *sxml = dynamic_cast<SerializerXML *>(sb);
248    if (!sxml) {
249       return false;
250    }
251
252    if (sxml->iomode() == sd_deserialize) {
253       fprintf(stderr, "%s[%d]:  ERROR:  request to deserialize xml\n", FILE__, __LINE__);
254       return false;
255    }
256
257    sxml->getSD_xml().start_element(tag);
258
259    return true;
260 }
261
262 COMMON_EXPORT bool ifxml_end_element(SerializerBase *sb, const char * /*tag*/)
263 {
264    SerializerXML *sxml = dynamic_cast<SerializerXML *>(sb);
265    if (!sxml) {
266       return false;
267    }
268
269    if (sxml->iomode() == sd_deserialize) {
270       fprintf(stderr, "%s[%d]:  ERROR:  request to deserialize xml\n", FILE__, __LINE__);
271       return false;
272    }
273
274    sxml->getSD_xml().end_element();
275
276    return true;
277 }
278 #endif
279
280 bool sb_is_input(SerializerBase *sb) 
281 {
282    return  (sb->iomode() == sd_deserialize);
283 }
284
285 bool sb_is_output(SerializerBase *sb) 
286 {
287    return  (sb->iomode() == sd_serialize);
288 }
289
290 } /* namespace Dyninst */
291
292 bool SerializerBase::global_disable = false;
293 COMMON_EXPORT dyn_hash_map<std::string, SerializerBase *> SerializerBase::active_bin_serializers;
294
295 #if 0
296 SerDesBin &SerializerBin::getSD_bin()
297 {
298    SerDes &sd = getSD();
299    SerDesBin *sdbin = dynamic_cast<SerDesBin *> (&sd);
300    assert(sdbin);
301    return *sdbin;
302 }
303 #endif
304
305 #if 0
306 //bool SerializerBin::global_disable = false;
307 dyn_hash_map<const char *, SerializerBase *> SerializerBase::active_bin_serializers;
308 #endif
309
310 void SerializerBase::dumpActiveBinSerializers()
311 {
312    fprintf(stderr, "%s[%d]:  have serializers:\n", FILE__, __LINE__);
313
314    dyn_hash_map<std::string, SerializerBase *>::iterator iter;
315
316    for (iter = active_bin_serializers.begin(); 
317          iter != active_bin_serializers.end(); 
318          iter++)
319    {
320       fprintf(stderr, "\t%s--%p\n", iter->first.c_str(), iter->second);
321    }
322 }
323
324
325 #if 0
326 template <class T>
327 SerializerBin::SerializerBin(const char *name_, std::string filename, 
328                 iomode_t dir, bool verbose) :
329         ScopedSerializerBase<T>(name_, filename, dir, verbose) 
330 {
331         if (global_disable) 
332         {
333                 fprintf(stderr, "%s[%d]:  Failing to construct Bin Translator:  global disable set\n", 
334                                 FILE__, __LINE__);
335
336                 throw SerializerError(FILE__, __LINE__, 
337                                 std::string("serialization disabled"), 
338                                 SerializerError::ser_err_disabled);
339         }
340
341         dyn_hash_map<const char *, SerializerBin *>::iterator iter;
342
343         iter = active_bin_serializers.find(name_);
344
345         if (iter == active_bin_serializers.end()) 
346         {
347                 fprintf(stderr, "%s[%d]:  Adding Active serializer for name %s\n", 
348                                 FILE__, __LINE__, name_);
349
350                 active_bin_serializers[name_] = this;
351         }
352         else
353         {
354                 fprintf(stderr, "%s[%d]:  Weird, already have active serializer for name %s\n", 
355                                 FILE__, __LINE__, name_);
356         }
357
358 }
359 #endif
360 #if 0
361 template <class T>
362 SerializerBin::~SerializerBin()
363 {
364    dyn_hash_map<const char *, SerializerBin *>::iterator iter;
365
366    iter = active_bin_serializers.find(name().c_str());
367
368    if (iter == active_bin_serializers.end()) 
369    {
370       fprintf(stderr, "%s[%d]:  Weird, no static ptr for name %s\n", 
371             FILE__, __LINE__, name().c_str());
372    }
373    else
374    {
375       fprintf(stderr, "%s[%d]:  Removing active serializer for name %s\n", 
376             FILE__, __LINE__, name().c_str());
377       active_bin_serializers.erase(iter);
378    }
379 }
380 #endif
381
382 #if 0
383 SerializerBin *SerializerBin::findSerializerByName(const char *name_)
384 {
385    dyn_hash_map<const char *, SerializerBin *>::iterator iter;
386
387    iter = active_bin_serializers.find(name_);
388
389    if (iter == active_bin_serializers.end()) 
390    {
391       fprintf(stderr, "%s[%d]:  No static ptr for name %s\n", 
392             FILE__, __LINE__, name_);
393       dumpActiveBinSerializers();
394    }
395    else
396    {
397       fprintf(stderr, "%s[%d]:  Found active serializer for name %s\n", 
398             FILE__, __LINE__, name_);
399
400       return iter->second;
401    }
402
403    return NULL;
404 }
405
406 void SerializerBin::globalDisable()
407 {
408    global_disable = true;
409 }
410
411 void SerializerBin::globalEnable()
412 {
413    global_disable = false;
414 }
415 #endif
416
417 FILE *SerDesBin::init(std::string filename, iomode_t mode, bool /*verbose*/) 
418 {
419    if (SerializerBase::serializationDisabled()) 
420    {
421       fprintf(stderr, "%s[%d]:  Failing to construct Bin Translator:  global disable set\n", FILE__, __LINE__);
422       throw SerializerError(FILE__, __LINE__, 
423             std::string("serialization disabled"), 
424             SerializerError::ser_err_disabled);
425    }
426
427    FILE *f = NULL;
428    //  NOTE:  fname is path-resolved and turned into "filename" by the SerDes ctor
429    std::string cache_name;
430    if (! SerDesBin::resolveCachePath(filename, cache_name)) {
431       serialize_printf("%s[%d]:  no cache file exists for %s\n", 
432             FILE__, __LINE__, filename.c_str());
433       if (mode == sd_deserialize) {
434          //  can't deserialize from a file that does not exist
435          char msg[128];
436          sprintf(msg, "%s[%d]:  no cache file exists for %s\n", 
437                FILE__, __LINE__, filename.c_str());
438          SER_ERR(msg);
439       }
440    }
441
442    errno = 0;
443    serialize_printf("%s[%d]:  opening cache file %s\n", FILE__, __LINE__, cache_name.c_str());
444    f = fopen(cache_name.c_str(), (mode == sd_serialize) ? "w+" : "r");
445    if (!f) {
446       char msg[128];
447       serialize_printf("%s[%d]: fopen(%s, %s): %s\n", FILE__, __LINE__, 
448             cache_name.c_str(), (mode == sd_serialize) ? "w+" : "r", strerror(errno));
449       sprintf(msg, "fopen(%s, %s): %s", cache_name.c_str(), 
450             (mode == sd_serialize) ? "w+" : "r", strerror(errno));
451       SER_ERR(msg);
452    }
453
454    serialize_printf("%s[%d]:  opened cache file %s: %s\n", FILE__, __LINE__, cache_name.c_str(), strerror(errno));
455
456    try {
457       if (mode == sd_serialize){
458          writeHeaderPreamble(f, filename, cache_name);
459       }
460       else {
461          readHeaderAndVerify(filename, cache_name, f);
462       }
463    }
464    catch(const SerializerError &err) {
465       fclose(f);
466       serialize_printf("%s[%d]:  %sserialize failed init...  \n\t%s[%d]: %s\n\trethrowing...\n",
467             FILE__, __LINE__, mode == sd_serialize ? "" : "de", 
468             err.file().c_str(), err.line(), err.what());
469       throw(err);
470    }
471
472    return f;
473 }
474
475 SerDesBin::~SerDesBin()
476 {
477 }
478
479 bool SerDesBin::getDefaultCacheDir(std::string &path)
480 {
481    char *home_dir = getenv("HOME");
482    if (!home_dir) {
483       fprintf(stderr, "%s[%d]:  weird, no $HOME dir\n", FILE__, __LINE__);
484       return false;
485    }
486
487    std::string dot_dyninst_dir = std::string(home_dir) + std::string("/")
488       + std::string(DEFAULT_DYNINST_DIR);
489
490    struct stat statbuf;
491    if (0 != stat(dot_dyninst_dir.c_str(), &statbuf)) {
492       if (errno == ENOENT) {
493 #if defined (os_windows)
494          if (0 != P_mkdir(dot_dyninst_dir.c_str(), 0)) {
495             fprintf(stderr, "%s[%d]:  failed to make %s\n", FILE__, __LINE__, 
496                   dot_dyninst_dir.c_str(), strerror(errno));
497             return false;
498          } 
499 #else
500          if (0 != mkdir(dot_dyninst_dir.c_str(), S_IRWXU)) {
501             fprintf(stderr, "%s[%d]:  failed to make %s: %s\n", FILE__, __LINE__, 
502                   dot_dyninst_dir.c_str(), strerror(errno));
503             return false;
504          } 
505 #endif
506       }
507       else {
508          fprintf(stderr, "%s[%d]:  stat(%s) failed: %s\n", FILE__, __LINE__, 
509                dot_dyninst_dir.c_str(), strerror(errno));
510          return false;
511       }
512    }
513    else {
514 #if !defined (os_windows)
515       //  sanity check that its a dir
516       if (!S_ISDIR(statbuf.st_mode)) {
517          fprintf(stderr, "%s[%d]:  ERROR:  %s is not a dir\n", FILE__, __LINE__, 
518                dot_dyninst_dir.c_str());
519          return false;
520       }
521 #else
522       //  windows equiv to S_ISDIR??
523 #endif
524    }
525
526    path = dot_dyninst_dir + std::string("/") + std::string(DEFAULT_CACHE_DIR);
527
528    if (0 != stat(path.c_str(), &statbuf)) {
529       if (errno == ENOENT) {
530 #if defined (os_windows)
531          if (0 != P_mkdir(path.c_str(), 0)) {
532             fprintf(stderr, "%s[%d]:  failed to make %s\n", FILE__, __LINE__, 
533                   path.c_str(), strerror(errno));
534             return false;
535          } 
536 #else
537          if (0 != mkdir(path.c_str(), S_IRWXU)) {
538             fprintf(stderr, "%s[%d]:  failed to make %s: %s\n", FILE__, __LINE__, 
539                   path.c_str(), strerror(errno));
540             return false;
541          } 
542 #endif
543       }
544       else {
545          fprintf(stderr, "%s[%d]:  stat(%s) failed: %s\n", FILE__, __LINE__, 
546                path.c_str(), strerror(errno));
547          return false;
548       }
549    }
550    else {
551 #if !defined (os_windows)
552       //  sanity check that its a dir
553       if (!S_ISDIR(statbuf.st_mode)) {
554          fprintf(stderr, "%s[%d]:  ERROR:  %s is not a dir\n", FILE__, __LINE__, 
555                path.c_str());
556          return false;
557       }
558 #else
559       //  windows equiv to S_ISDIR??
560 #endif
561    }
562    serialize_printf("%s[%d]:  using default cache dir: %s\n", FILE__, __LINE__, path.c_str());
563    return true;
564 }
565
566 bool SerDesBin::resolveCachePath(std::string full_file_path, std::string &cache_name)
567 {
568    std::string path;
569    char *path_dir = getenv(CACHE_DIR_VAR); 
570    if (!path_dir) {
571       if (!getDefaultCacheDir(path)) {
572          fprintf(stderr, "%s[%d]:  weird, failed to make $HOME/.dyninst/caches\n",
573                FILE__, __LINE__);
574          return false;
575       }
576    }
577
578    // get size of file (this is encoded into cache name)
579    struct stat statbuf;
580    if (0 != stat(full_file_path.c_str(), &statbuf)) {
581       fprintf(stderr, "%s[%d]:  stat %s failed: %s\n", FILE__, __LINE__, 
582             full_file_path.c_str(), strerror(errno));
583       return false;
584    }
585
586    std::string short_name = extract_pathname_tail(full_file_path);
587    serialize_printf("%s[%d]:  file %s short name: %s\n", FILE__, __LINE__, 
588          full_file_path.c_str(), short_name.c_str());
589
590    // construct cache name from cache path, cache prefix, short name, and size
591    char sizestr[16];
592    sprintf(sizestr, "%d", (int)statbuf.st_size);
593    cache_name = path + std::string("/") + std::string(CACHE_PREFIX) + short_name 
594       + std::string("_") 
595       + std::string(sizestr);
596
597    serialize_printf("%s[%d]:  constructed cache name: %s\n", FILE__, __LINE__, cache_name.c_str());
598    if (0 != stat(cache_name.c_str(), &statbuf)) {
599       if (errno != ENOENT) {
600          //  Its OK if the file doesn't exist, but complain if we get a different
601          // error
602          fprintf(stderr, "%s[%d]:  stat %s failed: %s\n", FILE__, __LINE__, 
603                cache_name.c_str(), strerror(errno));
604       }
605       serialize_printf("%s[%d]:  cache file %s does not exist\n", FILE__, __LINE__, 
606             cache_name.c_str());
607       return false;
608    }
609
610    serialize_printf("%s[%d]:  cache file %s exists\n", FILE__, __LINE__, cache_name.c_str());
611    return true;
612 }
613
614 bool SerDesBin::cacheFileExists(std::string fname)
615 {
616    std::string cache_name;
617    return resolveCachePath(fname, cache_name); 
618 }
619
620 void SerDesBin::readHeaderAndVerify(std::string full_file_path, std::string cache_name, FILE *fptr)
621 {
622    struct stat statbuf;
623
624    if (0 != stat(full_file_path.c_str(), &statbuf)) {
625       char msg[128];
626       if (errno != ENOENT) {
627          //  Its OK if the file doesn't exist, but complain if we get a different
628          // error
629          sprintf(msg, "%s[%d]:  stat %s failed: %s\n", FILE__, __LINE__, 
630                full_file_path.c_str(), strerror(errno));
631       }
632       SER_ERR(msg);
633    }
634
635    FILE *f = NULL;
636    if (fptr) 
637       f = fptr;
638    else {
639            serialize_printf("%s[%d]:  trying to open %s\n", FILE__, __LINE__, cache_name.c_str());
640       f = fopen(cache_name.c_str(), "r");
641       if (!f) {
642          char msg[128];
643          sprintf(msg, "%s[%d]:  failed to open file %s: %s\n", 
644                FILE__, __LINE__, full_file_path.c_str(), strerror(errno));
645          SER_ERR(msg);
646       }
647    }
648
649    size_t source_file_size = statbuf.st_size;
650
651    cache_header_t header;
652    int rc = fread(&header, sizeof(cache_header_t), 1, f);
653    if (1 != rc) {
654       char msg[128];
655       sprintf(msg, "%s[%d]:  failed to read header struct for %s: %s\n", 
656             FILE__, __LINE__, cache_name.c_str(), strerror(errno));
657       SER_ERR(msg);
658    }
659
660    if (header.cache_magic != (unsigned) CACHE_MAGIC) {
661       char msg[128];
662       sprintf(msg, "%s[%d]:  magic number check failure for %s--%s: got %d, expected %d\n", 
663             FILE__, __LINE__, full_file_path.c_str(), cache_name.c_str(), header.cache_magic, CACHE_MAGIC);
664       SER_ERR(msg);
665    }
666
667    if (header.source_file_size != source_file_size) 
668    {
669       char msg[128];
670       sprintf(msg, "%s[%d]:  size discrepancy found for %s/%s\n", 
671             FILE__, __LINE__, full_file_path.c_str(), cache_name.c_str());
672       SER_ERR(msg);
673    }
674
675    if (!verifyChecksum(full_file_path, header.sha1)) 
676    {
677       char msg[128];
678       sprintf(msg, "%s[%d]:  checksum discrepancy found for %s/%s\n", 
679             FILE__, __LINE__, full_file_path.c_str(), cache_name.c_str());
680
681       if (!invalidateCache(cache_name)) {
682          fprintf(stderr, "%s[%d]:  failed to invalidate cache for file %s/%s\n", 
683                FILE__, __LINE__, full_file_path.c_str(), cache_name.c_str());
684       }
685
686       SER_ERR(msg);
687    }
688
689    if (!fptr)
690    {
691            fprintf(stderr, "%s[%d]:  closing file pointer here\n", FILE__, __LINE__);
692       fclose (f);
693    }
694 }
695
696
697 void SerDesBin::writeHeaderPreamble(FILE *f, std::string full_file_path, std::string /*cache_name*/)
698 {
699    serialize_printf("%s[%d]:  welcome to write header preamble for %s\n", FILE__, __LINE__, full_file_path.c_str());
700
701    //  get a few bits of info on this file to construct the header of the cache
702    //  file...  checksum, size, ...  not mtime, since we don't care if someone 
703    //  copies the file around
704
705    struct stat statbuf;
706    if (0 != stat(full_file_path.c_str(), &statbuf)) {
707       char msg[128];
708       sprintf(msg, "%s[%d]:  stat %s failed: %s\n", FILE__, __LINE__, 
709             full_file_path.c_str(), strerror(errno));
710       SER_ERR(msg);
711    }
712
713    cache_header_t header;
714    header.cache_magic = CACHE_MAGIC;
715    header.source_file_size = statbuf.st_size;
716
717    if (NULL == sha1_file(full_file_path.c_str(), header.sha1)) {
718       char msg[128];
719       sprintf(msg, "sha1_file failed\n");
720       SER_ERR(msg);
721    }
722
723    int rc = fwrite(&header, sizeof(cache_header_t), 1, f);
724
725    if (1 != rc) 
726       SER_ERR("fwrite");
727
728 }
729
730 bool SerDesBin::verifyChecksum(std::string &full_file_path, 
731       const char comp_checksum[SHA1_DIGEST_LEN*2])
732 {
733    char new_checksum[SHA1_DIGEST_LEN*2]; 
734    if (NULL == sha1_file(full_file_path.c_str(), new_checksum)) {
735       fprintf(stderr, "%s[%d]:  sha1_file(%s) failed \n", 
736             FILE__, __LINE__, full_file_path.c_str());
737       return false;
738    }
739
740    if (strncmp(comp_checksum, new_checksum, SHA1_DIGEST_LEN*2)) {
741       fprintf(stderr, "%s[%d]:  sha1_file(%s): checksum mismatch: \n\told:%s\n\tnew:%s\n", 
742             FILE__, __LINE__, full_file_path.c_str(), comp_checksum, new_checksum);
743       return false;
744    }
745
746    return true;
747 }
748
749 bool SerDesBin::invalidateCache(std::string cache_name) 
750 {
751    if (-1 == P_unlink(cache_name.c_str())) {
752       fprintf(stderr, "%s[%d]:  unlink(%s): %s\n", FILE__, __LINE__, 
753             cache_name.c_str(), strerror(errno));
754       return false;
755    }
756
757    return true;
758 }
759
760 void SerDesBin::file_start(std::string &/*full_file_path*/)
761 {
762 }
763
764 void SerDesBin::vector_start(unsigned int &size, const char *) DECLTHROW (SerializerError)
765 {
766    //  before reading/writing a vector, we need to read its size
767    //  (so we know how many elements to read/alloc on deserialize
768    translate(size);
769 }
770
771 void SerDesBin::vector_end()
772 {
773    //  don't need to do anything
774 }
775
776 void SerDesBin::multimap_start(unsigned int &size, const char *) DECLTHROW (SerializerError)
777 {
778    //  before reading/writing a multimap, we need to read its size
779    //  (so we know how many elements to read/alloc on deserialize
780    translate(size);
781 }
782
783 void SerDesBin::multimap_end()
784 {
785    //  don't need to do anything
786 }
787
788 void SerDesBin::hash_map_start(unsigned int &size, const char *) DECLTHROW (SerializerError)
789 {
790    //  before reading/writing a hash map, we need to read its size
791    //  (so we know how many elements to read/alloc on deserialize
792    translate(size);
793 }
794
795 void SerDesBin::hash_map_end() 
796 {
797 }
798
799 void SerDesBin::annotation_start(const char *, const char *)
800 {
801 }
802
803 void SerDesBin::annotation_end()
804 {
805    //  don't need to do anything
806 }
807
808 void SerDesBin::translate(bool &param, const char *tag)
809 {
810    int rc;
811    if (iomode_ == sd_serialize) {
812       rc = fwrite(&param, sizeof(bool), 1, f);
813
814       if (1 != rc) 
815          SER_ERR("fwrite");
816    }
817    else {
818       rc = fread(&param, sizeof(bool), 1, f);
819
820       if (1 != rc) 
821          SER_ERR("fread");
822    }
823
824    if (noisy)
825       serialize_printf("%s[%d]:  %sserialize %s=%s\n", FILE__, __LINE__,
826             iomode_ == sd_serialize ? "" : "de", 
827             tag ? tag : "no-tag",
828             param ? "true": "false");
829 }
830
831 void SerDesBin::translate(char &param, const char *tag)
832 {
833    int rc;
834    if (iomode_ == sd_serialize) {
835       rc = fwrite(&param, sizeof(char), 1, f);
836
837       if (1 != rc) 
838          SER_ERR("fwrite");
839    }
840    else {
841       rc = fread(&param, sizeof(char), 1, f);
842
843       if (1 != rc) 
844          SER_ERR("fread");
845    }
846
847    if (noisy)
848       serialize_printf("%s[%d]:  %sserialize %s=%c\n", FILE__, __LINE__,
849             iomode_ == sd_serialize ? "" : "de", 
850             tag ? tag : "no-tag", param);
851 }
852
853 void SerDesBin::translate(int &param, const char *tag)
854 {
855    int rc;
856    if (iomode_ == sd_serialize) 
857    {
858       rc = fwrite(&param, sizeof(int), 1, f);
859
860       if (1 != rc) 
861          SER_ERR("fwrite");
862    }
863    else 
864    {
865            errno = 0;
866            rc = fread(&param, sizeof(int), 1, f);
867
868       if (1 != rc) 
869           {
870                   fprintf(stderr, "%s[%d]:  failed to deserialize int-'%s', rc = %d:%s, noisy = %d\n", 
871                                   FILE__, __LINE__, tag ? tag : "no_tag", rc, strerror(errno), noisy);
872          SER_ERR("fread");
873           }
874    }
875
876    if (noisy)
877       serialize_printf("%s[%d]:  %sserialize %s=%d\n", FILE__, __LINE__,
878             iomode_ == sd_serialize ? "" : "de", 
879             tag ? tag : "no-tag", param);
880 }
881
882 void SerDesBin::translate(long &param, const char *tag)
883 {
884    int rc;
885    if (iomode_ == sd_serialize) {
886       rc = fwrite(&param, sizeof(long), 1, f);
887
888       if (1 != rc) 
889          SER_ERR("fwrite");
890    }
891    else {
892       rc = fread(&param, sizeof(long), 1, f);
893
894       if (1 != rc) 
895          SER_ERR("fread");
896    }
897
898    if (noisy)
899       serialize_printf("%s[%d]:  %sserialize %s=%lu\n", FILE__, __LINE__,
900             iomode_ == sd_serialize ? "" : "de", 
901             tag ? tag : "no-tag", param);
902 }
903
904 void SerDesBin::translate(short &param, const char *tag)
905 {
906    int rc;
907    if (iomode_ == sd_serialize) {
908       rc = fwrite(&param, sizeof(short), 1, f);
909
910       if (1 != rc) 
911          SER_ERR("fwrite");
912    }
913    else {
914       rc = fread(&param, sizeof(short), 1, f);
915
916       if (1 != rc) 
917          SER_ERR("fread");
918    }
919
920    if (noisy)
921       serialize_printf("%s[%d]:  %sserialize %s=%d\n", FILE__, __LINE__,
922             iomode_ == sd_serialize ? "" : "de", 
923             tag ? tag : "no-tag", param);
924 }
925
926 void SerDesBin::translate(unsigned int &param, const char * tag)
927 {
928    //  overkill for a typecast??
929    translate( (int &) param, tag);
930 }
931
932 void SerDesBin::translate(float &param, const char *tag)
933 {
934    int rc;
935    if (iomode_ == sd_serialize) {
936       rc = fwrite(&param, sizeof(float), 1, f);
937
938       if (1 != rc) 
939          SER_ERR("fwrite");
940    }
941    else {
942       rc = fread(&param, sizeof(float), 1, f);
943
944       if (1 != rc) 
945          SER_ERR("fread");
946    }
947
948    if (noisy)
949       serialize_printf("%s[%d]:  %sserialize %s=%e\n", FILE__, __LINE__,
950             iomode_ == sd_serialize ? "" : "de", 
951             tag ? tag : "no-tag", param);
952 }
953
954 void SerDesBin::translate(double &param, const char *tag)
955 {
956    int rc;
957    if (iomode_ == sd_serialize) {
958       rc = fwrite(&param, sizeof(double), 1, f);
959
960       if (1 != rc) 
961          SER_ERR("fwrite");
962    }
963    else {
964       rc = fread(&param, sizeof(double), 1, f);
965
966       if (1 != rc) 
967          SER_ERR("fread");
968    }
969
970    if (noisy)
971       serialize_printf("%s[%d]:  %sserialize %s=%g\n", FILE__, __LINE__,
972             iomode_ == sd_serialize ? "" : "de", 
973             tag ? tag : "no-tag", param);
974 }
975
976 void SerDesBin::translate(Address &param, const char *tag)
977 {
978    int rc;
979    if (iomode_ == sd_serialize) {
980       rc = fwrite(&param, sizeof(Address), 1, f);
981
982       if (1 != rc) 
983          SER_ERR("fwrite");
984    }
985    else {
986       rc = fread(&param, sizeof(Address), 1, f);
987
988       if (1 != rc) 
989          SER_ERR("fread");
990    }
991
992    if (noisy)
993       serialize_printf("%s[%d]:  %sserialize %s=%lx\n", FILE__, __LINE__,
994             iomode_ == sd_serialize ? "" : "de", 
995             tag ? tag : "no-tag", param);
996 }
997
998 void SerDesBin::translate(const char * &param, int bufsize, const char *tag)
999 {
1000    //  string output format is
1001    //  [1]  length of string
1002    //  [2]  string data
1003    int rc, len;
1004    if (iomode_ == sd_serialize) 
1005    {
1006       len = strlen(param);
1007
1008       rc = fwrite( &len, sizeof(int), 1, f);
1009
1010       if (1 != rc) 
1011          SER_ERR("fwrite");
1012
1013       rc = fwrite(param, sizeof(char), len, f);
1014
1015       if (len != rc) 
1016          SER_ERR("fwrite");
1017    }
1018    else 
1019    {
1020       rc = fread(&len, sizeof(int), 1, f);
1021
1022       if (1 != rc)  
1023       {
1024          fprintf(stderr, "%s[%d]:  fread, got %d not 1: %s\n", FILE__, __LINE__, rc,  strerror(errno));
1025          SER_ERR("fread");
1026       }
1027
1028       if (len > bufsize) 
1029       {
1030          fprintf(stderr, "%s[%d]:  insufficient buffer\n", FILE__, __LINE__);
1031          char msg[128];
1032          sprintf(msg, "not enough space in string buffer, %d needed", len);
1033          SER_ERR("msg");
1034       }
1035
1036       if (len < 0) 
1037       {
1038          fprintf(stderr, "%s[%d]:  bad bufsize %d for %s\n", FILE__, __LINE__, len, tag ? tag : "no_tag");
1039          char msg[128];
1040          sprintf(msg, "bad bufsize, %d ", len);
1041          SER_ERR("msg");
1042       }
1043
1044           char *l_ptr = const_cast<char *> (param);
1045           if (len != 0)
1046           {
1047                   rc = fread(l_ptr, sizeof(char), len, f);
1048
1049                   if (len != rc) 
1050                   {
1051                           fprintf(stderr, "%s[%d]:  fread, got %d not %d: %s\n", 
1052                                           FILE__, __LINE__, rc, len, strerror(errno));
1053                           SER_ERR("fread");
1054                   }
1055           }
1056           else 
1057           {
1058                   //  Zero length strings are allowed
1059                   //fprintf(stderr, "%s[%d]:  WARN:  zero length string for %s\n", FILE__, __LINE__, tag ? tag : "no_tag_provided");
1060           }
1061
1062           l_ptr[len] = '\0';
1063
1064    }
1065
1066    if (noisy)
1067       serialize_printf("%s[%d]:  %sserialize %s=%s\n", FILE__, __LINE__,
1068             iomode_ == sd_serialize ? "" : "de", 
1069             tag ? tag : "no-tag", param);
1070 }
1071
1072 void SerDesBin::translate(char * &param, int bufsize, const char *tag)
1073 {
1074    const char * p = const_cast<const char *>(param);
1075    translate(p, bufsize, tag);
1076    param = const_cast<char *>(p);
1077 }
1078
1079 void SerDesBin::translate(std::string &param, const char *tag)
1080 {
1081    if (iomode_ == sd_serialize) 
1082    {
1083       const char *cstr = param.c_str();
1084       translate(cstr, 0, tag);
1085    }
1086    else 
1087    {
1088       char buf[2048];
1089       const char *buf2 = buf;
1090       translate(buf2, 2048, tag);
1091       param = std::string(buf2);
1092    }
1093    if ((iomode_ == sd_deserialize) ||strstr(param.c_str(), "file")) 
1094    {
1095       serialize_printf("%s[%d]:  %sserializing string %s--%s, len = %lu\n", 
1096             FILE__, __LINE__, (iomode_ == sd_serialize) ? "" : "de", tag ? tag : "unnamed",
1097               param.c_str(), (unsigned long) param.length());
1098    }
1099 }
1100
1101 void SerDesBin::translate(std::vector<std::string> &param, const char *tag, const char * elem_tag)
1102 {
1103    //  string list output format is
1104    //  [1]  length of list, n
1105    //  [2]  <n> strings
1106
1107    unsigned int nelem = param.size();
1108    translate(nelem, tag);
1109
1110    if (iomode_ == sd_serialize) 
1111    {
1112       for (unsigned int i = 0; i < nelem; ++i) 
1113       {
1114          translate(param[i], elem_tag);
1115       }
1116    }
1117    else 
1118    {
1119       param.resize(nelem);
1120       for (unsigned int i = 0; i < nelem; ++i) 
1121       {
1122          param[i] = "";
1123          translate(param[i], elem_tag);
1124       }
1125    }
1126 }
1127
1128 #if 0
1129 AnnotatableBase *SerDesBin::findAnnotatee(void *id) 
1130 {
1131    Address id_a = (Address) id;
1132    dyn_hash_map<Address, AnnotatableBase *>::iterator iter;
1133    iter = annotatable_id_map.find(id_a);
1134    if (iter == annotatable_id_map.end()) 
1135    {
1136       fprintf(stderr, "%s[%d]:  no parent for annotation\n", FILE__, __LINE__);
1137       return NULL;
1138    }
1139    
1140    return iter->second;
1141 }
1142 #endif
1143
1144
1145
1146 SerializerBase::SerializerBase(const char *name_, 
1147       std::string filename, 
1148       iomode_t dir, 
1149       bool verbose)  :
1150    serializer_name(std::string(name_)) 
1151 {
1152    sf = new SerFile(filename, dir, verbose);
1153    assert(sf);
1154    sd = sf->getSD();
1155    assert(sd);
1156 }
1157
1158 SerializerBase::SerializerBase() 
1159 {
1160 }
1161
1162 SerializerBase *SerializerBase::getSerializer(std::string subsystem, std::string fname)
1163 {
1164    dyn_hash_map<std::string, subsystem_serializers_t>::iterator ssiter; 
1165    ssiter = all_serializers.find(subsystem);
1166
1167    if (ssiter == all_serializers.end()) 
1168    {
1169       fprintf(stderr, "%s[%d]:  no serializer for subsystem %s\n", FILE__, __LINE__, subsystem.c_str());
1170       return NULL;
1171    }
1172
1173    subsystem_serializers_t &subsys_map = ssiter->second;
1174
1175    dyn_hash_map<std::string, SerializerBase *>::iterator sbiter;
1176    sbiter = subsys_map.find(fname);
1177    if (sbiter == subsys_map.end()) 
1178    {
1179       fprintf(stderr, "%s[%d]:  no serializer for filename %s\n", FILE__, __LINE__, fname.c_str());
1180       return NULL;
1181    }
1182
1183    SerializerBase *sb =  sbiter->second;
1184    if (!sb) 
1185    {
1186       fprintf(stderr, "%s[%d]:  ERROR:  NULL serializer\n", FILE__, __LINE__);
1187       return NULL;
1188    }
1189
1190    return sb;
1191 }
1192
1193 bool SerializerBase::addSerializer(std::string subsystem, std::string fname, SerializerBase *sb)
1194 {
1195    subsystem_serializers_t ss_serializers;
1196    dyn_hash_map<std::string, subsystem_serializers_t>::iterator ssiter; 
1197    ssiter =  all_serializers.find(subsystem);
1198
1199    if (ssiter == all_serializers.end()) 
1200    {
1201       //  make an entry 
1202       all_serializers[subsystem] = ss_serializers;
1203    }
1204
1205    ss_serializers = all_serializers[subsystem];
1206
1207    dyn_hash_map<std::string, SerializerBase *>::iterator sbiter;
1208    sbiter = ss_serializers.find(fname);
1209    if (sbiter != ss_serializers.end()) 
1210    {
1211       serializer_printf("%s[%d]:  already have serializer for filename %s\n", 
1212             FILE__, __LINE__, fname.c_str());
1213       return false;
1214    }
1215
1216    //  add serializer to map since it does not exist there already
1217
1218    ss_serializers[fname] = sb;
1219    return true;
1220 }
1221
1222 iomode_t SerializerBase::iomode()
1223 {
1224    if (sd) 
1225    {
1226       return sd->iomode();
1227    }
1228
1229    fprintf(stderr, "%s[%d]:  no sd for iomode query\n", FILE__, __LINE__);
1230    return sd_serialize;
1231 }
1232
1233 void SerializerBase::vector_start(unsigned int &size, const char *tag) 
1234 {
1235    getSD().vector_start(size, tag);
1236 }
1237
1238
1239 void SerializerBase::vector_end() 
1240 {
1241    getSD().vector_end();
1242 }
1243
1244 void SerializerBase::hash_map_start(unsigned int &size, const char *tag) 
1245 {
1246    getSD().hash_map_start(size, tag);
1247 }
1248
1249 void SerializerBase::hash_map_end() 
1250 {
1251    getSD().hash_map_end();
1252 }
1253
1254 void SerializerBase::translate_base(short &v, const char *&t)
1255 {
1256    getSD().translate(v, t);
1257 }
1258 void SerializerBase::translate_base(bool &v, const char *&t)
1259 {
1260    getSD().translate(v, t);
1261 }
1262 void SerializerBase::translate_base(char &v, const char *&t)
1263 {
1264    getSD().translate(v, t);
1265 }
1266 void SerializerBase::translate_base(int &v, const char *&t)
1267 {
1268    getSD().translate(v, t);
1269 }
1270 void SerializerBase::translate_base(unsigned int &v, const char *&t)
1271 {
1272    getSD().translate(v, t);
1273 }
1274 void SerializerBase::translate_base(long &v, const char *&t)
1275 {
1276    getSD().translate(v, t);
1277 }
1278 void SerializerBase::translate_base(unsigned long &v, const char *&t)
1279 {
1280    getSD().translate(v, t);
1281 }
1282 void SerializerBase::translate_base(float &v, const char *&t)
1283 {
1284    getSD().translate(v, t);
1285 }
1286 void SerializerBase::translate_base(double &v, const char *&t)
1287 {
1288    getSD().translate(v, t);
1289 }
1290 void SerializerBase::translate_base(const char *&v, int bufsize, const char *&t)
1291 {
1292    getSD().translate(v, bufsize, t);
1293 }
1294 void SerializerBase::translate_base(char *&v, int bufsize, const char *&t)
1295 {
1296    getSD().translate(v, bufsize, t);
1297 }
1298
1299 void SerializerBase::translate_base(std::string &v, const char *t)
1300 {
1301    getSD().translate(v, t);
1302 }
1303
1304
1305 #if 0
1306 namespace Dyninst {
1307         template <class T>
1308 SerializerBase *nonpublic_make_bin_serializer(T *t, std::string file)
1309 {
1310         SerializerBin *ser;
1311         ser = new SerializerBin<T>(t, "SerializerBin", file, sd_serialize, true);
1312         return ser;
1313 }
1314
1315 template <class T>
1316 void nonpublic_free_bin_serializer(SerializerBase *sb)
1317 {
1318         SerializerBin<T> *sbin = dynamic_cast<SerializerBin<T> *>(sb);
1319         if (sbin)
1320         {
1321                 delete(sbin);
1322         }
1323         else
1324                 fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
1325 }
1326
1327 template <class T>
1328 SerializerBase *nonpublic_make_bin_deserializer(T *t,std::string file)
1329 {
1330         SerializerBin *ser;
1331         ser = new SerializerBin<T>(t, "DeserializerBin", file, sd_deserialize, true);
1332         return ser;
1333 }
1334 }
1335 #endif