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:	StExecutableImage.h
 *
 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
 * See included license file for license details.
 */
#if !defined(_StExecutableImage_h_)
#define _StExecutableImage_h_

#include "stdafx.h"
#include <list>

/*!
 * \brief Used to build a representation of memory regions.
 *
 * An intermediate representation of the memory regions and segments loaded
 * from an executable file. Also used to find contiguous segments that are
 * specified separately in the source file.
 *
 * When regions are added, an attempt is made to coalesce contiguous regions.
 * In order for this to succeed, the touching regions must be of the same
 * type and have the same permissions. Regions are also kept sorted by their
 * address range as they are added.
 *
 * \todo Implement alignment support.
 */
class StExecutableImage
{
public:
	//! Possible types of memory regions.
	typedef enum {
		TEXT_REGION,	//!< A region containing data or instructions.
		FILL_REGION		//!< Region to be initialized with zero bytes.
	} MemoryRegionType;
	
	//! Memory region flag constants.
	enum {
		REGION_READ_FLAG = 1,	//!< Region is readable.
		REGION_WRITE_FLAG = 2,	//!< Region is writable.
		REGION_EXEC_FLAG = 4,	//!< Region may contain executable code.
		
		REGION_RW_FLAG = REGION_READ_FLAG | REGION_WRITE_FLAG,	//!< Region is read-write.
		
		//! Mask to access only permissions flags for a region.
		REGION_PERM_FLAG_MASK = 0x7
	};
	
	/*!
	 * Representation of a contiguous region of memory.
     *
     * \todo Add comparison operators so we can use the STL sort algorithm.
	 */
	struct MemoryRegion
	{
		MemoryRegionType m_type;	//!< Memory region type.
		uint32_t m_address;	//!< The 32-bit start address of this region.
		uint32_t m_length;	//!< Number of bytes in this region.
		uint8_t * m_data;	//!< Pointer to data. Will be NULL for FILL_REGION type.
		unsigned m_flags;	//!< Flags for the region.
        
        //! \brief Calculates the address of the last byte occupied by this region.
        inline uint32_t endAddress() const { return m_address + m_length - 1; }
        
        //! \brief Equality operator.
        bool operator == (const MemoryRegion & other) const;
	};
	
	//! A list of #StExecutableImage::MemoryRegion objects.
	typedef std::list<MemoryRegion> MemoryRegionList;
    
    //! The iterator type used to access #StExecutableImage::MemoryRegion objects. This type
    //! is used by the methods #getRegionBegin() and #getRegionEnd().
	typedef MemoryRegionList::const_iterator const_iterator;
	
    //! The possible actions for regions matching an address filter range.
    typedef enum {
        ADDR_FILTER_NONE,       //!< Do nothing.
        ADDR_FILTER_ERROR,      //!< Raise an error exception.
        ADDR_FILTER_WARNING,    //!< Raise a warning exception.
        ADDR_FILTER_CROP        //!< Don't include the matching address range in the executable image.
    } AddressFilterAction;
    
    /*!
     * An address filter consists of a single address range and an action. If a
     * memory region overlaps the filter's range then the action will be performed.
     * The possible filter actions are defined by the #AddressFilterAction enumeration.
     */
    struct AddressFilter
    {
        AddressFilterAction m_action;   //!< Action to be performed when the filter is matched.
        uint32_t m_fromAddress; //!< Start address of the filter. Should be lower than or equal to #m_toAddress.
        uint32_t m_toAddress;   //!< End address of the filter. Should be higher than or equal to #m_fromAddress.
        unsigned m_priority;     //!< Priority for this filter. Zero is the lowest priority.
        
        //! \brief Constructor.
        AddressFilter(AddressFilterAction action, uint32_t from, uint32_t to, unsigned priority=0)
        :   m_action(action), m_fromAddress(from), m_toAddress(to), m_priority(priority)
        {
        }
        
        //! \brief Test routine.
        bool matchesMemoryRegion(const MemoryRegion & region) const;
        
        //! \brief Compares two address filter objects.
        int compare(const AddressFilter & other) const;
        
        //! \name Comparison operators
        //@{
        inline bool operator < (const AddressFilter & other) const { return compare(other) == -1; }
        inline bool operator > (const AddressFilter & other) const { return compare(other) == 1; }
        inline bool operator == (const AddressFilter & other) const { return compare(other) == 0; }
        inline bool operator <= (const AddressFilter & other) const { return compare(other) != 1; }
        inline bool operator >= (const AddressFilter & other) const { return compare(other) != -1; }
        //@}
    };
    
    //! List of #StExecutableImage::AddressFilter objects.
    typedef std::list<AddressFilter> AddressFilterList;
    
