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
TrcMemAccessorFile()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
~TrcMemAccessorFile()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
initAccessor(const std::string & pathToFile,ocsd_vaddr_t startAddr,size_t offset,size_t size)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
getRegionForAddress(const ocsd_vaddr_t startAddr) const98 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
createFileAccessor(TrcMemAccessorFile ** p_acc,const std::string & pathToFile,ocsd_vaddr_t startAddr,size_t offset,size_t size)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
destroyFileAccessor(TrcMemAccessorFile * p_accessor)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
isExistingFileAccessor(const std::string & pathToFile)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
getExistingFileAccessor(const std::string & pathToFile)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 /***************************************************/
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)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
AddOffsetRange(const ocsd_vaddr_t startAddr,const size_t size,const size_t offset)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
addrInRange(const ocsd_vaddr_t s_address) const281 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
addrStartOfRange(const ocsd_vaddr_t s_address) const295 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 */
validateRange()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
bytesInRange(const ocsd_vaddr_t s_address,const uint32_t reqBytes) const330 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
overLapRange(const TrcMemAccessorBase * p_test_acc) const345 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. */
getMemAccString(std::string & accStr) const365 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