diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 07:24:57 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 07:24:57 +0000 |
commit | 070852d8604cece0c31f28ff3eb8d21d9ba415fb (patch) | |
tree | 9097175a6a5b8b7e37af9a96269ac0b61a0189cd /decoder/source/mem_acc | |
parent | Initial commit. (diff) | |
download | libopencsd-070852d8604cece0c31f28ff3eb8d21d9ba415fb.tar.xz libopencsd-070852d8604cece0c31f28ff3eb8d21d9ba415fb.zip |
Adding upstream version 1.3.3.upstream/1.3.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'decoder/source/mem_acc')
-rw-r--r-- | decoder/source/mem_acc/trc_mem_acc_base.cpp | 148 | ||||
-rw-r--r-- | decoder/source/mem_acc/trc_mem_acc_bufptr.cpp | 53 | ||||
-rw-r--r-- | decoder/source/mem_acc/trc_mem_acc_cache.cpp | 176 | ||||
-rw-r--r-- | decoder/source/mem_acc/trc_mem_acc_cb.cpp | 34 | ||||
-rw-r--r-- | decoder/source/mem_acc/trc_mem_acc_file.cpp | 391 | ||||
-rw-r--r-- | decoder/source/mem_acc/trc_mem_acc_mapper.cpp | 307 |
6 files changed, 1109 insertions, 0 deletions
diff --git a/decoder/source/mem_acc/trc_mem_acc_base.cpp b/decoder/source/mem_acc/trc_mem_acc_base.cpp new file mode 100644 index 0000000..1250bdc --- /dev/null +++ b/decoder/source/mem_acc/trc_mem_acc_base.cpp @@ -0,0 +1,148 @@ +/*! + * \file trc_mem_acc_base.cpp + * \brief OpenCSD : Trace memory accessor base class. + * + * \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_base.h" +#include "mem_acc/trc_mem_acc_file.h" +#include "mem_acc/trc_mem_acc_cb.h" +#include "mem_acc/trc_mem_acc_bufptr.h" + +#include <sstream> +#include <iomanip> + + /** Accessor Creation */ +ocsd_err_t TrcMemAccFactory::CreateBufferAccessor(TrcMemAccessorBase **pAccessor, const ocsd_vaddr_t s_address, const uint8_t *p_buffer, const uint32_t size) +{ + ocsd_err_t err = OCSD_OK; + TrcMemAccessorBase *pAcc = 0; + pAcc = new (std::nothrow) TrcMemAccBufPtr(s_address,p_buffer,size); + if(pAcc == 0) + err = OCSD_ERR_MEM; + *pAccessor = pAcc; + return err; +} + +ocsd_err_t TrcMemAccFactory::CreateFileAccessor(TrcMemAccessorBase **pAccessor, const std::string &pathToFile, ocsd_vaddr_t startAddr, size_t offset /*= 0*/, size_t size /*= 0*/) +{ + ocsd_err_t err = OCSD_OK; + TrcMemAccessorFile *pFileAccessor = 0; + err = TrcMemAccessorFile::createFileAccessor(&pFileAccessor, pathToFile, startAddr, offset,size); + *pAccessor = pFileAccessor; + return err; +} + +ocsd_err_t TrcMemAccFactory::CreateCBAccessor(TrcMemAccessorBase **pAccessor, const ocsd_vaddr_t s_address, const ocsd_vaddr_t e_address, const ocsd_mem_space_acc_t mem_space) +{ + ocsd_err_t err = OCSD_OK; + TrcMemAccessorBase *pAcc = 0; + pAcc = new (std::nothrow) TrcMemAccCB(s_address,e_address,mem_space); + if(pAcc == 0) + err = OCSD_ERR_MEM; + *pAccessor = pAcc; + return err; +} + +/** Accessor Destruction */ +void TrcMemAccFactory::DestroyAccessor(TrcMemAccessorBase *pAccessor) +{ + switch(pAccessor->getType()) + { + case TrcMemAccessorBase::MEMACC_FILE: + TrcMemAccessorFile::destroyFileAccessor(dynamic_cast<TrcMemAccessorFile *>(pAccessor)); + break; + + case TrcMemAccessorBase::MEMACC_CB_IF: + case TrcMemAccessorBase::MEMACC_BUFPTR: + delete pAccessor; + break; + + default: + break; + } +} + + +/* memory access info logging */ +void TrcMemAccessorBase::getMemAccString(std::string &accStr) const +{ + std::ostringstream oss; + + switch(m_type) + { + case MEMACC_FILE: + oss << "FileAcc; Range::0x"; + break; + + case MEMACC_BUFPTR: + oss << "BuffAcc; Range::0x"; + break; + + case MEMACC_CB_IF: + oss << "CB Acc; Range::0x"; + break; + + default: + oss << "UnknAcc; Range::0x"; + break; + } + oss << std::hex << std::setw(2) << std::setfill('0') << m_startAddress << ":" << m_endAddress; + oss << "; Mem Space::"; + switch(m_mem_space) + { + case OCSD_MEM_SPACE_EL1S: oss << "EL1S"; break; + case OCSD_MEM_SPACE_EL1N: oss << "EL1N"; break; + case OCSD_MEM_SPACE_EL2: oss << "EL2"; break; + case OCSD_MEM_SPACE_EL3: oss << "EL3"; break; + case OCSD_MEM_SPACE_S: oss << "Any S"; break; + case OCSD_MEM_SPACE_N: oss << "Any NS"; break; + case OCSD_MEM_SPACE_ANY: oss << "Any"; break; + + default: + { + uint8_t MSBits = (uint8_t)m_mem_space; + if(MSBits & (uint8_t)OCSD_MEM_SPACE_EL1S) + oss << "EL1S,"; + if(MSBits & (uint8_t)OCSD_MEM_SPACE_EL1N) + oss << "EL1N,"; + if(MSBits & (uint8_t)OCSD_MEM_SPACE_EL2) + oss << "EL2,"; + if(MSBits & (uint8_t)OCSD_MEM_SPACE_EL3) + oss << "EL3,"; + } + break; + } + accStr = oss.str(); +} + +/* End of File trc_mem_acc_base.cpp */ diff --git a/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp b/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp new file mode 100644 index 0000000..7ecd3b0 --- /dev/null +++ b/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp @@ -0,0 +1,53 @@ +/* + * \file trc_mem_acc_bufptr.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 <cstring> + +#include "mem_acc/trc_mem_acc_bufptr.h" + +TrcMemAccBufPtr::TrcMemAccBufPtr(const ocsd_vaddr_t s_address, const uint8_t *p_buffer, const uint32_t size) : + TrcMemAccessorBase(MEMACC_BUFPTR, s_address, s_address+size-1), + m_p_buffer(p_buffer) +{ +} + +const uint32_t TrcMemAccBufPtr::readBytes(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t trcID, const uint32_t reqBytes, uint8_t *byteBuffer) +{ + // mapper wlll filter memory spaces. + uint32_t bytesRead = bytesInRange(address,reqBytes); // check bytes available + if(bytesRead) + memcpy(byteBuffer,m_p_buffer+address-m_startAddress,bytesRead); + return bytesRead; +} + +/* End of File trc_mem_acc_bufptr.cpp */ diff --git a/decoder/source/mem_acc/trc_mem_acc_cache.cpp b/decoder/source/mem_acc/trc_mem_acc_cache.cpp new file mode 100644 index 0000000..444314e --- /dev/null +++ b/decoder/source/mem_acc/trc_mem_acc_cache.cpp @@ -0,0 +1,176 @@ +/*! +* \file trc_mem_acc_cache.cpp +* \brief OpenCSD : Memory accessor cache. +* +* \copyright Copyright (c) 2018, 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 <cstring> +#include <sstream> +#include <iomanip> +#include "mem_acc/trc_mem_acc_cache.h" +#include "mem_acc/trc_mem_acc_base.h" +#include "interfaces/trc_error_log_i.h" + +#ifdef LOG_CACHE_STATS +#define INC_HITS_RL(idx) m_hits++; m_hit_rl[m_mru_idx]++; +#define INC_MISS() m_misses++; +#define INC_PAGES() m_pages++; +#define SET_MAX_RL(idx) \ + { \ + if (m_hit_rl_max[idx] < m_hit_rl[idx]) \ + m_hit_rl_max[idx] = m_hit_rl[idx]; \ + m_hit_rl[idx] = 0; \ + } +#define INC_RL(idx) m_hit_rl[m_mru_idx]++; +#else +#define INC_HITS_RL(idx) +#define INC_MISS() +#define INC_PAGES() +#define SET_MAX_RL(idx) +#define INC_RL(idx) +#endif + +// uncomment to log cache ops +//#define LOG_CACHE_OPS + +ocsd_err_t TrcMemAccCache::readBytesFromCache(TrcMemAccessorBase *p_accessor, const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t trcID, uint32_t *numBytes, uint8_t *byteBuffer) +{ + uint32_t bytesRead = 0, reqBytes = *numBytes; + ocsd_err_t err = OCSD_OK; + +#ifdef LOG_CACHE_OPS + std::ostringstream oss; +#endif + + if (m_bCacheEnabled) + { + if (blockInCache(address, reqBytes)) + { + bytesRead = reqBytes; + memcpy(byteBuffer, &m_mru[m_mru_idx].data[address - m_mru[m_mru_idx].st_addr], reqBytes); +#ifdef LOG_CACHE_OPS + oss << "TrcMemAccCache:: hit [page: " << std::dec << m_mru_idx << "[addr:0x" << std::hex << address << ", bytes: " << std::dec << reqBytes << "]\n"; + logMsg(oss.str()); +#endif + INC_HITS_RL(m_mru_idx); + } + else + { + INC_MISS(); +#ifdef LOG_CACHE_OPS + oss << "TrcMemAccCache:: miss [addr:0x" << std::hex << address << ", bytes: " << std::dec << reqBytes << "]\n"; + logMsg(oss.str()); +#endif + /* need a new cache page - check the underlying accessor for the data */ + m_mru_idx = m_mru_next_new; + m_mru[m_mru_idx].valid_len = p_accessor->readBytes(address, mem_space, trcID, MEM_ACC_CACHE_PAGE_SIZE, &m_mru[m_mru_idx].data[0]); + + /* check return length valid - v bad if return length more than request */ + if (m_mru[m_mru_idx].valid_len > MEM_ACC_CACHE_PAGE_SIZE) + { + m_mru[m_mru_idx].valid_len = 0; // set to nothing returned. + err = OCSD_ERR_MEM_ACC_BAD_LEN; + } + + if (m_mru[m_mru_idx].valid_len > 0) + { + // got some data - so save the + m_mru[m_mru_idx].st_addr = address; + + // log the run length hit counts + SET_MAX_RL(m_mru_idx); + +#ifdef LOG_CACHE_OPS + oss.str(""); + oss << "TrcMemAccCache:: load [page: " << std::dec << m_mru_idx << "[addr:0x" << std::hex << address << ", bytes: " << std::dec << m_mru[m_mru_idx].valid_len << "]\n"; + logMsg(oss.str()); +#endif + INC_PAGES(); + + // increment the next new page counter. + m_mru_next_new++; + if (m_mru_next_new == MEM_ACC_CACHE_MRU_SIZE) + m_mru_next_new = 0; + + if (blockInPage(address, reqBytes)) /* check we got the data we needed */ + { + bytesRead = reqBytes; + memcpy(byteBuffer, &m_mru[m_mru_idx].data[address - m_mru[m_mru_idx].st_addr], reqBytes); + INC_RL(m_mru_idx); + } + else + { +#ifdef LOG_CACHE_OPS + oss.str(""); + oss << "TrcMemAccCache:: miss-after-load [page: " << std::dec << m_mru_idx << "[addr:0x" << std::hex << address << ", bytes: " << std::dec << m_mru[m_mru_idx].valid_len << "]\n"; + logMsg(oss.str()); +#endif + INC_MISS(); + } + } + } + } + *numBytes = bytesRead; + return err; +} + +void TrcMemAccCache::logMsg(const std::string &szMsg) +{ + if (m_err_log) + m_err_log->LogMessage(ITraceErrorLog::HANDLE_GEN_INFO, OCSD_ERR_SEV_INFO, szMsg); +} + +void TrcMemAccCache::setErrorLog(ITraceErrorLog *log) +{ + m_err_log = log; +} + +void TrcMemAccCache::logAndClearCounts() +{ +#ifdef LOG_CACHE_STATS + std::ostringstream oss; + + oss << "TrcMemAccCache:: cache performance: hits(" << std::dec << m_hits << "), miss(" << m_misses << "), pages(" << m_pages << ")\n"; + logMsg(oss.str()); + for (int i = 0; i < MEM_ACC_CACHE_MRU_SIZE; i++) + { + if (m_hit_rl_max[i] < m_hit_rl[i]) + m_hit_rl_max[i] = m_hit_rl[i]; + oss.str(""); + oss << "Run length max page " << std::dec << i << ": " << m_hit_rl_max[i] << "\n"; + logMsg(oss.str()); + } + m_hits = m_misses = m_pages = 0; +#endif +} + + +/* End of File trc_mem_acc_cache.cpp */ diff --git a/decoder/source/mem_acc/trc_mem_acc_cb.cpp b/decoder/source/mem_acc/trc_mem_acc_cb.cpp new file mode 100644 index 0000000..1a1565b --- /dev/null +++ b/decoder/source/mem_acc/trc_mem_acc_cb.cpp @@ -0,0 +1,34 @@ +/*! + * \file trc_mem_acc_cb.cpp + * \brief OpenCSD : Trace Mem accessor - callback function + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +#include "mem_acc/trc_mem_acc_cb.h" + +TrcMemAccCB::TrcMemAccCB(const ocsd_vaddr_t s_address, + const ocsd_vaddr_t e_address, + const ocsd_mem_space_acc_t mem_space) : + TrcMemAccessorBase(MEMACC_CB_IF, s_address, e_address), + m_p_CBclass(0), + m_p_CBfn(0), + m_p_cbfn_context(0) +{ + setMemSpace(mem_space); +} + +/** Memory access override - allow decoder to read bytes from the buffer. */ +const uint32_t TrcMemAccCB::readBytes(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t memSpace, const uint8_t trcID, const uint32_t reqBytes, uint8_t *byteBuffer) +{ + // if we have a callback object, use it to call back. + if(m_p_CBclass) + return m_p_CBclass->readBytes(address,memSpace,reqBytes,byteBuffer); + if(m_p_CBfn) + return m_p_CBfn(m_p_cbfn_context, address,memSpace,reqBytes,byteBuffer); + if (m_p_CBIDfn) + return m_p_CBIDfn(m_p_cbfn_context, address, memSpace, trcID, reqBytes, byteBuffer); + return 0; +} + +/* End of File trc_mem_acc_cb.cpp */ 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 0000000..25b718e --- /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 uint8_t trcID, 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 */ diff --git a/decoder/source/mem_acc/trc_mem_acc_mapper.cpp b/decoder/source/mem_acc/trc_mem_acc_mapper.cpp new file mode 100644 index 0000000..dc07a1e --- /dev/null +++ b/decoder/source/mem_acc/trc_mem_acc_mapper.cpp @@ -0,0 +1,307 @@ +/* + * \file trc_mem_acc_mapper.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_mapper.h" +#include "mem_acc/trc_mem_acc_file.h" +#include "common/ocsd_error.h" + +/************************************************************************************/ +/* mappers base class */ +/************************************************************************************/ + +#define USING_MEM_ACC_CACHE + +TrcMemAccMapper::TrcMemAccMapper() : + m_acc_curr(0), + m_trace_id_curr(0), + m_using_trace_id(false), + m_err_log(0) +{ +#ifdef USING_MEM_ACC_CACHE + m_cache.enableCaching(true); +#endif +} + +TrcMemAccMapper::TrcMemAccMapper(bool using_trace_id) : + m_acc_curr(0), + m_trace_id_curr(0), + m_using_trace_id(using_trace_id), + m_err_log(0) +{ +#ifdef USING_MEM_ACC_CACHE + m_cache.enableCaching(true); +#endif +} + +TrcMemAccMapper::~TrcMemAccMapper() +{ +} + +void TrcMemAccMapper::setErrorLog(ITraceErrorLog *err_log_i) +{ + m_err_log = err_log_i; + m_cache.setErrorLog(err_log_i); +} + +// memory access interface +ocsd_err_t TrcMemAccMapper::ReadTargetMemory(const ocsd_vaddr_t address, const uint8_t cs_trace_id, const ocsd_mem_space_acc_t mem_space, uint32_t *num_bytes, uint8_t *p_buffer) +{ + bool bReadFromCurr = true; + uint32_t readBytes = 0; + ocsd_err_t err = OCSD_OK; + + /* see if the address is in any range we know */ + if (!readFromCurrent(address, mem_space, cs_trace_id)) + { + bReadFromCurr = findAccessor(address, mem_space, cs_trace_id); + + // found a new accessor - invalidate any cache entries used by the previous one. + if (m_cache.enabled() && bReadFromCurr) + m_cache.invalidateAll(); + } + + /* if bReadFromCurr then we know m_acc_curr is set */ + if (bReadFromCurr) + { + // use cache if enabled and the amount fits into a cache page + if (m_cache.enabled_for_size(*num_bytes)) + { + // read from cache - or load a new cache page and read.... + readBytes = *num_bytes; + err = m_cache.readBytesFromCache(m_acc_curr, address, mem_space, cs_trace_id, &readBytes, p_buffer); + if (err != OCSD_OK) + LogWarn(err, "Mem Acc: Cache access error"); + } + else + { + readBytes = m_acc_curr->readBytes(address, mem_space, cs_trace_id, *num_bytes, p_buffer); + // guard against bad accessor returns (e.g. callback not obeying the rules for return values) + if (readBytes > *num_bytes) + { + err = OCSD_ERR_MEM_ACC_BAD_LEN; + LogWarn(err,"Mem acc: bad return length"); + } + } + } + + *num_bytes = readBytes; + return err; +} + +void TrcMemAccMapper::InvalidateMemAccCache(const uint8_t /* cs_trace_id */) +{ + // default mapper does not use cs_trace_id for cache invalidation. + if (m_cache.enabled()) + m_cache.invalidateAll(); + m_acc_curr = 0; +} + +void TrcMemAccMapper::RemoveAllAccessors() +{ + TrcMemAccessorBase *pAcc = 0; + pAcc = getFirstAccessor(); + while(pAcc != 0) + { + TrcMemAccFactory::DestroyAccessor(pAcc); + pAcc = getNextAccessor(); + if (m_cache.enabled()) + m_cache.invalidateAll(); + } + clearAccessorList(); + if (m_cache.enabled()) + m_cache.logAndClearCounts(); +} + +ocsd_err_t TrcMemAccMapper::RemoveAccessorByAddress(const ocsd_vaddr_t st_address, const ocsd_mem_space_acc_t mem_space, const uint8_t cs_trace_id /* = 0 */) +{ + ocsd_err_t err = OCSD_OK; + if(findAccessor(st_address,mem_space,cs_trace_id)) + { + err = RemoveAccessor(m_acc_curr); + m_acc_curr = 0; + if (m_cache.enabled()) + m_cache.invalidateAll(); + } + else + err = OCSD_ERR_INVALID_PARAM_VAL; + if (m_cache.enabled()) + m_cache.logAndClearCounts(); + return err; +} + +void TrcMemAccMapper::LogMessage(const std::string &msg) +{ + if(m_err_log) + m_err_log->LogMessage(ITraceErrorLog::HANDLE_GEN_INFO,OCSD_ERR_SEV_INFO,msg); +} + +void TrcMemAccMapper::LogWarn(const ocsd_err_t err, const std::string &msg) +{ + if (m_err_log) + { + ocsdError err_ocsd(OCSD_ERR_SEV_WARN,err,msg); + m_err_log->LogError(ITraceErrorLog::HANDLE_GEN_INFO, &err_ocsd); + } +} + + +/************************************************************************************/ +/* mappers global address space class - no differentiation in core trace IDs */ +/************************************************************************************/ +TrcMemAccMapGlobalSpace::TrcMemAccMapGlobalSpace() : TrcMemAccMapper() +{ +} + +TrcMemAccMapGlobalSpace::~TrcMemAccMapGlobalSpace() +{ +} + +ocsd_err_t TrcMemAccMapGlobalSpace::AddAccessor(TrcMemAccessorBase *p_accessor, const uint8_t /*cs_trace_id*/) +{ + ocsd_err_t err = OCSD_OK; + bool bOverLap = false; + + if(!p_accessor->validateRange()) + return OCSD_ERR_MEM_ACC_RANGE_INVALID; + + std::vector<TrcMemAccessorBase *>::const_iterator it = m_acc_global.begin(); + while((it != m_acc_global.end()) && !bOverLap) + { + // if overlap and memory space match + if( ((*it)->overLapRange(p_accessor)) && + ((*it)->inMemSpace(p_accessor->getMemSpace())) + ) + { + bOverLap = true; + err = OCSD_ERR_MEM_ACC_OVERLAP; + } + it++; + } + + // no overlap - add to the list of ranges. + if(!bOverLap) + m_acc_global.push_back(p_accessor); + + return err; +} + +bool TrcMemAccMapGlobalSpace::findAccessor(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t /*cs_trace_id*/) +{ + bool bFound = false; + std::vector<TrcMemAccessorBase *>::const_iterator it = m_acc_global.begin(); + while((it != m_acc_global.end()) && !bFound) + { + if( (*it)->addrInRange(address) && + (*it)->inMemSpace(mem_space)) + { + bFound = true; + m_acc_curr = *it; + } + it++; + } + return bFound; +} + +bool TrcMemAccMapGlobalSpace::readFromCurrent(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t /*cs_trace_id*/) +{ + bool readFromCurr = false; + if(m_acc_curr) + readFromCurr = (m_acc_curr->addrInRange(address) && m_acc_curr->inMemSpace(mem_space)); + return readFromCurr; +} + + +TrcMemAccessorBase * TrcMemAccMapGlobalSpace::getFirstAccessor() +{ + TrcMemAccessorBase *p_acc = 0; + m_acc_it = m_acc_global.begin(); + if(m_acc_it != m_acc_global.end()) + { + p_acc = *m_acc_it; + } + return p_acc; +} + +TrcMemAccessorBase *TrcMemAccMapGlobalSpace::getNextAccessor() +{ + TrcMemAccessorBase *p_acc = 0; + m_acc_it++; + if(m_acc_it != m_acc_global.end()) + { + p_acc = *m_acc_it; + } + return p_acc; +} + +void TrcMemAccMapGlobalSpace::clearAccessorList() +{ + m_acc_global.clear(); +} + +ocsd_err_t TrcMemAccMapGlobalSpace::RemoveAccessor(const TrcMemAccessorBase *p_accessor) +{ + bool bFound = false; + TrcMemAccessorBase *p_acc = getFirstAccessor(); + while(p_acc != 0) + { + if(p_acc == p_accessor) + { + m_acc_global.erase(m_acc_it); + TrcMemAccFactory::DestroyAccessor(p_acc); + p_acc = 0; + bFound = true; + } + else + p_acc = getNextAccessor(); + } + return bFound ? OCSD_OK : OCSD_ERR_INVALID_PARAM_VAL; +} + + +void TrcMemAccMapGlobalSpace::logMappedRanges() +{ + std::string accStr; + TrcMemAccessorBase *pAccessor = getFirstAccessor(); + LogMessage("Mapped Memory Accessors\n"); + while(pAccessor != 0) + { + pAccessor->getMemAccString(accStr); + accStr += "\n"; + LogMessage(accStr); + pAccessor = getNextAccessor(); + } + LogMessage("========================\n"); +} + +/* End of File trc_mem_acc_mapper.cpp */ |