/* * 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 #include 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(pattern)) { } DataSource::PatternSegment::PatternSegment(DataSource & source, uint16_t pattern) : DataSource::Segment(source), m_pattern(static_cast(pattern)) { } DataSource::PatternSegment::PatternSegment(DataSource & source, uint32_t pattern) : DataSource::Segment(source), m_pattern(static_cast(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(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 = 0; 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(region.m_length - offset, maxBytes); memcpy(buffer, ®ion.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; }