1 /*
2 * \file ocsd_dcd_tree.cpp
3 * \brief OpenCSD :
4 *
5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
6 */
7
8
9 /*
10 * Redistribution and use in source and binary forms, with or without modification,
11 * are permitted provided that the following conditions are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of the copyright holder nor the names of its contributors
21 * may be used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include "common/ocsd_dcd_tree.h"
37 #include "common/ocsd_lib_dcd_register.h"
38 #include "mem_acc/trc_mem_acc_mapper.h"
39
40 /***************************************************************/
41 ITraceErrorLog *DecodeTree::s_i_error_logger = &DecodeTree::s_error_logger;
42 std::list<DecodeTree *> DecodeTree::s_trace_dcd_trees; /**< list of pointers to decode tree objects */
43 ocsdDefaultErrorLogger DecodeTree::s_error_logger; /**< The library default error logger */
44 TrcIDecode DecodeTree::s_instruction_decoder; /**< default instruction decode library */
45
CreateDecodeTree(const ocsd_dcd_tree_src_t src_type,uint32_t formatterCfgFlags)46 DecodeTree *DecodeTree::CreateDecodeTree(const ocsd_dcd_tree_src_t src_type, uint32_t formatterCfgFlags)
47 {
48 DecodeTree *dcd_tree = new (std::nothrow) DecodeTree();
49 if(dcd_tree != 0)
50 {
51 if(dcd_tree->initialise(src_type, formatterCfgFlags))
52 {
53 s_trace_dcd_trees.push_back(dcd_tree);
54 s_instruction_decoder.envSetAA64_errOnBadOpcode();
55 }
56 else
57 {
58 delete dcd_tree;
59 dcd_tree = 0;
60 }
61 }
62 return dcd_tree;
63 }
64
DestroyDecodeTree(DecodeTree * p_dcd_tree)65 void DecodeTree::DestroyDecodeTree(DecodeTree *p_dcd_tree)
66 {
67 std::list<DecodeTree *>::iterator it;
68 bool bDestroyed = false;
69 it = s_trace_dcd_trees.begin();
70 while(!bDestroyed && (it != s_trace_dcd_trees.end()))
71 {
72 if(*it == p_dcd_tree)
73 {
74 s_trace_dcd_trees.erase(it);
75 delete p_dcd_tree;
76 bDestroyed = true;
77 }
78 else
79 it++;
80 }
81 }
82
setAlternateErrorLogger(ITraceErrorLog * p_error_logger)83 void DecodeTree::setAlternateErrorLogger(ITraceErrorLog *p_error_logger)
84 {
85 if(p_error_logger)
86 s_i_error_logger = p_error_logger;
87 else
88 s_i_error_logger = &s_error_logger;
89 }
90
91 /***************************************************************/
92
DecodeTree()93 DecodeTree::DecodeTree() :
94 m_i_instr_decode(&s_instruction_decoder),
95 m_i_mem_access(0),
96 m_i_gen_elem_out(0),
97 m_i_decoder_root(0),
98 m_frame_deformatter_root(0),
99 m_decode_elem_iter(0),
100 m_default_mapper(0),
101 m_created_mapper(false)
102 {
103 for(int i = 0; i < 0x80; i++)
104 m_decode_elements[i] = 0;
105
106 // reset the global demux stats.
107 m_demux_stats.frame_bytes = 0;
108 m_demux_stats.no_id_bytes = 0;
109 m_demux_stats.valid_id_bytes = 0;
110 m_demux_stats.unknown_id_bytes = 0;
111 m_demux_stats.reserved_id_bytes = 0;
112 }
113
~DecodeTree()114 DecodeTree::~DecodeTree()
115 {
116 destroyMemAccMapper();
117 for(uint8_t i = 0; i < 0x80; i++)
118 {
119 destroyDecodeElement(i);
120 }
121 PktPrinterFact::destroyAllPrinters(m_printer_list);
122 delete m_frame_deformatter_root;
123 }
124
125
126
TraceDataIn(const ocsd_datapath_op_t op,const ocsd_trc_index_t index,const uint32_t dataBlockSize,const uint8_t * pDataBlock,uint32_t * numBytesProcessed)127 ocsd_datapath_resp_t DecodeTree::TraceDataIn( const ocsd_datapath_op_t op,
128 const ocsd_trc_index_t index,
129 const uint32_t dataBlockSize,
130 const uint8_t *pDataBlock,
131 uint32_t *numBytesProcessed)
132 {
133 if(m_i_decoder_root)
134 return m_i_decoder_root->TraceDataIn(op,index,dataBlockSize,pDataBlock,numBytesProcessed);
135 *numBytesProcessed = 0;
136 return OCSD_RESP_FATAL_NOT_INIT;
137 }
138
139 /* set key interfaces - attach / replace on any existing tree components */
setInstrDecoder(IInstrDecode * i_instr_decode)140 void DecodeTree::setInstrDecoder(IInstrDecode *i_instr_decode)
141 {
142 uint8_t elemID;
143 DecodeTreeElement *pElem = 0;
144
145 pElem = getFirstElement(elemID);
146 while(pElem != 0)
147 {
148 pElem->getDecoderMngr()->attachInstrDecoder(pElem->getDecoderHandle(),i_instr_decode);
149 pElem = getNextElement(elemID);
150 }
151 }
152
setMemAccessI(ITargetMemAccess * i_mem_access)153 void DecodeTree::setMemAccessI(ITargetMemAccess *i_mem_access)
154 {
155 uint8_t elemID;
156 DecodeTreeElement *pElem = 0;
157
158 pElem = getFirstElement(elemID);
159 while(pElem != 0)
160 {
161 pElem->getDecoderMngr()->attachMemAccessor(pElem->getDecoderHandle(),i_mem_access);
162 pElem = getNextElement(elemID);
163 }
164 m_i_mem_access = i_mem_access;
165 }
166
setGenTraceElemOutI(ITrcGenElemIn * i_gen_trace_elem)167 void DecodeTree::setGenTraceElemOutI(ITrcGenElemIn *i_gen_trace_elem)
168 {
169 uint8_t elemID;
170 DecodeTreeElement *pElem = 0;
171
172 pElem = getFirstElement(elemID);
173 while(pElem != 0)
174 {
175 pElem->getDecoderMngr()->attachOutputSink(pElem->getDecoderHandle(),i_gen_trace_elem);
176 pElem = getNextElement(elemID);
177 }
178 /* set local copy of interface to return in getGenTraceElemOutI */
179 m_i_gen_elem_out = i_gen_trace_elem;
180 }
181
createMemAccMapper(memacc_mapper_t type)182 ocsd_err_t DecodeTree::createMemAccMapper(memacc_mapper_t type /* = MEMACC_MAP_GLOBAL*/ )
183 {
184 // clean up any old one
185 destroyMemAccMapper();
186
187 // make a new one
188 switch(type)
189 {
190 default:
191 case MEMACC_MAP_GLOBAL:
192 m_default_mapper = new (std::nothrow) TrcMemAccMapGlobalSpace();
193 break;
194 }
195
196 // set the access interface
197 if(m_default_mapper)
198 {
199 bool enableCaching;
200 int cachePageSize, cachePageNum;
201
202
203 m_created_mapper = true;
204 setMemAccessI(m_default_mapper);
205 m_default_mapper->setErrorLog(s_i_error_logger);
206 TrcMemAccCache::getenvMemaccCacheSizes(enableCaching, cachePageSize, cachePageNum);
207 if ((m_default_mapper->setCacheSizes(cachePageSize, cachePageNum) != OCSD_OK) ||
208 (m_default_mapper->enableCaching(enableCaching) != OCSD_OK))
209 destroyMemAccMapper();
210 }
211
212 return (m_default_mapper != 0) ? OCSD_OK : OCSD_ERR_MEM;
213 }
214
setExternMemAccMapper(TrcMemAccMapper * pMapper)215 void DecodeTree::setExternMemAccMapper(TrcMemAccMapper* pMapper)
216 {
217 destroyMemAccMapper(); // destroy any existing mapper - if decode tree created it.
218 m_default_mapper = pMapper;
219 }
220
destroyMemAccMapper()221 void DecodeTree::destroyMemAccMapper()
222 {
223 if(m_default_mapper && m_created_mapper)
224 {
225 m_default_mapper->RemoveAllAccessors();
226 delete m_default_mapper;
227 m_default_mapper = 0;
228 m_created_mapper = false;
229 }
230 }
231
logMappedRanges()232 void DecodeTree::logMappedRanges()
233 {
234 if(m_default_mapper)
235 m_default_mapper->logMappedRanges();
236 }
237
setMemAccCacheing(const bool enable,const uint16_t page_size,const int nr_pages)238 ocsd_err_t DecodeTree::setMemAccCacheing(const bool enable, const uint16_t page_size, const int nr_pages)
239 {
240 ocsd_err_t err = OCSD_OK;
241
242 if (!m_default_mapper)
243 return OCSD_ERR_NOT_INIT;
244
245 if (enable)
246 {
247 // set cache sizes - error if params out of limits
248 err = m_default_mapper->setCacheSizes(page_size, nr_pages, true);
249 if (err == OCSD_OK)
250 err = m_default_mapper->enableCaching(true);
251 }
252 else
253 err = m_default_mapper->enableCaching(false);
254 return err;
255 }
256
257 /* Memory accessor creation - all on default mem accessor using the 0 CSID for global core space. */
addBufferMemAcc(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const uint8_t * p_mem_buffer,const uint32_t mem_length)258 ocsd_err_t DecodeTree::addBufferMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t *p_mem_buffer, const uint32_t mem_length)
259 {
260 if(!hasMemAccMapper())
261 return OCSD_ERR_NOT_INIT;
262
263 // need a valid memory buffer, and a least enough bytes for one opcode.
264 if((p_mem_buffer == 0) || (mem_length < 4))
265 return OCSD_ERR_INVALID_PARAM_VAL;
266
267 TrcMemAccessorBase *p_accessor;
268 ocsd_err_t err = TrcMemAccFactory::CreateBufferAccessor(&p_accessor, address, p_mem_buffer, mem_length);
269 if(err == OCSD_OK)
270 {
271 TrcMemAccBufPtr *pMBuffAcc = dynamic_cast<TrcMemAccBufPtr *>(p_accessor);
272 if(pMBuffAcc)
273 {
274 pMBuffAcc->setMemSpace(mem_space);
275 err = m_default_mapper->AddAccessor(p_accessor,0);
276 }
277 else
278 err = OCSD_ERR_MEM; // wrong type of object - treat as mem error
279
280 if(err != OCSD_OK)
281 TrcMemAccFactory::DestroyAccessor(p_accessor);
282 }
283 return err;
284 }
285
addBinFileMemAcc(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const std::string & filepath)286 ocsd_err_t DecodeTree::addBinFileMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const std::string &filepath)
287 {
288 if(!hasMemAccMapper())
289 return OCSD_ERR_NOT_INIT;
290
291 if(filepath.length() == 0)
292 return OCSD_ERR_INVALID_PARAM_VAL;
293
294 TrcMemAccessorBase *p_accessor;
295 ocsd_err_t err = TrcMemAccFactory::CreateFileAccessor(&p_accessor,filepath,address);
296
297 if(err == OCSD_OK)
298 {
299 TrcMemAccessorFile *pAcc = dynamic_cast<TrcMemAccessorFile *>(p_accessor);
300 if(pAcc)
301 {
302 pAcc->setMemSpace(mem_space);
303 err = m_default_mapper->AddAccessor(pAcc,0);
304 }
305 else
306 err = OCSD_ERR_MEM; // wrong type of object - treat as mem error
307
308 if(err != OCSD_OK)
309 TrcMemAccFactory::DestroyAccessor(p_accessor);
310 }
311 return err;
312
313 }
314
addBinFileRegionMemAcc(const ocsd_file_mem_region_t * region_array,const int num_regions,const ocsd_mem_space_acc_t mem_space,const std::string & filepath)315 ocsd_err_t DecodeTree::addBinFileRegionMemAcc(const ocsd_file_mem_region_t *region_array, const int num_regions, const ocsd_mem_space_acc_t mem_space, const std::string &filepath)
316 {
317 if(!hasMemAccMapper())
318 return OCSD_ERR_NOT_INIT;
319
320 if((region_array == 0) || (num_regions == 0) || (filepath.length() == 0))
321 return OCSD_ERR_INVALID_PARAM_VAL;
322
323 TrcMemAccessorBase *p_accessor;
324 int curr_region_idx = 0;
325
326 // add first region during the creation of the file accessor.
327 ocsd_err_t err = TrcMemAccFactory::CreateFileAccessor(&p_accessor,filepath,region_array[curr_region_idx].start_address,region_array[curr_region_idx].file_offset, region_array[curr_region_idx].region_size);
328 if(err == OCSD_OK)
329 {
330 TrcMemAccessorFile *pAcc = dynamic_cast<TrcMemAccessorFile *>(p_accessor);
331 if(pAcc)
332 {
333 // add additional regions to the file accessor.
334 curr_region_idx++;
335 while(curr_region_idx < num_regions)
336 {
337 pAcc->AddOffsetRange(region_array[curr_region_idx].start_address,
338 region_array[curr_region_idx].region_size,
339 region_array[curr_region_idx].file_offset);
340 curr_region_idx++;
341 }
342 pAcc->setMemSpace(mem_space);
343
344 // add the accessor to the map.
345 err = m_default_mapper->AddAccessor(pAcc,0);
346 }
347 else
348 err = OCSD_ERR_MEM; // wrong type of object - treat as mem error
349
350 if(err != OCSD_OK)
351 TrcMemAccFactory::DestroyAccessor(p_accessor);
352 }
353 return err;
354 }
355
updateBinFileRegionMemAcc(const ocsd_file_mem_region_t * region_array,const int num_regions,const ocsd_mem_space_acc_t mem_space,const std::string & filepath)356 ocsd_err_t DecodeTree::updateBinFileRegionMemAcc(const ocsd_file_mem_region_t *region_array, const int num_regions, const ocsd_mem_space_acc_t mem_space, const std::string &filepath)
357 {
358 if (!hasMemAccMapper())
359 return OCSD_ERR_NOT_INIT;
360
361 if ((region_array == 0) || (num_regions == 0) || (filepath.length() == 0))
362 return OCSD_ERR_INVALID_PARAM_VAL;
363
364 TrcMemAccessorFile *pAcc = TrcMemAccessorFile::getExistingFileAccessor(filepath);
365 if (!pAcc)
366 return OCSD_ERR_INVALID_PARAM_VAL;
367
368 int curr_region_idx = 0;
369 while (curr_region_idx < num_regions)
370 {
371 // check "new" range
372 if (!pAcc->addrStartOfRange(region_array[curr_region_idx].start_address))
373 {
374 // ensure adds cleanly
375 if (!pAcc->AddOffsetRange(region_array[curr_region_idx].start_address,
376 region_array[curr_region_idx].region_size,
377 region_array[curr_region_idx].file_offset))
378 return OCSD_ERR_INVALID_PARAM_VAL; // otherwise bail out
379 }
380 curr_region_idx++;
381 }
382 return OCSD_OK;
383 }
initCallbackMemAcc(const ocsd_vaddr_t st_address,const ocsd_vaddr_t en_address,const ocsd_mem_space_acc_t mem_space,void * p_cb_func,bool IDfn,const void * p_context)384 ocsd_err_t DecodeTree::initCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address,
385 const ocsd_mem_space_acc_t mem_space, void *p_cb_func, bool IDfn, const void *p_context)
386 {
387 if(!hasMemAccMapper())
388 return OCSD_ERR_NOT_INIT;
389
390 if(p_cb_func == 0)
391 return OCSD_ERR_INVALID_PARAM_VAL;
392
393 TrcMemAccessorBase *p_accessor;
394 ocsd_err_t err = TrcMemAccFactory::CreateCBAccessor(&p_accessor, st_address, en_address, mem_space);
395 if(err == OCSD_OK)
396 {
397 TrcMemAccCB *pCBAcc = dynamic_cast<TrcMemAccCB *>(p_accessor);
398 if(pCBAcc)
399 {
400 if (IDfn)
401 pCBAcc->setCBIDIfFn((Fn_MemAccID_CB)p_cb_func, p_context);
402 else
403 pCBAcc->setCBIfFn((Fn_MemAcc_CB)p_cb_func, p_context);
404
405 err = m_default_mapper->AddAccessor(p_accessor,0);
406 }
407 else
408 err = OCSD_ERR_MEM; // wrong type of object - treat as mem error
409
410 if(err != OCSD_OK)
411 TrcMemAccFactory::DestroyAccessor(p_accessor);
412 }
413 return err;
414 }
415
addCallbackMemAcc(const ocsd_vaddr_t st_address,const ocsd_vaddr_t en_address,const ocsd_mem_space_acc_t mem_space,Fn_MemAcc_CB p_cb_func,const void * p_context)416 ocsd_err_t DecodeTree::addCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, Fn_MemAcc_CB p_cb_func, const void *p_context)
417 {
418 return initCallbackMemAcc(st_address, en_address, mem_space, (void *)p_cb_func, false, p_context);
419 }
420
addCallbackIDMemAcc(const ocsd_vaddr_t st_address,const ocsd_vaddr_t en_address,const ocsd_mem_space_acc_t mem_space,Fn_MemAccID_CB p_cb_func,const void * p_context)421 ocsd_err_t DecodeTree::addCallbackIDMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, Fn_MemAccID_CB p_cb_func, const void *p_context)
422 {
423 return initCallbackMemAcc(st_address, en_address, mem_space, (void *)p_cb_func, true, p_context);
424 }
425
removeMemAccByAddress(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space)426 ocsd_err_t DecodeTree::removeMemAccByAddress(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space)
427 {
428 if(!hasMemAccMapper())
429 return OCSD_ERR_NOT_INIT;
430 return m_default_mapper->RemoveAccessorByAddress(address,mem_space,0);
431 }
432
createDecoder(const std::string & decoderName,const int createFlags,const CSConfig * pConfig)433 ocsd_err_t DecodeTree::createDecoder(const std::string &decoderName, const int createFlags, const CSConfig *pConfig)
434 {
435 ocsd_err_t err = OCSD_OK;
436 IDecoderMngr *pDecoderMngr = 0;
437 TraceComponent *pTraceComp = 0;
438 int crtFlags = createFlags;
439
440 uint8_t CSID = 0; // default for single stream decoder (no deformatter) - we ignore the ID
441 if(usingFormatter())
442 {
443 CSID = pConfig->getTraceID();
444 crtFlags |= OCSD_CREATE_FLG_INST_ID;
445 }
446
447 // check for the aa64 check.
448 if (createFlags & ETM4_OPFLG_PKTDEC_AA64_OPCODE_CHK)
449 s_instruction_decoder.setAA64_errOnBadOpcode(true);
450
451 // create the decode element to attach to the channel.
452 if((err = createDecodeElement(CSID)) != OCSD_OK)
453 return err;
454
455 // get the libary decoder register.
456 OcsdLibDcdRegister * lib_reg = OcsdLibDcdRegister::getDecoderRegister();
457 if(lib_reg == 0)
458 return OCSD_ERR_NOT_INIT;
459
460 // find the named decoder
461 if((err = lib_reg->getDecoderMngrByName(decoderName,&pDecoderMngr)) != OCSD_OK)
462 return err;
463
464 // got the decoder...
465 if((err = pDecoderMngr->createDecoder(crtFlags,(int)CSID,pConfig,&pTraceComp)) != OCSD_OK)
466 return err;
467
468 m_decode_elements[CSID]->SetDecoderElement(decoderName, pDecoderMngr, pTraceComp, true);
469
470 // always attach an error logger
471 if(err == OCSD_OK)
472 err = pDecoderMngr->attachErrorLogger(pTraceComp,DecodeTree::s_i_error_logger);
473
474 // if we created a packet decoder it may need additional components.
475 if(crtFlags & OCSD_CREATE_FLG_FULL_DECODER)
476 {
477 if(m_i_instr_decode && (err == OCSD_OK))
478 err = pDecoderMngr->attachInstrDecoder(pTraceComp,m_i_instr_decode);
479
480 if(err == OCSD_ERR_DCD_INTERFACE_UNUSED) // ignore if instruction decoder refused
481 err = OCSD_OK;
482
483 if(m_i_mem_access && (err == OCSD_OK))
484 err = pDecoderMngr->attachMemAccessor(pTraceComp,m_i_mem_access);
485
486 if(err == OCSD_ERR_DCD_INTERFACE_UNUSED) // ignore if mem accessor refused
487 err = OCSD_OK;
488
489 if( m_i_gen_elem_out && (err == OCSD_OK))
490 err = pDecoderMngr->attachOutputSink(pTraceComp,m_i_gen_elem_out);
491 }
492
493 // finally attach the packet processor input to the demux output channel
494 if(err == OCSD_OK)
495 {
496 ITrcDataIn *pDataIn = 0;
497 if((err = pDecoderMngr->getDataInputI(pTraceComp,&pDataIn)) == OCSD_OK)
498 {
499 // got the interface -> attach to demux, or direct to input of decode tree
500 if(usingFormatter())
501 err = m_frame_deformatter_root->getIDStreamAttachPt(CSID)->attach(pDataIn);
502 else
503 m_i_decoder_root = pDataIn;
504 }
505 }
506
507 if(err != OCSD_OK)
508 {
509 destroyDecodeElement(CSID); // will destroy decoder as well.
510 }
511 return err;
512 }
513
removeDecoder(const uint8_t CSID)514 ocsd_err_t DecodeTree::removeDecoder(const uint8_t CSID)
515 {
516 ocsd_err_t err = OCSD_OK;
517 uint8_t localID = CSID;
518 if(!usingFormatter())
519 localID = 0;
520
521 if(usingFormatter() && !OCSD_IS_VALID_CS_SRC_ID(CSID))
522 err = OCSD_ERR_INVALID_ID;
523 else
524 {
525 destroyDecodeElement(localID);
526 }
527 return err;
528 }
529
getDecoderStats(const uint8_t CSID,ocsd_decode_stats_t ** p_stats_block)530 ocsd_err_t DecodeTree::getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block)
531 {
532 ocsd_err_t err = OCSD_OK;
533 TrcPktProcI *pPktProc = getPktProcI(CSID);
534 if (!pPktProc)
535 return OCSD_ERR_INVALID_PARAM_VAL;
536 err = pPktProc->getStatsBlock(p_stats_block);
537 if (err == OCSD_OK) {
538 // copy in the global demux stats.
539 (*p_stats_block)->demux.frame_bytes = m_demux_stats.frame_bytes;
540 (*p_stats_block)->demux.no_id_bytes = m_demux_stats.no_id_bytes;
541 (*p_stats_block)->demux.valid_id_bytes = m_demux_stats.valid_id_bytes;
542 (*p_stats_block)->demux.unknown_id_bytes = m_demux_stats.unknown_id_bytes;
543 (*p_stats_block)->demux.reserved_id_bytes = m_demux_stats.reserved_id_bytes;
544 }
545 return err;
546 }
547
resetDecoderStats(const uint8_t CSID)548 ocsd_err_t DecodeTree::resetDecoderStats(const uint8_t CSID)
549 {
550 TrcPktProcI *pPktProc = getPktProcI(CSID);
551 if (!pPktProc)
552 return OCSD_ERR_INVALID_PARAM_VAL;
553 pPktProc->resetStats();
554
555 // reset the global demux stats.
556 m_demux_stats.frame_bytes = 0;
557 m_demux_stats.no_id_bytes = 0;
558 m_demux_stats.valid_id_bytes = 0;
559 m_demux_stats.unknown_id_bytes = 0;
560 m_demux_stats.reserved_id_bytes = 0;
561 return OCSD_OK;
562 }
563
getPktProcI(const uint8_t CSID)564 TrcPktProcI *DecodeTree::getPktProcI(const uint8_t CSID)
565 {
566 TrcPktProcI *pPktProc = 0;
567 TraceComponent *pComp, *pAssoc;
568 DecodeTreeElement *pElem = getDecoderElement(CSID);
569
570 if (pElem)
571 {
572 pComp = pElem->getDecoderHandle();
573 if (pComp)
574 {
575 /* if this is a full decoder then the associated component is the packet processor */
576 pAssoc = pComp->getAssocComponent();
577 if (pAssoc)
578 pPktProc = dynamic_cast<TrcPktProcI *>(pAssoc);
579 else
580 pPktProc = dynamic_cast<TrcPktProcI *>(pComp);
581 }
582 }
583 return pPktProc;
584 }
585
getDecoderElement(const uint8_t CSID) const586 DecodeTreeElement * DecodeTree::getDecoderElement(const uint8_t CSID) const
587 {
588 DecodeTreeElement *ret_elem = 0;
589 if(usingFormatter() && OCSD_IS_VALID_CS_SRC_ID(CSID))
590 {
591 ret_elem = m_decode_elements[CSID];
592 }
593 else
594 ret_elem = m_decode_elements[0]; // ID 0 is used if single leaf tree.
595 return ret_elem;
596 }
597
getFirstElement(uint8_t & elemID)598 DecodeTreeElement *DecodeTree::getFirstElement(uint8_t &elemID)
599 {
600 m_decode_elem_iter = 0;
601 return getNextElement(elemID);
602 }
603
getNextElement(uint8_t & elemID)604 DecodeTreeElement *DecodeTree::getNextElement(uint8_t &elemID)
605 {
606 DecodeTreeElement *ret_elem = 0;
607
608 if(m_decode_elem_iter < 0x80)
609 {
610 // find a none zero entry or end of range
611 while((m_decode_elem_iter < 0x80) && (m_decode_elements[m_decode_elem_iter] == 0))
612 m_decode_elem_iter++;
613
614 // return entry unless end of range
615 if(m_decode_elem_iter < 0x80)
616 {
617 ret_elem = m_decode_elements[m_decode_elem_iter];
618 elemID = m_decode_elem_iter;
619 m_decode_elem_iter++;
620 }
621 }
622 return ret_elem;
623 }
624
initialise(const ocsd_dcd_tree_src_t type,uint32_t formatterCfgFlags)625 bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCfgFlags)
626 {
627 ocsd_err_t err;
628 m_dcd_tree_type = type;
629 if(type == OCSD_TRC_SRC_FRAME_FORMATTED)
630 {
631 // frame formatted - we want to create the deformatter and hook it up
632 m_frame_deformatter_root = new (std::nothrow) TraceFormatterFrameDecoder();
633 if(m_frame_deformatter_root)
634 {
635 if (m_frame_deformatter_root->Init() != OCSD_OK)
636 return false;
637 m_frame_deformatter_root->getErrLogAttachPt()->attach(DecodeTree::s_i_error_logger);
638 err = m_frame_deformatter_root->Configure(formatterCfgFlags);
639 if (err != OCSD_OK)
640 return false;
641 m_i_decoder_root = dynamic_cast<ITrcDataIn*>(m_frame_deformatter_root);
642 m_frame_deformatter_root->SetDemuxStatsBlock(&m_demux_stats);
643 }
644 else
645 return false;
646 }
647 return true;
648 }
649
setSingleRoot(TrcPktProcI * pComp)650 void DecodeTree::setSingleRoot(TrcPktProcI *pComp)
651 {
652 m_i_decoder_root = static_cast<ITrcDataIn*>(pComp);
653 }
654
createDecodeElement(const uint8_t CSID)655 ocsd_err_t DecodeTree::createDecodeElement(const uint8_t CSID)
656 {
657 ocsd_err_t err = OCSD_ERR_INVALID_ID;
658 if(CSID < 0x80)
659 {
660 if(m_decode_elements[CSID] == 0)
661 {
662 m_decode_elements[CSID] = new (std::nothrow) DecodeTreeElement();
663 if(m_decode_elements[CSID] == 0)
664 err = OCSD_ERR_MEM;
665 else
666 err = OCSD_OK;
667 }
668 else
669 err = OCSD_ERR_ATTACH_TOO_MANY;
670 }
671 return err;
672 }
673
destroyDecodeElement(const uint8_t CSID)674 void DecodeTree::destroyDecodeElement(const uint8_t CSID)
675 {
676 if(CSID < 0x80)
677 {
678 if(m_decode_elements[CSID] != 0)
679 {
680 m_decode_elements[CSID]->DestroyElem();
681 delete m_decode_elements[CSID];
682 m_decode_elements[CSID] = 0;
683 }
684 }
685 }
686
setIDFilter(std::vector<uint8_t> & ids)687 ocsd_err_t DecodeTree::setIDFilter(std::vector<uint8_t> &ids)
688 {
689 ocsd_err_t err = OCSD_ERR_DCDT_NO_FORMATTER;
690 if(usingFormatter())
691 {
692 err = m_frame_deformatter_root->OutputFilterAllIDs(false);
693 if(err == OCSD_OK)
694 err = m_frame_deformatter_root->OutputFilterIDs(ids,true);
695 }
696 return err;
697 }
698
clearIDFilter()699 ocsd_err_t DecodeTree::clearIDFilter()
700 {
701 ocsd_err_t err = OCSD_ERR_DCDT_NO_FORMATTER;
702 if(usingFormatter())
703 {
704 err = m_frame_deformatter_root->OutputFilterAllIDs(true);
705 }
706 return err;
707 }
708
709 /** add a protocol packet printer */
addPacketPrinter(uint8_t CSID,bool bMonitor,ItemPrinter ** ppPrinter)710 ocsd_err_t DecodeTree::addPacketPrinter(uint8_t CSID, bool bMonitor, ItemPrinter **ppPrinter)
711 {
712 ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL;
713 DecodeTreeElement *pElement = getDecoderElement(CSID);
714 if (pElement)
715 {
716 ocsd_trace_protocol_t protocol = pElement->getProtocol();
717 ItemPrinter *pPrinter;
718
719 pPrinter = PktPrinterFact::createProtocolPrinter(getPrinterList(), protocol, CSID);
720 if (pPrinter)
721 {
722 pPrinter->setMessageLogger(getCurrentErrorLogI()->getOutputLogger());
723 switch (protocol)
724 {
725 case OCSD_PROTOCOL_ETMV4I:
726 case OCSD_PROTOCOL_ETE:
727 {
728 PacketPrinter<EtmV4ITrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<EtmV4ITrcPacket> *>(pPrinter);
729 if (bMonitor)
730 err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<EtmV4ITrcPacket> *)pTPrinter);
731 else
732 err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<EtmV4ITrcPacket> *)pTPrinter);
733 }
734 break;
735
736 case OCSD_PROTOCOL_ETMV3:
737 {
738 PacketPrinter<EtmV3TrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<EtmV3TrcPacket> *>(pPrinter);
739 if (bMonitor)
740 err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<EtmV3TrcPacket> *)pTPrinter);
741 else
742 err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<EtmV3TrcPacket> *)pTPrinter);
743 }
744 break;
745
746 case OCSD_PROTOCOL_PTM:
747 {
748 PacketPrinter<PtmTrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<PtmTrcPacket> *>(pPrinter);
749 if (bMonitor)
750 err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<PtmTrcPacket> *)pTPrinter);
751 else
752 err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<PtmTrcPacket> *)pTPrinter);
753 }
754 break;
755
756 case OCSD_PROTOCOL_STM:
757 {
758 PacketPrinter<StmTrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<StmTrcPacket> *>(pPrinter);
759 if (bMonitor)
760 err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<StmTrcPacket> *)pTPrinter);
761 else
762 err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<StmTrcPacket> *)pTPrinter);
763 }
764 break;
765
766 default:
767 err = OCSD_ERR_NO_PROTOCOL;
768 break;
769 }
770
771 if (err == OCSD_OK)
772 {
773 if (ppPrinter)
774 *ppPrinter = pPrinter;
775 }
776 else
777 PktPrinterFact::destroyPrinter(getPrinterList(), pPrinter);
778 }
779 }
780 return err;
781 }
782
783 /** add a raw frame printer */
addRawFramePrinter(RawFramePrinter ** ppPrinter,uint32_t flags)784 ocsd_err_t DecodeTree::addRawFramePrinter(RawFramePrinter **ppPrinter, uint32_t flags)
785 {
786 ocsd_err_t err = OCSD_ERR_MEM;
787 RawFramePrinter *pPrinter = PktPrinterFact::createRawFramePrinter(getPrinterList());
788 if (pPrinter)
789 {
790 pPrinter->setMessageLogger((DecodeTree::getCurrentErrorLogI()->getOutputLogger()));
791 TraceFormatterFrameDecoder *pFrameDecoder = getFrameDeformatter();
792 uint32_t cfgFlags = pFrameDecoder->getConfigFlags();
793 cfgFlags |= ((uint32_t)flags & (OCSD_DFRMTR_PACKED_RAW_OUT | OCSD_DFRMTR_UNPACKED_RAW_OUT));
794 pFrameDecoder->Configure(cfgFlags);
795 err = pFrameDecoder->getTrcRawFrameAttachPt()->attach(pPrinter);
796 if (ppPrinter && (err==OCSD_OK))
797 *ppPrinter = pPrinter;
798 }
799 return err;
800 }
801
802 /** add a generic element output printer */
addGenElemPrinter(TrcGenericElementPrinter ** ppPrinter)803 ocsd_err_t DecodeTree::addGenElemPrinter(TrcGenericElementPrinter **ppPrinter)
804 {
805 ocsd_err_t err = OCSD_ERR_MEM;
806 TrcGenericElementPrinter *pPrinter = PktPrinterFact::createGenElemPrinter(getPrinterList());
807 if (pPrinter)
808 {
809 pPrinter->setMessageLogger((DecodeTree::getCurrentErrorLogI()->getOutputLogger()));
810 setGenTraceElemOutI(pPrinter);
811 err = OCSD_OK;
812 if (ppPrinter)
813 *ppPrinter = pPrinter;
814 }
815 return err;
816
817 }
818
819 /* End of File ocsd_dcd_tree.cpp */
820