head	1.1;
access;
symbols
	netbsd-11-0-RC6:1.1
	netbsd-11-0-RC5:1.1
	netbsd-11-0-RC4:1.1
	netbsd-11-0-RC3:1.1
	netbsd-11-0-RC2:1.1
	netbsd-11-0-RC1:1.1
	perseant-exfatfs-base-20250801:1.1
	netbsd-11:1.1.0.50
	netbsd-11-base:1.1
	netbsd-10-1-RELEASE:1.1
	perseant-exfatfs-base-20240630:1.1
	perseant-exfatfs:1.1.0.48
	perseant-exfatfs-base:1.1
	netbsd-8-3-RELEASE:1.1
	netbsd-9-4-RELEASE:1.1
	netbsd-10-0-RELEASE:1.1
	netbsd-10-0-RC6:1.1
	netbsd-10-0-RC5:1.1
	netbsd-10-0-RC4:1.1
	netbsd-10-0-RC3:1.1
	netbsd-10-0-RC2:1.1
	netbsd-10-0-RC1:1.1
	netbsd-10:1.1.0.46
	netbsd-10-base:1.1
	netbsd-9-3-RELEASE:1.1
	cjep_sun2x-base1:1.1
	cjep_sun2x:1.1.0.44
	cjep_sun2x-base:1.1
	cjep_staticlib_x-base1:1.1
	netbsd-9-2-RELEASE:1.1
	cjep_staticlib_x:1.1.0.42
	cjep_staticlib_x-base:1.1
	netbsd-9-1-RELEASE:1.1
	phil-wifi-20200421:1.1
	phil-wifi-20200411:1.1
	is-mlppp:1.1.0.40
	is-mlppp-base:1.1
	phil-wifi-20200406:1.1
	netbsd-8-2-RELEASE:1.1
	netbsd-9-0-RELEASE:1.1
	netbsd-9-0-RC2:1.1
	netbsd-9-0-RC1:1.1
	phil-wifi-20191119:1.1
	netbsd-9:1.1.0.38
	netbsd-9-base:1.1
	phil-wifi-20190609:1.1
	netbsd-8-1-RELEASE:1.1
	netbsd-8-1-RC1:1.1
	pgoyette-compat-merge-20190127:1.1
	pgoyette-compat-20190127:1.1
	pgoyette-compat-20190118:1.1
	pgoyette-compat-1226:1.1
	pgoyette-compat-1126:1.1
	pgoyette-compat-1020:1.1
	pgoyette-compat-0930:1.1
	pgoyette-compat-0906:1.1
	netbsd-7-2-RELEASE:1.1
	pgoyette-compat-0728:1.1
	netbsd-8-0-RELEASE:1.1
	phil-wifi:1.1.0.36
	phil-wifi-base:1.1
	pgoyette-compat-0625:1.1
	netbsd-8-0-RC2:1.1
	pgoyette-compat-0521:1.1
	pgoyette-compat-0502:1.1
	pgoyette-compat-0422:1.1
	netbsd-8-0-RC1:1.1
	pgoyette-compat-0415:1.1
	pgoyette-compat-0407:1.1
	pgoyette-compat-0330:1.1
	pgoyette-compat-0322:1.1
	pgoyette-compat-0315:1.1
	netbsd-7-1-2-RELEASE:1.1
	pgoyette-compat:1.1.0.34
	pgoyette-compat-base:1.1
	netbsd-7-1-1-RELEASE:1.1
	matt-nb8-mediatek:1.1.0.32
	matt-nb8-mediatek-base:1.1
	perseant-stdc-iso10646:1.1.0.30
	perseant-stdc-iso10646-base:1.1
	netbsd-8:1.1.0.28
	netbsd-8-base:1.1
	prg-localcount2-base3:1.1
	prg-localcount2-base2:1.1
	prg-localcount2-base1:1.1
	prg-localcount2:1.1.0.26
	prg-localcount2-base:1.1
	pgoyette-localcount-20170426:1.1
	bouyer-socketcan-base1:1.1
	pgoyette-localcount-20170320:1.1
	netbsd-7-1:1.1.0.24
	netbsd-7-1-RELEASE:1.1
	netbsd-7-1-RC2:1.1
	netbsd-7-nhusb-base-20170116:1.1
	bouyer-socketcan:1.1.0.22
	bouyer-socketcan-base:1.1
	pgoyette-localcount-20170107:1.1
	netbsd-7-1-RC1:1.1
	pgoyette-localcount-20161104:1.1
	netbsd-7-0-2-RELEASE:1.1
	localcount-20160914:1.1
	netbsd-7-nhusb:1.1.0.20
	netbsd-7-nhusb-base:1.1
	pgoyette-localcount-20160806:1.1
	pgoyette-localcount-20160726:1.1
	pgoyette-localcount:1.1.0.18
	pgoyette-localcount-base:1.1
	netbsd-7-0-1-RELEASE:1.1
	netbsd-7-0:1.1.0.16
	netbsd-7-0-RELEASE:1.1
	netbsd-7-0-RC3:1.1
	netbsd-7-0-RC2:1.1
	netbsd-7-0-RC1:1.1
	netbsd-7:1.1.0.14
	netbsd-7-base:1.1
	yamt-pagecache-base9:1.1
	yamt-pagecache-tag8:1.1.4.2
	tls-earlyentropy:1.1.0.12
	tls-earlyentropy-base:1.1
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1
	riastradh-drm2-base3:1.1
	riastradh-drm2-base2:1.1
	riastradh-drm2-base1:1.1
	riastradh-drm2:1.1.0.6
	riastradh-drm2-base:1.1
	khorben-n900:1.1.0.10
	agc-symver:1.1.0.8
	agc-symver-base:1.1
	yamt-pagecache-base8:1.1
	yamt-pagecache:1.1.0.4
	yamt-pagecache-base7:1.1
	tls-maxphys-base:1.1
	tls-maxphys:1.1.0.2;
