xref: /netbsd-src/external/bsd/elftosb/dist/common/StExecutableImage.cpp (revision 93f5e2c30272859d294e5c9c68ed3d0473b9c75d)
1993229b6Sjkunz /*
2993229b6Sjkunz  * File:	StExecutableImage.cpp
3993229b6Sjkunz  *
4993229b6Sjkunz  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5993229b6Sjkunz  * See included license file for license details.
6993229b6Sjkunz  */
7993229b6Sjkunz 
8993229b6Sjkunz #include "StExecutableImage.h"
9993229b6Sjkunz #include <stdexcept>
10993229b6Sjkunz #include <algorithm>
11993229b6Sjkunz #include <string.h>
12993229b6Sjkunz #include <stdio.h>
13993229b6Sjkunz 
StExecutableImage(int inAlignment)14993229b6Sjkunz StExecutableImage::StExecutableImage(int inAlignment)
15993229b6Sjkunz :	m_alignment(inAlignment),
16993229b6Sjkunz 	m_hasEntry(false),
17993229b6Sjkunz 	m_entry(0)
18993229b6Sjkunz {
19993229b6Sjkunz }
20993229b6Sjkunz 
21993229b6Sjkunz //! Makes a duplicate of each memory region.
StExecutableImage(const StExecutableImage & inOther)22993229b6Sjkunz StExecutableImage::StExecutableImage(const StExecutableImage & inOther)
23993229b6Sjkunz :	m_name(inOther.m_name),
24993229b6Sjkunz     m_alignment(inOther.m_alignment),
25993229b6Sjkunz 	m_hasEntry(inOther.m_hasEntry),
26993229b6Sjkunz 	m_entry(inOther.m_entry),
27993229b6Sjkunz     m_filters(inOther.m_filters)
28993229b6Sjkunz {
29993229b6Sjkunz 	const_iterator it = inOther.getRegionBegin();
30993229b6Sjkunz 	for (; it != inOther.getRegionEnd(); ++it)
31993229b6Sjkunz 	{
32993229b6Sjkunz 		const MemoryRegion & region = *it;
33993229b6Sjkunz 
34993229b6Sjkunz 		MemoryRegion regionCopy(region);
35993229b6Sjkunz 		if (region.m_type == FILL_REGION && region.m_data != NULL)
36993229b6Sjkunz 		{
37993229b6Sjkunz 			regionCopy.m_data = new uint8_t[region.m_length];
38993229b6Sjkunz 			memcpy(regionCopy.m_data, region.m_data, region.m_length);
39993229b6Sjkunz 		}
40993229b6Sjkunz 
41993229b6Sjkunz 		m_image.push_back(regionCopy);
42993229b6Sjkunz 	}
43993229b6Sjkunz }
44993229b6Sjkunz 
45993229b6Sjkunz //! Disposes of memory allocated for each region.
~StExecutableImage()46993229b6Sjkunz StExecutableImage::~StExecutableImage()
47993229b6Sjkunz {
48993229b6Sjkunz 	MemoryRegionList::iterator it;
49993229b6Sjkunz 	for (it = m_image.begin(); it != m_image.end(); ++it)
50993229b6Sjkunz 	{
51993229b6Sjkunz 		if (it->m_data)
52993229b6Sjkunz 		{
53993229b6Sjkunz 			delete [] it->m_data;
54993229b6Sjkunz 			it->m_data = NULL;
55993229b6Sjkunz 		}
56993229b6Sjkunz 	}
57993229b6Sjkunz }
58993229b6Sjkunz 
59993229b6Sjkunz //! A copy of \a inName is made, so the original may be disposed of by the caller
60993229b6Sjkunz //! after this method returns.
setName(const std::string & inName)61993229b6Sjkunz void StExecutableImage::setName(const std::string & inName)
62993229b6Sjkunz {
63993229b6Sjkunz 	m_name = inName;
64993229b6Sjkunz }
65993229b6Sjkunz 
getName() const66993229b6Sjkunz std::string StExecutableImage::getName() const
67993229b6Sjkunz {
68993229b6Sjkunz 	return m_name;
69993229b6Sjkunz }
70993229b6Sjkunz 
71993229b6Sjkunz // The region is added with read and write flags set.
72993229b6Sjkunz //! \exception std::runtime_error will be thrown if the new overlaps an
73993229b6Sjkunz //!		existing region.
addFillRegion(uint32_t inAddress,unsigned inLength)74993229b6Sjkunz void StExecutableImage::addFillRegion(uint32_t inAddress, unsigned inLength)
75993229b6Sjkunz {
76993229b6Sjkunz 	MemoryRegion region;
77993229b6Sjkunz 	region.m_type = FILL_REGION;
78993229b6Sjkunz 	region.m_address = inAddress;
79993229b6Sjkunz 	region.m_data = NULL;
80993229b6Sjkunz 	region.m_length = inLength;
81993229b6Sjkunz 	region.m_flags = REGION_RW_FLAG;
82993229b6Sjkunz 
83993229b6Sjkunz 	insertOrMergeRegion(region);
84993229b6Sjkunz }
85993229b6Sjkunz 
86993229b6Sjkunz //! A copy of \a inData is made before returning. The copy will be deleted when
87993229b6Sjkunz //! the executable image is destructed. Currently, the text region is created with
88993229b6Sjkunz //! read, write, and executable flags set.
89993229b6Sjkunz //! \exception std::runtime_error will be thrown if the new overlaps an
90993229b6Sjkunz //!		existing region.
91993229b6Sjkunz //! \exception std::bad_alloc is thrown if memory for the copy of \a inData
92993229b6Sjkunz //!		cannot be allocated.
addTextRegion(uint32_t inAddress,const uint8_t * inData,unsigned inLength)93993229b6Sjkunz void StExecutableImage::addTextRegion(uint32_t inAddress, const uint8_t * inData, unsigned inLength)
94993229b6Sjkunz {
95993229b6Sjkunz 	MemoryRegion region;
96993229b6Sjkunz 	region.m_type = TEXT_REGION;
97993229b6Sjkunz 	region.m_address = inAddress;
98993229b6Sjkunz 	region.m_flags = REGION_RW_FLAG | REGION_EXEC_FLAG;
99993229b6Sjkunz 
100993229b6Sjkunz 	// copy the data
101993229b6Sjkunz 	region.m_data = new uint8_t[inLength];
102993229b6Sjkunz 	region.m_length = inLength;
103993229b6Sjkunz 	memcpy(region.m_data, inData, inLength);
104993229b6Sjkunz 
105993229b6Sjkunz 	insertOrMergeRegion(region);
106993229b6Sjkunz }
107993229b6Sjkunz 
108993229b6Sjkunz //! \exception std::out_of_range is thrown if \a inIndex is out of range.
109993229b6Sjkunz //!
getRegionAtIndex(unsigned inIndex) const110993229b6Sjkunz const StExecutableImage::MemoryRegion & StExecutableImage::getRegionAtIndex(unsigned inIndex) const
111993229b6Sjkunz {
112993229b6Sjkunz 	// check bounds
113993229b6Sjkunz 	if (inIndex >= m_image.size())
114993229b6Sjkunz 		throw std::out_of_range("inIndex");
115993229b6Sjkunz 
116993229b6Sjkunz 	// find region by index
117993229b6Sjkunz 	MemoryRegionList::const_iterator it = m_image.begin();
118993229b6Sjkunz 	unsigned i = 0;
119993229b6Sjkunz 	for (; it != m_image.end(); ++it, ++i)
120993229b6Sjkunz 	{
121993229b6Sjkunz 		if (i == inIndex)
122993229b6Sjkunz 			break;
123993229b6Sjkunz 	}
124993229b6Sjkunz 	return *it;
125993229b6Sjkunz }
126993229b6Sjkunz 
127993229b6Sjkunz //! The list of address filters is kept sorted as filters are added.
128993229b6Sjkunz //!
addAddressFilter(const AddressFilter & filter)129993229b6Sjkunz void StExecutableImage::addAddressFilter(const AddressFilter & filter)
130993229b6Sjkunz {
131993229b6Sjkunz     m_filters.push_back(filter);
132993229b6Sjkunz     m_filters.sort();
133993229b6Sjkunz }
134993229b6Sjkunz 
135993229b6Sjkunz //!
clearAddressFilters()136993229b6Sjkunz void StExecutableImage::clearAddressFilters()
137993229b6Sjkunz {
138993229b6Sjkunz     m_filters.clear();
139993229b6Sjkunz }
140993229b6Sjkunz 
141993229b6Sjkunz //! \exception StExecutableImage::address_filter_exception Raised when a filter
142993229b6Sjkunz //!     with the type #ADDR_FILTER_ERROR or #ADDR_FILTER_WARNING is matched.
143993229b6Sjkunz //!
144993229b6Sjkunz //! \todo Build a list of all matching filters and then execute them at once.
145993229b6Sjkunz //!     For the warning and error filters, a single exception should be raised
146993229b6Sjkunz //!     that identifies all the overlapping errors. Currently the user will only
147993229b6Sjkunz //!     see the first (lowest address) overlap.
applyAddressFilters()148993229b6Sjkunz void StExecutableImage::applyAddressFilters()
149993229b6Sjkunz {
150993229b6Sjkunz restart_loops:
151993229b6Sjkunz     // Iterate over filters.
152993229b6Sjkunz     AddressFilterList::const_iterator fit = m_filters.begin();
153993229b6Sjkunz     for (; fit != m_filters.end(); ++fit)
154993229b6Sjkunz     {
155993229b6Sjkunz         const AddressFilter & filter = *fit;
156993229b6Sjkunz 
157993229b6Sjkunz         // Iterator over regions.
158993229b6Sjkunz         MemoryRegionList::iterator rit = m_image.begin();
159993229b6Sjkunz         for (; rit != m_image.end(); ++rit)
160993229b6Sjkunz         {
161993229b6Sjkunz             MemoryRegion & region = *rit;
162993229b6Sjkunz 
163993229b6Sjkunz             if (filter.matchesMemoryRegion(region))
164993229b6Sjkunz             {
165993229b6Sjkunz                 switch (filter.m_action)
166993229b6Sjkunz                 {
167993229b6Sjkunz                     case ADDR_FILTER_NONE:
168993229b6Sjkunz                         // Do nothing.
169993229b6Sjkunz                         break;
170993229b6Sjkunz 
171993229b6Sjkunz                     case ADDR_FILTER_ERROR:
172993229b6Sjkunz                         // throw error exception
173993229b6Sjkunz                         throw address_filter_exception(true, m_name, filter);
174993229b6Sjkunz                         break;
175993229b6Sjkunz 
176993229b6Sjkunz                     case ADDR_FILTER_WARNING:
177993229b6Sjkunz                         // throw warning exception
178993229b6Sjkunz                         throw address_filter_exception(false, m_name, filter);
179993229b6Sjkunz                         break;
180993229b6Sjkunz 
181993229b6Sjkunz                     case ADDR_FILTER_CROP:
182993229b6Sjkunz                         // Delete the offending portion of the region and restart
183993229b6Sjkunz                         // the iteration loops.
184993229b6Sjkunz                         cropRegionToFilter(region, filter);
185993229b6Sjkunz                         goto restart_loops;
186993229b6Sjkunz                         break;
187993229b6Sjkunz                 }
188993229b6Sjkunz             }
189993229b6Sjkunz         }
190993229b6Sjkunz     }
191993229b6Sjkunz }
192993229b6Sjkunz 
193993229b6Sjkunz //! There are several possible cases here:
194993229b6Sjkunz //!     - No overlap at all. Nothing is done.
195993229b6Sjkunz //!
196993229b6Sjkunz //!     - All of the memory region is matched by the \a filter. The region is
197993229b6Sjkunz //!         removed from #StExecutableImage::m_image and its data memory freed.
198993229b6Sjkunz //!
199993229b6Sjkunz //!     - The remaining portion of the region is one contiguous chunk. In this
200993229b6Sjkunz //!         case, \a region is simply modified.
201993229b6Sjkunz //!
202993229b6Sjkunz //!     - The region is split in the middle by the filter. The original \a region
203993229b6Sjkunz //!         is modified to match the first remaining chunk. And a new #StExecutableImage::MemoryRegion
204993229b6Sjkunz //!         instance is created to hold the other leftover piece.
cropRegionToFilter(MemoryRegion & region,const AddressFilter & filter)205993229b6Sjkunz void StExecutableImage::cropRegionToFilter(MemoryRegion & region, const AddressFilter & filter)
206993229b6Sjkunz {
207993229b6Sjkunz     uint32_t firstByte = region.m_address;      // first byte occupied by this region
208993229b6Sjkunz     uint32_t lastByte = region.endAddress();    // last used byte in this region
209993229b6Sjkunz 
210993229b6Sjkunz     // compute new address range
211993229b6Sjkunz     uint32_t cropFrom = filter.m_fromAddress;
212993229b6Sjkunz     if (cropFrom < firstByte)
213993229b6Sjkunz     {
214993229b6Sjkunz         cropFrom = firstByte;
215993229b6Sjkunz     }
216993229b6Sjkunz 
217993229b6Sjkunz     uint32_t cropTo = filter.m_toAddress;
218993229b6Sjkunz     if (cropTo > lastByte)
219993229b6Sjkunz     {
220993229b6Sjkunz         cropTo = lastByte;
221993229b6Sjkunz     }
222993229b6Sjkunz 
223993229b6Sjkunz     // is there actually a match?
224993229b6Sjkunz     if (cropFrom > filter.m_toAddress || cropTo < filter.m_fromAddress)
225993229b6Sjkunz     {
226993229b6Sjkunz         // nothing to do, so bail
227993229b6Sjkunz         return;
228993229b6Sjkunz     }
229993229b6Sjkunz 
230993229b6Sjkunz     printf("Deleting region 0x%08x-0x%08x\n", cropFrom, cropTo);
231993229b6Sjkunz 
232993229b6Sjkunz     // handle if the entire region is to be deleted
233993229b6Sjkunz     if (cropFrom == firstByte && cropTo == lastByte)
234993229b6Sjkunz     {
235993229b6Sjkunz         delete [] region.m_data;
236993229b6Sjkunz         region.m_data = NULL;
237993229b6Sjkunz         m_image.remove(region);
238993229b6Sjkunz     }
239993229b6Sjkunz 
240993229b6Sjkunz     // there is at least a little of the original region remaining
241993229b6Sjkunz     uint32_t newLength = cropTo - cropFrom + 1;
242993229b6Sjkunz     uint32_t leftoverLength = lastByte - cropTo;
243993229b6Sjkunz     uint8_t * oldData = region.m_data;
244993229b6Sjkunz 
245993229b6Sjkunz     // update the region
246993229b6Sjkunz     region.m_address = cropFrom;
247993229b6Sjkunz     region.m_length = newLength;
248993229b6Sjkunz 
249993229b6Sjkunz     // crop data buffer for text regions
250993229b6Sjkunz     if (region.m_type == TEXT_REGION && oldData)
251993229b6Sjkunz     {
252993229b6Sjkunz         region.m_data = new uint8_t[newLength];
253993229b6Sjkunz         memcpy(region.m_data, &oldData[cropFrom - firstByte], newLength);
254993229b6Sjkunz 
255993229b6Sjkunz         // dispose of old data
256993229b6Sjkunz         delete [] oldData;
257993229b6Sjkunz     }
258993229b6Sjkunz 
259993229b6Sjkunz     // create a new region for any part of the original region that was past
260993229b6Sjkunz     // the crop to address. this will happen if the filter range falls in the
261993229b6Sjkunz     // middle of the region.
262993229b6Sjkunz     if (leftoverLength)
263993229b6Sjkunz     {
264993229b6Sjkunz         MemoryRegion newRegion;
265993229b6Sjkunz         newRegion.m_type = region.m_type;
266993229b6Sjkunz         newRegion.m_flags = region.m_flags;
267993229b6Sjkunz         newRegion.m_address = cropTo + 1;
268993229b6Sjkunz         newRegion.m_length = leftoverLength;
269993229b6Sjkunz 
270993229b6Sjkunz         if (region.m_type == TEXT_REGION && oldData)
271993229b6Sjkunz         {
272993229b6Sjkunz             newRegion.m_data = new uint8_t[leftoverLength];
273993229b6Sjkunz             memcpy(newRegion.m_data, &oldData[cropTo - firstByte + 1], leftoverLength);
274993229b6Sjkunz         }
275993229b6Sjkunz 
276993229b6Sjkunz         insertOrMergeRegion(newRegion);
277993229b6Sjkunz     }
278993229b6Sjkunz }
279993229b6Sjkunz 
280993229b6Sjkunz //! \exception std::runtime_error will be thrown if \a inRegion overlaps an
281993229b6Sjkunz //!		existing region.
282993229b6Sjkunz //!
283993229b6Sjkunz //! \todo Need to investigate if we can use the STL sort algorithm at all. Even
284993229b6Sjkunz //!     though we're doing merges too, we could sort first then examine the list
285993229b6Sjkunz //!     for merges.
insertOrMergeRegion(MemoryRegion & inRegion)286993229b6Sjkunz void StExecutableImage::insertOrMergeRegion(MemoryRegion & inRegion)
287993229b6Sjkunz {
288993229b6Sjkunz 	uint32_t newStart = inRegion.m_address;
289993229b6Sjkunz 	uint32_t newEnd = newStart + inRegion.m_length;
290993229b6Sjkunz 
291993229b6Sjkunz 	MemoryRegionList::iterator it = m_image.begin();
292993229b6Sjkunz 	MemoryRegionList::iterator sortedPosition = m_image.begin();
293993229b6Sjkunz 	for (; it != m_image.end(); ++it)
294993229b6Sjkunz 	{
295993229b6Sjkunz 		MemoryRegion & region = *it;
296993229b6Sjkunz 		uint32_t thisStart = region.m_address;
297993229b6Sjkunz 		uint32_t thisEnd = thisStart + region.m_length;
298993229b6Sjkunz 
299993229b6Sjkunz 		// keep track of where to insert it to retain sort order
300993229b6Sjkunz 		if (thisStart >= newEnd)
301993229b6Sjkunz 		{
302993229b6Sjkunz 			break;
303993229b6Sjkunz 		}
304993229b6Sjkunz 
305993229b6Sjkunz 		// region types and flags must match in order to merge
306993229b6Sjkunz 		if (region.m_type == inRegion.m_type && region.m_flags == inRegion.m_flags)
307993229b6Sjkunz 		{
308993229b6Sjkunz 			if (newStart == thisEnd || newEnd == thisStart)
309993229b6Sjkunz 			{
310993229b6Sjkunz 				mergeRegions(region, inRegion);
311993229b6Sjkunz 				return;
312993229b6Sjkunz 			}
313993229b6Sjkunz 			else if ((newStart >= thisStart && newStart < thisEnd) || (newEnd >= thisStart && newEnd < thisEnd))
314993229b6Sjkunz 			{
315993229b6Sjkunz 				throw std::runtime_error("new region overlaps existing region");
316993229b6Sjkunz 			}
317993229b6Sjkunz 		}
318993229b6Sjkunz 	}
319993229b6Sjkunz 
320993229b6Sjkunz 	// not merged, so just insert it in the sorted position
321993229b6Sjkunz 	m_image.insert(it, inRegion);
322993229b6Sjkunz }
323993229b6Sjkunz 
324993229b6Sjkunz //! Extends \a inNewRegion to include the data in \a inOldRegion. It is
325993229b6Sjkunz //! assumed that the two regions are compatible. The new region may come either
326993229b6Sjkunz //! before or after the old region in memory. Note that while the two regions
327993229b6Sjkunz //! don't necessarily have to be touching, it's probably a good idea. That's
328993229b6Sjkunz //! because any data between the regions will be set to 0.
329993229b6Sjkunz //!
330993229b6Sjkunz //! For TEXT_REGION types, the two original regions will have their data deleted
331993229b6Sjkunz //! during the merge. Thus, this method is not safe if any outside callers may
332993229b6Sjkunz //! be accessing the region's data.
mergeRegions(MemoryRegion & inOldRegion,MemoryRegion & inNewRegion)333993229b6Sjkunz void StExecutableImage::mergeRegions(MemoryRegion & inOldRegion, MemoryRegion & inNewRegion)
334993229b6Sjkunz {
335993229b6Sjkunz 	bool isOldBefore = inOldRegion.m_address < inNewRegion.m_address;
336993229b6Sjkunz 	uint32_t oldEnd = inOldRegion.m_address + inOldRegion.m_length;
337993229b6Sjkunz 	uint32_t newEnd = inNewRegion.m_address + inNewRegion.m_length;
338993229b6Sjkunz 
339993229b6Sjkunz 	switch (inOldRegion.m_type)
340993229b6Sjkunz 	{
341993229b6Sjkunz 		case TEXT_REGION:
342993229b6Sjkunz 		{
343993229b6Sjkunz 			// calculate new length
344993229b6Sjkunz 			unsigned newLength;
345993229b6Sjkunz 			if (isOldBefore)
346993229b6Sjkunz 			{
347993229b6Sjkunz 				newLength = newEnd - inOldRegion.m_address;
348993229b6Sjkunz 			}
349993229b6Sjkunz 			else
350993229b6Sjkunz 			{
351993229b6Sjkunz 				newLength = oldEnd - inNewRegion.m_address;
352993229b6Sjkunz 			}
353993229b6Sjkunz 
354993229b6Sjkunz 			// alloc memory
355993229b6Sjkunz 			uint8_t * newData = new uint8_t[newLength];
356993229b6Sjkunz 			memset(newData, 0, newLength);
357993229b6Sjkunz 
358993229b6Sjkunz 			// copy data from the two regions into new block
359993229b6Sjkunz 			if (isOldBefore)
360993229b6Sjkunz 			{
361993229b6Sjkunz 				memcpy(newData, inOldRegion.m_data, inOldRegion.m_length);
362993229b6Sjkunz 				memcpy(&newData[newLength - inNewRegion.m_length], inNewRegion.m_data, inNewRegion.m_length);
363993229b6Sjkunz 			}
364993229b6Sjkunz 			else
365993229b6Sjkunz 			{
366993229b6Sjkunz 				memcpy(newData, inNewRegion.m_data, inNewRegion.m_length);
367993229b6Sjkunz 				memcpy(&newData[newLength - inOldRegion.m_length], inOldRegion.m_data, inOldRegion.m_length);
368993229b6Sjkunz 
369993229b6Sjkunz 				inOldRegion.m_address = inNewRegion.m_address;
370993229b6Sjkunz 			}
371993229b6Sjkunz 
372993229b6Sjkunz 			// replace old region's data
373993229b6Sjkunz 			delete [] inOldRegion.m_data;
374993229b6Sjkunz 			inOldRegion.m_data = newData;
375993229b6Sjkunz 			inOldRegion.m_length = newLength;
376993229b6Sjkunz 
377993229b6Sjkunz 			// delete new region's data
378993229b6Sjkunz 			delete [] inNewRegion.m_data;
379993229b6Sjkunz 			inNewRegion.m_data = NULL;
380993229b6Sjkunz 			break;
381993229b6Sjkunz 		}
382993229b6Sjkunz 
383993229b6Sjkunz 		case FILL_REGION:
384993229b6Sjkunz 		{
385993229b6Sjkunz 			if (isOldBefore)
386993229b6Sjkunz 			{
387993229b6Sjkunz 				inOldRegion.m_length = newEnd - inOldRegion.m_address;
388993229b6Sjkunz 			}
389993229b6Sjkunz 			else
390993229b6Sjkunz 			{
391993229b6Sjkunz 				inOldRegion.m_length = oldEnd - inNewRegion.m_address;
392993229b6Sjkunz 				inOldRegion.m_address = inNewRegion.m_address;
393993229b6Sjkunz 			}
394993229b6Sjkunz 			break;
395993229b6Sjkunz 		}
396993229b6Sjkunz 	}
397993229b6Sjkunz }
398993229b6Sjkunz 
399993229b6Sjkunz //! Used when we remove a region from the region list by value. Because this
400993229b6Sjkunz //! operator compares the #m_data member, it will only return true for either an
401993229b6Sjkunz //! exact copy or a reference to the original.
operator ==(const MemoryRegion & other) const402*93f5e2c3Sjoerg bool StExecutableImage::MemoryRegion::operator == (const MemoryRegion & other) const
403993229b6Sjkunz {
404993229b6Sjkunz    return (m_type == other.m_type) && (m_address == other.m_address) && (m_length == other.m_length) && (m_flags == other.m_flags) && (m_data == other.m_data);
405993229b6Sjkunz }
406993229b6Sjkunz 
407993229b6Sjkunz //! Returns true if the address filter overlaps \a region.
matchesMemoryRegion(const MemoryRegion & region) const408993229b6Sjkunz bool StExecutableImage::AddressFilter::matchesMemoryRegion(const MemoryRegion & region) const
409993229b6Sjkunz {
410993229b6Sjkunz     uint32_t firstByte = region.m_address;      // first byte occupied by this region
411993229b6Sjkunz     uint32_t lastByte = region.endAddress();    // last used byte in this region
412993229b6Sjkunz     return (firstByte >= m_fromAddress && firstByte <= m_toAddress) || (lastByte >= m_fromAddress && lastByte <= m_toAddress);
413993229b6Sjkunz }
414993229b6Sjkunz 
415993229b6Sjkunz //! The comparison does \em not take the action into account. It only looks at the
416993229b6Sjkunz //! priority and address ranges of each filter. Priority is considered only if the two
417993229b6Sjkunz //! filters overlap. Lower priority filters will come after higher priority ones.
418993229b6Sjkunz //!
419993229b6Sjkunz //! \retval -1 This filter is less than filter \a b.
420993229b6Sjkunz //! \retval 0 This filter is equal to filter \a b.
421993229b6Sjkunz //! \retval 1 This filter is greater than filter \a b.
compare(const AddressFilter & other) const422993229b6Sjkunz int StExecutableImage::AddressFilter::compare(const AddressFilter & other) const
423993229b6Sjkunz {
424993229b6Sjkunz     if (m_priority != other.m_priority && ((m_fromAddress >= other.m_fromAddress && m_fromAddress <= other.m_toAddress) || (m_toAddress >= other.m_fromAddress && m_toAddress <= other.m_toAddress)))
425993229b6Sjkunz     {
426993229b6Sjkunz         // we know the priorities are not equal
427993229b6Sjkunz         if (m_priority > other.m_priority)
428993229b6Sjkunz         {
429993229b6Sjkunz             return -1;
430993229b6Sjkunz         }
431993229b6Sjkunz         else
432993229b6Sjkunz         {
433993229b6Sjkunz             return 1;
434993229b6Sjkunz         }
435993229b6Sjkunz     }
436993229b6Sjkunz 
437993229b6Sjkunz     if (m_fromAddress == other.m_fromAddress)
438993229b6Sjkunz     {
439993229b6Sjkunz         if (m_toAddress == other.m_toAddress)
440993229b6Sjkunz         {
441993229b6Sjkunz             return 0;
442993229b6Sjkunz         }
443993229b6Sjkunz         else if (m_toAddress < other.m_toAddress)
444993229b6Sjkunz         {
445993229b6Sjkunz             return -1;
446993229b6Sjkunz         }
447993229b6Sjkunz         else
448993229b6Sjkunz         {
449993229b6Sjkunz             return 1;
450993229b6Sjkunz         }
451993229b6Sjkunz     }
452993229b6Sjkunz     else if (m_fromAddress < other.m_fromAddress)
453993229b6Sjkunz     {
454993229b6Sjkunz         return -1;
455993229b6Sjkunz     }
456993229b6Sjkunz     else
457993229b6Sjkunz     {
458993229b6Sjkunz         return 1;
459993229b6Sjkunz     }
460993229b6Sjkunz }
461993229b6Sjkunz 
462993229b6Sjkunz 
463993229b6Sjkunz 
464