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