locks; strict;
comment	@// @;


1.1
date	2012.11.15.19.49.13;	author jkunz;	state Exp;
branches
	1.1.2.1
	1.1.4.1;
next	;

1.1.2.1
date	2012.11.15.19.49.13;	author jkunz;	state dead;
branches;
next	1.1.2.2;

1.1.2.2
date	2012.11.15.19.49.14;	author jkunz;	state Exp;
branches;
next	;

1.1.4.1
date	2012.11.15.19.49.13;	author yamt;	state dead;
branches;
next	1.1.4.2;

1.1.4.2
date	2013.01.16.05.27.45;	author yamt;	state Exp;
branches;
next	;


desc
@@


1.1
log
@Add elftosb tools to evbarm userland and toolchain.
Elftosb is used to create a digitaly signed "secure boot" file.
This sb file can be booted by the first stage boot loader found in
Freescale i.MX23 and i.MX28 application processors.

Copyright (c) 2004-2010 Freescale Semiconductor, Inc.
@
text
@/*
 * File:	DataSource.cpp
 *
 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
 * See included license file for license details.
 */

#include "DataSource.h"
#include "DataTarget.h"
#include <assert.h>
#include <string.h>
using namespace elftosb;

#pragma mark *** DataSource::PatternSegment ***

DataSource::PatternSegment::PatternSegment(DataSource & source)
:	DataSource::Segment(source), m_pattern()
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, const SizedIntegerValue & pattern)
:	DataSource::Segment(source), m_pattern(pattern)
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, uint8_t pattern)
:	DataSource::Segment(source), m_pattern(static_cast<uint8_t>(pattern))
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, uint16_t pattern)
:	DataSource::Segment(source), m_pattern(static_cast<uint16_t>(pattern))
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, uint32_t pattern)
:	DataSource::Segment(source), m_pattern(static_cast<uint32_t>(pattern))
{
}

unsigned DataSource::PatternSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
{
	memset(buffer, 0, maxBytes);
	
	return maxBytes;
}

