diff options
Diffstat (limited to 'decoder/source/mem_acc/trc_mem_acc_file.cpp')
| -rw-r--r-- | decoder/source/mem_acc/trc_mem_acc_file.cpp | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/decoder/source/mem_acc/trc_mem_acc_file.cpp b/decoder/source/mem_acc/trc_mem_acc_file.cpp new file mode 100644 index 000000000000..87901c83dcee --- /dev/null +++ b/decoder/source/mem_acc/trc_mem_acc_file.cpp @@ -0,0 +1,391 @@ +/* + * \file trc_mem_acc_file.cpp + * \brief OpenCSD : + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mem_acc/trc_mem_acc_file.h" + +#include <sstream> +#include <iomanip> + +/***************************************************/ +/* protected construction and reference counting */ +/***************************************************/ + +TrcMemAccessorFile::TrcMemAccessorFile() : TrcMemAccessorBase(MEMACC_FILE) +{ + m_ref_count = 0; + m_base_range_set = false; + m_has_access_regions = false; + m_file_size = 0; +} + +TrcMemAccessorFile::~TrcMemAccessorFile() +{ + if(m_mem_file.is_open()) + m_mem_file.close(); + if(m_access_regions.size()) + { + std::list<FileRegionMemAccessor *>::iterator it; + it = m_access_regions.begin(); + while(it != m_access_regions.end()) + { + delete (*it); + it++; + } + m_access_regions.clear(); + } +} + +ocsd_err_t TrcMemAccessorFile::initAccessor(const std::string &pathToFile, ocsd_vaddr_t startAddr, size_t offset, size_t size) +{ + ocsd_err_t err = OCSD_OK; + bool init = false; + + m_mem_file.open(pathToFile.c_str(), std::ifstream::binary | std::ifstream::ate); + if(m_mem_file.is_open()) + { + m_file_size = (ocsd_vaddr_t)m_mem_file.tellg() & ((ocsd_vaddr_t)~0x1); + m_mem_file.seekg(0, m_mem_file.beg); + // adding an offset of 0, sets the base range. + if((offset == 0) && (size == 0)) + { + init = AddOffsetRange(startAddr, ((size_t)m_file_size)-offset, offset); + } + else if((offset + size) <= m_file_size) + { + // if offset != 0, size must by != 0 + init = AddOffsetRange(startAddr, size, offset); + } + m_file_path = pathToFile; + } + else + err = OCSD_ERR_MEM_ACC_FILE_NOT_FOUND; + if(!init) + err = OCSD_ERR_NOT_INIT; + return err; +} + + +FileRegionMemAccessor *TrcMemAccessorFile::getRegionForAddress(const ocsd_vaddr_t startAddr) const +{ + FileRegionMemAccessor *p_region = 0; + if(m_has_access_regions) + { + std::list<FileRegionMemAccessor *>::const_iterator it; + it = m_access_regions.begin(); + while((it != m_access_regions.end()) && (p_region == 0)) + { + if((*it)->addrInRange(startAddr)) + p_region = *it; + it++; + } + } + return p_region; +} + + +/***************************************************/ +/* static object creation */ +/***************************************************/ + +std::map<std::string, TrcMemAccessorFile *> TrcMemAccessorFile::s_FileAccessorMap; + +// return existing or create new accessor +ocsd_err_t TrcMemAccessorFile::createFileAccessor(TrcMemAccessorFile **p_acc, const std::string &pathToFile, ocsd_vaddr_t startAddr, size_t offset /*= 0*/, size_t size /*= 0*/) +{ + ocsd_err_t err = OCSD_OK; + TrcMemAccessorFile * acc = 0; + std::map<std::string, TrcMemAccessorFile *>::iterator it = s_FileAccessorMap.find(pathToFile); + if(it != s_FileAccessorMap.end()) + { + acc = it->second; + if(acc->addrStartOfRange(startAddr)) + acc->IncRefCount(); + else + { + err = OCSD_ERR_MEM_ACC_FILE_DIFF_RANGE; + acc = 0; + } + } + else + { + acc = new (std::nothrow) TrcMemAccessorFile(); + if(acc != 0) + { + if((err = acc->initAccessor(pathToFile,startAddr, offset,size)) == OCSD_OK) + { + acc->IncRefCount(); + s_FileAccessorMap.insert(std::pair<std::string, TrcMemAccessorFile *>(pathToFile,acc)); + } + else + { + delete acc; + acc = 0; + } + } + else + err = OCSD_ERR_MEM; + } + *p_acc = acc; + return err; +} + +void TrcMemAccessorFile::destroyFileAccessor(TrcMemAccessorFile *p_accessor) +{ + if(p_accessor != 0) + { + p_accessor->DecRefCount(); + if(p_accessor->getRefCount() == 0) + { + std::map<std::string, TrcMemAccessorFile *>::iterator it = s_FileAccessorMap.find(p_accessor->getFilePath()); + if(it != s_FileAccessorMap.end()) + { + s_FileAccessorMap.erase(it); + } + delete p_accessor; + } + } +} + +const bool TrcMemAccessorFile::isExistingFileAccessor(const std::string &pathToFile) +{ + bool bExists = false; + std::map<std::string, TrcMemAccessorFile *>::const_iterator it = s_FileAccessorMap.find(pathToFile); + if(it != s_FileAccessorMap.end()) + bExists = true; + return bExists; +} + +TrcMemAccessorFile * TrcMemAccessorFile::getExistingFileAccessor(const std::string &pathToFile) +{ + TrcMemAccessorFile * p_acc = 0; + std::map<std::string, TrcMemAccessorFile *>::iterator it = s_FileAccessorMap.find(pathToFile); + if(it != s_FileAccessorMap.end()) + p_acc = it->second; + return p_acc; +} + + + +/***************************************************/ +/* accessor instance functions */ +/***************************************************/ +const uint32_t TrcMemAccessorFile::readBytes(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint32_t reqBytes, uint8_t *byteBuffer) +{ + if(!m_mem_file.is_open()) + return 0; + uint32_t bytesRead = 0; + + if(m_base_range_set) + { + bytesRead = TrcMemAccessorBase::bytesInRange(address,reqBytes); // get avialable bytes in range. + if(bytesRead) + { + ocsd_vaddr_t addr_pos = (ocsd_vaddr_t)m_mem_file.tellg(); + if((address - m_startAddress) != addr_pos) + m_mem_file.seekg(address - m_startAddress); + m_mem_file.read((char *)byteBuffer,bytesRead); + } + } + + if((bytesRead == 0) && m_has_access_regions) + { + bytesRead = bytesInRange(address,reqBytes); + if(bytesRead) + { + FileRegionMemAccessor *p_region = getRegionForAddress(address); + ocsd_vaddr_t addr_pos = (ocsd_vaddr_t)m_mem_file.tellg(); + if((address - p_region->regionStartAddress() + p_region->getOffset()) != addr_pos) + m_mem_file.seekg(address - p_region->regionStartAddress() + p_region->getOffset()); + m_mem_file.read((char *)byteBuffer,bytesRead); + } + } + return bytesRead; +} + +bool TrcMemAccessorFile::AddOffsetRange(const ocsd_vaddr_t startAddr, const size_t size, const size_t offset) +{ + bool addOK = false; + if(m_file_size == 0) // must have set the file size + return false; + if(addrInRange(startAddr) || addrInRange(startAddr+size-1)) // cannot be overlapping + return false; + + // now either set the base range or an offset range + if(offset == 0) + { + if(!m_base_range_set) + { + setRange(startAddr, startAddr+size-1); + m_base_range_set = true; + addOK = true; + } + } + else + { + if((offset + size) <= m_file_size) + { + FileRegionMemAccessor *frmacc = new (std::nothrow) FileRegionMemAccessor(); + if(frmacc) + { + frmacc->setOffset(offset); + frmacc->setRange(startAddr,startAddr+size-1); + m_access_regions.push_back(frmacc); + m_access_regions.sort(); + // may need to trim the 0 offset base range... + if(m_base_range_set) + { + std::list<FileRegionMemAccessor *>::iterator it; + it = m_access_regions.begin(); + size_t first_range_offset = (*it)->getOffset(); + if((m_startAddress + first_range_offset - 1) > m_endAddress) + m_endAddress = m_startAddress + first_range_offset - 1; + } + addOK = true; + m_has_access_regions = true; + } + } + } + return addOK; +} + +const bool TrcMemAccessorFile::addrInRange(const ocsd_vaddr_t s_address) const +{ + bool bInRange = false; + if(m_base_range_set) + bInRange = TrcMemAccessorBase::addrInRange(s_address); + + if(!bInRange && m_has_access_regions) + { + if(getRegionForAddress(s_address) != 0) + bInRange = true; + } + return bInRange; +} + +const bool TrcMemAccessorFile::addrStartOfRange(const ocsd_vaddr_t s_address) const +{ + bool bInRange = false; + if(m_base_range_set) + bInRange = TrcMemAccessorBase::addrStartOfRange(s_address); + if(!bInRange && m_has_access_regions) + { + FileRegionMemAccessor *pRegion = getRegionForAddress(s_address); + if(pRegion) + bInRange = (pRegion->regionStartAddress() == s_address); + } + return bInRange; +} + + + /* validate ranges */ +const bool TrcMemAccessorFile::validateRange() +{ + bool bRangeValid = true; + if(m_base_range_set) + bRangeValid = TrcMemAccessorBase::validateRange(); + + if(m_has_access_regions && bRangeValid) + { + std::list<FileRegionMemAccessor *>::const_iterator it; + it = m_access_regions.begin(); + while((it != m_access_regions.end()) && bRangeValid) + { + bRangeValid = (*it)->validateRange(); + it++; + } + } + return bRangeValid; +} + +const uint32_t TrcMemAccessorFile::bytesInRange(const ocsd_vaddr_t s_address, const uint32_t reqBytes) const +{ + uint32_t bytesInRange = 0; + if(m_base_range_set) + bytesInRange = TrcMemAccessorBase::bytesInRange(s_address,reqBytes); + + if((bytesInRange == 0) && (m_has_access_regions)) + { + FileRegionMemAccessor *p_region = getRegionForAddress(s_address); + bytesInRange = p_region->bytesInRange(s_address,reqBytes); + } + + return bytesInRange; +} + +const bool TrcMemAccessorFile::overLapRange(const TrcMemAccessorBase *p_test_acc) const +{ + bool bOverLapRange = false; + if(m_base_range_set) + bOverLapRange = TrcMemAccessorBase::overLapRange(p_test_acc); + + if(!bOverLapRange && (m_has_access_regions)) + { + std::list<FileRegionMemAccessor *>::const_iterator it; + it = m_access_regions.begin(); + while((it != m_access_regions.end()) && !bOverLapRange) + { + bOverLapRange = (*it)->overLapRange(p_test_acc); + it++; + } + } + return bOverLapRange; +} + + /*! Override to handle ranges and offset accessors plus add in file name. */ +void TrcMemAccessorFile::getMemAccString(std::string &accStr) const +{ + std::ostringstream oss; + accStr = ""; + if(m_base_range_set) + { + TrcMemAccessorBase::getMemAccString(accStr); + } + + if(m_has_access_regions) + { + std::string addStr; + std::list<FileRegionMemAccessor *>::const_iterator it; + it = m_access_regions.begin(); + while(it != m_access_regions.end()) + { + (*it)->getMemAccString(addStr); + if(accStr.length()) + accStr += "\n"; + accStr += addStr; + it++; + } + } + accStr += (std::string)"\nFilename=" + m_file_path; +} + +/* End of File trc_mem_acc_file.cpp */ |
