/* * 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 /*! * \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); }; //! A list of #StExecutableImage::MemoryRegion objects. typedef std::list 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 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(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 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_