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 destroyMemAccessors();
117 destroyMemAccMapper();
118 for(uint8_t i = 0; i < 0x80; i++)
119 {
120 destroyDecodeElement(i);
121 }
122 PktPrinterFact::destroyAllPrinters(m_printer_list);
123 delete m_frame_deformatter_root;
124 }
125
126
127
TraceDataIn(const ocsd_datapath_op_t op,const ocsd_trc_index_t index,const uint32_t dataBlockSize,const uint8_t * pDataBlock,uint32_t * numBytesProcessed)128 ocsd_datapath_resp_t DecodeTree::TraceDataIn( const ocsd_datapath_op_t op,
129 const ocsd_trc_index_t index,
130 const uint32_t dataBlockSize,
131 const uint8_t *pDataBlock,
132 uint32_t *numBytesProcessed)
133 {
134 if(m_i_decoder_root)
135 return m_i_decoder_root->TraceDataIn(op,index,dataBlockSize,pDataBlock,numBytesProcessed);
136 *numBytesProcessed = 0;
137 return OCSD_RESP_FATAL_NOT_INIT;
138 }
139
140 /* set key interfaces - attach / replace on any existing tree components */
setInstrDecoder(IInstrDecode * i_instr_decode)141 void DecodeTree::setInstrDecoder(IInstrDecode *i_instr_decode)
142 {
143 uint8_t elemID;
144 DecodeTreeElement *pElem = 0;
145
146 pElem = getFirstElement(elemID);
147 while(pElem != 0)
148 {
149 pElem->getDecoderMngr()->attachInstrDecoder(pElem->getDecoderHandle(),i_instr_decode);
150 pElem = getNextElement(elemID);
151 }
152 }
153
setMemAccessI(ITargetMemAccess * i_mem_access)154 void DecodeTree::setMemAccessI(ITargetMemAccess *i_mem_access)
155 {
156 uint8_t elemID;
157 DecodeTreeElement *pElem = 0;
158
159 pElem = getFirstElement(elemID);
160 while(pElem != 0)
161 {
162 pElem->getDecoderMngr()->attachMemAccessor(pElem->getDecoderHandle(),i_mem_access);
163 pElem = getNextElement(elemID);
164 }
165 m_i_mem_access = i_mem_access;
166 }
167
setGenTraceElemOutI(ITrcGenElemIn * i_gen_trace_elem)168 void DecodeTree::setGenTraceElemOutI(ITrcGenElemIn *i_gen_trace_elem)
169 {
170 uint8_t elemID;
171 DecodeTreeElement *pElem = 0;
172
173 pElem = getFirstElement(elemID);
174 while(pElem != 0)
175 {
176 pElem->getDecoderMngr()->attachOutputSink(pElem->getDecoderHandle(),i_gen_trace_elem);
177 pElem = getNextElement(elemID);
178 }
179 /* set local copy of interface to return in getGenTraceElemOutI */
180 m_i_gen_elem_out = i_gen_trace_elem;
181 }
182
createMemAccMapper(memacc_mapper_t type)183 ocsd_err_t DecodeTree::createMemAccMapper(memacc_mapper_t type /* = MEMACC_MAP_GLOBAL*/ )
184 {
185 // clean up any old one
186 destroyMemAccMapper();
187
188 // make a new one
189 switch(type)
190 {
191 default:
192 case MEMACC_MAP_GLOBAL:
193 m_default_mapper = new (std::nothrow) TrcMemAccMapGlobalSpace();
194 break;
195 }
196
197 // set the access interface
198 if(m_default_mapper)
199 {
200 bool enableCaching;
201 int cachePageSize, cachePageNum;
202
203
204 m_created_mapper = true;
205 setMemAccessI(m_default_mapper);
206 m_default_mapper->setErrorLog(s_i_error_logger);
207 TrcMemAccCache::getenvMemaccCacheSizes(enableCaching, cachePageSize, cachePageNum);
208 if ((m_default_mapper->setCacheSizes(cachePageSize, cachePageNum) != OCSD_OK) ||
209 (m_default_mapper->enableCaching(enableCaching) != OCSD_OK))
210 destroyMemAccMapper();
211 }
212
213 return (m_default_mapper != 0) ? OCSD_OK : OCSD_ERR_MEM;
214 }
215
setExternMemAccMapper(TrcMemAccMapper * pMapper)216 void DecodeTree::setExternMemAccMapper(TrcMemAccMapper* pMapper)
217 {
218 destroyMemAccMapper(); // destroy any existing mapper - if decode tree created it.
219 m_default_mapper = pMapper;
220 }
221
destroyMemAccMapper()222 void DecodeTree::destroyMemAccMapper()
223 {
224 if(m_default_mapper && m_created_mapper)
225 {
226 m_default_mapper->RemoveAllAccessors();
227 delete m_default_mapper;
228 m_default_mapper = 0;
229 m_created_mapper = false;
230 }
231 }
232
addMemAccessorToList(TrcMemAccessorBase * p_accessor)233 void DecodeTree::addMemAccessorToList(TrcMemAccessorBase* p_accessor)
234 {
235 m_mem_accessors.push_back(p_accessor);
236 }
237
238 // destroy mem accessors in use by this object
destroyMemAccessors()239 void DecodeTree::destroyMemAccessors()
240 {
241 std::list<TrcMemAccessorBase*>::iterator it;
242
243 it = m_mem_accessors.begin();
244 while (it != m_mem_accessors.end())
245 {
246 TrcMemAccFactory::DestroyAccessor(*it);
247 it++;
248 }
249 m_mem_accessors.clear();
250 }
251
logMappedRanges()252 void DecodeTree::logMappedRanges()
253 {
254 if(m_default_mapper)
255 m_default_mapper->logMappedRanges();
256 }
257
setMemAccCacheing(const bool enable,const uint16_t page_size,const int nr_pages)258 ocsd_err_t DecodeTree::setMemAccCacheing(const bool enable, const uint16_t page_size, const int nr_pages)
259 {
260 ocsd_err_t err = OCSD_OK;
261
262 if (!m_default_mapper)
263 return OCSD_ERR_NOT_INIT;
264
265 if (enable)
266 {
267 // set cache sizes - error if params out of limits
268 err = m_default_mapper->setCacheSizes(page_size, nr_pages, true);
269 if (err == OCSD_OK)
270 err = m_default_mapper->enableCaching(true);
271 }
272 else
273 err = m_default_mapper->enableCaching(false);
274 return err;
275 }
276
277 /* 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)278 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)
279 {
280 if(!hasMemAccMapper())
281 return OCSD_ERR_NOT_INIT;
282
283 // need a valid memory buffer, and a least enough bytes for one opcode.
284 if((p_mem_buffer == 0) || (mem_length < 4))
285 return OCSD_ERR_INVALID_PARAM_VAL;
286
287 TrcMemAccessorBase *p_accessor;
288 ocsd_err_t err = TrcMemAccFactory::CreateBufferAccessor(&p_accessor, address, p_mem_buffer, mem_length);
289 if(err == OCSD_OK)
290 {
291 TrcMemAccBufPtr *pMBuffAcc = dynamic_cast<TrcMemAccBufPtr *>(p_accessor);
292 if(pMBuffAcc)
293 {
294 pMBuffAcc->setMemSpace(mem_space);
295 err = m_default_mapper->AddAccessor(p_accessor,0);
296 }
297 else
298 err = OCSD_ERR_MEM; // wrong type of object - treat as mem error
299
300 if (err != OCSD_OK)
301 TrcMemAccFactory::DestroyAccessor(p_accessor);
302 else
303 addMemAccessorToList(p_accessor);
304 }
305 return err;
306 }
307
addBinFileMemAcc(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const std::string & filepath)308 ocsd_err_t DecodeTree::addBinFileMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const std::string &filepath)
309 {
310 if(!hasMemAccMapper())
311 return OCSD_ERR_NOT_INIT;
312
313 if(filepath.length() == 0)
314 return OCSD_ERR_INVALID_PARAM_VAL;
315
316 TrcMemAccessorBase *p_accessor;
317 ocsd_err_t err = TrcMemAccFactory::CreateFileAccessor(&p_accessor,filepath,address);
318
319 if(err == OCSD_OK)
320 {
321 TrcMemAccessorFile *pAcc = dynamic_cast<TrcMemAccessorFile *>(p_accessor);
322 if(pAcc)
323 {
324 pAcc->setMemSpace(mem_space);
325 err = m_default_mapper->AddAccessor(pAcc,0);
326 }
327 else
328 err = OCSD_ERR_MEM; // wrong type of object - treat as mem error
329
330 if (err != OCSD_OK)
331 TrcMemAccFactory::DestroyAccessor(p_accessor);
332 else
333 addMemAccessorToList(p_accessor);
334 }
335 return err;
336
337 }
338
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)339 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)
340 {
341 if(!hasMemAccMapper())
342 return OCSD_ERR_NOT_INIT;
343
344 if((region_array == 0) || (num_regions == 0) || (filepath.length() == 0))
345 return OCSD_ERR_INVALID_PARAM_VAL;
346
347 TrcMemAccessorBase *p_accessor;
348 int curr_region_idx = 0;
349
350 // add first region during the creation of the file accessor.
351 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);
352 if(err == OCSD_OK)
353 {
354 TrcMemAccessorFile *pAcc = dynamic_cast<TrcMemAccessorFile *>(p_accessor);
355 if(pAcc)
356 {
357 // add additional regions to the file accessor.
358 curr_region_idx++;
359 while(curr_region_idx < num_regions)
360 {
361 pAcc->AddOffsetRange(region_array[curr_region_idx].start_address,
362 region_array[curr_region_idx].region_size,
363 region_array[curr_region_idx].file_offset);
364 curr_region_idx++;
365 }
366 pAcc->setMemSpace(mem_space);
367
368 // add the accessor to the map.
369 err = m_default_mapper->AddAccessor(pAcc,0);
370 }
371 else
372 err = OCSD_ERR_MEM; // wrong type of object - treat as mem error
373
374 if (err != OCSD_OK)
375 TrcMemAccFactory::DestroyAccessor(p_accessor);
376 else
377 addMemAccessorToList(p_accessor);
378 }
379 return err;
380 }
381
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)382 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)
383 {
384 if (!hasMemAccMapper())
385 return OCSD_ERR_NOT_INIT;
386
387 if ((region_array == 0) || (num_regions == 0) || (filepath.length() == 0))
388 return OCSD_ERR_INVALID_PARAM_VAL;
389
390 TrcMemAccessorFile *pAcc = TrcMemAccessorFile::getExistingFileAccessor(filepath);
391 if (!pAcc)
392 return OCSD_ERR_INVALID_PARAM_VAL;
393
394 int curr_region_idx = 0;
395 while (curr_region_idx < num_regions)
396 {
397 // check "new" range
398 if (!pAcc->addrStartOfRange(region_array[curr_region_idx].start_address))
399 {
400 // ensure adds cleanly
401 if (!pAcc->AddOffsetRange(region_array[curr_region_idx].start_address,
402 region_array[curr_region_idx].region_size,
403 region_array[curr_region_idx].file_offset))
404 return OCSD_ERR_INVALID_PARAM_VAL; // otherwise bail out
405 }
406 curr_region_idx++;
407 }
408 return OCSD_OK;
409 }
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)410 ocsd_err_t DecodeTree::initCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address,
411 const ocsd_mem_space_acc_t mem_space, void *p_cb_func, bool IDfn, const void *p_context)
412 {
413 if(!hasMemAccMapper())
414 return OCSD_ERR_NOT_INIT;
415
416 if(p_cb_func == 0)
417 return OCSD_ERR_INVALID_PARAM_VAL;
418
419 TrcMemAccessorBase *p_accessor;
420 ocsd_err_t err = TrcMemAccFactory::CreateCBAccessor(&p_accessor, st_address, en_address, mem_space);
421 if(err == OCSD_OK)
422 {
423 TrcMemAccCB *pCBAcc = dynamic_cast<TrcMemAccCB *>(p_accessor);
424 if(pCBAcc)
425 {
426 if (IDfn)
427 pCBAcc->setCBIDIfFn((Fn_MemAccID_CB)p_cb_func, p_context);
428 else
429 pCBAcc->setCBIfFn((Fn_MemAcc_CB)p_cb_func, p_context);
430
431 err = m_default_mapper->AddAccessor(p_accessor,0);
432 }
433 else
434 err = OCSD_ERR_MEM; // wrong type of object - treat as mem error
435
436 if (err != OCSD_OK)
437 TrcMemAccFactory::DestroyAccessor(p_accessor);
438 else
439 addMemAccessorToList(p_accessor);
440 }
441 return err;
442 }
443
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)444 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)
445 {
446 return initCallbackMemAcc(st_address, en_address, mem_space, (void *)p_cb_func, false, p_context);
447 }
448
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)449 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)
450 {
451 return initCallbackMemAcc(st_address, en_address, mem_space, (void *)p_cb_func, true, p_context);
452 }
453
removeMemAccByAddress(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space)454 ocsd_err_t DecodeTree::removeMemAccByAddress(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space)
455 {
456 if(!hasMemAccMapper())
457 return OCSD_ERR_NOT_INIT;
458 return m_default_mapper->RemoveAccessorByAddress(address,mem_space,0);
459 }
460
createDecoder(const std::string & decoderName,const int createFlags,const CSConfig * pConfig)461 ocsd_err_t DecodeTree::createDecoder(const std::string &decoderName, const int createFlags, const CSConfig *pConfig)
462 {
463 ocsd_err_t err = OCSD_OK;
464 IDecoderMngr *pDecoderMngr = 0;
465 TraceComponent *pTraceComp = 0;
466 int crtFlags = createFlags;
467
468 uint8_t CSID = 0; // default for single stream decoder (no deformatter) - we ignore the ID
469 if(usingFormatter())
470 {
471 CSID = pConfig->getTraceID();
472 crtFlags |= OCSD_CREATE_FLG_INST_ID;
473 }
474
475 // check for the aa64 check.
476 if (createFlags & ETM4_OPFLG_PKTDEC_AA64_OPCODE_CHK)
477 s_instruction_decoder.setAA64_errOnBadOpcode(true);
478
479 // create the decode element to attach to the channel.
480 if((err = createDecodeElement(CSID)) != OCSD_OK)
481 return err;
482
483 // get the libary decoder register.
484 OcsdLibDcdRegister * lib_reg = OcsdLibDcdRegister::getDecoderRegister();
485 if(lib_reg == 0)
486 return OCSD_ERR_NOT_INIT;
487
488 // find the named decoder
489 if((err = lib_reg->getDecoderMngrByName(decoderName,&pDecoderMngr)) != OCSD_OK)
490 return err;
491
492 // got the decoder...
493 if((err = pDecoderMngr->createDecoder(crtFlags,(int)CSID,pConfig,&pTraceComp)) != OCSD_OK)
494 return err;
495
496 m_decode_elements[CSID]->SetDecoderElement(decoderName, pDecoderMngr, pTraceComp, true);
497
498 // always attach an error logger
499 if(err == OCSD_OK)
500 err = pDecoderMngr->attachErrorLogger(pTraceComp,DecodeTree::s_i_error_logger);
501
502 // if we created a packet decoder it may need additional components.
503 if(crtFlags & OCSD_CREATE_FLG_FULL_DECODER)
504 {
505 if(m_i_instr_decode && (err == OCSD_OK))
506 err = pDecoderMngr->attachInstrDecoder(pTraceComp,m_i_instr_decode);
507
508 if(err == OCSD_ERR_DCD_INTERFACE_UNUSED) // ignore if instruction decoder refused
509 err = OCSD_OK;
510
511 if(m_i_mem_access && (err == OCSD_OK))
512 err = pDecoderMngr->attachMemAccessor(pTraceComp,m_i_mem_access);
513
514 if(err == OCSD_ERR_DCD_INTERFACE_UNUSED) // ignore if mem accessor refused
515 err = OCSD_OK;
516
517 if( m_i_gen_elem_out && (err == OCSD_OK))
518 err = pDecoderMngr->attachOutputSink(pTraceComp,m_i_gen_elem_out);
519 }
520
521 // finally attach the packet processor input to the demux output channel
522 if(err == OCSD_OK)
523 {
524 ITrcDataIn *pDataIn = 0;
525 if((err = pDecoderMngr->getDataInputI(pTraceComp,&pDataIn)) == OCSD_OK)
526 {
527 // got the interface -> attach to demux, or direct to input of decode tree
528 if(usingFormatter())
529 err = m_frame_deformatter_root->getIDStreamAttachPt(CSID)->attach(pDataIn);
530 else
531 m_i_decoder_root = pDataIn;
532 }
533 }
534
535 if(err != OCSD_OK)
536 {
537 destroyDecodeElement(CSID); // will destroy decoder as well.
538 }
539 return err;
540 }
541
removeDecoder(const uint8_t CSID)542 ocsd_err_t DecodeTree::removeDecoder(const uint8_t CSID)
543 {
544 ocsd_err_t err = OCSD_OK;
545 uint8_t localID = CSID;
546 if(!usingFormatter())
547 localID = 0;
548
549 if(usingFormatter() && !OCSD_IS_VALID_CS_SRC_ID(CSID))
550 err = OCSD_ERR_INVALID_ID;
551 else
552 {
553 destroyDecodeElement(localID);
554 }
555 return err;
556 }
557
getDecoderStats(const uint8_t CSID,ocsd_decode_stats_t ** p_stats_block)558 ocsd_err_t DecodeTree::getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block)
559 {
560 ocsd_err_t err = OCSD_OK;
561 TrcPktProcI *pPktProc = getPktProcI(CSID);
562 if (!pPktProc)
563 return OCSD_ERR_INVALID_PARAM_VAL;
564 err = pPktProc->getStatsBlock(p_stats_block);
565 if (err == OCSD_OK) {
566 // copy in the global demux stats.
567 (*p_stats_block)->demux.frame_bytes = m_demux_stats.frame_bytes;
568 (*p_stats_block)->demux.no_id_bytes = m_demux_stats.no_id_bytes;
569 (*p_stats_block)->demux.valid_id_bytes = m_demux_stats.valid_id_bytes;
570 (*p_stats_block)->demux.unknown_id_bytes = m_demux_stats.unknown_id_bytes;
571 (*p_stats_block)->demux.reserved_id_bytes = m_demux_stats.reserved_id_bytes;
572 }
573 return err;
574 }
575
resetDecoderStats(const uint8_t CSID)576 ocsd_err_t DecodeTree::resetDecoderStats(const uint8_t CSID)
577 {
578 TrcPktProcI *pPktProc = getPktProcI(CSID);
579 if (!pPktProc)
580 return OCSD_ERR_INVALID_PARAM_VAL;
581 pPktProc->resetStats();
582
583 // reset the global demux stats.
584 m_demux_stats.frame_bytes = 0;
585 m_demux_stats.no_id_bytes = 0;
586 m_demux_stats.valid_id_bytes = 0;
587 m_demux_stats.unknown_id_bytes = 0;
588 m_demux_stats.reserved_id_bytes = 0;
589 return OCSD_OK;
590 }
591
getPktProcI(const uint8_t CSID)592 TrcPktProcI *DecodeTree::getPktProcI(const uint8_t CSID)
593 {
594 TrcPktProcI *pPktProc = 0;
595 TraceComponent *pComp, *pAssoc;
596 DecodeTreeElement *pElem = getDecoderElement(CSID);
597
598 if (pElem)
599 {
600 pComp = pElem->getDecoderHandle();
601 if (pComp)
602 {
603 /* if this is a full decoder then the associated component is the packet processor */
604 pAssoc = pComp->getAssocComponent();
605 if (pAssoc)
606 pPktProc = dynamic_cast<TrcPktProcI *>(pAssoc);
607 else
608 pPktProc = dynamic_cast<TrcPktProcI *>(pComp);
609 }
610 }
611 return pPktProc;
612 }
613
getDecoderElement(const uint8_t CSID) const614 DecodeTreeElement * DecodeTree::getDecoderElement(const uint8_t CSID) const
615 {
616 DecodeTreeElement *ret_elem = 0;
617 if(usingFormatter() && OCSD_IS_VALID_CS_SRC_ID(CSID))
618 {
619 ret_elem = m_decode_elements[CSID];
620 }
621 else
622 ret_elem = m_decode_elements[0]; // ID 0 is used if single leaf tree.
623 return ret_elem;
624 }
625
getFirstElement(uint8_t & elemID)626 DecodeTreeElement *DecodeTree::getFirstElement(uint8_t &elemID)
627 {
628 m_decode_elem_iter = 0;
629 return getNextElement(elemID);
630 }
631
getNextElement(uint8_t & elemID)632 DecodeTreeElement *DecodeTree::getNextElement(uint8_t &elemID)
633 {
634 DecodeTreeElement *ret_elem = 0;
635
636 if(m_decode_elem_iter < 0x80)
637 {
638 // find a none zero entry or end of range
639 while((m_decode_elem_iter < 0x80) && (m_decode_elements[m_decode_elem_iter] == 0))
640 m_decode_elem_iter++;
641
642 // return entry unless end of range
643 if(m_decode_elem_iter < 0x80)
644 {
645 ret_elem = m_decode_elements[m_decode_elem_iter];
646 elemID = m_decode_elem_iter;
647 m_decode_elem_iter++;
648 }
649 }
650 return ret_elem;
651 }
652
initialise(const ocsd_dcd_tree_src_t type,uint32_t formatterCfgFlags)653 bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCfgFlags)
654 {
655 ocsd_err_t err;
656 m_dcd_tree_type = type;
657 if(type == OCSD_TRC_SRC_FRAME_FORMATTED)
658 {
659 // frame formatted - we want to create the deformatter and hook it up
660 m_frame_deformatter_root = new (std::nothrow) TraceFormatterFrameDecoder();
661 if(m_frame_deformatter_root)
662 {
663 if (m_frame_deformatter_root->Init() != OCSD_OK)
664 return false;
665 m_frame_deformatter_root->getErrLogAttachPt()->attach(DecodeTree::s_i_error_logger);
666 err = m_frame_deformatter_root->Configure(formatterCfgFlags);
667 if (err != OCSD_OK)
668 return false;
669 m_i_decoder_root = dynamic_cast<ITrcDataIn*>(m_frame_deformatter_root);
670 m_frame_deformatter_root->SetDemuxStatsBlock(&m_demux_stats);
671 }
672 else
673 return false;
674 }
675 return true;
676 }
677
setSingleRoot(TrcPktProcI * pComp)678 void DecodeTree::setSingleRoot(TrcPktProcI *pComp)
679 {
680 m_i_decoder_root = static_cast<ITrcDataIn*>(pComp);
681 }
682
createDecodeElement(const uint8_t CSID)683 ocsd_err_t DecodeTree::createDecodeElement(const uint8_t CSID)
684 {
685 ocsd_err_t err = OCSD_ERR_INVALID_ID;
686 if(CSID < 0x80)
687 {
688 if(m_decode_elements[CSID] == 0)
689 {
690 m_decode_elements[CSID] = new (std::nothrow) DecodeTreeElement();
691 if(m_decode_elements[CSID] == 0)
692 err = OCSD_ERR_MEM;
693 else
694 err = OCSD_OK;
695 }
696 else
697 err = OCSD_ERR_ATTACH_TOO_MANY;
698 }
699 return err;
700 }
701
destroyDecodeElement(const uint8_t CSID)702 void DecodeTree::destroyDecodeElement(const uint8_t CSID)
703 {
704 if(CSID < 0x80)
705 {
706 if(m_decode_elements[CSID] != 0)
707 {
708 m_decode_elements[CSID]->DestroyElem();
709 delete m_decode_elements[CSID];
710 m_decode_elements[CSID] = 0;
711 }
712 }
713 }
714
setIDFilter(std::vector<uint8_t> & ids)715 ocsd_err_t DecodeTree::setIDFilter(std::vector<uint8_t> &ids)
716 {
717 ocsd_err_t err = OCSD_ERR_DCDT_NO_FORMATTER;
718 if(usingFormatter())
719 {
720 err = m_frame_deformatter_root->OutputFilterAllIDs(false);
721 if(err == OCSD_OK)
722 err = m_frame_deformatter_root->OutputFilterIDs(ids,true);
723 }
724 return err;
725 }
726
clearIDFilter()727 ocsd_err_t DecodeTree::clearIDFilter()
728 {
729 ocsd_err_t err = OCSD_ERR_DCDT_NO_FORMATTER;
730 if(usingFormatter())
731 {
732 err = m_frame_deformatter_root->OutputFilterAllIDs(true);
733 }
734 return err;
735 }
736
737 /** add a protocol packet printer */
addPacketPrinter(uint8_t CSID,bool bMonitor,ItemPrinter ** ppPrinter)738 ocsd_err_t DecodeTree::addPacketPrinter(uint8_t CSID, bool bMonitor, ItemPrinter **ppPrinter)
739 {
740 ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL;
741 DecodeTreeElement *pElement = getDecoderElement(CSID);
742 if (pElement)
743 {
744 ocsd_trace_protocol_t protocol = pElement->getProtocol();
745 ItemPrinter *pPrinter;
746
747 pPrinter = PktPrinterFact::createProtocolPrinter(getPrinterList(), protocol, CSID);
748 if (pPrinter)
749 {
750 pPrinter->setMessageLogger(getCurrentErrorLogI()->getOutputLogger());
751 switch (protocol)
752 {
753 case OCSD_PROTOCOL_ETMV4I:
754 case OCSD_PROTOCOL_ETE:
755 {
756 PacketPrinter<EtmV4ITrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<EtmV4ITrcPacket> *>(pPrinter);
757 if (bMonitor)
758 err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<EtmV4ITrcPacket> *)pTPrinter);
759 else
760 err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<EtmV4ITrcPacket> *)pTPrinter);
761 }
762 break;
763
764 case OCSD_PROTOCOL_ETMV3:
765 {
766 PacketPrinter<EtmV3TrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<EtmV3TrcPacket> *>(pPrinter);
767 if (bMonitor)
768 err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<EtmV3TrcPacket> *)pTPrinter);
769 else
770 err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<EtmV3TrcPacket> *)pTPrinter);
771 }
772 break;
773
774 case OCSD_PROTOCOL_PTM:
775 {
776 PacketPrinter<PtmTrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<PtmTrcPacket> *>(pPrinter);
777 if (bMonitor)
778 err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<PtmTrcPacket> *)pTPrinter);
779 else
780 err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<PtmTrcPacket> *)pTPrinter);
781 }
782 break;
783
784 case OCSD_PROTOCOL_STM:
785 {
786 PacketPrinter<StmTrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<StmTrcPacket> *>(pPrinter);
787 if (bMonitor)
788 err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<StmTrcPacket> *)pTPrinter);
789 else
790 err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<StmTrcPacket> *)pTPrinter);
791 }
792 break;
793
794 default:
795 err = OCSD_ERR_NO_PROTOCOL;
796 break;
797 }
798
799 if (err == OCSD_OK)
800 {
801 if (ppPrinter)
802 *ppPrinter = pPrinter;
803 }
804 else
805 PktPrinterFact::destroyPrinter(getPrinterList(), pPrinter);
806 }
807 }
808 return err;
809 }
810
811 /** add a raw frame printer */
addRawFramePrinter(RawFramePrinter ** ppPrinter,uint32_t flags)812 ocsd_err_t DecodeTree::addRawFramePrinter(RawFramePrinter **ppPrinter, uint32_t flags)
813 {
814 ocsd_err_t err = OCSD_ERR_MEM;
815 RawFramePrinter *pPrinter = PktPrinterFact::createRawFramePrinter(getPrinterList());
816 if (pPrinter)
817 {
818 pPrinter->setMessageLogger((DecodeTree::getCurrentErrorLogI()->getOutputLogger()));
819 TraceFormatterFrameDecoder *pFrameDecoder = getFrameDeformatter();
820 uint32_t cfgFlags = pFrameDecoder->getConfigFlags();
821 cfgFlags |= ((uint32_t)flags & (OCSD_DFRMTR_PACKED_RAW_OUT | OCSD_DFRMTR_UNPACKED_RAW_OUT));
822 pFrameDecoder->Configure(cfgFlags);
823 err = pFrameDecoder->getTrcRawFrameAttachPt()->attach(pPrinter);
824 if (ppPrinter && (err==OCSD_OK))
825 *ppPrinter = pPrinter;
826 }
827 return err;
828 }
829
830 /** add a generic element output printer */
addGenElemPrinter(TrcGenericElementPrinter ** ppPrinter)831 ocsd_err_t DecodeTree::addGenElemPrinter(TrcGenericElementPrinter **ppPrinter)
832 {
833 ocsd_err_t err = OCSD_ERR_MEM;
834 TrcGenericElementPrinter *pPrinter = PktPrinterFact::createGenElemPrinter(getPrinterList());
835 if (pPrinter)
836 {
837 pPrinter->setMessageLogger((DecodeTree::getCurrentErrorLogI()->getOutputLogger()));
838 setGenTraceElemOutI(pPrinter);
839 err = OCSD_OK;
840 if (ppPrinter)
841 *ppPrinter = pPrinter;
842 }
843 return err;
844
845 }
846
847 /* End of File ocsd_dcd_tree.cpp */
848