//! The pattern segment's length is a function of the data target. If the
//! target is bounded, then the segment's length is simply the target's
//! length. Otherwise, if no target has been set or the target is unbounded,
//! then the length returned is 0.
unsigned DataSource::PatternSegment::getLength()
{
	DataTarget * target = m_source.getTarget();
	if (!target)
	{
		return 0;
	}
	
	uint32_t length;
	if (target->isBounded())
	{
		length = target->getEndAddress() - target->getBeginAddress();
	}
	else
	{
		length = m_pattern.getSize();
	}
	return length;
}

#pragma mark *** PatternSource ***

PatternSource::PatternSource()
:	DataSource(), DataSource::PatternSegment((DataSource&)*this)
{
}

PatternSource::PatternSource(const SizedIntegerValue & value)
:	DataSource(), DataSource::PatternSegment((DataSource&)*this, value)
{
}

#pragma mark *** UnmappedDataSource ***

UnmappedDataSource::UnmappedDataSource()
:	DataSource(), DataSource::Segment((DataSource&)*this), m_data(), m_length(0)
{
}

UnmappedDataSource::UnmappedDataSource(const uint8_t * data, unsigned length)
:	DataSource(), DataSource::Segment((DataSource&)*this), m_data(), m_length(0)
{
	setData(data, length);
}

//! Makes a copy of \a data that is freed when the data source is
//! destroyed. The caller does not have to maintain \a data after this call
//! returns.
void UnmappedDataSource::setData(const uint8_t * data, unsigned length)
{
	m_data.safe_delete();
	
	uint8_t * dataCopy = new uint8_t[length];
	memcpy(dataCopy, data, length);
	m_data = dataCopy;
	m_length = length;
}

unsigned UnmappedDataSource::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
{
	assert(offset < m_length);
	unsigned copyBytes = std::min<unsigned>(m_length - offset, maxBytes);
	memcpy(buffer, m_data.get(), copyBytes);
	return copyBytes;
}

#pragma mark *** MemoryImageDataSource ***

MemoryImageDataSource::MemoryImageDataSource(StExecutableImage * image)
:	DataSource(), m_image(image)
{
	// reserve enough room for all segments
	m_segments.reserve(m_image->getRegionCount());
}

MemoryImageDataSource::~MemoryImageDataSource()
{
	segment_array_t::iterator it = m_segments.begin();
	for (; it != m_segments.end(); ++it)
	{
		// delete this segment if it has been created
		if (*it)
		{
			delete *it;
		}
	}
}

unsigned MemoryImageDataSource::getSegmentCount()
{
	return m_image->getRegionCount();
}

DataSource::Segment * MemoryImageDataSource::getSegmentAt(unsigned index)
{
	// return previously created segment
	if (index < m_segments.size() && m_segments[index])
	{
		return m_segments[index];
	}
	
	// extend array out to this index
	if (index >= m_segments.size() && index < m_image->getRegionCount())
	{
		m_segments.resize(index + 1, NULL);
	}
	
	// create the new segment object
	DataSource::Segment * newSegment;
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(index);
	if (region.m_type == StExecutableImage::TEXT_REGION)
	{
		newSegment = new TextSegment(*this, m_image, index);
	}
	else if (region.m_type == StExecutableImage::FILL_REGION)
	{
		newSegment = new FillSegment(*this, m_image, index);
	}
	
	m_segments[index] = newSegment;
	return newSegment;
}

#pragma mark *** MemoryImageDataSource::TextSegment ***

MemoryImageDataSource::TextSegment::TextSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index)
:	DataSource::Segment(source), m_image(image), m_index(index)
{
}

unsigned MemoryImageDataSource::TextSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	assert(region.m_type == StExecutableImage::TEXT_REGION);
	
	unsigned copyBytes = std::min<unsigned>(region.m_length - offset, maxBytes);	
	memcpy(buffer, &region.m_data[offset], copyBytes);
	
	return copyBytes;
}

unsigned MemoryImageDataSource::TextSegment::getLength()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_length;
}

uint32_t MemoryImageDataSource::TextSegment::getBaseAddress()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_address;
}

#pragma mark *** MemoryImageDataSource::FillSegment ***

MemoryImageDataSource::FillSegment::FillSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index)
:	DataSource::PatternSegment(source), m_image(image), m_index(index)
{
	SizedIntegerValue zero(0, kWordSize);
	setPattern(zero);
}

