xref: /netbsd-src/external/bsd/elftosb/dist/common/DataSource.cpp (revision 993229b6fea628ff8b1fa09146c80b0cfb2768eb)
1 /*
2  * File:	DataSource.cpp
3  *
4  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5  * See included license file for license details.
6  */
7 
8 #include "DataSource.h"
9 #include "DataTarget.h"
10 #include <assert.h>
11 #include <string.h>
12 using namespace elftosb;
13 
14 #pragma mark *** DataSource::PatternSegment ***
15 
PatternSegment(DataSource & source)16 DataSource::PatternSegment::PatternSegment(DataSource & source)
17 :	DataSource::Segment(source), m_pattern()
18 {
19 }
20 
PatternSegment(DataSource & source,const SizedIntegerValue & pattern)21 DataSource::PatternSegment::PatternSegment(DataSource & source, const SizedIntegerValue & pattern)
22 :	DataSource::Segment(source), m_pattern(pattern)
23 {
24 }
25 
PatternSegment(DataSource & source,uint8_t pattern)26 DataSource::PatternSegment::PatternSegment(DataSource & source, uint8_t pattern)
27 :	DataSource::Segment(source), m_pattern(static_cast<uint8_t>(pattern))
28 {
29 }
30 
PatternSegment(DataSource & source,uint16_t pattern)31 DataSource::PatternSegment::PatternSegment(DataSource & source, uint16_t pattern)
32 :	DataSource::Segment(source), m_pattern(static_cast<uint16_t>(pattern))
33 {
34 }
35 
PatternSegment(DataSource & source,uint32_t pattern)36 DataSource::PatternSegment::PatternSegment(DataSource & source, uint32_t pattern)
37 :	DataSource::Segment(source), m_pattern(static_cast<uint32_t>(pattern))
38 {
39 }
40 
getData(unsigned offset,unsigned maxBytes,uint8_t * buffer)41 unsigned DataSource::PatternSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
42 {
43 	memset(buffer, 0, maxBytes);
44 
45 	return maxBytes;
46 }
47 
48 //! The pattern segment's length is a function of the data target. If the
49 //! target is bounded, then the segment's length is simply the target's
50 //! length. Otherwise, if no target has been set or the target is unbounded,
51 //! then the length returned is 0.
getLength()52 unsigned DataSource::PatternSegment::getLength()
53 {
54 	DataTarget * target = m_source.getTarget();
55 	if (!target)
56 	{
57 		return 0;
58 	}
59 
60 	uint32_t length;
61 	if (target->isBounded())
62 	{
63 		length = target->getEndAddress() - target->getBeginAddress();
64 	}
65 	else
66 	{
67 		length = m_pattern.getSize();
68 	}
69 	return length;
70 }
71 
72 #pragma mark *** PatternSource ***
73 
PatternSource()74 PatternSource::PatternSource()
75 :	DataSource(), DataSource::PatternSegment((DataSource&)*this)
76 {
77 }
78 
PatternSource(const SizedIntegerValue & value)79 PatternSource::PatternSource(const SizedIntegerValue & value)
80 :	DataSource(), DataSource::PatternSegment((DataSource&)*this, value)
81 {
82 }
83 
84 #pragma mark *** UnmappedDataSource ***
85 
UnmappedDataSource()86 UnmappedDataSource::UnmappedDataSource()
87 :	DataSource(), DataSource::Segment((DataSource&)*this), m_data(), m_length(0)
88 {
89 }
90 
UnmappedDataSource(const uint8_t * data,unsigned length)91 UnmappedDataSource::UnmappedDataSource(const uint8_t * data, unsigned length)
92 :	DataSource(), DataSource::Segment((DataSource&)*this), m_data(), m_length(0)
93 {
94 	setData(data, length);
95 }
96 
97 //! Makes a copy of \a data that is freed when the data source is
98 //! destroyed. The caller does not have to maintain \a data after this call
99 //! returns.
setData(const uint8_t * data,unsigned length)100 void UnmappedDataSource::setData(const uint8_t * data, unsigned length)
101 {
102 	m_data.safe_delete();
103 
104 	uint8_t * dataCopy = new uint8_t[length];
105 	memcpy(dataCopy, data, length);
106 	m_data = dataCopy;
107 	m_length = length;
108 }
109 
getData(unsigned offset,unsigned maxBytes,uint8_t * buffer)110 unsigned UnmappedDataSource::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
111 {
112 	assert(offset < m_length);
113 	unsigned copyBytes = std::min<unsigned>(m_length - offset, maxBytes);
114 	memcpy(buffer, m_data.get(), copyBytes);
115 	return copyBytes;
116 }
117 
118 #pragma mark *** MemoryImageDataSource ***
119 
MemoryImageDataSource(StExecutableImage * image)120 MemoryImageDataSource::MemoryImageDataSource(StExecutableImage * image)
121 :	DataSource(), m_image(image)
122 {
123 	// reserve enough room for all segments
124 	m_segments.reserve(m_image->getRegionCount());
125 }
126 
~MemoryImageDataSource()127 MemoryImageDataSource::~MemoryImageDataSource()
128 {
129 	segment_array_t::iterator it = m_segments.begin();
130 	for (; it != m_segments.end(); ++it)
131 	{
132 		// delete this segment if it has been created
133 		if (*it)
134 		{
135 			delete *it;
136 		}
137 	}
138 }
139 
getSegmentCount()140 unsigned MemoryImageDataSource::getSegmentCount()
141 {
142 	return m_image->getRegionCount();
143 }
144 
getSegmentAt(unsigned index)145 DataSource::Segment * MemoryImageDataSource::getSegmentAt(unsigned index)
146 {
147 	// return previously created segment
148 	if (index < m_segments.size() && m_segments[index])
149 	{
150 		return m_segments[index];
151 	}
152 
153 	// extend array out to this index
154 	if (index >= m_segments.size() && index < m_image->getRegionCount())
155 	{
156 		m_segments.resize(index + 1, NULL);
157 	}
158 
159 	// create the new segment object
160 	DataSource::Segment * newSegment;
161 	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(index);
162 	if (region.m_type == StExecutableImage::TEXT_REGION)
163 	{
164 		newSegment = new TextSegment(*this, m_image, index);
165 	}
166 	else if (region.m_type == StExecutableImage::FILL_REGION)
167 	{
168 		newSegment = new FillSegment(*this, m_image, index);
169 	}
170 
171 	m_segments[index] = newSegment;
172 	return newSegment;
173 }
174 
175 #pragma mark *** MemoryImageDataSource::TextSegment ***
176 
TextSegment(MemoryImageDataSource & source,StExecutableImage * image,unsigned index)177 MemoryImageDataSource::TextSegment::TextSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index)
178 :	DataSource::Segment(source), m_image(image), m_index(index)
179 {
180 }
181 
getData(unsigned offset,unsigned maxBytes,uint8_t * buffer)182 unsigned MemoryImageDataSource::TextSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
183 {
184 	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
185 	assert(region.m_type == StExecutableImage::TEXT_REGION);
186 
187 	unsigned copyBytes = std::min<unsigned>(region.m_length - offset, maxBytes);
188 	memcpy(buffer, &region.m_data[offset], copyBytes);
189 
190 	return copyBytes;
191 }
192 
getLength()193 unsigned MemoryImageDataSource::TextSegment::getLength()
194 {
195 	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
196 	return region.m_length;
197 }
198 
getBaseAddress()199 uint32_t MemoryImageDataSource::TextSegment::getBaseAddress()
200 {
201 	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
202 	return region.m_address;
203 }
204 
205 #pragma mark *** MemoryImageDataSource::FillSegment ***
206 
FillSegment(MemoryImageDataSource & source,StExecutableImage * image,unsigned index)207 MemoryImageDataSource::FillSegment::FillSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index)
208 :	DataSource::PatternSegment(source), m_image(image), m_index(index)
209 {
210 	SizedIntegerValue zero(0, kWordSize);
211 	setPattern(zero);
212 }
213 
getLength()214 unsigned MemoryImageDataSource::FillSegment::getLength()
215 {
216 	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
217 	return region.m_length;
218 }
219 
getBaseAddress()220 uint32_t MemoryImageDataSource::FillSegment::getBaseAddress()
221 {
222 	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
223 	return region.m_address;
224 }
225