/*
* File: DataSource.h
*
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
* See included license file for license details.
*/
#if !defined(_DataSource_h_)
#define _DataSource_h_
#include <vector>
#include "Value.h"
#include "smart_ptr.h"
#include "StExecutableImage.h"
namespace elftosb
{
// Forward declaration
class DataTarget;
/*!
* \brief Abstract base class for data sources.
*
* Data sources represent any sort of data that can be placed or loaded
* into a target region. Sources may be a single blob of data read from
* a file or may consist of many segments.
*
* The three most important features of data sources are:
* - Sources may be multi-segmented.
* - Sources and/or segments can have a "natural" or default target location.
* - The target for a source may be taken into consideration when the source
* describes itself.
*/
class DataSource
{
public:
/*!
* \brief Discrete, contiguous part of the source's data.
*
* This class is purely abstract and subclasses of DataSource are expected
* to subclass it to implement a segment particular to their needs.
*/
class Segment
{
public:
//! \brief Default constructor.
Segment(DataSource & source) : m_source(source) {}
//! \brief Destructor.
virtual ~Segment() {}
//! \brief Gets all or a portion of the segment's data.
//!
//! The data is copied into \a buffer. Up to \a maxBytes bytes may be
//! copied, so \a buffer must be at least that large.
//!
//! \param offset Index of the first byte to start copying from.
//! \param maxBytes The maximum number of bytes that can be returned. \a buffer
//! must be at least this large.
//! \param buffer Pointer to buffer where the data is copied.
//! \return The number of bytes copied into \a buffer.
virtual unsigned getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)=0;
//! \brief Gets the length of the segment's data.
virtual unsigned getLength()=0;
//! \brief Returns whether the segment has an associated address.
virtual bool hasNaturalLocation()=0;
//! \brief Returns the address associated with the segment.
virtual uint32_t getBaseAddress() { return 0; }
protected:
DataSource & m_source; //!< The data source to which this segment belongs.
};
/*!
* \brief This is a special type of segment containing a repeating pattern.
*
* By default the segment doesn't have a specific length or data. The length depends
* on the target's address range. And the data is just the pattern, repeated
* many times. In addition, pattern segments do not have a natural location.
*
* Calling code should look for instances of PatternSegment and handle them
* as special cases that can be optimized.
*/
class PatternSegment : public Segment
{
public:
//! \brief Default constructor.
PatternSegment(DataSource & source);
//! \brief Constructor taking a fill pattern.
PatternSegment(DataSource & source, const SizedIntegerValue & pattern);
//! \brief Constructor taking a byte fill pattern.
PatternSegment(DataSource & source, uint8_t pattern);
//! \brief Constructor taking a half-word fill pattern.
PatternSegment(DataSource & source, uint16_t pattern);
//! \brief Constructor taking a word fill pattern.
PatternSegment(DataSource & source, uint32_t pattern);
//! \name Segment methods
//@{
//! \brief Pattern segments have no natural address.
virtual bool hasNaturalLocation() { return false; }
//! \brief Performs a pattern fill into the \a buffer.
virtual unsigned getData(unsigned offset, unsigned maxBytes, uint8_t * buffer);
//! \brief Returns a length based on the data target's address range.
virtual unsigned getLength();
//@}
//! \name Pattern accessors
//@{
//! \brief Assigns a new fill pattern.
inline void setPattern(const SizedIntegerValue & newPattern) { m_pattern = newPattern; }
//! \brief Return the fill pattern for the segment.
inline SizedIntegerValue & getPattern() { return m_pattern; }
//! \brief Assignment operator, sets the pattern value and length.
PatternSegment & operator = (const SizedIntegerValue & value) { m_pattern = value; return *this; }
//@}
protected:
SizedIntegerValue m_pattern; //!< The fill pattern.
};
public:
//! \brief Default constructor.
DataSource() : m_target(0) {}
//! \brief Destructor.
virtual ~DataSource() {}
//! \name Data target
//@{
//! \brief Sets the associated data target.
inline void setTarget(DataTarget * target) { m_target = target; }
//! \brief Gets the associated data target.
inline DataTarget * getTarget() const { return m_target; }
//@}
//! \name Segments
//@{
//! \brief Returns the number of segments in this data source.
virtual unsigned getSegmentCount()=0;
//! \brief Returns segment number \a index of the data source.
virtual Segment * getSegmentAt(unsigned index)=0;
//@}
protected:
DataTarget * m_target; //!< Corresponding target for this source.
};
/*!
* \brief Data source for a repeating pattern.
*
* The pattern is represented by a SizedIntegerValue object. Thus the pattern
* can be either byte, half-word, or word sized.
*
* This data source has only one segment, and the PatternSource instance acts
* as its own single segment.
*/
class PatternSource : public DataSource, public DataSource::PatternSegment
{
public:
//! \brief Default constructor.
PatternSource();
//! \brief Constructor taking the pattern value.
PatternSource(const SizedIntegerValue & value);
//! \brief There is only one segment.
virtual unsigned getSegmentCount() { return 1; }
//! \brief Returns this object, as it is its own segment.
virtual DataSource::Segment * getSegmentAt(unsigned index) { return this; }
//! \brief Assignment operator, sets the pattern value and length.
PatternSource & operator = (const SizedIntegerValue & value) { setPattern(value); return *this; }
};
/*!
* \brief Data source for data that is not memory mapped (has no natural address).
*
* This data source can only manage a single block of data, which has no
* associated address. It acts as its own Segment.
*/
class UnmappedDataSource : public DataSource, public DataSource::Segment
{
public:
//! \brief Default constructor.
UnmappedDataSource();
//! \brief Constructor taking the data, which is copied.
UnmappedDataSource(const uint8_t * data, unsigned length);
//! \brief Sets the source's data.
void setData(const uint8_t * data, unsigned length);
//! \brief There is only one segment.
virtual unsigned getSegmentCount() { return 1; }
//! \brief Returns this object, as it is its own segment.
virtual DataSource::Segment * getSegmentAt(unsigned index) { return this; }
//! \name Segment methods
//@{
//! \brief Unmapped data sources have no natural address.
virtual bool hasNaturalLocation() { return false; }
//! \brief Copies a portion of the data into \a buffer.
virtual unsigned getData(unsigned offset, unsigned maxBytes, uint8_t * buffer);
//! \brief Returns the number of bytes of data managed by the source.
virtual unsigned getLength() { return m_length; }
//@}
protected:
smart_array_ptr<uint8_t> m_data; //!< The data.
unsigned m_length; //!< Byte count of the data.
};
/*!
* \brief Data source that takes its data from an executable image.
*
* \see StExecutableImage
*/
class MemoryImageDataSource : public DataSource
{
public:
//! \brief Default constructor.
MemoryImageDataSource(StExecutableImage * image);
//! \brief Destructor.
virtual ~MemoryImageDataSource();
//! \brief Returns the number of memory regions in the image.
virtual unsigned getSegmentCount();
//! \brief Returns the data source segment at position \a index.
virtual DataSource::Segment * getSegmentAt(unsigned index);
protected:
/*!
* \brief Segment corresponding to a text region of the executable image.
*/
class TextSegment : public DataSource::Segment
{
public:
//! \brief Default constructor
TextSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index);
virtual unsigned getData(unsigned offset, unsigned maxBytes, uint8_t * buffer);
virtual unsigned getLength();
virtual bool hasNaturalLocation() { return true; }
virtual uint32_t getBaseAddress();
protected:
StExecutableImage * m_image; //!< Coalesced image of the file.
unsigned m_index; //!< Record index.
};
/*!
* \brief Segment corresponding to a fill region of the executable image.
*/
class FillSegment : public DataSource::PatternSegment
{
public:
FillSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index);
virtual unsigned getLength();
virtual bool hasNaturalLocation() { return true; }
virtual uint32_t getBaseAddress();
protected:
StExecutableImage * m_image; //!< Coalesced image of the file.
unsigned m_index; //!< Record index.
};
protected:
StExecutableImage * m_image; //!< The memory image that is the data source.
typedef std::vector<DataSource::Segment*> segment_array_t; //!< An array of segments.
segment_array_t m_segments; //!< The array of Segment instances.
};
}; // namespace elftosb
#endif // _DataSource_h_