unsigned MemoryImageDataSource::FillSegment::getLength()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_length;
}

uint32_t MemoryImageDataSource::FillSegment::getBaseAddress()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_address;
}
@


1.1.4.1
log
@file DataSource.cpp was added on branch yamt-pagecache on 2013-01-16 05:27:45 +0000
@
text
@d1 224
@


1.1.4.2
log
@sync with (a bit old) head
@
text
@a0 224
/*
 * File:	DataSource.cpp
 *
 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
 * See included license file for license details.
 */

#include "DataSource.h"
#include "DataTarget.h"
#include <assert.h>
#include <string.h>
using namespace elftosb;

#pragma mark *** DataSource::PatternSegment ***

DataSource::PatternSegment::PatternSegment(DataSource & source)
:	DataSource::Segment(source), m_pattern()
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, const SizedIntegerValue & pattern)
:	DataSource::Segment(source), m_pattern(pattern)
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, uint8_t pattern)
:	DataSource::Segment(source), m_pattern(static_cast<uint8_t>(pattern))
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, uint16_t pattern)
:	DataSource::Segment(source), m_pattern(static_cast<uint16_t>(pattern))
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, uint32_t pattern)
:	DataSource::Segment(source), m_pattern(static_cast<uint32_t>(pattern))
{
}

unsigned DataSource::PatternSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
{
	memset(buffer, 0, maxBytes);
	
	return maxBytes;
}

//! The pattern segment's length is a function of the data target. If the
//! target is bounded, then the segment's length is simply the target's
//! length. Otherwise, if no target has been set or the target is unbounded,
//! then the length returned is 0.
unsigned DataSource::PatternSegment::getLength()
{
	DataTarget * target = m_source.getTarget();
	if (!target)
	{
		return 0;
	}
	
	uint32_t length;
	if (target->isBounded())
	{
		length = target->getEndAddress() - target->getBeginAddress();
	}
	else
	{
		length = m_pattern.getSize();
	}
	return length;
}

#pragma mark *** PatternSource ***

PatternSource::PatternSource()
:	DataSource(), DataSource::PatternSegment((DataSource&)*this)
{
}

PatternSource::PatternSource(const SizedIntegerValue & value)
:	DataSource(), DataSource::PatternSegment((DataSource&)*this, value)
{
}

#pragma mark *** UnmappedDataSource ***

UnmappedDataSource::UnmappedDataSource()
:	DataSource(), DataSource::Segment((DataSource&)*this), m_data(), m_length(0)
{
}

UnmappedDataSource::UnmappedDataSource(const uint8_t * data, unsigned length)
:	DataSource(), DataSource::Segment((DataSource&)*this), m_data(), m_length(0)
{
	setData(data, length);
}

//! Makes a copy of \a data that is freed when the data source is
//! destroyed. The caller does not have to maintain \a data after this call
//! returns.
void UnmappedDataSource::setData(const uint8_t * data, unsigned length)
{
	m_data.safe_delete();
	
	uint8_t * dataCopy = new uint8_t[length];
	memcpy(dataCopy, data, length);
	m_data = dataCopy;
	m_length = length;
}

unsigned UnmappedDataSource::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
{
	assert(offset < m_length);
	unsigned copyBytes = std::min<unsigned>(m_length - offset, maxBytes);
	memcpy(buffer, m_data.get(), copyBytes);
	return copyBytes;
}

#pragma mark *** MemoryImageDataSource ***

MemoryImageDataSource::MemoryImageDataSource(StExecutableImage * image)
:	DataSource(), m_image(image)
{
	// reserve enough room for all segments
	m_segments.reserve(m_image->getRegionCount());
}

MemoryImageDataSource::~MemoryImageDataSource()
{
	segment_array_t::iterator it = m_segments.begin();
	for (; it != m_segments.end(); ++it)
	{
		// delete this segment if it has been created
		if (*it)
		{
			delete *it;
		}
	}
}

unsigned MemoryImageDataSource::getSegmentCount()
{
	return m_image->getRegionCount();
}

