1 /* 2 * \file trc_mem_acc_file.cpp 3 * \brief OpenCSD : 4 * 5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. 6 */ 7 /* 8 * Redistribution and use in source and binary forms, with or without modification, 9 * are permitted provided that the following conditions are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright notice, 15 * this list of conditions and the following disclaimer in the documentation 16 * and/or other materials provided with the distribution. 17 * 18 * 3. Neither the name of the copyright holder nor the names of its contributors 19 * may be used to endorse or promote products derived from this software without 20 * specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "mem_acc/trc_mem_acc_file.h" 35 36 #include <sstream> 37 #include <iomanip> 38 39 /***************************************************/ 40 /* protected construction and reference counting */ 41 /***************************************************/ 42 43 TrcMemAccessorFile::TrcMemAccessorFile() : TrcMemAccessorBase(MEMACC_FILE) 44 { 45 m_ref_count = 0; 46 m_base_range_set = false; 47 m_has_access_regions = false; 48 m_file_size = 0; 49 } 50 51 TrcMemAccessorFile::~TrcMemAccessorFile() 52 { 53 if(m_mem_file.is_open()) 54 m_mem_file.close(); 55 if(m_access_regions.size()) 56 { 57 std::list<FileRegionMemAccessor *>::iterator it; 58 it = m_access_regions.begin(); 59 while(it != m_access_regions.end()) 60 { 61 delete (*it); 62 it++; 63 } 64 m_access_regions.clear(); 65 } 66 } 67 68 ocsd_err_t TrcMemAccessorFile::initAccessor(const std::string &pathToFile, ocsd_vaddr_t startAddr, size_t offset, size_t size) 69 { 70 ocsd_err_t err = OCSD_OK; 71 bool init = false; 72 73 m_mem_file.open(pathToFile.c_str(), std::ifstream::binary | std::ifstream::ate); 74 if(m_mem_file.is_open()) 75 { 76 m_file_size = (ocsd_vaddr_t)m_mem_file.tellg() & ((ocsd_vaddr_t)~0x1); 77 m_mem_file.seekg(0, m_mem_file.beg); 78 // adding an offset of 0, sets the base range. 79 if((offset == 0) && (size == 0)) 80 { 81 init = AddOffsetRange(startAddr, ((size_t)m_file_size)-offset, offset); 82 } 83 else if((offset + size) <= m_file_size) 84 { 85 // if offset != 0, size must by != 0 86 init = AddOffsetRange(startAddr, size, offset); 87 } 88 m_file_path = pathToFile; 89 } 90 else 91 err = OCSD_ERR_MEM_ACC_FILE_NOT_FOUND; 92 if(!init) 93 err = OCSD_ERR_NOT_INIT; 94 return err; 95 } 96 97 98 FileRegionMemAccessor *TrcMemAccessorFile::getRegionForAddress(const ocsd_vaddr_t startAddr) const 99 { 100 FileRegionMemAccessor *p_region = 0; 101 if(m_has_access_regions) 102 { 103 std::list<FileRegionMemAccessor *>::const_iterator it; 104 it = m_access_regions.begin(); 105 while((it != m_access_regions.end()) && (p_region == 0)) 106 { 107 if((*it)->addrInRange(startAddr)) 108 p_region = *it; 109 it++; 110 } 111 } 112 return p_region; 113 } 114 115 116 /***************************************************/ 117 /* static object creation */ 118 /***************************************************/ 119 120 std::map<std::string, TrcMemAccessorFile *> TrcMemAccessorFile::s_FileAccessorMap; 121 122 // return existing or create new accessor 123 ocsd_err_t TrcMemAccessorFile::createFileAccessor(TrcMemAccessorFile **p_acc, const std::string &pathToFile, ocsd_vaddr_t startAddr, size_t offset /*= 0*/, size_t size /*= 0*/) 124 { 125 ocsd_err_t err = OCSD_OK; 126 TrcMemAccessorFile * acc = 0; 127 std::map<std::string, TrcMemAccessorFile *>::iterator it = s_FileAccessorMap.find(pathToFile); 128 if(it != s_FileAccessorMap.end()) 129 { 130 acc = it->second; 131 if(acc->addrStartOfRange(startAddr)) 132 acc->IncRefCount(); 133 else 134 { 135 err = OCSD_ERR_MEM_ACC_FILE_DIFF_RANGE; 136 acc = 0; 137 } 138 } 139 else 140 { 141 acc = new (std::nothrow) TrcMemAccessorFile(); 142 if(acc != 0) 143 { 144 if((err = acc->initAccessor(pathToFile,startAddr, offset,size)) == OCSD_OK) 145 { 146 acc->IncRefCount(); 147 s_FileAccessorMap.insert(std::pair<std::string, TrcMemAccessorFile *>(pathToFile,acc)); 148 } 149 else 150 { 151 delete acc; 152 acc = 0; 153 } 154 } 155 else 156 err = OCSD_ERR_MEM; 157 } 158 *p_acc = acc; 159 return err; 160 } 161 162 void TrcMemAccessorFile::destroyFileAccessor(TrcMemAccessorFile *p_accessor) 163 { 164 if(p_accessor != 0) 165 { 166 p_accessor->DecRefCount(); 167 if(p_accessor->getRefCount() == 0) 168 { 169 std::map<std::string, TrcMemAccessorFile *>::iterator it = s_FileAccessorMap.find(p_accessor->getFilePath()); 170 if(it != s_FileAccessorMap.end()) 171 { 172 s_FileAccessorMap.erase(it); 173 } 174 delete p_accessor; 175 } 176 } 177 } 178 179 const bool TrcMemAccessorFile::isExistingFileAccessor(const std::string &pathToFile) 180 { 181 bool bExists = false; 182 std::map<std::string, TrcMemAccessorFile *>::const_iterator it = s_FileAccessorMap.find(pathToFile); 183 if(it != s_FileAccessorMap.end()) 184 bExists = true; 185 return bExists; 186 } 187 188 TrcMemAccessorFile * TrcMemAccessorFile::getExistingFileAccessor(const std::string &pathToFile) 189 { 190 TrcMemAccessorFile * p_acc = 0; 191 std::map<std::string, TrcMemAccessorFile *>::iterator it = s_FileAccessorMap.find(pathToFile); 192 if(it != s_FileAccessorMap.end()) 193 p_acc = it->second; 194 return p_acc; 195 } 196 197 198 199 /***************************************************/ 200 /* accessor instance functions */ 201 /***************************************************/ 202 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) 203 { 204 if(!m_mem_file.is_open()) 205 return 0; 206 uint32_t bytesRead = 0; 207 208 if(m_base_range_set) 209 { 210 bytesRead = TrcMemAccessorBase::bytesInRange(address,reqBytes); // get avialable bytes in range. 211 if(bytesRead) 212 { 213 ocsd_vaddr_t addr_pos = (ocsd_vaddr_t)m_mem_file.tellg(); 214 if((address - m_startAddress) != addr_pos) 215 m_mem_file.seekg(address - m_startAddress); 216 m_mem_file.read((char *)byteBuffer,bytesRead); 217 } 218 } 219 220 if((bytesRead == 0) && m_has_access_regions) 221 { 222 bytesRead = bytesInRange(address,reqBytes); 223 if(bytesRead) 224 { 225 FileRegionMemAccessor *p_region = getRegionForAddress(address); 226 ocsd_vaddr_t addr_pos = (ocsd_vaddr_t)m_mem_file.tellg(); 227 if((address - p_region->regionStartAddress() + p_region->getOffset()) != addr_pos) 228 m_mem_file.seekg(address - p_region->regionStartAddress() + p_region->getOffset()); 229 m_mem_file.read((char *)byteBuffer,bytesRead); 230 } 231 } 232 return bytesRead; 233 } 234 235 bool TrcMemAccessorFile::AddOffsetRange(const ocsd_vaddr_t startAddr, const size_t size, const size_t offset) 236 { 237 bool addOK = false; 238 if(m_file_size == 0) // must have set the file size 239 return false; 240 if(addrInRange(startAddr) || addrInRange(startAddr+size-1)) // cannot be overlapping 241 return false; 242 243 // now either set the base range or an offset range 244 if(offset == 0) 245 { 246 if(!m_base_range_set) 247 { 248 setRange(startAddr, startAddr+size-1); 249 m_base_range_set = true; 250 addOK = true; 251 } 252 } 253 else 254 { 255 if((offset + size) <= m_file_size) 256 { 257 FileRegionMemAccessor *frmacc = new (std::nothrow) FileRegionMemAccessor(); 258 if(frmacc) 259 { 260 frmacc->setOffset(offset); 261 frmacc->setRange(startAddr,startAddr+size-1); 262 m_access_regions.push_back(frmacc); 263 m_access_regions.sort(); 264 // may need to trim the 0 offset base range... 265 if(m_base_range_set) 266 { 267 std::list<FileRegionMemAccessor *>::iterator it; 268 it = m_access_regions.begin(); 269 size_t first_range_offset = (*it)->getOffset(); 270 if((m_startAddress + first_range_offset - 1) > m_endAddress) 271 m_endAddress = m_startAddress + first_range_offset - 1; 272 } 273 addOK = true; 274 m_has_access_regions = true; 275 } 276 } 277 } 278 return addOK; 279 } 280 281 const bool TrcMemAccessorFile::addrInRange(const ocsd_vaddr_t s_address) const 282 { 283 bool bInRange = false; 284 if(m_base_range_set) 285 bInRange = TrcMemAccessorBase::addrInRange(s_address); 286 287 if(!bInRange && m_has_access_regions) 288 { 289 if(getRegionForAddress(s_address) != 0) 290 bInRange = true; 291 } 292 return bInRange; 293 } 294 295 const bool TrcMemAccessorFile::addrStartOfRange(const ocsd_vaddr_t s_address) const 296 { 297 bool bInRange = false; 298 if(m_base_range_set) 299 bInRange = TrcMemAccessorBase::addrStartOfRange(s_address); 300 if(!bInRange && m_has_access_regions) 301 { 302 FileRegionMemAccessor *pRegion = getRegionForAddress(s_address); 303 if(pRegion) 304 bInRange = (pRegion->regionStartAddress() == s_address); 305 } 306 return bInRange; 307 } 308 309 310 /* validate ranges */ 311 const bool TrcMemAccessorFile::validateRange() 312 { 313 bool bRangeValid = true; 314 if(m_base_range_set) 315 bRangeValid = TrcMemAccessorBase::validateRange(); 316 317 if(m_has_access_regions && bRangeValid) 318 { 319 std::list<FileRegionMemAccessor *>::const_iterator it; 320 it = m_access_regions.begin(); 321 while((it != m_access_regions.end()) && bRangeValid) 322 { 323 bRangeValid = (*it)->validateRange(); 324 it++; 325 } 326 } 327 return bRangeValid; 328 } 329 330 const uint32_t TrcMemAccessorFile::bytesInRange(const ocsd_vaddr_t s_address, const uint32_t reqBytes) const 331 { 332 uint32_t bytesInRange = 0; 333 if(m_base_range_set) 334 bytesInRange = TrcMemAccessorBase::bytesInRange(s_address,reqBytes); 335 336 if((bytesInRange == 0) && (m_has_access_regions)) 337 { 338 FileRegionMemAccessor *p_region = getRegionForAddress(s_address); 339 bytesInRange = p_region->bytesInRange(s_address,reqBytes); 340 } 341 342 return bytesInRange; 343 } 344 345 const bool TrcMemAccessorFile::overLapRange(const TrcMemAccessorBase *p_test_acc) const 346 { 347 bool bOverLapRange = false; 348 if(m_base_range_set) 349 bOverLapRange = TrcMemAccessorBase::overLapRange(p_test_acc); 350 351 if(!bOverLapRange && (m_has_access_regions)) 352 { 353 std::list<FileRegionMemAccessor *>::const_iterator it; 354 it = m_access_regions.begin(); 355 while((it != m_access_regions.end()) && !bOverLapRange) 356 { 357 bOverLapRange = (*it)->overLapRange(p_test_acc); 358 it++; 359 } 360 } 361 return bOverLapRange; 362 } 363 364 /*! Override to handle ranges and offset accessors plus add in file name. */ 365 void TrcMemAccessorFile::getMemAccString(std::string &accStr) const 366 { 367 std::ostringstream oss; 368 accStr = ""; 369 if(m_base_range_set) 370 { 371 TrcMemAccessorBase::getMemAccString(accStr); 372 } 373 374 if(m_has_access_regions) 375 { 376 std::string addStr; 377 std::list<FileRegionMemAccessor *>::const_iterator it; 378 it = m_access_regions.begin(); 379 while(it != m_access_regions.end()) 380 { 381 (*it)->getMemAccString(addStr); 382 if(accStr.length()) 383 accStr += "\n"; 384 accStr += addStr; 385 it++; 386 } 387 } 388 accStr += (std::string)"\nFilename=" + m_file_path; 389 } 390 391 /* End of File trc_mem_acc_file.cpp */ 392