ROSE 2.1.0
Loading...
Searching...
No Matches
SerialIo.h
1#ifndef ROSE_BinaryAnalysis_SerialIo_H
2#define ROSE_BinaryAnalysis_SerialIo_H
3#include <featureTests.h>
4#ifdef ROSE_ENABLE_BINARY_ANALYSIS
5
6#include <ROSE_UNUSED.h>
7#include <Rose/BinaryAnalysis/BasicTypes.h>
8#include <Rose/BinaryAnalysis/Serialization/SerialFrame.h>
9#include <Rose/Exception.h>
10#include <Rose/Progress.h>
11
12#include <Sawyer/Message.h>
13#include <Sawyer/ProgressBar.h>
14#include <Sawyer/Synchronization.h>
15
16#include <boost/filesystem.hpp>
17#include <boost/lexical_cast.hpp>
18#include <functional>
19#include <memory>
20#include <type_traits>
21#include <vector>
22
23#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
24#include <boost/archive/binary_iarchive.hpp>
25#include <boost/archive/binary_oarchive.hpp>
26#include <boost/archive/text_iarchive.hpp>
27#include <boost/archive/text_oarchive.hpp>
28#include <boost/archive/xml_iarchive.hpp>
29#include <boost/archive/xml_oarchive.hpp>
30#endif
31
32namespace Rose {
33namespace BinaryAnalysis {
34
36// SerialIo
38
95class SerialIo {
96 public:
99
100 class Deserializer;
101 class Serializer;
102
104 Serialization::Format format = Serialization::BINARY;
105 std::function<std::shared_ptr<Deserializer>()> deserializer;
106 std::function<std::shared_ptr<Serializer>()> serializer;
107 };
108
109 static void registerSerialization(SerializationRegistration);
110 static const Sawyer::Optional<SerializationRegistration> findSerialization(Serialization::Format);
111
112 private:
113 mutable SAWYER_THREAD_TRAITS::Mutex mutex_; // protects the following data members
114 Serialization::Format format_;
115 Progress::Ptr progress_;
116 bool isOpen_;
117 Serialization::Savable objectType_;
118
119 protected:
120 Sawyer::ProgressBar<size_t> progressBar_;
121 int fd_; // Used by SerialFrame
122
123 protected:
124 SerialIo() :
125 format_(Serialization::BINARY), progress_(Progress::instance()), isOpen_(false),
126 objectType_(Serialization::NO_OBJECT), progressBar_(mlog[Sawyer::Message::MARCH]), fd_(-1) {
127 init();
128 progressBar_.suffix(" bytes");
129 }
130
131 public:
134
142 virtual ~SerialIo();
143
147 static Serialization::Savable userSavable(unsigned offset);
148
157 Serialization::Format format() const;
158 void format(Serialization::Format);
182 virtual void open(const boost::filesystem::path&) = 0;
183
195 virtual void close() = 0;
196
202 bool isOpen() const;
203
208 Serialization::Savable objectType() const;
209
210 protected:
211 // Set or clear the isOpen flag.
212 void setIsOpen(bool b);
213
214 // Set object type to ERROR to indicate that a read was unsuccessful
215 void objectType(Serialization::Savable);
216
217 private:
218 void init();
219
220 protected:
226 Serialization::ProgressCallback makeProgressCB(const std::string& phase);
227
228 /* Legacy declarations for compatibility */
229 public:
230 using Format = Serialization::Format;
231 static constexpr Format BINARY = Serialization::BINARY;
232 static constexpr Format TEXT = Serialization::TEXT;
233 static constexpr Format XML = Serialization::XML;
234};
235
242 public:
243 virtual ~Serializer() = default;
244
251 virtual std::vector<char>
252 savePartitioner(const Partitioner2::PartitionerConstPtr& partitioner, Serialization::ProgressCallback progress) = 0;
253};
254
261 public:
262 virtual ~Deserializer() = default;
263
271 loadPartitioner(const std::vector<char>& data, Serialization::ProgressCallback progress);
272
281 loadPartitioner(const std::vector<char>& data, const Partitioner2::BasePartitionerSettings& settings, Serialization::ProgressCallback progress) = 0;
282};
283
285// SerialOutput
287
291class SerialOutput: public SerialIo {
292 public:
295
296 private:
297 std::shared_ptr<Serialization::SerialFrame> frame_;
298 std::shared_ptr<SerialIo::Serializer> serializer_;
299
300 protected:
301 SerialOutput() {}
302
303 public:
305 void open(const boost::filesystem::path& fileName) override;
306 void close() override;
307
312 static Ptr instance() { return Ptr(new SerialOutput); }
313
324
337#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
340#endif
341
342 private:
343 // The saveAstHelper is what actually gets called for the functions above. It doesn't descriminate between nodes
344 // that support serialization and those that don't, which is why it's private. Use only the public functions because
345 // they'll give you a nice compiler error if you try to save an Ast node type that isn't supported.
346#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
347 void saveAstHelper(SgNode*);
348#endif
349
350 public:
365 template <class T> void saveObject(Serialization::Savable objectTypeId, const T& object) {
366 if (!isOpen())
367 throw Exception("cannot save object when no file is open");
368 if (Serialization::ERROR == objectType())
369 throw Exception("cannot save object because stream is in error state");
370 if (!frame_)
371 throw Exception("frame container not initialized");
372 if (!serializer_)
373 throw Exception("serializer not initialized");
374
375 // Save the object in a different thread and update the progress in this thread
376 std::string errorMessage;
377 boost::thread worker(startWorker<T>, this, objectTypeId, object, errorMessage);
378 boost::chrono::milliseconds timeout((unsigned)(1000 * Sawyer::ProgressBarSettings::minimumUpdateInterval()));
379
380 progressBar_.prefix("writing");
381
382 while (!worker.try_join_for(timeout)) {
383 off_t cur = ::lseek(fd_, 0, SEEK_CUR);
384 if (-1 == cur) {
385 ++progressBar_; // so a spinner moves
386 } else {
387 progressBar_.value(cur);
388 if (Progress::Ptr p = progress())
389 p->update(Progress::Report(cur, NAN));
390 }
391 }
392 if (!errorMessage.empty())
393 throw Exception(errorMessage);
394 }
395
396 private:
397 template <class T>
398 static void
399 startWorker(SerialOutput* saver, Serialization::Savable objectTypeId, const T& object, std::string& errorMessage) {
400 saver->saveWorker(objectTypeId, object, errorMessage);
401 }
402
403 template <class T>
404 void saveWorker(Serialization::Savable objectTypeId, const T& object, std::string& errorMessage) {
405 try {
406 // Create a FrameRecord with appropriate metadata
407 Serialization::FrameRecord frameRecord(objectTypeId, format());
408
409 // Serialize the object into the frameRecord's payload
410 frameRecord.serializeObject(object);
411
412 // Write the frame record
413 frame_->writeFrameRecord(frameRecord);
414 this->objectType(objectTypeId);
415 } catch (const std::exception& e) {
416 errorMessage = std::string("Failed to save object using container: ") + e.what();
417 } catch (...) {
418 errorMessage = "failed to write object to output stream";
419 }
420 }
421};
422
424// SerialInput
426
430class SerialInput: public SerialIo {
431 public:
434
435 private:
436 std::shared_ptr<Serialization::SerialFrame> frame_;
437 std::shared_ptr<SerialIo::Deserializer> deserializer_;
438
439 protected:
440 SerialInput() {}
441
442 public:
443 ~SerialInput();
444 void open(const boost::filesystem::path& fileName) override;
445 void close() override;
446
451 static Ptr instance() { return Ptr(new SerialInput); }
452
459 Serialization::FrameRecord readAndValidateRecord(Serialization::Savable expectedType);
460
468 Serialization::Savable nextObjectType();
469
477
485#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
487#endif
488
496 template <class T> T loadObject(Serialization::Savable objectTypeId) {
497 if (!deserializer_)
498 throw Exception("serialization backend not initialized");
499
500 T object;
501 loadObject<T>(objectTypeId, object);
502 return object;
503 }
504 template <class T> void loadObject(Serialization::Savable objectTypeId, T& object) {
505 if (!isOpen())
506 throw Exception("cannot load object when no file is open");
507 if (!frame_)
508 throw Exception("frame container not initialized");
509 if (!deserializer_)
510 throw Exception("deserializer not initialized");
511
512 try {
513 // Read and validate the frame record
514 auto frameRecord = readAndValidateRecord(objectTypeId);
515
516 // Deserialize object from payload
517 frameRecord.deserializeObject(object);
518
519 objectType(Serialization::END_OF_DATA);
520 } catch (const boost::archive::archive_exception& e) {
521 throw Exception(std::string("Failed to load object from Boost archive: ") + e.what());
522 } catch (const std::exception& e) {
523 throw Exception(std::string("Failed to load object using container: ") + e.what());
524 }
525 }
526
529 protected:
530 // Read the next object type from the input stream
531 void advanceObjectType();
532
533 // Check ROSE version compatibility
534 void checkCompatibility(const std::string& fileVersion);
535};
536
537} // namespace BinaryAnalysis
538} // namespace Rose
539
540#endif
541#endif
Input binary analysis state.
Definition SerialIo.h:430
Partitioner2::PartitionerPtr loadPartitioner()
Load a partitioner from the input stream.
T loadObject(Serialization::Savable objectTypeId)
Load an object from the input stream.
Definition SerialIo.h:496
SerialInputPtr Ptr
Reference counting pointer.
Definition SerialIo.h:433
void loadObject(Serialization::Savable objectTypeId, T &object)
Load an object from the input stream.
Definition SerialIo.h:504
SgNode * loadAst()
Load an AST from the input stream.
void close() override
Detach a file.
Serialization::Savable nextObjectType()
Type of next object in the input stream.
Serialization::FrameRecord readAndValidateRecord(Serialization::Savable expectedType)
Read a frame record from the container and validate its metadata.
void open(const boost::filesystem::path &fileName) override
Attach a file.
static Ptr instance()
Factory method to create a new instance.
Definition SerialIo.h:451
Interface for deserializer implementations.
Definition SerialIo.h:260
virtual Partitioner2::PartitionerPtr loadPartitioner(const std::vector< char > &data, Serialization::ProgressCallback progress)
Deserialize a partitioner from a binary payload with default partitioner settings.
virtual Partitioner2::PartitionerPtr loadPartitioner(const std::vector< char > &data, const Partitioner2::BasePartitionerSettings &settings, Serialization::ProgressCallback progress)=0
Deserialize a partitioner from a binary payload.
Interface for serializer implementations.
Definition SerialIo.h:241
virtual std::vector< char > savePartitioner(const Partitioner2::PartitionerConstPtr &partitioner, Serialization::ProgressCallback progress)=0
Serialize a partitioner to a binary payload.
Extension of the base SerialIo class defined in BasicTypes.h.
Definition SerialIo.h:95
Serialization::ProgressCallback makeProgressCB(const std::string &phase)
Create progress callbacks that wraps the IO progress reporting.
virtual void close()=0
Detach a file.
virtual ~SerialIo()
Destructor.
void progress(const Progress::Ptr &)
Property: Progress reporter.
void format(Serialization::Format)
Property: File format.
static Serialization::Savable userSavable(unsigned offset)
Create a new Savable enum constant.
SerialIoPtr Ptr
Reference counting pointer.
Definition SerialIo.h:98
Progress::Ptr progress() const
Property: Progress reporter.
virtual void open(const boost::filesystem::path &)=0
Attach a file.
Serialization::Format format() const
Property: File format.
Serialization::Savable objectType() const
Type ID for next object.
bool isOpen() const
Whether a file is attached.
static Sawyer::Message::Facility mlog
Message facility.
Definition SerialIo.h:133
Output binary analysis state.
Definition SerialIo.h:291
SerialOutputPtr Ptr
Reference counting pointer.
Definition SerialIo.h:294
static Ptr instance()
Factory method to create a new instance.
Definition SerialIo.h:312
void saveObject(Serialization::Savable objectTypeId, const T &object)
Save an object to the output stream.
Definition SerialIo.h:365
void close() override
Detach a file.
void savePartitioner(const Partitioner2::PartitionerConstPtr &)
Save a binary analysis partitioner.
void open(const boost::filesystem::path &fileName) override
Attach a file.
void saveAst(SgAsmNode *)
Save a binary AST.
Helper class for metadata and payload handling.
Definition SerialFrame.h:57
Base class for all ROSE exceptions.
A general, thread-safe way to report progress made on some task.
Definition Progress.h:167
Collection of streams.
Definition Message.h:1606
Holds a value or nothing.
Definition Optional.h:54
Progress bars.
const std::string & prefix() const
String to show before the beginning of the bar.
Suffix suffix()
Property: suffix.
ValueType value() const
Value for the progress bar.
Base class for all binary analysis IR nodes.
This class represents the base class for all IR nodes within Sage III.
std::shared_ptr< SerialInput > SerialInputPtr
Reference counting pointer.
std::shared_ptr< SerialOutput > SerialOutputPtr
Reference counting pointer.
std::shared_ptr< SerialIo > SerialIoPtr
Reference counting pointer.
The ROSE library.
double minimumUpdateInterval()
Minimum time between updates.
Sawyer support library.
A single progress report.
Definition Progress.h:181