258 lines
9.9 KiB
C++
258 lines
9.9 KiB
C++
/*
|
|
* 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 ®ion) 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 ®ion, 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_
|