1 /*
2 * \file trc_pkt_lister.cpp
3 * \brief OpenCSD : Trace Packet Lister Test program
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 /* Test program / utility - list trace packets in supplied snapshot. */
37
38 #include <cstdio>
39 #include <string>
40 #include <iostream>
41 #include <sstream>
42 #include <cstring>
43 #include <chrono>
44 #include <ctime>
45
46 #include "opencsd.h" // the library
47 #include "trace_snapshots.h" // the snapshot reading test library
48
49 static bool process_cmd_line_opts( int argc, char* argv[]);
50 static void ListTracePackets(ocsdDefaultErrorLogger &err_logger, SnapShotReader &reader, const std::string &trace_buffer_name);
51 static bool process_cmd_line_logger_opts(int argc, char* argv[]);
52 static void log_cmd_line_opts(int argc, char* argv[]);
53
54 // default path
55 #ifdef WIN32
56 static std::string ss_path = ".\\";
57 #else
58 static std::string ss_path = "./";
59 #endif
60
61 static std::string source_buffer_name = ""; // source name - used if more than one source
62 static bool all_source_ids = true; // output all IDs in source.
63 static std::vector<uint8_t> id_list; // output specific IDs in source
64
65 static ocsdMsgLogger logger;
66 static int logOpts = ocsdMsgLogger::OUT_STDOUT | ocsdMsgLogger::OUT_FILE;
67 static std::string logfileName = "trc_pkt_lister.ppl";
68 static bool outRawPacked = false;
69 static bool outRawUnpacked = false;
70 static bool ss_verbose = false;
71 static bool decode = false;
72 static bool no_undecoded_packets = false;
73 static bool pkt_mon = false;
74 static int test_waits = 0;
75 static bool dstream_format = false;
76 static bool tpiu_format = false;
77 static bool has_hsync = false;
78 static bool stats = false;
79 static bool profile = false;
80 static bool multi_session = false; // decode all buffers in snapshot as same config.
81
82 static uint32_t add_create_flags = 0;
83
84 static bool macc_cache_disable = false;
85 static uint32_t macc_cache_page_size = 0;
86 static uint32_t macc_cache_page_num = 0;
87
88 static SnapShotReader ss_reader;
89
main(int argc,char * argv[])90 int main(int argc, char* argv[])
91 {
92 std::ostringstream moss;
93
94 if(process_cmd_line_logger_opts(argc,argv))
95 {
96 printf("Bad logger command line options\nProgram Exiting\n");
97 return -2;
98 }
99
100 logger.setLogOpts(logOpts);
101 logger.setLogFileName(logfileName.c_str());
102
103 moss << "Trace Packet Lister: CS Decode library testing\n";
104 moss << "-----------------------------------------------\n\n";
105 moss << "** Library Version : " << ocsdVersion::vers_str() << "\n\n";
106 logger.LogMsg(moss.str());
107
108 log_cmd_line_opts(argc,argv);
109
110 ocsdDefaultErrorLogger err_log;
111 err_log.initErrorLogger(OCSD_ERR_SEV_INFO);
112 err_log.setOutputLogger(&logger);
113
114 if(!process_cmd_line_opts(argc, argv))
115 return -1;
116
117 moss.str("");
118 moss << "Trace Packet Lister : reading snapshot from path " << ss_path << "\n";
119 logger.LogMsg(moss.str());
120
121 ss_reader.setSnapshotDir(ss_path);
122 ss_reader.setErrorLogger(&err_log);
123 ss_reader.setVerboseOutput(ss_verbose);
124
125 if(ss_reader.snapshotFound())
126 {
127 if(ss_reader.readSnapShot())
128 {
129 std::vector<std::string> sourceBuffList;
130 if(ss_reader.getSourceBufferNameList(sourceBuffList))
131 {
132 bool bValidSourceName = false;
133 // check source name list
134 if(source_buffer_name.size() == 0)
135 {
136 // default to first in the list
137 source_buffer_name = sourceBuffList[0];
138 bValidSourceName = true;
139 }
140 else
141 {
142 for(size_t i = 0; i < sourceBuffList.size(); i++)
143 {
144 if(sourceBuffList[i] == source_buffer_name)
145 {
146 bValidSourceName = true;
147 break;
148 }
149 }
150 }
151
152 if(bValidSourceName)
153 {
154 std::ostringstream oss;
155 oss << "Using " << source_buffer_name << " as trace source\n";
156 logger.LogMsg(oss.str());
157 ListTracePackets(err_log,ss_reader,source_buffer_name);
158 }
159 else
160 {
161 std::ostringstream oss;
162 oss << "Trace Packet Lister : Trace source name " << source_buffer_name << " not found\n";
163 logger.LogMsg(oss.str());
164 oss.str("");
165 oss << "Valid source names are:-\n";
166 for(size_t i = 0; i < sourceBuffList.size(); i++)
167 {
168 oss << sourceBuffList[i] << "\n";
169 }
170 logger.LogMsg(oss.str());
171 }
172
173 }
174 else
175 logger.LogMsg("Trace Packet Lister : No trace source buffer names found\n");
176 }
177 else
178 logger.LogMsg("Trace Packet Lister : Failed to read snapshot\n");
179 }
180 else
181 {
182 std::ostringstream oss;
183 oss << "Trace Packet Lister : Snapshot path" << ss_path << " not found\n";
184 logger.LogMsg(oss.str());
185 }
186
187 return 0;
188 }
189
print_help()190 void print_help()
191 {
192 std::ostringstream oss;
193 oss << "Trace Packet Lister - commands\n\n";
194 oss << "Snapshot:\n\n";
195 oss << "-ss_dir <dir> Set the directory path to a trace snapshot\n";
196 oss << "-ss_verbose Verbose output when reading the snapshot\n";
197 oss << "\nDecode:\n\n";
198 oss << "-id <n> Set an ID to list (may be used multiple times) - default if no id set is for all IDs to be printed\n";
199 oss << "-src_name <name> List packets from a given snapshot source name (defaults to first source found)\n";
200 oss << "-multi_session List packets from all sources - assumes same config for all (ignored if -src_name used)\n";
201 oss << "-dstream_format Input is DSTREAM framed.\n";
202 oss << "-tpiu Input from TPIU - sync by FSYNC.\n";
203 oss << "-tpiu_hsync Input from TPIU - sync by FSYNC and HSYNC.\n";
204 oss << "-decode Full decode of the packets from the trace snapshot (default is to list undecoded packets only)\n";
205 oss << "-decode_only Does not list the undecoded packets, just the trace decode.\n";
206 oss << "-o_raw_packed Output raw packed trace frames\n";
207 oss << "-o_raw_unpacked Output raw unpacked trace data per ID\n";
208 oss << "-src_addr_n ETE protocol: Split source address ranges on N atoms\n";
209 oss << "-stats Output packet processing statistics (if available).\n";
210 oss << "\nConsistency checks\n\n";
211 oss << "-aa64_opcode_chk Check for correct AA64 opcodes (MSW != 0x0000)\n";
212 oss << "-direct_br_cond Check for incorrect N atom on direct unconditional branches\n";
213 oss << "-strict_br_cond Strict conditional checks - look for incorrect N atom on all unconditional branches.\n";
214 oss << "-range_cont Range continuity checks - check next range after N atom is continuous.\n";
215 oss << "-halt_err Halt on bad packet error (default attempts to resync).\n";
216 oss << "\nDevelopment:\nOptions used during develop and test of the library\n\n";
217 oss << "-profile Mute logging output while profiling library performance\n";
218 oss << "-test_waits <N> Force wait from packet printer for N packets - test the wait/flush mechanisms for the decoder\n";
219 oss << "-macc_cache_disable Switch off caching on memory accessor\n";
220 oss << "-macc_cache_p_size Set size of caching pages\n";
221 oss << "-macc_cache_p_num Set number of caching pages\n";
222 oss << "\nOutput:\n";
223 oss << " Setting any of these options cancels the default output to file & stdout,\n using _only_ the options supplied.\n\n";
224 oss << "-logstdout Output to stdout -> console.\n";
225 oss << "-logstderr Output to stderr.\n";
226 oss << "-logfile Output to default file - " << logfileName << "\n";
227 oss << "-logfilename <name> Output to file <name> \n";
228
229
230 logger.LogMsg(oss.str());
231 }
232
log_cmd_line_opts(int argc,char * argv[])233 void log_cmd_line_opts(int argc, char* argv[])
234 {
235 std::ostringstream oss;
236 oss << "Test Command Line:-\n";
237 oss << argv[0] << " ";
238 for(int i = 1; i < argc; i++)
239 {
240 oss << argv[i] << " ";
241 }
242 oss << "\n\n";
243 logger.LogMsg(oss.str());
244 }
245
246 // true if element ID filtered out
element_filtered(uint8_t elemID)247 bool element_filtered(uint8_t elemID)
248 {
249 bool filtered = false;
250 if(!all_source_ids)
251 {
252 filtered = true;
253 std::vector<uint8_t>::const_iterator it;
254 it = id_list.begin();
255 while((it != id_list.end()) && filtered)
256 {
257 if(*it == elemID)
258 filtered = false;
259 it++;
260 }
261 }
262 return filtered;
263 }
264
process_cmd_line_logger_opts(int argc,char * argv[])265 bool process_cmd_line_logger_opts(int argc, char* argv[])
266 {
267 bool badLoggerOpts = false;
268 bool bChangingOptFlags = false;
269 int newlogOpts = ocsdMsgLogger::OUT_NONE;
270 std::string opt;
271 if(argc > 1)
272 {
273 int options_to_process = argc - 1;
274 int optIdx = 1;
275 while(options_to_process > 0)
276 {
277 opt = argv[optIdx];
278 if(opt == "-logstdout")
279 {
280 newlogOpts |= ocsdMsgLogger::OUT_STDOUT;
281 bChangingOptFlags = true;
282 }
283 else if(opt == "-logstderr")
284 {
285 newlogOpts |= ocsdMsgLogger::OUT_STDERR;
286 bChangingOptFlags = true;
287 }
288 else if(opt == "-logfile")
289 {
290 newlogOpts |= ocsdMsgLogger::OUT_FILE;
291 bChangingOptFlags = true;
292 }
293 else if(opt == "-logfilename")
294 {
295 options_to_process--;
296 optIdx++;
297 if(options_to_process)
298 {
299 logfileName = argv[optIdx];
300 newlogOpts |= ocsdMsgLogger::OUT_FILE;
301 bChangingOptFlags = true;
302 }
303 else
304 {
305 badLoggerOpts = true;
306 }
307 }
308 options_to_process--;
309 optIdx++;
310 }
311 }
312 if(bChangingOptFlags)
313 logOpts = newlogOpts;
314 return badLoggerOpts;
315 }
316
process_cmd_line_opts(int argc,char * argv[])317 bool process_cmd_line_opts(int argc, char* argv[])
318 {
319 bool bOptsOK = true;
320 std::string opt;
321 if(argc > 1)
322 {
323 int options_to_process = argc - 1;
324 int optIdx = 1;
325 while((options_to_process > 0) && bOptsOK)
326 {
327 opt = argv[optIdx];
328 if(opt == "-ss_dir")
329 {
330 options_to_process--;
331 optIdx++;
332 if(options_to_process)
333 ss_path = argv[optIdx];
334 else
335 {
336 logger.LogMsg("Trace Packet Lister : Error: Missing directory string on -ss_dir option\n");
337 bOptsOK = false;
338 }
339 }
340 else if(opt == "-id")
341 {
342 options_to_process--;
343 optIdx++;
344 if(options_to_process)
345 {
346 uint8_t Id = (uint8_t)strtoul(argv[optIdx],0,0);
347 if((Id == 0) || (Id >= 0x70))
348 {
349 std::ostringstream iderrstr;
350 iderrstr << "Trace Packet Lister : Error: invalid ID number 0x" << std::hex << (uint32_t)Id << " on -id option" << std::endl;
351 logger.LogMsg(iderrstr.str());
352 bOptsOK = false;
353 }
354 else
355 {
356 all_source_ids = false;
357 id_list.push_back(Id);
358 }
359 }
360 else
361 {
362 logger.LogMsg("Trace Packet Lister : Error: No ID number on -id option\n");
363 bOptsOK = false;
364 }
365 }
366 else if(strcmp(argv[optIdx], "-src_name") == 0)
367 {
368 options_to_process--;
369 optIdx++;
370 if (options_to_process) {
371 source_buffer_name = argv[optIdx];
372 multi_session = false;
373 }
374 else
375 {
376 logger.LogMsg("Trace Packet Lister : Error: Missing source name string on -src_name option\n");
377 bOptsOK = false;
378 }
379 }
380 else if (strcmp(argv[optIdx], "-multi_session") == 0)
381 {
382 if (source_buffer_name.length() == 0)
383 multi_session = true;
384 }
385 else if(strcmp(argv[optIdx], "-test_waits") == 0)
386 {
387 options_to_process--;
388 optIdx++;
389 if(options_to_process)
390 {
391 test_waits = (int)strtol(argv[optIdx],0,0);
392 if(test_waits < 0)
393 test_waits = 0;
394 }
395 else
396 {
397 logger.LogMsg("Trace Packet Lister : Error: wait count value on -test_waits option\n");
398 bOptsOK = false;
399 }
400 }
401 else if(strcmp(argv[optIdx], "-o_raw_packed") == 0)
402 {
403 outRawPacked = true;
404 }
405 else if(strcmp(argv[optIdx], "-o_raw_unpacked") == 0)
406 {
407 outRawUnpacked = true;
408 }
409 else if(strcmp(argv[optIdx], "-ss_verbose") == 0)
410 {
411 ss_verbose = true;
412 }
413 else if(strcmp(argv[optIdx], "-decode") == 0)
414 {
415 decode = true;
416 }
417 else if(strcmp(argv[optIdx], "-pkt_mon") == 0)
418 {
419 pkt_mon = true;
420 }
421 else if(strcmp(argv[optIdx], "-decode_only") == 0)
422 {
423 no_undecoded_packets = true;
424 decode = true;
425 }
426 else if (strcmp(argv[optIdx], "-src_addr_n") == 0)
427 {
428 add_create_flags |= ETE_OPFLG_PKTDEC_SRCADDR_N_ATOMS;
429 }
430 else if (strcmp(argv[optIdx], "-stats") == 0)
431 {
432 stats = true;
433 }
434 else if((strcmp(argv[optIdx], "-help") == 0) || (strcmp(argv[optIdx], "--help") == 0) || (strcmp(argv[optIdx], "-h") == 0))
435 {
436 print_help();
437 bOptsOK = false;
438 }
439 else if((opt == "-logstdout") || (opt == "-logstderr") ||
440 (opt == "-logfile") || (opt == "-logfilename"))
441 {
442 // skip all these as processed earlier
443
444 // also additionally skip any filename parameter
445 if(opt == "-logfilename")
446 {
447 options_to_process--;
448 optIdx++;
449 }
450 }
451 else if (strcmp(argv[optIdx], "-dstream_format") == 0)
452 {
453 dstream_format = true;
454 }
455 else if (strcmp(argv[optIdx], "-tpiu") == 0)
456 {
457 tpiu_format = true;
458 }
459 else if (strcmp(argv[optIdx], "-tpiu_hsync") == 0)
460 {
461 has_hsync = true;
462 tpiu_format = true;
463 }
464 else if (strcmp(argv[optIdx], "-profile") == 0)
465 {
466 profile = true;
467 }
468 else if (strcmp(argv[optIdx], "-direct_br_cond") == 0)
469 {
470 add_create_flags |= OCSD_OPFLG_N_UNCOND_DIR_BR_CHK;
471 }
472 else if (strcmp(argv[optIdx], "-strict_br_cond") == 0)
473 {
474 add_create_flags |= OCSD_OPFLG_STRICT_N_UNCOND_BR_CHK;
475 }
476 else if (strcmp(argv[optIdx], "-range_cont") == 0)
477 {
478 add_create_flags |= OCSD_OPFLG_CHK_RANGE_CONTINUE;
479 }
480 else if (strcmp(argv[optIdx], "-halt_err") == 0)
481 {
482 add_create_flags |= OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS;
483 }
484 else if (strcmp(argv[optIdx], "-aa64_opcode_chk") == 0)
485 {
486 add_create_flags |= ETM4_OPFLG_PKTDEC_AA64_OPCODE_CHK;
487 }
488 else if (strcmp(argv[optIdx], "-macc_cache_disable") == 0)
489 {
490 macc_cache_disable = true;
491 }
492 else if (strcmp(argv[optIdx], "-macc_cache_p_size") == 0)
493 {
494 options_to_process--;
495 optIdx++;
496 if (options_to_process)
497 macc_cache_page_size = (uint32_t)strtoul(argv[optIdx], 0, 0);
498 }
499 else if (strcmp(argv[optIdx], "-macc_cache_p_num") == 0)
500 {
501 options_to_process--;
502 optIdx++;
503 if (options_to_process)
504 macc_cache_page_num = (uint32_t)strtoul(argv[optIdx], 0, 0);
505 }
506 else
507 {
508 std::ostringstream errstr;
509 errstr << "Trace Packet Lister : Warning: Ignored unknown option " << argv[optIdx] << "." << std::endl;
510 logger.LogMsg(errstr.str());
511 }
512 options_to_process--;
513 optIdx++;
514 }
515
516 }
517 return bOptsOK;
518 }
519
520 //
521 // if decoding the gen elem printer will be injecting waits, but we may ge a cont from the packet processors if a complete packet is not available.
522 // if packet processing only, then waits will be coming from there until the count is extinguished
523 // wait testing with packet processor only really works correctly if we are doing a single source as there is no way at this
524 // point to know which source has sent the _WAIT. with multi packet processor waiting may get false warnings once the _WAITs run out.
ExpectingPPrintWaitResp(DecodeTree * dcd_tree,TrcGenericElementPrinter & genElemPrinter)525 bool ExpectingPPrintWaitResp(DecodeTree *dcd_tree, TrcGenericElementPrinter &genElemPrinter)
526 {
527 bool ExpectingWaits = false;
528 std::vector<ItemPrinter *> &printers = dcd_tree->getPrinterList();
529 if(test_waits > 0)
530 {
531 // see if last response was from the Gen elem printer expecting a wait
532 ExpectingWaits = genElemPrinter.needAckWait();
533
534 // now see if any of the active packet printers are returing wait responses.
535 if(!ExpectingWaits)
536 {
537 std::vector<ItemPrinter *>::iterator it;
538 it = printers.begin();
539 while((it != printers.end()) && !ExpectingWaits)
540 {
541 ExpectingWaits = (bool)((*it)->getTestWaits() != 0);
542 it++;
543 }
544 }
545
546 // nothing waiting - and no outstanding wait cycles in the Gen elem printer.
547 if(!ExpectingWaits && (genElemPrinter.getTestWaits() == 0))
548 test_waits = 0; // zero out the input value if none of the printers currently have waits scheduled.
549 }
550 return ExpectingWaits;
551 }
552
AttachPacketPrinters(DecodeTree * dcd_tree)553 void AttachPacketPrinters( DecodeTree *dcd_tree)
554 {
555 uint8_t elemID;
556 std::ostringstream oss;
557
558 // attach packet printers to each trace source in the tree
559 DecodeTreeElement *pElement = dcd_tree->getFirstElement(elemID);
560 while(pElement && !no_undecoded_packets)
561 {
562 if(!element_filtered(elemID))
563 {
564 oss.str("");
565
566 ItemPrinter *pPrinter;
567 ocsd_err_t err = dcd_tree->addPacketPrinter(elemID, (bool)(decode || pkt_mon),&pPrinter);
568 if (err == OCSD_OK)
569 {
570 // if not decoding or monitor only
571 if((!(decode || pkt_mon)) && test_waits)
572 pPrinter->setTestWaits(test_waits);
573
574 oss << "Trace Packet Lister : Protocol printer " << pElement->getDecoderTypeName() << " on Trace ID 0x" << std::hex << (uint32_t)elemID << "\n";
575 }
576 else
577 oss << "Trace Packet Lister : Failed to Protocol printer " << pElement->getDecoderTypeName() << " on Trace ID 0x" << std::hex << (uint32_t)elemID << "\n";
578 logger.LogMsg(oss.str());
579 if (profile)
580 pPrinter->setMute(true);
581
582 }
583 pElement = dcd_tree->getNextElement(elemID);
584 }
585
586 }
587
ConfigureFrameDeMux(DecodeTree * dcd_tree,RawFramePrinter ** framePrinter)588 void ConfigureFrameDeMux(DecodeTree *dcd_tree, RawFramePrinter **framePrinter)
589 {
590 // configure the frame deformatter, and attach a frame printer to the frame deformatter if needed
591 TraceFormatterFrameDecoder *pDeformatter = dcd_tree->getFrameDeformatter();
592 if(pDeformatter != 0)
593 {
594 // configuration - memory alinged buffer
595 uint32_t configFlags = pDeformatter->getConfigFlags();
596
597 // check for TPIU FSYNC & HSYNC
598 if (tpiu_format) configFlags |= OCSD_DFRMTR_HAS_FSYNCS;
599 if (has_hsync) configFlags |= OCSD_DFRMTR_HAS_HSYNCS;
600 // if FSYNC (& HSYNC) - cannot be mem frame aligned.
601 if (tpiu_format) configFlags &= ~OCSD_DFRMTR_FRAME_MEM_ALIGN;
602
603 if (!configFlags)
604 {
605 configFlags = OCSD_DFRMTR_FRAME_MEM_ALIGN;
606 }
607 pDeformatter->Configure(configFlags);
608
609 if (outRawPacked || outRawUnpacked)
610 {
611 if (outRawPacked) configFlags |= OCSD_DFRMTR_PACKED_RAW_OUT;
612 if (outRawUnpacked) configFlags |= OCSD_DFRMTR_UNPACKED_RAW_OUT;
613 dcd_tree->addRawFramePrinter(framePrinter, configFlags);
614 }
615 }
616 }
617
PrintDecodeStats(DecodeTree * dcd_tree)618 void PrintDecodeStats(DecodeTree *dcd_tree)
619 {
620 uint8_t elemID;
621 std::ostringstream oss;
622 ocsd_decode_stats_t *pStats = 0;
623 ocsd_err_t err;
624 bool gotDemuxStats = false;
625 ocsd_demux_stats_t demux_stats;
626
627 oss << "\nReading packet decoder statistics....\n\n";
628 logger.LogMsg(oss.str());
629
630 DecodeTreeElement *pElement = dcd_tree->getFirstElement(elemID);
631 while (pElement)
632 {
633 oss.str("");
634 err = dcd_tree->getDecoderStats(elemID, &pStats);
635 if (!err && pStats)
636 {
637 oss << "Decode stats ID 0x" << std::hex << (uint32_t)elemID << "\n";
638 oss << "Total Bytes: " << std::dec << pStats->channel_total << "; Unsynced Bytes: " << std::dec << pStats->channel_unsynced << "\n";
639 oss << "Bad Header Errors: " << std::dec << pStats->bad_header_errs << "; Bad Sequence Errors: " << std::dec << pStats->bad_sequence_errs << "\n";
640
641 // demux stats same for all IDs - grab them at the first opportunity..
642 if (!gotDemuxStats) {
643 memcpy(&demux_stats, &pStats->demux, sizeof(ocsd_demux_stats_t));
644 gotDemuxStats = true;
645 }
646
647 }
648 else
649 oss << "Decode stats unavailable on Trace ID 0x" << std::hex << (uint32_t)elemID << "\n";
650
651
652 logger.LogMsg(oss.str());
653 pElement = dcd_tree->getNextElement(elemID);
654 }
655
656 // if we have copied over the stats and there is at least 1 frame byte (impossible for there to be 0 if demuxing)
657 if (gotDemuxStats && demux_stats.frame_bytes) {
658 uint64_t total = demux_stats.valid_id_bytes + demux_stats.no_id_bytes + demux_stats.unknown_id_bytes +
659 demux_stats.reserved_id_bytes + demux_stats.frame_bytes;
660 oss.str("");
661 oss << "\nFrame Demux Stats\n";
662 oss << "Trace data bytes sent to registered ID decoders: " << std::dec << demux_stats.valid_id_bytes << "\n";
663 oss << "Trace data bytes without registered ID decoders: " << std::dec << demux_stats.no_id_bytes << "\n";
664 oss << "Trace data bytes with unknown ID: " << std::dec << demux_stats.unknown_id_bytes << "\n";
665 oss << "Trace data bytes with reserved ID: " << std::dec << demux_stats.reserved_id_bytes << "\n";
666 oss << "Frame demux bytes, ID bytes and sync bytes: " << std::dec << demux_stats.frame_bytes << "\n";
667 oss << "Total bytes processed by frame demux: " << std::dec << total << "\n\n";
668 logger.LogMsg(oss.str());
669 }
670 }
671
ProcessInputFile(DecodeTree * dcd_tree,std::string & in_filename,TrcGenericElementPrinter * genElemPrinter,ocsdDefaultErrorLogger & err_logger)672 bool ProcessInputFile(DecodeTree *dcd_tree, std::string &in_filename,
673 TrcGenericElementPrinter* genElemPrinter, ocsdDefaultErrorLogger& err_logger)
674 {
675 bool bOK = true;
676 std::chrono::time_point<std::chrono::steady_clock> start, end; // measure decode time
677
678 // need to push the data through the decode tree.
679 std::ifstream in;
680
681 in.open(in_filename, std::ifstream::in | std::ifstream::binary);
682 if (in.is_open())
683 {
684 ocsd_datapath_resp_t dataPathResp = OCSD_RESP_CONT;
685 static const int bufferSize = 1024;
686 uint8_t trace_buffer[bufferSize]; // temporary buffer to load blocks of data from the file
687 uint32_t trace_index = 0; // index into the overall trace buffer (file).
688
689 start = std::chrono::steady_clock::now();
690
691 // process the file, a buffer load at a time
692 while (!in.eof() && !OCSD_DATA_RESP_IS_FATAL(dataPathResp))
693 {
694 if (dstream_format)
695 {
696 in.read((char*)&trace_buffer[0], 512 - 8);
697 }
698 else
699 in.read((char*)&trace_buffer[0], bufferSize); // load a block of data into the buffer
700
701 std::streamsize nBuffRead = in.gcount(); // get count of data loaded.
702 std::streamsize nBuffProcessed = 0; // amount processed in this buffer.
703 uint32_t nUsedThisTime = 0;
704
705 // process the current buffer load until buffer done, or fatal error occurs
706 while ((nBuffProcessed < nBuffRead) && !OCSD_DATA_RESP_IS_FATAL(dataPathResp))
707 {
708 if (OCSD_DATA_RESP_IS_CONT(dataPathResp))
709 {
710 dataPathResp = dcd_tree->TraceDataIn(
711 OCSD_OP_DATA,
712 trace_index,
713 (uint32_t)(nBuffRead - nBuffProcessed),
714 &(trace_buffer[0]) + nBuffProcessed,
715 &nUsedThisTime);
716
717 nBuffProcessed += nUsedThisTime;
718 trace_index += nUsedThisTime;
719
720 // test printers can inject _WAIT responses - see if we are expecting one...
721 if (ExpectingPPrintWaitResp(dcd_tree, *genElemPrinter))
722 {
723 if (OCSD_DATA_RESP_IS_CONT(dataPathResp))
724 {
725 // not wait or fatal - log a warning here.
726 std::ostringstream oss;
727 oss << "Trace Packet Lister : WARNING : Data in; data Path expected WAIT response\n";
728 logger.LogMsg(oss.str());
729 }
730 }
731 }
732 else // last response was _WAIT
733 {
734 // may need to acknowledge a wait from the gen elem printer
735 if (genElemPrinter->needAckWait())
736 genElemPrinter->ackWait();
737
738 // dataPathResp not continue or fatal so must be wait...
739 dataPathResp = dcd_tree->TraceDataIn(OCSD_OP_FLUSH, 0, 0, 0, 0);
740 }
741 }
742
743 /* dump dstream footers */
744 if (dstream_format) {
745 in.read((char*)&trace_buffer[0], 8);
746 if (outRawPacked)
747 {
748 std::ostringstream oss;
749 oss << "DSTREAM footer [";
750 for (int i = 0; i < 8; i++)
751 {
752 oss << "0x" << std::hex << (int)trace_buffer[i] << " ";
753 }
754 oss << "]\n";
755 logger.LogMsg(oss.str());
756 }
757 }
758 }
759
760 // fatal error - no futher processing
761 if (OCSD_DATA_RESP_IS_FATAL(dataPathResp))
762 {
763 std::ostringstream oss;
764 oss << "Trace Packet Lister : Data Path fatal error\n";
765 logger.LogMsg(oss.str());
766 ocsdError* perr = err_logger.GetLastError();
767 if (perr != 0)
768 logger.LogMsg(ocsdError::getErrorString(perr));
769 bOK = false;
770 }
771 else
772 {
773 // mark end of trace into the data path
774 dcd_tree->TraceDataIn(OCSD_OP_EOT, 0, 0, 0, 0);
775 }
776
777 // close the input file.
778 in.close();
779
780 std::ostringstream oss;
781 end = std::chrono::steady_clock::now();
782 std::chrono::duration<double> sec_elapsed{end -start};
783
784 oss << "Trace Packet Lister : Trace buffer done, processed " << trace_index << " bytes in " << std::setprecision(8) << sec_elapsed.count() << " seconds.\n";
785 logger.LogMsg(oss.str());
786 if (stats)
787 PrintDecodeStats(dcd_tree);
788 if (profile)
789 genElemPrinter->printStats();
790
791 // multi-session - reset the decoder for the next pass.
792 if (multi_session)
793 dcd_tree->TraceDataIn(OCSD_OP_RESET, 0, 0, 0, 0);
794 }
795 else
796 {
797 std::ostringstream oss;
798 oss << "Trace Packet Lister : Error : Unable to open trace buffer.\n";
799 logger.LogMsg(oss.str());
800 }
801 return bOK;
802 }
803
ListTracePackets(ocsdDefaultErrorLogger & err_logger,SnapShotReader & reader,const std::string & trace_buffer_name)804 void ListTracePackets(ocsdDefaultErrorLogger &err_logger, SnapShotReader &reader, const std::string &trace_buffer_name)
805 {
806 CreateDcdTreeFromSnapShot tree_creator;
807 uint32_t createFlags = add_create_flags;
808
809 tree_creator.initialise(&reader, &err_logger);
810
811 if(tree_creator.createDecodeTree(trace_buffer_name, (decode == false), createFlags))
812 {
813 DecodeTree *dcd_tree = tree_creator.getDecodeTree();
814 dcd_tree->setAlternateErrorLogger(&err_logger);
815
816 RawFramePrinter *framePrinter = 0;
817 TrcGenericElementPrinter *genElemPrinter = 0;
818
819 AttachPacketPrinters(dcd_tree);
820
821 ConfigureFrameDeMux(dcd_tree, &framePrinter);
822 if (profile && framePrinter)
823 framePrinter->setMute(true);
824
825 // if decoding set the generic element printer to the output interface on the tree.
826 if(decode)
827 {
828 std::ostringstream oss;
829 //dcd_tree->setGenTraceElemOutI(genElemPrinter);
830 dcd_tree->addGenElemPrinter(&genElemPrinter);
831 oss << "Trace Packet Lister : Set trace element decode printer\n";
832 logger.LogMsg(oss.str());
833 genElemPrinter->setTestWaits(test_waits);
834 if (profile)
835 {
836 genElemPrinter->setMute(true);
837 genElemPrinter->set_collect_stats();
838 }
839 if (macc_cache_disable || macc_cache_page_size || macc_cache_page_num)
840 {
841 if (macc_cache_disable)
842 dcd_tree->setMemAccCacheing(false, 0, 0);
843 else
844 {
845 // one value set - set the other to default
846 if (!macc_cache_page_size)
847 macc_cache_page_size = MEM_ACC_CACHE_DEFAULT_PAGE_SIZE;
848 if (!macc_cache_page_num)
849 macc_cache_page_num = MEM_ACC_CACHE_DEFAULT_MRU_SIZE;
850 dcd_tree->setMemAccCacheing(true, macc_cache_page_size, macc_cache_page_num);
851 }
852 }
853 }
854
855 if(decode)
856 dcd_tree->logMappedRanges(); // print out the mapped ranges
857
858 // check if we have attached at least one printer
859 if(decode || (PktPrinterFact::numPrinters(dcd_tree->getPrinterList()) > 0))
860 {
861 // set up the filtering at the tree level (avoid pushing to processors with no attached printers)
862 if(!all_source_ids)
863 dcd_tree->setIDFilter(id_list);
864 else
865 dcd_tree->clearIDFilter();
866
867 std::string binFileName;
868 if (!multi_session)
869 {
870 binFileName = tree_creator.getBufferFileName();
871 ProcessInputFile(dcd_tree, binFileName, genElemPrinter, err_logger);
872 }
873 else
874 {
875 std::ostringstream oss;
876 std::vector<std::string> sourceBuffList;
877 ss_reader.getSourceBufferNameList(sourceBuffList);
878
879 for (size_t i = 0; i < sourceBuffList.size(); i++)
880 {
881 oss.str("");
882 oss << "####### Multi Session decode: Buffer " << (i+1) << " of " << sourceBuffList.size();
883 oss << "; Source name = " << sourceBuffList[i] << ".\n\n";
884 logger.LogMsg(oss.str());
885
886 binFileName = tree_creator.getBufferFileNameFromBuffName(sourceBuffList[i]);
887 if (binFileName.length() <= 0)
888 {
889 oss.str("");
890 oss << "Trace Packet Lister : ERROR : Multi-session decode for buffer " << sourceBuffList[i] << " - buffer not found. Aborting.\n\n";
891 logger.LogMsg(oss.str());
892 break;
893 }
894
895 if (!ProcessInputFile(dcd_tree, binFileName, genElemPrinter, err_logger)) {
896 oss.str("");
897 oss << "Trace Packet Lister : ERROR : Multi-session decode for buffer " << sourceBuffList[i] << " failed. Aborting.\n\n";
898 logger.LogMsg(oss.str());
899 break;
900 }
901 oss.str("");
902 oss << "####### Buffer " << (i + 1) << " : " << sourceBuffList[i] << " Complete\n\n";
903 logger.LogMsg(oss.str());
904 }
905 }
906 }
907 else
908 {
909 std::ostringstream oss;
910 oss << "Trace Packet Lister : No supported protocols found.\n";
911 logger.LogMsg(oss.str());
912 }
913
914 // clean up
915
916 // get rid of the decode tree.
917 tree_creator.destroyDecodeTree();
918 }
919 }
920
921 /* End of File trc_pkt_lister.cpp */
922