DataSource::Segment * MemoryImageDataSource::getSegmentAt(unsigned index)
{
	// return previously created segment
	if (index < m_segments.size() && m_segments[index])
	{
		return m_segments[index];
	}
	
	// extend array out to this index
	if (index >= m_segments.size() && index < m_image->getRegionCount())
	{
		m_segments.resize(index + 1, NULL);
	}
	
	// create the new segment object
	DataSource::Segment * newSegment;
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(index);
	if (region.m_type == StExecutableImage::TEXT_REGION)
	{
		newSegment = new TextSegment(*this, m_image, index);
	}
	else if (region.m_type == StExecutableImage::FILL_REGION)
	{
		newSegment = new FillSegment(*this, m_image, index);
	}
	
	m_segments[index] = newSegment;
	return newSegment;
}

#pragma mark *** MemoryImageDataSource::TextSegment ***

MemoryImageDataSource::TextSegment::TextSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index)
:	DataSource::Segment(source), m_image(image), m_index(index)
{
}

unsigned MemoryImageDataSource::TextSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	assert(region.m_type == StExecutableImage::TEXT_REGION);
	
	unsigned copyBytes = std::min<unsigned>(region.m_length - offset, maxBytes);	
	memcpy(buffer, &region.m_data[offset], copyBytes);
	
	return copyBytes;
}

unsigned MemoryImageDataSource::TextSegment::getLength()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_length;
}

uint32_t MemoryImageDataSource::TextSegment::getBaseAddress()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_address;
}

#pragma mark *** MemoryImageDataSource::FillSegment ***

MemoryImageDataSource::FillSegment::FillSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index)
:	DataSource::PatternSegment(source), m_image(image), m_index(index)
{
	SizedIntegerValue zero(0, kWordSize);
	setPattern(zero);
}

unsigned MemoryImageDataSource::FillSegment::getLength()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_length;
}

uint32_t MemoryImageDataSource::FillSegment::getBaseAddress()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_address;
}
@


1.1.2.1
log
@file DataSource.cpp was added on branch tls-maxphys on 2012-11-15 19:49:14 +0000
@
text
@d1 224
@


1.1.2.2
log
@Add elftosb tools to evbarm userland and toolchain.
Elftosb is used to create a digitaly signed "secure boot" file.
This sb file can be booted by the first stage boot loader found in
Freescale i.MX23 and i.MX28 application processors.

Copyright (c) 2004-2010 Freescale Semiconductor, Inc.
@
text
@a0 224
/*
 * File:	DataSource.cpp
 *
 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
 * See included license file for license details.
 */

#include "DataSource.h"
#include "DataTarget.h"
#include <assert.h>
#include <string.h>
using namespace elftosb;

#pragma mark *** DataSource::PatternSegment ***

DataSource::PatternSegment::PatternSegment(DataSource & source)
:	DataSource::Segment(source), m_pattern()
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, const SizedIntegerValue & pattern)
:	DataSource::Segment(source), m_pattern(pattern)
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, uint8_t pattern)
:	DataSource::Segment(source), m_pattern(static_cast<uint8_t>(pattern))
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, uint16_t pattern)
:	DataSource::Segment(source), m_pattern(static_cast<uint16_t>(pattern))
{
}

DataSource::PatternSegment::PatternSegment(DataSource & source, uint32_t pattern)
:	DataSource::Segment(source), m_pattern(static_cast<uint32_t>(pattern))
{
}

unsigned DataSource::PatternSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
{
	memset(buffer, 0, maxBytes);
	
	return maxBytes;
}

//! The pattern segment's length is a function of the data target. If the
//! target is bounded, then the segment's length is simply the target's
//! length. Otherwise, if no target has been set or the target is unbounded,
//! then the length returned is 0.
unsigned DataSource::PatternSegment::getLength()
{
	DataTarget * target = m_source.getTarget();
	if (!target)
	{
		return 0;
	}
	
	uint32_t length;
	if (target->isBounded())
	{
		length = target->getEndAddress() - target->getBeginAddress();
	}
	else
	{
		length = m_pattern.getSize();
	}
	return length;
}

#pragma mark *** PatternSource ***

