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  */
27 class StExecutableImage
28 {
29 public:
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.
endAddressMemoryRegion62         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)
m_actionAddressFilter97         :   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.
address_filter_exception(bool isError,std::string & imageName,const AddressFilter & matchingFilter)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.
isError()136         inline bool isError() const { return m_isError; }
137 
138         //! \brief
getImageName()139         inline std::string getImageName() const { return m_imageName; }
140 
141         //! \brief
getMatchingFilter()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 
150 public:
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.
getRegionCount()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.
getRegionBegin()189           inline const_iterator getRegionBegin() const { return m_image.begin(); }
190 
191     //! \brief Return an iterator to the next-after-last region.
getRegionEnd()192           inline const_iterator getRegionEnd() const { return m_image.end(); }
193           //@}
194 
195           //! \name Entry point
196           //@{
197           //! \brief Sets the entry point address.
setEntryPoint(uint32_t inEntryAddress)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.
hasEntryPoint()201           inline bool hasEntryPoint() const { return m_hasEntry; }
202 
203           //! \brief Returns the entry point address.
getEntryPoint()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.
addAddressFilters(_T from,_T to)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 
233 protected:
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