1 #ifndef Rose_BinaryAnalysis_SerialIo_H
2 #define Rose_BinaryAnalysis_SerialIo_H
4 #include <featureTests.h>
5 #ifdef ROSE_ENABLE_BINARY_ANALYSIS
8 #include <RoseException.h>
9 #include <boost/filesystem.hpp>
10 #include <boost/lexical_cast.hpp>
11 #include <boost/thread.hpp>
12 #include <Sawyer/Message.h>
13 #include <Sawyer/ProgressBar.h>
14 #include <Sawyer/Synchronization.h>
19 #if defined(BOOST_WINDOWS)
21 #undef ROSE_SUPPORTS_SERIAL_IO
22 #elif !defined(ROSE_HAVE_BOOST_SERIALIZATION_LIB)
24 #undef ROSE_SUPPORTS_SERIAL_IO
25 #elif defined(__clang__)
26 #define ROSE_SUPPORTS_SERIAL_IO
27 #elif defined(__GNUC__)
28 #if __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNU_C_PATCHLEVEL__ <= 40204
30 #undef ROSE_SUPPORTS_SERIAL_IO
32 #define ROSE_SUPPORTS_SERIAL_IO
35 #define ROSE_SUPPORTS_SERIAL_IO
38 #ifdef ROSE_SUPPORTS_SERIAL_IO
39 #include <boost/archive/binary_iarchive.hpp>
40 #include <boost/archive/binary_oarchive.hpp>
41 #include <boost/archive/text_iarchive.hpp>
42 #include <boost/archive/text_oarchive.hpp>
43 #include <boost/archive/xml_iarchive.hpp>
44 #include <boost/archive/xml_oarchive.hpp>
45 #include <boost/iostreams/device/file_descriptor.hpp>
46 #include <boost/iostreams/stream.hpp>
52 namespace Partitioner2 {
152 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
170 progressBar_(
mlog[
Sawyer::Message::MARCH]), fd_(-1) {
172 progressBar_.
suffix(
" bytes");
225 virtual void open(
const boost::filesystem::path&) = 0;
238 virtual void close() = 0;
255 void setIsOpen(
bool b);
277 #ifdef ROSE_SUPPORTS_SERIAL_IO
278 boost::iostreams::file_descriptor_sink device_;
279 boost::iostreams::stream<boost::iostreams::file_descriptor_sink> file_;
280 boost::archive::binary_oarchive *binary_archive_;
281 boost::archive::text_oarchive *text_archive_;
282 boost::archive::xml_oarchive *xml_archive_;
286 #ifdef ROSE_SUPPORTS_SERIAL_IO
287 SerialOutput(): binary_archive_(NULL), text_archive_(NULL), xml_archive_(NULL) {}
294 void open(
const boost::filesystem::path &fileName) ROSE_OVERRIDE;
295 void close() ROSE_OVERRIDE;
331 void saveAstHelper(
SgNode*);
351 throw Exception(
"cannot save object when no file is open");
353 throw Exception(
"cannot save object because stream is in error state");
355 #ifndef ROSE_SUPPORTS_SERIAL_IO
356 throw Exception(
"binary state files are not supported in this configuration");
357 #elif defined(ROSE_DEBUG_SERIAL_IO)
358 std::string errorMessage;
359 asyncSave(objectTypeId,
object, &errorMessage);
362 std::string errorMessage;
363 boost::thread worker(startWorker<T>,
this, objectTypeId, &
object, &errorMessage);
365 progressBar_.
prefix(
"writing");
366 while (!worker.try_join_for(timeout)) {
367 off_t cur = ::lseek(fd_, 0, SEEK_CUR);
371 progressBar_.
value(cur);
376 if (!errorMessage.empty())
383 static void startWorker(
SerialOutput *saver,
Savable objectTypeId,
const T *
object, std::string *errorMessage) {
384 ASSERT_not_null(
object);
385 saver->asyncSave(objectTypeId, *
object, errorMessage);
390 void asyncSave(
Savable objectTypeId,
const T &
object, std::string *errorMessage) {
391 ASSERT_not_null(errorMessage);
392 #ifndef ROSE_SUPPORTS_SERIAL_IO
393 ASSERT_not_reachable(
"not supported in this configuration");
395 #if !defined(ROSE_DEBUG_SERIAL_IO)
401 ASSERT_not_null(binary_archive_);
402 *binary_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
403 *binary_archive_ <<BOOST_SERIALIZATION_NVP(
object);
406 ASSERT_not_null(text_archive_);
407 *text_archive_ <<BOOST_SERIALIZATION_NVP(objectTypeId);
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(
object);
417 #if !defined(ROSE_DEBUG_SERIAL_IO)
418 }
catch (
const Exception &e) {
419 *errorMessage = e.what();
421 *errorMessage =
"failed to write object to output stream";
441 #ifdef ROSE_SUPPORTS_SERIAL_IO
443 boost::iostreams::file_descriptor_source device_;
444 boost::iostreams::stream<boost::iostreams::file_descriptor_source> file_;
445 boost::archive::binary_iarchive *binary_archive_;
446 boost::archive::text_iarchive *text_archive_;
447 boost::archive::xml_iarchive *xml_archive_;
451 #ifdef ROSE_SUPPORTS_SERIAL_IO
452 SerialInput(): fileSize_(0), binary_archive_(NULL), text_archive_(NULL), xml_archive_(NULL) {}
459 void open(
const boost::filesystem::path &fileName) ROSE_OVERRIDE;
460 void close() ROSE_OVERRIDE;
503 loadObject<T>(objectTypeId, object);
509 throw Exception(
"cannot load object when no file is open");
511 #ifndef ROSE_SUPPORTS_SERIAL_IO
512 throw Exception(
"binary state files are not supported in this configuration");
515 throw Exception(
"cannot read object because stream is in error state");
517 throw Exception(
"unexpected object type (expected " + boost::lexical_cast<std::string>(objectTypeId) +
518 " but read " + boost::lexical_cast<std::string>(
objectType()) +
")");
521 std::string errorMessage;
522 #ifdef ROSE_DEBUG_SERIAL_IO
523 asyncLoad(
object, &errorMessage);
525 boost::thread worker(startWorker<T>,
this, &
object, &errorMessage);
527 progressBar_.
prefix(
"reading");
528 while (!worker.try_join_for(timeout)) {
530 off_t cur = ::lseek(fd_, 0, SEEK_CUR);
532 progressBar_.
value(cur);
540 if (!errorMessage.empty())
550 static void startWorker(
SerialInput *loader, T *
object, std::string *errorMessage) {
551 loader->asyncLoad(*
object, errorMessage);
556 void asyncLoad(T &
object, std::string *errorMessage) {
557 ASSERT_not_null(errorMessage);
558 #ifndef ROSE_SUPPORTS_SERIAL_IO
559 ASSERT_not_reachable(
"not supported in this configuration");
561 #if !defined(ROSE_DEBUG_SERIAL_IO)
566 ASSERT_not_null(binary_archive_);
567 *binary_archive_ >>object;
570 ASSERT_not_null(text_archive_);
571 *text_archive_ >>object;
574 ASSERT_not_null(xml_archive_);
575 *xml_archive_ >>BOOST_SERIALIZATION_NVP(
object);
578 #if !defined(ROSE_DEBUG_SERIAL_IO)
579 }
catch (
const Exception &e) {
580 *errorMessage = e.what();
582 *errorMessage =
"failed to read object from input stream";
590 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...
void savePartitioner(const Partitioner2::Partitioner &)
Save a binary analysis partitioner.
static Savable userSavable(unsigned offset)
Create a new Savable enum constant.
void close() ROSE_OVERRIDE
Detach a file.
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.
static Sawyer::Message::Facility mlog
Message facility.
Main namespace for the ROSE library.
Base class for binary state input and output.
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.
void open(const boost::filesystem::path &fileName) ROSE_OVERRIDE
Attach a file.
static Ptr instance()
Factory method to create a new instance.
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.
ValueType value() const
Value for the progress bar.
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.
Partitions instructions into basic blocks and functions.
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.
Sawyer::SharedPointer< SerialIo > Ptr
Reference-counting pointer.