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>
12using namespace elftosb;
13
14#pragma mark *** DataSource::PatternSegment ***
15
16DataSource::PatternSegment::PatternSegment(DataSource & source)
17:	DataSource::Segment(source), m_pattern()
18{
19}
20
21DataSource::PatternSegment::PatternSegment(DataSource & source, const SizedIntegerValue & pattern)
22:	DataSource::Segment(source), m_pattern(pattern)
23{
24}
25
26DataSource::PatternSegment::PatternSegment(DataSource & source, uint8_t pattern)
27:	DataSource::Segment(source), m_pattern(static_cast<uint8_t>(pattern))
28{
29}
30
31DataSource::PatternSegment::PatternSegment(DataSource & source, uint16_t pattern)
32:	DataSource::Segment(source), m_pattern(static_cast<uint16_t>(pattern))
33{
34}
35
36DataSource::PatternSegment::PatternSegment(DataSource & source, uint32_t pattern)
37:	DataSource::Segment(source), m_pattern(static_cast<uint32_t>(pattern))
38{
39}
40
41unsigned 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.
52unsigned 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
74PatternSource::PatternSource()
75:	DataSource(), DataSource::PatternSegment((DataSource&)*this)
76{
77}
78
79PatternSource::PatternSource(const SizedIntegerValue & value)
80:	DataSource(), DataSource::PatternSegment((DataSource&)*this, value)
81{
82}
83
84#pragma mark *** UnmappedDataSource ***
85
86UnmappedDataSource::UnmappedDataSource()
87:	DataSource(), DataSource::Segment((DataSource&)*this), m_data(), m_length(0)
88{
89}
90
91UnmappedDataSource::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.
100void 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
110unsigned 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
120MemoryImageDataSource::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
127MemoryImageDataSource::~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
140unsigned MemoryImageDataSource::getSegmentCount()
141{
142	return m_image->getRegionCount();
143}
144
145DataSource::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
177MemoryImageDataSource::TextSegment::TextSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index)
178:	DataSource::Segment(source), m_image(image), m_index(index)
179{
180}
181
182unsigned 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
193unsigned MemoryImageDataSource::TextSegment::getLength()
194{
195	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
196	return region.m_length;
197}
198
199uint32_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
207MemoryImageDataSource::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
214unsigned MemoryImageDataSource::FillSegment::getLength()
215{
216	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
217	return region.m_length;
218}
219
220uint32_t MemoryImageDataSource::FillSegment::getBaseAddress()
221{
222	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
223	return region.m_address;
224}
225