1 #ifndef ROSE_BinaryAnalysis_SerialIo_H
2 #define ROSE_BinaryAnalysis_SerialIo_H
3 #include <featureTests.h>
4 #ifdef ROSE_ENABLE_BINARY_ANALYSIS
9 #if defined(BOOST_WINDOWS)
11 #undef ROSE_SUPPORTS_SERIAL_IO
12 #elif !defined(ROSE_HAVE_BOOST_SERIALIZATION_LIB)
14 #undef ROSE_SUPPORTS_SERIAL_IO
15 #elif defined(__clang__)
16 #define ROSE_SUPPORTS_SERIAL_IO
17 #elif defined(__GNUC__)
18 #if __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNU_C_PATCHLEVEL__ <= 40204
20 #undef ROSE_SUPPORTS_SERIAL_IO
22 #define ROSE_SUPPORTS_SERIAL_IO
25 #define ROSE_SUPPORTS_SERIAL_IO
29 #ifdef ROSE_SUPPORTS_SERIAL_IO
30 #include <boost/archive/binary_iarchive.hpp>
31 #include <boost/archive/binary_oarchive.hpp>
32 #include <boost/archive/text_iarchive.hpp>
33 #include <boost/archive/text_oarchive.hpp>
34 #include <boost/archive/xml_iarchive.hpp>
35 #include <boost/archive/xml_oarchive.hpp>
36 #include <boost/iostreams/device/file_descriptor.hpp>
37 #include <boost/iostreams/stream.hpp>
40 #include <Rose/Progress.h>
41 #include <Rose/Exception.h>
42 #include <boost/filesystem.hpp>
43 #include <boost/lexical_cast.hpp>
44 #include <boost/thread.hpp>
45 #include <Sawyer/Message.h>
46 #include <Sawyer/ProgressBar.h>
47 #include <Sawyer/Synchronization.h>
50 namespace BinaryAnalysis {
148 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
166 progressBar_(
mlog[
Sawyer::Message::MARCH]), fd_(-1) {
168 progressBar_.
suffix(
" bytes");
221 virtual void open(
const boost::filesystem::path&) = 0;
234 virtual void close() = 0;
251 void setIsOpen(
bool b);
274 #ifdef ROSE_SUPPORTS_SERIAL_IO
275 boost::iostreams::file_descriptor_sink device_;
276 boost::iostreams::stream<boost::iostreams::file_descriptor_sink> file_;
277 boost::archive::binary_oarchive *binary_archive_;
278 boost::archive::text_oarchive *text_archive_;
279 boost::archive::xml_oarchive *xml_archive_;
283 #ifdef ROSE_SUPPORTS_SERIAL_IO
284 SerialOutput(): binary_archive_(NULL), text_archive_(NULL), xml_archive_(NULL) {}
291 void open(
const boost::filesystem::path &fileName)
override;
292 void close()
override;
328 void saveAstHelper(
SgNode*);
348 throw Exception(
"cannot save object when no file is open");
350 throw Exception(
"cannot save object because stream is in error state");
352 #ifndef ROSE_SUPPORTS_SERIAL_IO
353 throw Exception(
"binary state files are not supported in this configuration");
354 #elif defined(ROSE_DEBUG_SERIAL_IO)
355 std::string errorMessage;
356 asyncSave(objectTypeId,
object, &errorMessage);
359 std::string errorMessage;
360 boost::thread worker(startWorker<T>,
this, objectTypeId, &
object, &errorMessage);
362 progressBar_.
prefix(
"writing");
363 while (!worker.try_join_for(timeout)) {
364 off_t cur = ::lseek(fd_, 0, SEEK_CUR);
368 progressBar_.
value(cur);
373 if (!errorMessage.empty())
380 static void startWorker(
SerialOutput *saver,
Savable objectTypeId,
const T *
object, std::string *errorMessage) {
381 ASSERT_not_null(
object);
382 saver->asyncSave(objectTypeId, *
object, errorMessage);
387 void asyncSave(
Savable objectTypeId,
const T &
object, std::string *errorMessage) {
388 ASSERT_not_null(errorMessage);
389 #ifndef ROSE_SUPPORTS_SERIAL_IO
390 ASSERT_not_reachable(
"not supported in this configuration");
392 #if !defined(ROSE_DEBUG_SERIAL_IO)
395 std::string roseVersion = ROSE_PACKAGE_VERSION;
399 ASSERT_not_null(binary_archive_);
400 *binary_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
401 *binary_archive_ <<BOOST_SERIALIZATION_NVP(roseVersion);
402 *binary_archive_ <<BOOST_SERIALIZATION_NVP(
object);
405 ASSERT_not_null(text_archive_);
406 *text_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
407 *text_archive_ <<BOOST_SERIALIZATION_NVP(roseVersion);
408 *text_archive_ <<BOOST_SERIALIZATION_NVP(
object);
411 ASSERT_not_null(xml_archive_);
412 *xml_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
413 *xml_archive_ <<BOOST_SERIALIZATION_NVP(roseVersion);
414 *xml_archive_ <<BOOST_SERIALIZATION_NVP(
object);
418 #if !defined(ROSE_DEBUG_SERIAL_IO)
419 }
catch (
const Exception &e) {
420 *errorMessage = e.what();
422 *errorMessage =
"failed to write object to output stream";
443 #ifdef ROSE_SUPPORTS_SERIAL_IO
445 boost::iostreams::file_descriptor_source device_;
446 boost::iostreams::stream<boost::iostreams::file_descriptor_source> file_;
447 boost::archive::binary_iarchive *binary_archive_;
448 boost::archive::text_iarchive *text_archive_;
449 boost::archive::xml_iarchive *xml_archive_;
453 #ifdef ROSE_SUPPORTS_SERIAL_IO
454 SerialInput(): fileSize_(0), binary_archive_(NULL), text_archive_(NULL), xml_archive_(NULL) {}
461 void open(
const boost::filesystem::path &fileName)
override;
462 void close()
override;
505 loadObject<T>(objectTypeId, object);
511 throw Exception(
"cannot load object when no file is open");
513 #ifndef ROSE_SUPPORTS_SERIAL_IO
514 throw Exception(
"binary state files are not supported in this configuration");
517 throw Exception(
"cannot read object because stream is in error state");
519 throw Exception(
"unexpected object type (expected " + boost::lexical_cast<std::string>(objectTypeId) +
520 " but read " + boost::lexical_cast<std::string>(
objectType()) +
")");
523 std::string errorMessage;
524 #ifdef ROSE_DEBUG_SERIAL_IO
525 asyncLoad(
object, &errorMessage);
527 boost::thread worker(startWorker<T>,
this, &
object, &errorMessage);
529 progressBar_.
prefix(
"reading");
530 while (!worker.try_join_for(timeout)) {
532 off_t cur = ::lseek(fd_, 0, SEEK_CUR);
534 progressBar_.
value(cur);
542 if (!errorMessage.empty())
552 static void startWorker(
SerialInput *loader, T *
object, std::string *errorMessage) {
553 loader->asyncLoad(*
object, errorMessage);
558 void asyncLoad(T &
object, std::string *errorMessage) {
559 ASSERT_not_null(errorMessage);
560 #ifndef ROSE_SUPPORTS_SERIAL_IO
561 ASSERT_not_reachable(
"not supported in this configuration");
563 #if !defined(ROSE_DEBUG_SERIAL_IO)
566 std::string roseVersion;
569 ASSERT_not_null(binary_archive_);
570 *binary_archive_ >>BOOST_SERIALIZATION_NVP(roseVersion);
571 checkCompatibility(roseVersion);
572 *binary_archive_ >>BOOST_SERIALIZATION_NVP(
object);
575 ASSERT_not_null(text_archive_);
576 *text_archive_ >>BOOST_SERIALIZATION_NVP(roseVersion);
577 checkCompatibility(roseVersion);
578 *text_archive_ >>BOOST_SERIALIZATION_NVP(
object);
581 ASSERT_not_null(xml_archive_);
582 *xml_archive_ >>BOOST_SERIALIZATION_NVP(roseVersion);
583 checkCompatibility(roseVersion);
584 *xml_archive_ >>BOOST_SERIALIZATION_NVP(
object);
587 #if !defined(ROSE_DEBUG_SERIAL_IO)
588 }
catch (
const Exception &e) {
589 *errorMessage = e.what();
591 *errorMessage =
"failed to read object from input stream";
597 void checkCompatibility(
const std::string &fileVersion);
601 void advanceObjectType();
Savable
Types of objects that can be saved.
A single progress report.
double minimumUpdateInterval()
Minimum time between updates.
Base class for all binary analysis IR nodes.
Textual binary state files use a custom format (Boost serialization format) that stores the data as A...
static Savable userSavable(unsigned offset)
Create a new Savable enum constant.
Sawyer::SharedPointer< SerialOutput > SerialOutputPtr
Reference counting pointer.
First user-defined object number.
void saveObject(Savable objectTypeId, const T &object)
Save an object to the output stream.
Format format() const
Property: File format.
Output binary analysis state.
Rose::BinaryAnalysis::Partitioner2::Partitioner.
void saveAst(SgAsmNode *)
Save a binary AST.
void open(const boost::filesystem::path &fileName) override
Attach a file.
static Sawyer::Message::Facility mlog
Message facility.
Main namespace for the ROSE library.
Base class for binary state input and output.
void savePartitioner(const Partitioner2::PartitionerConstPtr &)
Save a binary analysis partitioner.
Progress::Ptr progress() const
Property: Progress reporter.
Reference-counting intrusive smart pointer.
Name space for the entire library.
Object type for newly-initialized serializers.
Savable objectType() const
Type ID for next object.
Exception(const std::string &s)
Construct an exception with an error message.
virtual void open(const boost::filesystem::path &)=0
Attach a file.
Marks that the stream has encountered an error condition.
static Ptr instance()
Factory method to create a new instance.
Sawyer::SharedPointer< SerialInput > SerialInputPtr
Reference counting pointer.
void close() override
Detach a file.
The states are stored as XML, which is a very verbose and slow format.
This class represents the base class for all IR nodes within Sage III.
Sawyer::SharedPointer< SerialIo > SerialIoPtr
Reference counting pointer.
ValueType value() const
Value for the progress bar.
SerialOutputPtr Ptr
Reference counting pointer.
bool isOpen() const
Whether a file is attached.
const std::string & prefix() const
String to show before the beginning of the bar.
virtual ~SerialIo()
Destructor.
Suffix suffix()
Property: suffix.
Base class for reference counted objects.
A general, thread-safe way to report progress made on some task.
Marks the end of the data stream.
Errors thrown by this API.
Format
Format of the state file.
Base class for all ROSE exceptions.
Binary state files are smaller and faster than the other formats, but are not portable across archite...
Last user-defined object number.
virtual void close()=0
Detach a file.