mleach | 6c73c83 | 2015-11-25 16:23:21 +0000 | [diff] [blame] | 1 | /*! |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 2 | * \file trc_mem_acc_base.h |
mleach | 6c73c83 | 2015-11-25 16:23:21 +0000 | [diff] [blame] | 3 | * \brief Reference CoreSight Trace Decoder : Memory accessor base class. |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 4 | * |
| 5 | * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. |
| 6 | */ |
| 7 | |
| 8 | /* |
| 9 | * Redistribution and use in source and binary forms, with or without modification, |
| 10 | * are permitted provided that the following conditions are met: |
| 11 | * |
| 12 | * 1. Redistributions of source code must retain the above copyright notice, |
| 13 | * this list of conditions and the following disclaimer. |
| 14 | * |
| 15 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
| 16 | * this list of conditions and the following disclaimer in the documentation |
| 17 | * and/or other materials provided with the distribution. |
| 18 | * |
| 19 | * 3. Neither the name of the copyright holder nor the names of its contributors |
| 20 | * may be used to endorse or promote products derived from this software without |
| 21 | * specific prior written permission. |
| 22 | * |
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND |
| 24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 26 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| 27 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 33 | */ |
| 34 | |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 35 | #ifndef ARM_TRC_MEM_ACC_BASE_H_INCLUDED |
| 36 | #define ARM_TRC_MEM_ACC_BASE_H_INCLUDED |
| 37 | |
| 38 | #include "rctdl_if_types.h" |
mleach | ebc28b0 | 2015-12-11 11:15:34 +0000 | [diff] [blame] | 39 | #include <string> |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 40 | |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 41 | /*! |
| 42 | * @class TrcMemAccessorBase |
| 43 | * @brief Memory range to access by trace decoder. |
| 44 | * |
| 45 | * Represents a memory access range for the trace decoder. |
| 46 | * Range inclusive from m_startAddress to m_endAddress. |
| 47 | * e.g. a 1k range from 0x1000 has start of 0x1000 and end of 0x13FF |
| 48 | * |
| 49 | * Derived classes provide specific access types such as binary files and memory buffers. |
| 50 | * |
| 51 | */ |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 52 | class TrcMemAccessorBase |
| 53 | { |
| 54 | public: |
mleach | c964108 | 2015-08-24 14:38:13 +0100 | [diff] [blame] | 55 | |
mleach | ebc28b0 | 2015-12-11 11:15:34 +0000 | [diff] [blame] | 56 | /** Describes the storage type of the underlying memory accessor */ |
mleach | c964108 | 2015-08-24 14:38:13 +0100 | [diff] [blame] | 57 | enum MemAccTypes { |
| 58 | MEMACC_UNKNOWN, |
mleach | ebc28b0 | 2015-12-11 11:15:34 +0000 | [diff] [blame] | 59 | MEMACC_FILE, //<! Binary data file accessor |
| 60 | MEMACC_BUFPTR, //<! memory buffer accessor |
| 61 | MEMACC_CB_IF, //<! callback interface accessor - use for live memory access |
mleach | c964108 | 2015-08-24 14:38:13 +0100 | [diff] [blame] | 62 | }; |
| 63 | |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 64 | /** default constructor */ |
mleach | c964108 | 2015-08-24 14:38:13 +0100 | [diff] [blame] | 65 | TrcMemAccessorBase(MemAccTypes type); |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 66 | |
| 67 | /** costruct with address range values */ |
mleach | c964108 | 2015-08-24 14:38:13 +0100 | [diff] [blame] | 68 | TrcMemAccessorBase(MemAccTypes type, rctdl_vaddr_t startAddr, rctdl_vaddr_t endAddr); |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 69 | |
| 70 | /** default desctructor */ |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 71 | virtual ~TrcMemAccessorBase() {}; |
mleach | 66c99f1 | 2015-08-27 17:53:11 +0100 | [diff] [blame] | 72 | |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 73 | /*! |
| 74 | * Set the inclusive address range of this accessor. |
| 75 | * |
| 76 | * @param startAddr : start address of the range. |
| 77 | * @param endAddr : end address of the range. |
| 78 | */ |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 79 | void setRange(rctdl_vaddr_t startAddr, rctdl_vaddr_t endAddr); |
| 80 | |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 81 | /*! |
| 82 | * test if an address is in the inclusive range for this accessor |
| 83 | * |
| 84 | * @param s_address : Address to test. |
| 85 | * |
| 86 | * @return const bool : true if the address is in range. |
| 87 | */ |
mleach | 66c99f1 | 2015-08-27 17:53:11 +0100 | [diff] [blame] | 88 | virtual const bool addrInRange(const rctdl_vaddr_t s_address) const; |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 89 | |
mleach | f1acc38 | 2015-09-14 17:27:05 +0100 | [diff] [blame] | 90 | |
| 91 | /*! |
| 92 | * test if an address is the start of range for this accessor |
| 93 | * |
| 94 | * @param s_address : Address to test. |
| 95 | * |
| 96 | * @return const bool : true if the address is start of range. |
| 97 | */ |
| 98 | virtual const bool addrStartOfRange(const rctdl_vaddr_t s_address) const; |
| 99 | |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 100 | /*! |
| 101 | * Test number of bytes available from the start address, up to the number of requested bytes. |
| 102 | * Tests if all the requested bytes are available from the supplied start address. |
| 103 | * Returns the number available up to full requested amount. |
| 104 | * |
| 105 | * @param s_address : Start address within the range. |
| 106 | * @param reqBytes : Number of bytes needed from the start address. |
| 107 | * |
| 108 | * @return const uint32_t : Bytes available, up to reqBytes. 0 is s_address not in range. |
| 109 | */ |
mleach | 66c99f1 | 2015-08-27 17:53:11 +0100 | [diff] [blame] | 110 | virtual const uint32_t bytesInRange(const rctdl_vaddr_t s_address, const uint32_t reqBytes) const; |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 111 | |
| 112 | /*! |
| 113 | * test is supplied range accessor overlaps this range. |
| 114 | * |
| 115 | * @param *p_test_acc : Accessor to test for overlap. |
| 116 | * |
| 117 | * @return bool : true if overlap, false if not. |
| 118 | */ |
mleach | 66c99f1 | 2015-08-27 17:53:11 +0100 | [diff] [blame] | 119 | virtual const bool overLapRange(const TrcMemAccessorBase *p_test_acc) const; |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 120 | |
| 121 | /*! |
| 122 | * Read bytes from via the accessor from the memory range. |
| 123 | * |
| 124 | * @param s_address : Start address of the read. |
mleach | ebc28b0 | 2015-12-11 11:15:34 +0000 | [diff] [blame] | 125 | * @param memSpace : memory space for this access. |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 126 | * @param reqBytes : Number of bytes required. |
| 127 | * @param *byteBuffer : Buffer to copy the bytes into. |
| 128 | * |
mleach | ebc28b0 | 2015-12-11 11:15:34 +0000 | [diff] [blame] | 129 | * @return uint32_t : Number of bytes read, 0 if s_address out of range, or mem space not accessible. |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 130 | */ |
mleach | ebc28b0 | 2015-12-11 11:15:34 +0000 | [diff] [blame] | 131 | virtual const uint32_t readBytes(const rctdl_vaddr_t s_address, const rctdl_mem_space_acc_t memSpace, const uint32_t reqBytes, uint8_t *byteBuffer) = 0; |
| 132 | |
| 133 | /*! |
| 134 | * Validate the address range - ensure addresses aligned, different, st < en etc. |
| 135 | * |
| 136 | * @return bool : true if valid range. |
| 137 | */ |
Mike Leach | 000073b | 2016-02-18 01:27:23 +0000 | [diff] [blame] | 138 | virtual const bool validateRange(); |
mleach | ebc28b0 | 2015-12-11 11:15:34 +0000 | [diff] [blame] | 139 | |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 140 | |
mleach | c964108 | 2015-08-24 14:38:13 +0100 | [diff] [blame] | 141 | const enum MemAccTypes getType() const { return m_type; }; |
| 142 | |
mleach | 66c99f1 | 2015-08-27 17:53:11 +0100 | [diff] [blame] | 143 | /* handle memory spaces */ |
| 144 | void setMemSpace(rctdl_mem_space_acc_t memSpace) { m_mem_space = memSpace; }; |
| 145 | const rctdl_mem_space_acc_t getMemSpace() const { return m_mem_space; }; |
mleach | 5e0cde7 | 2015-10-27 14:16:20 +0000 | [diff] [blame] | 146 | const bool inMemSpace(const rctdl_mem_space_acc_t mem_space) const { return (bool)(((uint8_t)m_mem_space & (uint8_t)mem_space) != 0); }; |
mleach | 66c99f1 | 2015-08-27 17:53:11 +0100 | [diff] [blame] | 147 | |
mleach | d9bd232 | 2015-12-18 18:12:48 +0000 | [diff] [blame] | 148 | /* memory access info logging */ |
| 149 | virtual void getMemAccString(std::string &accStr) const; |
| 150 | |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 151 | protected: |
mleach | ebc28b0 | 2015-12-11 11:15:34 +0000 | [diff] [blame] | 152 | rctdl_vaddr_t m_startAddress; /**< accessible range start address */ |
| 153 | rctdl_vaddr_t m_endAddress; /**< accessible range end address */ |
| 154 | const MemAccTypes m_type; /**< memory accessor type */ |
mleach | 66c99f1 | 2015-08-27 17:53:11 +0100 | [diff] [blame] | 155 | rctdl_mem_space_acc_t m_mem_space; |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 156 | }; |
| 157 | |
mleach | c964108 | 2015-08-24 14:38:13 +0100 | [diff] [blame] | 158 | inline TrcMemAccessorBase::TrcMemAccessorBase(MemAccTypes accType, rctdl_vaddr_t startAddr, rctdl_vaddr_t endAddr) : |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 159 | m_startAddress(startAddr), |
mleach | c964108 | 2015-08-24 14:38:13 +0100 | [diff] [blame] | 160 | m_endAddress(endAddr), |
mleach | 66c99f1 | 2015-08-27 17:53:11 +0100 | [diff] [blame] | 161 | m_type(accType), |
| 162 | m_mem_space(RCTDL_MEM_SPACE_ANY) |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 163 | { |
| 164 | } |
| 165 | |
mleach | c964108 | 2015-08-24 14:38:13 +0100 | [diff] [blame] | 166 | inline TrcMemAccessorBase::TrcMemAccessorBase(MemAccTypes accType) : |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 167 | m_startAddress(0), |
mleach | c964108 | 2015-08-24 14:38:13 +0100 | [diff] [blame] | 168 | m_endAddress(0), |
mleach | 66c99f1 | 2015-08-27 17:53:11 +0100 | [diff] [blame] | 169 | m_type(accType), |
| 170 | m_mem_space(RCTDL_MEM_SPACE_ANY) |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 171 | { |
| 172 | } |
| 173 | |
| 174 | inline void TrcMemAccessorBase::setRange(rctdl_vaddr_t startAddr, rctdl_vaddr_t endAddr) |
| 175 | { |
| 176 | m_startAddress = startAddr; |
| 177 | m_endAddress = endAddr; |
| 178 | } |
| 179 | |
| 180 | inline const bool TrcMemAccessorBase::addrInRange(const rctdl_vaddr_t s_address) const |
| 181 | { |
| 182 | return (s_address >= m_startAddress) && (s_address <= m_endAddress); |
| 183 | } |
| 184 | |
mleach | f1acc38 | 2015-09-14 17:27:05 +0100 | [diff] [blame] | 185 | inline const bool TrcMemAccessorBase::addrStartOfRange(const rctdl_vaddr_t s_address) const |
| 186 | { |
| 187 | return (s_address == m_startAddress); |
| 188 | } |
| 189 | |
| 190 | |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 191 | inline const uint32_t TrcMemAccessorBase::bytesInRange(const rctdl_vaddr_t s_address, const uint32_t reqBytes) const |
| 192 | { |
mleach | 5e0cde7 | 2015-10-27 14:16:20 +0000 | [diff] [blame] | 193 | rctdl_vaddr_t bytesInRange = 0; |
mleach | a37d643 | 2015-08-20 17:53:50 +0100 | [diff] [blame] | 194 | if(addrInRange(s_address)) // start not in range, return 0. |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 195 | { |
mleach | a37d643 | 2015-08-20 17:53:50 +0100 | [diff] [blame] | 196 | // bytes available till end address. |
| 197 | bytesInRange = m_endAddress - s_address + 1; |
| 198 | if(bytesInRange > reqBytes) |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 199 | bytesInRange = reqBytes; |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 200 | } |
mleach | 5e0cde7 | 2015-10-27 14:16:20 +0000 | [diff] [blame] | 201 | return (uint32_t)bytesInRange; |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 202 | } |
| 203 | |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 204 | inline const bool TrcMemAccessorBase::overLapRange(const TrcMemAccessorBase *p_test_acc) const |
| 205 | { |
mleach | 66c99f1 | 2015-08-27 17:53:11 +0100 | [diff] [blame] | 206 | if( addrInRange(p_test_acc->m_startAddress) || |
| 207 | addrInRange(p_test_acc->m_endAddress) |
mleach | 34d6ee1 | 2015-08-21 12:47:32 +0100 | [diff] [blame] | 208 | ) |
| 209 | return true; |
| 210 | return false; |
| 211 | } |
| 212 | |
mleach | ebc28b0 | 2015-12-11 11:15:34 +0000 | [diff] [blame] | 213 | inline const bool TrcMemAccessorBase::validateRange() |
| 214 | { |
| 215 | if(m_startAddress & 0x1) // at least hword aligned for thumb |
| 216 | return false; |
| 217 | if((m_endAddress + 1) & 0x1) |
| 218 | return false; |
| 219 | if(m_startAddress == m_endAddress) // zero length range. |
| 220 | return false; |
| 221 | if(m_startAddress > m_endAddress) // values bakcwards / invalid |
| 222 | return false; |
| 223 | return true; |
| 224 | } |
| 225 | |
| 226 | |
| 227 | class TrcMemAccFactory |
| 228 | { |
| 229 | public: |
| 230 | /** Accessor Creation */ |
| 231 | static rctdl_err_t CreateBufferAccessor(TrcMemAccessorBase **pAccessor, const rctdl_vaddr_t s_address, const uint8_t *p_buffer, const uint32_t size); |
| 232 | static rctdl_err_t CreateFileAccessor(TrcMemAccessorBase **pAccessor, const std::string &pathToFile, rctdl_vaddr_t startAddr, size_t offset = 0, size_t size = 0); |
| 233 | static rctdl_err_t CreateCBAccessor(TrcMemAccessorBase **pAccessor, const rctdl_vaddr_t s_address, const rctdl_vaddr_t e_address, const rctdl_mem_space_acc_t mem_space); |
| 234 | |
| 235 | /** Accessor Destruction */ |
| 236 | static void DestroyAccessor(TrcMemAccessorBase *pAccessor); |
| 237 | private: |
| 238 | TrcMemAccFactory() {}; |
| 239 | ~TrcMemAccFactory() {}; |
| 240 | }; |
| 241 | |
mike leach | a6baf05 | 2015-08-20 00:24:15 +0100 | [diff] [blame] | 242 | #endif // ARM_TRC_MEM_ACC_BASE_H_INCLUDED |
| 243 | |
| 244 | /* End of File trc_mem_acc_base.h */ |