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