1/*
2 * File:	StExecutableImage.h
3 *
4 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5 * See included license file for license details.
6 */
7#if !defined(_StExecutableImage_h_)
8#define _StExecutableImage_h_
9
10#include "stdafx.h"
11#include <list>
12
13/*!
14 * \brief Used to build a representation of memory regions.
15 *
16 * An intermediate representation of the memory regions and segments loaded
17 * from an executable file. Also used to find contiguous segments that are
18 * specified separately in the source file.
19 *
20 * When regions are added, an attempt is made to coalesce contiguous regions.
21 * In order for this to succeed, the touching regions must be of the same
22 * type and have the same permissions. Regions are also kept sorted by their
23 * address range as they are added.
24 *
25 * \todo Implement alignment support.
26 */
27class StExecutableImage
28{
29public:
30	//! Possible types of memory regions.
31	typedef enum {
32		TEXT_REGION,	//!< A region containing data or instructions.
33		FILL_REGION		//!< Region to be initialized with zero bytes.
34	} MemoryRegionType;
35
36	//! Memory region flag constants.
37	enum {
38		REGION_READ_FLAG = 1,	//!< Region is readable.
39		REGION_WRITE_FLAG = 2,	//!< Region is writable.
40		REGION_EXEC_FLAG = 4,	//!< Region may contain executable code.
41
42		REGION_RW_FLAG = REGION_READ_FLAG | REGION_WRITE_FLAG,	//!< Region is read-write.
43
44		//! Mask to access only permissions flags for a region.
45		REGION_PERM_FLAG_MASK = 0x7
46	};
47
48	/*!
49	 * Representation of a contiguous region of memory.
50     *
51     * \todo Add comparison operators so we can use the STL sort algorithm.
52	 */
53	struct MemoryRegion
54	{
55		MemoryRegionType m_type;	//!< Memory region type.
56		uint32_t m_address;	//!< The 32-bit start address of this region.
57		uint32_t m_length;	//!< Number of bytes in this region.
58		uint8_t * m_data;	//!< Pointer to data. Will be NULL for FILL_REGION type.
59		unsigned m_flags;	//!< Flags for the region.
60
61        //! \brief Calculates the address of the last byte occupied by this region.
62        inline uint32_t endAddress() const { return m_address + m_length - 1; }
63
64        //! \brief Equality operator.
65        bool operator == (const MemoryRegion & other) const;
66	};
67
68	//! A list of #StExecutableImage::MemoryRegion objects.
69	typedef std::list<MemoryRegion> MemoryRegionList;
70
71    //! The iterator type used to access #StExecutableImage::MemoryRegion objects. This type
72    //! is used by the methods #getRegionBegin() and #getRegionEnd().
73	typedef MemoryRegionList::const_iterator const_iterator;
74
75    //! The possible actions for regions matching an address filter range.
76    typedef enum {
77        ADDR_FILTER_NONE,       //!< Do nothing.
78        ADDR_FILTER_ERROR,      //!< Raise an error exception.
79        ADDR_FILTER_WARNING,    //!< Raise a warning exception.
80        ADDR_FILTER_CROP        //!< Don't include the matching address range in the executable image.
81    } AddressFilterAction;
82
83    /*!
84     * An address filter consists of a single address range and an action. If a
85     * memory region overlaps the filter's range then the action will be performed.
86     * The possible filter actions are defined by the #AddressFilterAction enumeration.
87     */
88    struct AddressFilter
89    {
90        AddressFilterAction m_action;   //!< Action to be performed when the filter is matched.
91        uint32_t m_fromAddress; //!< Start address of the filter. Should be lower than or equal to #m_toAddress.
92        uint32_t m_toAddress;   //!< End address of the filter. Should be higher than or equal to #m_fromAddress.
93        unsigned m_priority;     //!< Priority for this filter. Zero is the lowest priority.
94
95        //! \brief Constructor.
96        AddressFilter(AddressFilterAction action, uint32_t from, uint32_t to, unsigned priority=0)
97        :   m_action(action), m_fromAddress(from), m_toAddress(to), m_priority(priority)
98        {
99        }
100
101        //! \brief Test routine.
102        bool matchesMemoryRegion(const MemoryRegion & region) const;
103
104        //! \brief Compares two address filter objects.
105        int compare(const AddressFilter & other) const;
106
107        //! \name Comparison operators
108        //@{
109        inline bool operator < (const AddressFilter & other) const { return compare(other) == -1; }
110        inline bool operator > (const AddressFilter & other) const { return compare(other) == 1; }
111        inline bool operator == (const AddressFilter & other) const { return compare(other) == 0; }
112        inline bool operator <= (const AddressFilter & other) const { return compare(other) != 1; }
113        inline bool operator >= (const AddressFilter & other) const { return compare(other) != -1; }
114        //@}
115    };
116
117    //! List of #StExecutableImage::AddressFilter objects.
118    typedef std::list<AddressFilter> AddressFilterList;
119
120    //! The exception class raised for the #ADDR_FILTER_ERROR and #ADDR_FILTER_WARNING
121    //! filter actions.
122    class address_filter_exception
123    {
124    public:
125        //! \brief Constructor.
126        //!
127        //! A local copy of \a matchingFilter is made, in case the image and/or filter
128        //! are on the stack and would be disposed of when the exception is raised.
129        address_filter_exception(bool isError, std::string & imageName, const AddressFilter & matchingFilter)
130        : m_isError(isError), m_imageName(imageName), m_filter(matchingFilter)
131        {
132        }
133
134        //! \brief Returns true if the exception is an error. Otherwise the exception
135        //!     is for a warning.
136        inline bool isError() const { return m_isError; }
137
138        //! \brief
139        inline std::string getImageName() const { return m_imageName; }
140
141        //! \brief
142        inline const AddressFilter & getMatchingFilter() const { return m_filter; }
143
144    protected:
145        bool m_isError;
146        std::string m_imageName;
147        AddressFilter m_filter;
148    };
149
150public:
151	//! \brief Constructor.
152	StExecutableImage(int inAlignment=256);
153
154	//! \brief Copy constructor.
155	StExecutableImage(const StExecutableImage & inOther);
156
157	//! \brief Destructor.
158	virtual ~StExecutableImage();
159
160	//! \name Image name
161	//! Methods for getting and setting the image name.
162	//@{
163	//! \brief Sets the image's name to \a inName.
164	virtual void setName(const std::string & inName);
165
166	//! \brief Returns a copy of the image's name.
167	virtual std::string getName() const;
168	//@}
169
170	//! \name Regions
171	//! Methods to add and access memory regions.
172	//@{
173	//! \brief Add a region to be filled with zeroes.
174	virtual void addFillRegion(uint32_t inAddress, unsigned inLength);
175
176	//! \brief Add a region containing data to be loaded.
177	virtual void addTextRegion(uint32_t inAddress, const uint8_t * inData, unsigned inLength);
178
179	//! \brief Returns the total number of regions.
180	//!
181	//! Note that this count may not be the same as the number of calls to
182	//! addFillRegion() and addTextRegion() due to region coalescing.
183	inline unsigned getRegionCount() const { return static_cast<unsigned>(m_image.size()); }
184
185	//! \brief Returns a reference to the region specified by \a inIndex.
186	const MemoryRegion & getRegionAtIndex(unsigned inIndex) const;
187
188    //! \brief Return an iterator to the first region.
189	inline const_iterator getRegionBegin() const { return m_image.begin(); }
190
191    //! \brief Return an iterator to the next-after-last region.
192	inline const_iterator getRegionEnd() const { return m_image.end(); }
193	//@}
194
195	//! \name Entry point
196	//@{
197	//! \brief Sets the entry point address.
198	inline void setEntryPoint(uint32_t inEntryAddress) { m_entry = inEntryAddress; m_hasEntry = true; }
199
200	//! \brief Returns true if an entry point has been set.
201	inline bool hasEntryPoint() const { return m_hasEntry; }
202
203	//! \brief Returns the entry point address.
204	inline uint32_t getEntryPoint() const { return hasEntryPoint() ? m_entry : 0; }
205	//@}
206
207    //! \name Address filter
208    //@{
209    //! \brief Add a new address filter.
210    virtual void addAddressFilter(const AddressFilter & filter);
211
212    //! \brief Add multiple address filters at once.
213    //!
214    //! The template argument \a _T must be an iterator or const iterator that
215    //! dereferences to an StExecutableImage::AddressFilter reference. All filters
216    //! from \a from to \a to will be added to the address filter list.
217    template<typename _T> void addAddressFilters(_T from, _T to)
218    {
219        _T it = from;
220        for (; it != to; ++it)
221        {
222            addAddressFilter(*it);
223        }
224    }
225
226    //! \brief Remove all active filters.
227    virtual void clearAddressFilters();
228
229    //! \brief Process all active filters and perform associated actions.
230    virtual void applyAddressFilters();
231    //@}
232
233protected:
234	std::string m_name;	//!< The name of the image (can be a file name, for instance).
235	int m_alignment;	//!< The required address alignment for each memory region.
236	bool m_hasEntry;	//!< True if an entry point has been set.
237	uint32_t m_entry;	//!< Entry point address.
238	MemoryRegionList m_image;	//!< The memory regions.
239    AddressFilterList m_filters;    //!< List of active address filters.
240
241    //! \brief Deletes the portion \a region that overlaps \a filter.
242    void cropRegionToFilter(MemoryRegion & region, const AddressFilter & filter);
243
244	//! \brief Inserts the region in sorted order or merges with one already in the image.
245	void insertOrMergeRegion(MemoryRegion & inRegion);
246
247	//! \brief Merges two memory regions into one.
248	void mergeRegions(MemoryRegion & inOldRegion, MemoryRegion & inNewRegion);
249};
250
251#endif // _StExecutableImage_h_
252