Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

/*
 * 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_