PatternSource::PatternSource()
:	DataSource(), DataSource::PatternSegment((DataSource&)*this)
{
}

PatternSource::PatternSource(const SizedIntegerValue & value)
:	DataSource(), DataSource::PatternSegment((DataSource&)*this, value)
{
}

#pragma mark *** UnmappedDataSource ***

UnmappedDataSource::UnmappedDataSource()
:	DataSource(), DataSource::Segment((DataSource&)*this), m_data(), m_length(0)
{
}

UnmappedDataSource::UnmappedDataSource(const uint8_t * data, unsigned length)
:	DataSource(), DataSource::Segment((DataSource&)*this), m_data(), m_length(0)
{
	setData(data, length);
}

//! Makes a copy of \a data that is freed when the data source is
//! destroyed. The caller does not have to maintain \a data after this call
//! returns.
void UnmappedDataSource::setData(const uint8_t * data, unsigned length)
{
	m_data.safe_delete();
	
	uint8_t * dataCopy = new uint8_t[length];
	memcpy(dataCopy, data, length);
	m_data = dataCopy;
	m_length = length;
}

unsigned UnmappedDataSource::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
{
	assert(offset < m_length);
	unsigned copyBytes = std::min<unsigned>(m_length - offset, maxBytes);
	memcpy(buffer, m_data.get(), copyBytes);
	return copyBytes;
}

#pragma mark *** MemoryImageDataSource ***

MemoryImageDataSource::MemoryImageDataSource(StExecutableImage * image)
:	DataSource(), m_image(image)
{
	// reserve enough room for all segments
	m_segments.reserve(m_image->getRegionCount());
}

MemoryImageDataSource::~MemoryImageDataSource()
{
	segment_array_t::iterator it = m_segments.begin();
	for (; it != m_segments.end(); ++it)
	{
		// delete this segment if it has been created
		if (*it)
		{
			delete *it;
		}
	}
}

unsigned MemoryImageDataSource::getSegmentCount()
{
	return m_image->getRegionCount();
}

DataSource::Segment * MemoryImageDataSource::getSegmentAt(unsigned index)
{
	// return previously created segment
	if (index < m_segments.size() && m_segments[index])
	{
		return m_segments[index];
	}
	
	// extend array out to this index
	if (index >= m_segments.size() && index < m_image->getRegionCount())
	{
		m_segments.resize(index + 1, NULL);
	}
	
	// create the new segment object
	DataSource::Segment * newSegment;
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(index);
	if (region.m_type == StExecutableImage::TEXT_REGION)
	{
		newSegment = new TextSegment(*this, m_image, index);
	}
	else if (region.m_type == StExecutableImage::FILL_REGION)
	{
		newSegment = new FillSegment(*this, m_image, index);
	}
	
	m_segments[index] = newSegment;
	return newSegment;
}

#pragma mark *** MemoryImageDataSource::TextSegment ***

MemoryImageDataSource::TextSegment::TextSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index)
:	DataSource::Segment(source), m_image(image), m_index(index)
{
}

unsigned MemoryImageDataSource::TextSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	assert(region.m_type == StExecutableImage::TEXT_REGION);
	
	unsigned copyBytes = std::min<unsigned>(region.m_length - offset, maxBytes);	
	memcpy(buffer, &region.m_data[offset], copyBytes);
	
	return copyBytes;
}

unsigned MemoryImageDataSource::TextSegment::getLength()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_length;
}

uint32_t MemoryImageDataSource::TextSegment::getBaseAddress()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_address;
}

#pragma mark *** MemoryImageDataSource::FillSegment ***

MemoryImageDataSource::FillSegment::FillSegment(MemoryImageDataSource & source, StExecutableImage * image, unsigned index)
:	DataSource::PatternSegment(source), m_image(image), m_index(index)
{
	SizedIntegerValue zero(0, kWordSize);
	setPattern(zero);
}

unsigned MemoryImageDataSource::FillSegment::getLength()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_length;
}

uint32_t MemoryImageDataSource::FillSegment::getBaseAddress()
{
	const StExecutableImage::MemoryRegion & region = m_image->getRegionAtIndex(m_index);
	return region.m_address;
}
@
