xref: /aosp_15_r20/external/OpenCSD/decoder/tests/source/trc_pkt_lister.cpp (revision 02ca8ccacfba7e0df68f3332a95f3180334d6649)
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