    //! The exception class raised for the #ADDR_FILTER_ERROR and #ADDR_FILTER_WARNING
    //! filter actions.
    class address_filter_exception
    {
    public:
        //! \brief Constructor.
        //!
        //! A local copy of \a matchingFilter is made, in case the image and/or filter
        //! are on the stack and would be disposed of when the exception is raised.
        address_filter_exception(bool isError, std::string & imageName, const AddressFilter & matchingFilter)
        : m_isError(isError), m_imageName(imageName), m_filter(matchingFilter)
        {
        }
        
        //! \brief Returns true if the exception is an error. Otherwise the exception
        //!     is for a warning.
        inline bool isError() const { return m_isError; }
        
        //! \brief
        inline std::string getImageName() const { return m_imageName; }
        
        //! \brief
        inline const AddressFilter & getMatchingFilter() const { return m_filter; }
    
    protected:
        bool m_isError;
        std::string m_imageName;
        AddressFilter m_filter;
    };
    
public:
	//! \brief Constructor.
	StExecutableImage(int inAlignment=256);
	
	//! \brief Copy constructor.
	StExecutableImage(const StExecutableImage & inOther);
	
	//! \brief Destructor.
	virtual ~StExecutableImage();
	
	//! \name Image name
	//! Methods for getting and setting the image name.
	//@{
	//! \brief Sets the image's name to \a inName.
	virtual void setName(const std::string & inName);
	
	//! \brief Returns a copy of the image's name.
	virtual std::string getName() const;
	//@}
	
	//! \name Regions
	//! Methods to add and access memory regions.
	//@{
	//! \brief Add a region to be filled with zeroes.
	virtual void addFillRegion(uint32_t inAddress, unsigned inLength);
	
	//! \brief Add a region containing data to be loaded.
	virtual void addTextRegion(uint32_t inAddress, const uint8_t * inData, unsigned inLength);
	
	//! \brief Returns the total number of regions.
	//!
	//! Note that this count may not be the same as the number of calls to
	//! addFillRegion() and addTextRegion() due to region coalescing.
	inline unsigned getRegionCount() const { return static_cast<unsigned>(m_image.size()); }
	
	//! \brief Returns a reference to the region specified by \a inIndex.
	const MemoryRegion & getRegionAtIndex(unsigned inIndex) const;
	
    //! \brief Return an iterator to the first region.
	inline const_iterator getRegionBegin() const { return m_image.begin(); }
    
    //! \brief Return an iterator to the next-after-last region.
	inline const_iterator getRegionEnd() const { return m_image.end(); }
	//@}
	
	//! \name Entry point
	//@{
	//! \brief Sets the entry point address.
	inline void setEntryPoint(uint32_t inEntryAddress) { m_entry = inEntryAddress; m_hasEntry = true; }
	
	//! \brief Returns true if an entry point has been set.
	inline bool hasEntryPoint() const { return m_hasEntry; }
	
	//! \brief Returns the entry point address.
	inline uint32_t getEntryPoint() const { return hasEntryPoint() ? m_entry : 0; }
	//@}
    
    //! \name Address filter
    //@{
    //! \brief Add a new address filter.
    virtual void addAddressFilter(const AddressFilter & filter);
    
    //! \brief Add multiple address filters at once.
    //!
    //! The template argument \a _T must be an iterator or const iterator that
    //! dereferences to an StExecutableImage::AddressFilter reference. All filters
    //! from \a from to \a to will be added to the address filter list.
    template<typename _T> void addAddressFilters(_T from, _T to)
    {
        _T it = from;
        for (; it != to; ++it)
        {
            addAddressFilter(*it);
        }
    }
    
    //! \brief Remove all active filters.
    virtual void clearAddressFilters();
    
    //! \brief Process all active filters and perform associated actions.
    virtual void applyAddressFilters();
    //@}
	
protected:
	std::string m_name;	//!< The name of the image (can be a file name, for instance).
	int m_alignment;	//!< The required address alignment for each memory region.
	bool m_hasEntry;	//!< True if an entry point has been set.
	uint32_t m_entry;	//!< Entry point address.
	MemoryRegionList m_image;	//!< The memory regions.
    AddressFilterList m_filters;    //!< List of active address filters.
    
    //! \brief Deletes the portion \a region that overlaps \a filter.
    void cropRegionToFilter(MemoryRegion & region, const AddressFilter & filter);
	
	//! \brief Inserts the region in sorted order or merges with one already in the image.
	void insertOrMergeRegion(MemoryRegion & inRegion);
	
	//! \brief Merges two memory regions into one.
	void mergeRegions(MemoryRegion & inOldRegion, MemoryRegion & inNewRegion);
};

#endif // _StExecutableImage_h_