1#ifndef ROSE_BinaryAnalysis_SerialIo_H
2#define ROSE_BinaryAnalysis_SerialIo_H
3#include <featureTests.h>
4#ifdef ROSE_ENABLE_BINARY_ANALYSIS
10#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
11#include <boost/archive/binary_iarchive.hpp>
12#include <boost/archive/binary_oarchive.hpp>
13#include <boost/archive/text_iarchive.hpp>
14#include <boost/archive/text_oarchive.hpp>
15#include <boost/archive/xml_iarchive.hpp>
16#include <boost/archive/xml_oarchive.hpp>
17#include <boost/iostreams/device/file_descriptor.hpp>
18#include <boost/iostreams/stream.hpp>
21#include <Rose/Progress.h>
22#include <Rose/Exception.h>
23#include <ROSE_UNUSED.h>
25#include <Sawyer/Message.h>
26#include <Sawyer/ProgressBar.h>
27#include <Sawyer/Synchronization.h>
29#include <boost/filesystem.hpp>
30#include <boost/lexical_cast.hpp>
31#include <boost/thread.hpp>
34namespace BinaryAnalysis {
132 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
150 progressBar_(
mlog[
Sawyer::Message::MARCH]), fd_(-1) {
152 progressBar_.
suffix(
" bytes");
205 virtual void open(
const boost::filesystem::path&) = 0;
235 void setIsOpen(
bool b);
258#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
259 boost::iostreams::file_descriptor_sink device_;
260 boost::iostreams::stream<boost::iostreams::file_descriptor_sink> file_;
261 boost::archive::binary_oarchive *binary_archive_;
262 boost::archive::text_oarchive *text_archive_;
263 boost::archive::xml_oarchive *xml_archive_;
267#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
268 SerialOutput(): binary_archive_(NULL), text_archive_(NULL), xml_archive_(NULL) {}
275 void open(
const boost::filesystem::path &fileName)
override;
312 void saveAstHelper(
SgNode*);
332 throw Exception(
"cannot save object when no file is open");
334 throw Exception(
"cannot save object because stream is in error state");
336#ifndef ROSE_ENABLE_BOOST_SERIALIZATION
337 ROSE_UNUSED(objectTypeId);
339 throw Exception(
"binary state files are not supported in this configuration");
340#elif defined(ROSE_DEBUG_SERIAL_IO)
341 std::string errorMessage;
342 asyncSave(objectTypeId,
object, &errorMessage);
345 std::string errorMessage;
346 boost::thread worker(startWorker<T>,
this, objectTypeId, &
object, &errorMessage);
348 progressBar_.
prefix(
"writing");
349 while (!worker.try_join_for(timeout)) {
350 off_t cur = ::lseek(fd_, 0, SEEK_CUR);
354 progressBar_.
value(cur);
359 if (!errorMessage.empty())
366 static void startWorker(
SerialOutput *saver,
Savable objectTypeId,
const T *
object, std::string *errorMessage) {
367 ASSERT_not_null(
object);
368 saver->asyncSave(objectTypeId, *
object, errorMessage);
373 void asyncSave(
Savable objectTypeId,
const T &
object, std::string *errorMessage) {
374 ASSERT_not_null(errorMessage);
375#ifndef ROSE_ENABLE_BOOST_SERIALIZATION
376 ROSE_UNUSED(objectTypeId);
378 ASSERT_not_reachable(
"not supported in this configuration");
380#if !defined(ROSE_DEBUG_SERIAL_IO)
383 std::string roseVersion = ROSE_PACKAGE_VERSION;
387 ASSERT_not_null(binary_archive_);
388 *binary_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
389 *binary_archive_ <<BOOST_SERIALIZATION_NVP(roseVersion);
390 *binary_archive_ <<BOOST_SERIALIZATION_NVP(
object);
393 ASSERT_not_null(text_archive_);
394 *text_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
395 *text_archive_ <<BOOST_SERIALIZATION_NVP(roseVersion);
396 *text_archive_ <<BOOST_SERIALIZATION_NVP(
object);
399 ASSERT_not_null(xml_archive_);
400 *xml_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
401 *xml_archive_ <<BOOST_SERIALIZATION_NVP(roseVersion);
402 *xml_archive_ <<BOOST_SERIALIZATION_NVP(
object);
406#if !defined(ROSE_DEBUG_SERIAL_IO)
407 }
catch (std::exception &e) {
408 *errorMessage = e.what();
410 *errorMessage =
"failed to write object to output stream";
431#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
433 boost::iostreams::file_descriptor_source device_;
434 boost::iostreams::stream<boost::iostreams::file_descriptor_source> file_;
435 boost::archive::binary_iarchive *binary_archive_;
436 boost::archive::text_iarchive *text_archive_;
437 boost::archive::xml_iarchive *xml_archive_;
441#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
442 SerialInput(): fileSize_(0), binary_archive_(NULL), text_archive_(NULL), xml_archive_(NULL) {}
449 void open(
const boost::filesystem::path &fileName)
override;
493 loadObject<T>(objectTypeId,
object);
499 throw Exception(
"cannot load object when no file is open");
501#ifndef ROSE_ENABLE_BOOST_SERIALIZATION
502 ROSE_UNUSED(objectTypeId);
504 throw Exception(
"binary state files are not supported in this configuration");
507 throw Exception(
"cannot read object because stream is in error state");
509 throw Exception(
"unexpected object type (expected " + boost::lexical_cast<std::string>(objectTypeId) +
510 " but read " + boost::lexical_cast<std::string>(
objectType()) +
")");
513 std::string errorMessage;
514#ifdef ROSE_DEBUG_SERIAL_IO
515 asyncLoad(
object, &errorMessage);
517 boost::thread worker(startWorker<T>,
this, &
object, &errorMessage);
519 progressBar_.
prefix(
"reading");
520 while (!worker.try_join_for(timeout)) {
522 off_t cur = ::lseek(fd_, 0, SEEK_CUR);
524 progressBar_.
value(cur);
532 if (!errorMessage.empty())
542 static void startWorker(
SerialInput *loader, T *
object, std::string *errorMessage) {
543 loader->asyncLoad(*
object, errorMessage);
548 void asyncLoad(T &
object, std::string *errorMessage) {
549 ASSERT_not_null(errorMessage);
550#ifndef ROSE_ENABLE_BOOST_SERIALIZATION
552 ASSERT_not_reachable(
"not supported in this configuration");
554#if !defined(ROSE_DEBUG_SERIAL_IO)
557 std::string roseVersion;
560 ASSERT_not_null(binary_archive_);
561 *binary_archive_ >>BOOST_SERIALIZATION_NVP(roseVersion);
562 checkCompatibility(roseVersion);
563 *binary_archive_ >>BOOST_SERIALIZATION_NVP(
object);
566 ASSERT_not_null(text_archive_);
567 *text_archive_ >>BOOST_SERIALIZATION_NVP(roseVersion);
568 checkCompatibility(roseVersion);
569 *text_archive_ >>BOOST_SERIALIZATION_NVP(
object);
572 ASSERT_not_null(xml_archive_);
573 *xml_archive_ >>BOOST_SERIALIZATION_NVP(roseVersion);
574 checkCompatibility(roseVersion);
575 *xml_archive_ >>BOOST_SERIALIZATION_NVP(
object);
578#if !defined(ROSE_DEBUG_SERIAL_IO)
579 }
catch (
const std::exception &e) {
580 *errorMessage = e.what();
582 *errorMessage =
"failed to read object from input stream";
588 void checkCompatibility(
const std::string &fileVersion);
592 void advanceObjectType();
Errors thrown by this API.
Exception(const std::string &s)
Construct an exception with an error message.
Base class for binary state input and output.
virtual void close()=0
Detach a file.
virtual ~SerialIo()
Destructor.
Format
Format of the state file.
@ XML
The states are stored as XML, which is a very verbose and slow format.
@ TEXT
Textual binary state files use a custom format (Boost serialization format) that stores the data as A...
@ BINARY
Binary state files are smaller and faster than the other formats, but are not portable across archite...
void progress(const Progress::Ptr &)
Property: Progress reporter.
static Savable userSavable(unsigned offset)
Create a new Savable enum constant.
Format format() const
Property: File format.
Savable
Types of objects that can be saved.
@ END_OF_DATA
Marks the end of the data stream.
@ USER_DEFINED
First user-defined object number.
@ USER_DEFINED_LAST
Last user-defined object number.
@ ERROR
Marks that the stream has encountered an error condition.
@ PARTITIONER
Rose::BinaryAnalysis::Partitioner2::Partitioner.
@ AST
Abstract syntax tree.
@ NO_OBJECT
Object type for newly-initialized serializers.
Progress::Ptr progress() const
Property: Progress reporter.
virtual void open(const boost::filesystem::path &)=0
Attach a file.
Savable objectType() const
Type ID for next object.
bool isOpen() const
Whether a file is attached.
static Sawyer::Message::Facility mlog
Message facility.
void format(Format)
Property: File format.
Output binary analysis state.
SerialOutputPtr Ptr
Reference counting pointer.
static Ptr instance()
Factory method to create a new instance.
void saveObject(Savable objectTypeId, const T &object)
Save an object to the output stream.
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.
Base class for all ROSE exceptions.
A general, thread-safe way to report progress made on some task.
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 reference counted objects.
Reference-counting intrusive smart pointer.
Base class for all binary analysis IR nodes.
This class represents the base class for all IR nodes within Sage III.
Sawyer::SharedPointer< SerialOutput > SerialOutputPtr
Reference counting pointer.
Sawyer::SharedPointer< SerialIo > SerialIoPtr
Reference counting pointer.
Sawyer::SharedPointer< SerialInput > SerialInputPtr
Reference counting pointer.
double minimumUpdateInterval()
Minimum time between updates.
A single progress report.