summaryrefslogtreecommitdiffstats
path: root/common/StExecutableImage.h
blob: edfd5f43c8dc8fe8470b370ffba3b3c1416d40ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/*
 * 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);
	};
	
	//! 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_