1 /*
2 * \file snapshot_parser.cpp
3 * \brief OpenCSD : Snapshot Parser Library
4 *
5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
6 */
7
8 /*
9 * Redistribution and use in source and binary forms, with or without modification,
10 * are permitted provided that the following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the copyright holder nor the names of its contributors
20 * may be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include "snapshot_parser.h"
36
37 #include <memory>
38 #include <algorithm>
39 #include <istream>
40 #include <iostream>
41 #include <string>
42 #include <utility>
43 using namespace std;
44
45 #include "snapshot_parser_util.h"
46 #include "ini_section_names.h"
47 using namespace Util;
48 using namespace Parser;
49
50 #include "opencsd.h"
51
52 static ITraceErrorLog *s_pErrorLogger = 0;
53 static ocsd_hndl_err_log_t s_errlog_handle = 0;
54 static bool s_verbose_logging = true;
55
56 /*************************************************************************
57 * Note, this file handles the parsring of the general (device specific)
58 * ini file and the (much smaller) device_list file
59 *************************************************************************/
60
61 namespace ParserPrivate
62 {
63 //! Handle CRLF terminators and '#' and ';' comments
CleanLine(string & line)64 void CleanLine(string& line)
65 {
66 string::size_type endpos = line.find_first_of("\r;#");
67 if (endpos != string::npos)
68 {
69 line.erase(endpos);
70 }
71 }
72
73 //! Split foo=bar into pair <foo, bar>
SplitKeyValue(const string & kv)74 pair<string, string> SplitKeyValue(const string& kv)
75 {
76 string::size_type eq(kv.find('='));
77 if (eq == string::npos)
78 {
79 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Couldn't parse '" + kv + "' as key=value");
80 }
81 return make_pair(Trim(kv.substr(0, eq)), Trim(kv.substr(eq + 1)));
82 }
83
84 //! Whether line is just tabs and spaces
IsEmpty(const string & line)85 bool IsEmpty(const string& line)
86 {
87 return TrimLeft(line) == "";
88 }
89
90 /*! \brief Whether line is of form '[header]'
91 * \param line the line
92 * \param sectionName if function returns true, returns the text between the brackets
93 */
IsSectionHeader(const string & line,string & sectionName)94 bool IsSectionHeader(const string& line, string& sectionName)
95 {
96 string::size_type openBracket(line.find('['));
97 if (openBracket == string::npos)
98 {
99 return false;
100 }
101 string::size_type textStart(openBracket + 1);
102 string::size_type closeBracket(line.find(']', textStart));
103 if (closeBracket == string::npos)
104 {
105 return false;
106 }
107 sectionName.assign(Trim(line.substr(textStart, closeBracket - textStart)));
108 return true;
109 }
110
111 template <class M, class K, class V>
AddUniqueKey(M & m,const K & key,const V & value,const std::string & keyStr)112 void AddUniqueKey(M& m, const K& key, const V& value, const std::string &keyStr )
113 {
114 if (!m.insert(make_pair(key, value)).second)
115 {
116 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Duplicate key: " + keyStr);
117 }
118 }
119
PreventDupes(bool & store,const string & key,const string & section)120 void PreventDupes(bool& store, const string& key, const string& section)
121 {
122 if (store)
123 {
124 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE,
125 "Duplicate " + key + " key found in "
126 + section + " section");
127 }
128 store = true;
129 }
130
131
132 /*! \class Section
133 * \brief Handle an ini file section begun with a section header ([header])
134 */
135 class Section
136 {
137 public:
~Section()138 virtual ~Section() {}
139
140 //! Notify a key=value definition
141 virtual void Define(const string& k, const string& v) = 0;
142
143 //! Notify end of section - we can't handle in dtor because misparses throw.
144 virtual void End() = 0;
145 };
146
147 //! The initial state
148 class NullSection : public Section
149 {
150 public:
Define(const string & k,const string &)151 void Define(const string& k, const string&)
152 {
153 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Definition of '" + k + "' has no section header");
154 }
End()155 void End() {}
156 };
157
158 //! Silently ignore sections that are undefined
159 class IgnoredSection : public Section
160 {
161 public:
Define(const string &,const string &)162 void Define(const string& , const string&)
163 {
164 }
End()165 void End() {}
166 };
167
168 //! Handle a [global] section.
169 class GlobalSection : public Section
170 {
171 public:
GlobalSection(Parsed & result)172 GlobalSection(Parsed& result) : m_result(result), m_got_core()
173 {
174 if (m_result.foundGlobal)
175 {
176 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, string("Only one ") + GlobalSectionName + " section allowed");
177 }
178 m_result.foundGlobal = true;
179 }
180
Define(const string & k,const string & v)181 void Define(const string& k, const string& v)
182 {
183 if (k == CoreKey)
184 {
185 PreventDupes(m_got_core, CoreKey, GlobalSectionName);
186 m_result.core.assign(v);
187 }
188 else
189 {
190 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Unknown global option '" + k + '\'');
191 }
192 }
193
End()194 void End() {}
195
196 private:
197 Parsed& m_result;
198 bool m_got_core;
199 };
200
201 //! Handle a [dump] section
202 class DumpSection : public Section
203 {
204 public:
DumpSection(Parsed & result)205 DumpSection(Parsed& result)
206 : m_result(result),
207 m_got_file(), m_got_address(), m_got_length(), m_got_offset(), m_got_space(),
208 m_address(), m_length(), m_offset(), m_file(), m_space()
209 {}
210
Define(const string & k,const string & v)211 void Define(const string& k, const string& v)
212 {
213 if (k == DumpAddressKey)
214 {
215 PreventDupes(m_got_address, DumpAddressKey, DumpFileSectionPrefix);
216 m_address = DecodeUnsigned<uint64_t>(v);
217 }
218 else if (k == DumpLengthKey)
219 {
220 PreventDupes(m_got_length, DumpLengthKey, DumpFileSectionPrefix);
221 m_length = DecodeUnsigned<size_t>(v);
222 }
223 else if (k == DumpOffsetKey)
224 {
225 PreventDupes(m_got_offset, DumpOffsetKey, DumpFileSectionPrefix);
226 m_offset = DecodeUnsigned<size_t>(v);
227 }
228 else if (k == DumpFileKey)
229 {
230 PreventDupes(m_got_file, DumpFileKey, DumpFileSectionPrefix);
231 m_file = Trim(v, "\"'"); // strip quotes
232 }
233 else if (k == DumpSpaceKey)
234 {
235 PreventDupes(m_got_space, DumpSpaceKey, DumpFileSectionPrefix);
236 m_space = Trim(v, "\"'"); // strip quotes
237 }
238 else
239 {
240 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Unknown dump section key '" + k + '\'');
241 }
242 }
243
End()244 void End()
245 {
246 if (!m_got_address)
247 {
248 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Dump section is missing mandatory address definition");
249 }
250 if (!m_got_file)
251 {
252 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Dump section is missing mandatory file definition");
253 }
254
255 struct DumpDef add = { m_address, m_file, m_length, m_offset, m_space};
256 m_result.dumpDefs.push_back(add);
257 }
258
259 private:
260 Parsed& m_result;
261 bool m_got_file;
262 bool m_got_address;
263 bool m_got_length;
264 bool m_got_offset;
265 bool m_got_space;
266 uint64_t m_address;
267 size_t m_length;
268 size_t m_offset;
269 string m_file;
270 string m_space;
271 };
272
273 //! Handle an [extendregs] section.
274 class ExtendRegsSection : public Section
275 {
276 public:
ExtendRegsSection(Parsed & result)277 ExtendRegsSection(Parsed& result) : m_result(result)
278 {}
279
Define(const string & k,const string & v)280 void Define(const string& k, const string& v)
281 {
282 AddUniqueKey(m_result.extendRegDefs, DecodeUnsigned<uint32_t>(k), DecodeUnsigned<uint32_t>(v),k);
283 }
284
End()285 void End() {}
286
287 private:
288 Parsed& m_result;
289 };
290
291 // Handle a [regs] section
292 class SymbolicRegsSection : public Section
293 {
294 public:
SymbolicRegsSection(Parsed & result)295 SymbolicRegsSection(Parsed& result) : m_result(result)
296 {}
297
Define(const string & k,const string & v)298 void Define(const string& k, const string& v)
299 {
300 const string value = Trim(v, "\"'"); // strip quotes
301 AddUniqueKey(m_result.regDefs, k, value,k);
302 }
303
End()304 void End() {}
305
306 private:
307 Parsed& m_result;
308 };
309
310 // Handle a [device] section
311 class DeviceSection : public Section
312 {
313 public:
DeviceSection(Parsed & result)314 DeviceSection(Parsed& result) : m_result(result), gotName(false), gotClass(false), gotType(false)
315 {}
316
Define(const string & k,const string & v)317 void Define(const string& k, const string& v)
318 {
319 if (k == DeviceNameKey)
320 {
321 PreventDupes(gotName, k, DeviceSectionName);
322 m_result.deviceName = v;
323 }
324 else if(k == DeviceClassKey)
325 {
326 PreventDupes(gotClass, k, DeviceSectionName);
327 m_result.deviceClass = v;
328 }
329 else if(k == DeviceTypeKey)
330 {
331 PreventDupes(gotType, k, DeviceSectionName);
332 m_result.deviceTypeName = v;
333 }
334 }
335
End()336 void End() {}
337
338 private:
339 Parsed& m_result;
340 bool gotName;
341 bool gotClass;
342 bool gotType;
343 };
344
345 //! Instantiate the appropriate handler for the section name
NewSection(const string & sectionName,Parsed & result)346 auto_ptr<Section> NewSection( const string& sectionName, Parsed& result)
347 {
348 LogInfoStr( "Start of " + sectionName + " section\n");
349
350 if (sectionName == GlobalSectionName)
351 {
352 return auto_ptr<Section>(new GlobalSection(result));
353 }
354 if (sectionName.substr(0,DumpFileSectionLen) == DumpFileSectionPrefix)
355 {
356 return auto_ptr<Section>(new DumpSection(result));
357 }
358 else if (sectionName == ExtendedRegsSectionName)
359 {
360 return auto_ptr<Section>(new ExtendRegsSection(result));
361 }
362 else if (sectionName == SymbolicRegsSectionName)
363 {
364 return auto_ptr<Section>(new SymbolicRegsSection(result));
365 }
366 else if (sectionName == DeviceSectionName)
367 {
368 return auto_ptr<Section>(new DeviceSection(result));
369 }
370 else
371 {
372 LogInfoStr("Unknown section ignored: " + sectionName + "\n");
373 return auto_ptr<Section>(new IgnoredSection);
374 }
375 }
376
377 /***** Device List file parsing *********************/
378 //! Handle a [device_list] section.
379 class DeviceListSection : public Section
380 {
381 public:
DeviceListSection(ParsedDevices & result)382 DeviceListSection(ParsedDevices& result) : m_result(result), nextId(1)
383 {}
384
Define(const string &,const string & v)385 void Define(const string& , const string& v)
386 {
387 // throw away supplied key - DTSL wants them monotonically increasing from 1
388 std::ostringstream id;
389 id << nextId++;
390 m_result.deviceList[id.str()] = v;
391 }
392
End()393 void End() {}
394
395 private:
396 ParsedDevices& m_result;
397 uint32_t nextId;
398 };
399
400 //! Instantiate the appropriate handler for the section name
NewDeviceList(const string & sectionName,ParsedDevices & result)401 auto_ptr<Section> NewDeviceList(const string& sectionName, ParsedDevices& result)
402 {
403 LogInfoStr("Start of " + sectionName + " section\n");
404
405 if (sectionName == DeviceListSectionName)
406 {
407 return auto_ptr<Section>(new DeviceListSection(result));
408 }
409 else
410 {
411 // ignore unexpected sections, there may be others like [trace]
412 // which RDDI doesn't care about
413 return auto_ptr<Section>(new NullSection);
414 }
415 }
416
417 // Handle a [snapshot] section
418 class SnapshotSection : public Section
419 {
420 public:
SnapshotSection(SnapshotInfo & result)421 SnapshotSection(SnapshotInfo& result) : m_result(result), m_gotDescription(false), m_gotVersion(false)
422 {}
423
Define(const string & k,const string & v)424 void Define(const string& k, const string& v)
425 {
426 if (k == VersionKey)
427 {
428 PreventDupes(m_gotVersion, k, SnapshotSectionName);
429 m_result.version = v;
430 // the only valid contents of this are 1.0, as this is the version that introduced the "snapshot" section
431 if (v != "1.0" && v != "1")
432 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Illegal snapshot file version: " + v);
433 }
434 else if (k == DescriptionKey)
435 {
436 PreventDupes(m_gotDescription, k, SnapshotSectionName);
437 m_result.description = v;
438 }
439 }
getSnapshotInfo()440 SnapshotInfo getSnapshotInfo() { return m_result; }
End()441 void End() {}
442
443 private:
444 SnapshotInfo &m_result;
445 bool m_gotDescription;
446 bool m_gotVersion;
447
448 };
449
450 //! Instantiate the appropriate handler for the section name
NewSnapshotInfo(const string & sectionName,ParsedDevices & result)451 auto_ptr<Section> NewSnapshotInfo(const string& sectionName, ParsedDevices& result)
452 {
453 LogInfoStr((std::string)"Start of " + sectionName + (std::string)" section\n");
454
455 if (sectionName == SnapshotSectionName)
456 {
457 return auto_ptr<Section>(new SnapshotSection(result.snapshotInfo));
458 }
459 else
460 {
461 // ignore unexpected sections, there may be others like [trace]
462 // which RDDI doesn't care about
463 return auto_ptr<Section>(new NullSection);
464 }
465 };
466
467 class TraceSection : public Section
468 {
469 public:
TraceSection(ParsedDevices & result)470 TraceSection(ParsedDevices& result) : m_result(result), gotName(false)
471 {}
472
Define(const string & k,const string & v)473 void Define(const string& k, const string& v)
474 {
475 if (k == MetadataKey)
476 {
477 PreventDupes(gotName, k, TraceSectionName);
478 m_result.traceMetaDataName = v;
479 }
480 }
481
End()482 void End() {}
483
484 private:
485 ParsedDevices& m_result;
486 bool gotName;
487 };
488
489 //! Instantiate the appropriate handler for the section name
NewTraceMetaData(const string & sectionName,ParsedDevices & result)490 auto_ptr<Section> NewTraceMetaData(const string& sectionName, ParsedDevices& result)
491 {
492 LogInfoStr((std::string)"Start of " + sectionName + (std::string)" section\n");
493
494 if (sectionName == TraceSectionName)
495 {
496 return auto_ptr<Section>(new TraceSection(result));
497 }
498 else
499 {
500 // ignore unexpected sections, there may be others like [trace]
501 // which RDDI doesn't care about
502 return auto_ptr<Section>(new NullSection);
503 }
504 };
505
506 class TraceBufferListSection : public Section
507 {
508 public:
TraceBufferListSection(ParsedTrace & result)509 TraceBufferListSection(ParsedTrace& result) : m_result(result), gotList(false)
510 {}
511
Define(const string & k,const string & v)512 void Define(const string& k, const string& v)
513 {
514 if (k == BufferListKey)
515 {
516 PreventDupes(gotList, k, TraceBuffersSectionName);
517 std::string nameList = v;
518 std::string::size_type pos;
519 while((pos = nameList.find_first_of(',')) != std::string::npos)
520 {
521 m_result.buffer_section_names.push_back(nameList.substr(0,pos));
522 nameList=nameList.substr(pos+1,std::string::npos);
523 }
524 m_result.buffer_section_names.push_back(nameList);
525 }
526 }
527
End()528 void End() {}
529
530 private:
531 ParsedTrace& m_result;
532 bool gotList;
533 };
534
535 //! Instantiate the appropriate handler for the section name
536
537
538 class TraceBufferSection : public Section
539 {
540 public:
TraceBufferSection(ParsedTrace & result,const std::string & sectionName)541 TraceBufferSection(ParsedTrace& result, const std::string §ionName) : m_result(result), m_sectionName(sectionName),
542 name(""), file(""), format(""), gotName(false), gotFile(false), gotFormat(false)
543 {}
544
Define(const string & k,const string & v)545 void Define(const string& k, const string& v)
546 {
547 if (k == BufferNameKey)
548 {
549 PreventDupes(gotName, k, m_sectionName);
550 name = v;
551 }
552 else if (k == BufferFileKey)
553 {
554 PreventDupes(gotFile, k, m_sectionName);
555 file = v;
556 }
557 else if (k == BufferFormatKey)
558 {
559 PreventDupes(gotFormat, k, m_sectionName);
560 format = v;
561 }
562 }
563
End()564 void End()
565 {
566 if (!gotName)
567 {
568 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Trace Buffer section missing required buffer name");
569 }
570 if (!gotFile)
571 {
572 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Trace Buffer section is missing mandatory file definition");
573 }
574
575 struct TraceBufferInfo info = { name, file, format };
576 m_result.trace_buffers.push_back(info);
577 }
578
579
580 private:
581 ParsedTrace& m_result;
582 std::string m_sectionName;
583 std::string name;
584 bool gotName;
585 std::string file;
586 bool gotFile;
587 std::string format;
588 bool gotFormat;
589
590 };
591
592 class TraceSourceBuffersSection : public Section
593 {
594 public:
TraceSourceBuffersSection(ParsedTrace & result)595 TraceSourceBuffersSection(ParsedTrace& result) : m_result(result)
596 {}
597
Define(const string & k,const string & v)598 void Define(const string& k, const string& v)
599 {
600 // k is the source name, v is the buffer name
601 m_result.source_buffer_assoc[k] = v;
602 }
603
End()604 void End() {}
605
606 private:
607 ParsedTrace& m_result;
608 };
609
610 class TraceCpuSourceSection : public Section
611 {
612 public:
TraceCpuSourceSection(ParsedTrace & result)613 TraceCpuSourceSection(ParsedTrace& result) : m_result(result)
614 {}
615
Define(const string & k,const string & v)616 void Define(const string& k, const string& v)
617 {
618 // k is the cpu name, v is the source name
619 m_result.cpu_source_assoc[v] = k;
620 }
621
End()622 void End() {}
623
624 private:
625 ParsedTrace& m_result;
626 };
627
NewTraceSection(const string & sectionName,ParsedTrace & result)628 auto_ptr<Section> NewTraceSection(const string& sectionName, ParsedTrace& result)
629 {
630 LogInfoStr((std::string)"Start of " + sectionName + (std::string)" section\n");
631
632 if (sectionName == TraceBuffersSectionName)
633 {
634 return auto_ptr<Section>(new TraceBufferListSection(result));
635 }
636 else if(sectionName == SourceBuffersSectionName)
637 {
638 return auto_ptr<Section>(new TraceSourceBuffersSection(result));
639 }
640 else if(sectionName == CoreSourcesSectionName)
641 {
642 return auto_ptr<Section>(new TraceCpuSourceSection(result));
643 }
644 else
645 {
646 // check the list of buffer sections
647 std::vector<std::string>::iterator it = result.buffer_section_names.begin();
648 bool matchedName = false;
649 while(it != result.buffer_section_names.end())
650 {
651 if(sectionName == *it)
652 {
653 return auto_ptr<Section>(new TraceBufferSection(result, sectionName));
654 }
655 it++;
656 }
657 // ignore unexpected sections,
658 return auto_ptr<Section>(new IgnoredSection);
659 }
660 };
661
662
663 }
664
665 using namespace ParserPrivate;
666
ParseSingleDevice(istream & in)667 Parser::Parsed Parser::ParseSingleDevice(istream& in)
668 {
669 Parsed result;
670
671 string line;
672 auto_ptr<Section> section(new NullSection);
673
674 while (getline(in, line))
675 {
676 CleanLine(line); // remove LF, comments
677 string sectionName;
678
679 if (IsSectionHeader(line, sectionName))
680 {
681 // Section ends with start of next section...
682 section->End();
683 section = NewSection(sectionName, result);
684 }
685 else if (!IsEmpty(line))
686 {
687 if (dynamic_cast<IgnoredSection *>(section.get()) == NULL)
688 { // NOT an ignored section, so process it
689 pair<string, string> kv(SplitKeyValue(line));
690 section->Define(kv.first, kv.second);
691 }
692 }
693 }
694 // ... or end of file
695 section->End();
696 return result;
697 }
698
ParseDeviceList(istream & in)699 Parser::ParsedDevices Parser::ParseDeviceList(istream& in)
700 {
701 ParsedDevices result;
702 result.snapshotInfo.description = "";
703 // call the original format 0.0, the device_list format 0.1 and the flexible format (including version) 1.0
704 result.snapshotInfo.version = "0.1";
705 string line;
706 auto_ptr<Section> section(new NullSection);
707
708 while (getline(in, line))
709 {
710 CleanLine(line); // remove LF, comments
711 string sectionName;
712
713 if (IsSectionHeader(line, sectionName))
714 {
715 // Section ends with start of next section...
716 section->End();
717
718 if (sectionName == SnapshotSectionName)
719 section = NewSnapshotInfo(sectionName, result);
720 else if(sectionName == TraceSectionName)
721 section = NewTraceMetaData(sectionName, result);
722 else // else rather than elseif for closer compatibility with old tests
723 section = NewDeviceList(sectionName, result);
724 }
725 else if (!IsEmpty(line) &&
726 ( dynamic_cast<DeviceListSection *>(section.get()) != NULL ||
727 dynamic_cast<SnapshotSection *>(section.get()) != NULL ||
728 dynamic_cast<TraceSection *>(section.get()) != NULL
729 )
730 )
731 {
732 pair<string, string> kv(SplitKeyValue(line));
733 section->Define(kv.first, kv.second);
734 }
735 }
736 // ... or end of file
737 section->End();
738
739 return result;
740 }
741
742
743 // parse the trace metadata ini file.
ParseTraceMetaData(std::istream & in)744 ParsedTrace Parser::ParseTraceMetaData(std::istream& in)
745 {
746 ParsedTrace result;
747
748 string line;
749 auto_ptr<Section> section(new NullSection);
750
751 while (getline(in, line))
752 {
753 CleanLine(line); // remove LF, comments
754 string sectionName;
755
756 if (IsSectionHeader(line, sectionName))
757 {
758 // Section ends with start of next section...
759 section->End();
760 section = NewTraceSection(sectionName, result);
761 }
762 else if (!IsEmpty(line))
763 {
764 if (dynamic_cast<IgnoredSection *>(section.get()) == NULL)
765 { // NOT an ignored section, so process it
766 pair<string, string> kv(SplitKeyValue(line));
767 section->Define(kv.first, kv.second);
768 }
769 }
770 }
771 // ... or end of file
772 section->End();
773 return result;
774 }
775
776 // build a source tree for a single buffer
ExtractSourceTree(const std::string & buffer_name,ParsedTrace & metadata,TraceBufferSourceTree & buffer_data)777 bool Parser::ExtractSourceTree(const std::string &buffer_name, ParsedTrace &metadata, TraceBufferSourceTree &buffer_data)
778 {
779 bool bFoundbuffer = false;
780 std::vector<TraceBufferInfo>::iterator it = metadata.trace_buffers.begin();
781
782 while((it != metadata.trace_buffers.end()) && !bFoundbuffer)
783 {
784 if(it->bufferName == buffer_name)
785 {
786 bFoundbuffer = true;
787 buffer_data.buffer_info = *it;
788 }
789 it++;
790 }
791
792 if(bFoundbuffer)
793 {
794 std::map<std::string, std::string>::iterator sbit = metadata.source_buffer_assoc.begin();
795 while(sbit != metadata.source_buffer_assoc.end())
796 {
797 if(sbit->second == buffer_data.buffer_info.bufferName)
798 {
799 // found a source in this buffer...
800 buffer_data.source_core_assoc[sbit->first] = metadata.cpu_source_assoc[sbit->first];
801 }
802 sbit++;
803 }
804 }
805 return bFoundbuffer;
806 }
807
GetBufferNameList(ParsedTrace & metadata)808 std::vector<std::string> Parser::GetBufferNameList(ParsedTrace &metadata)
809 {
810 std::vector<std::string> nameList;
811 std::vector<TraceBufferInfo>::iterator it = metadata.trace_buffers.begin();
812 while(it != metadata.trace_buffers.end())
813 {
814 nameList.push_back(it->bufferName);
815 it++;
816 }
817 return nameList;
818 }
819
SetIErrorLogger(ITraceErrorLog * i_err_log)820 void Parser::SetIErrorLogger(ITraceErrorLog *i_err_log)
821 {
822 s_pErrorLogger = i_err_log;
823 if(s_pErrorLogger)
824 {
825 s_errlog_handle = s_pErrorLogger->RegisterErrorSource("snapshot_parser");
826 }
827 }
828
GetIErrorLogger()829 ITraceErrorLog *Parser::GetIErrorLogger()
830 {
831 return s_pErrorLogger;
832 }
833
LogInfoStr(const std::string & logMsg)834 void Parser::LogInfoStr(const std::string &logMsg)
835 {
836 if(GetIErrorLogger() && s_verbose_logging)
837 GetIErrorLogger()->LogMessage(s_errlog_handle,OCSD_ERR_SEV_INFO,logMsg);
838 }
839
SetVerboseLogging(bool verbose)840 void Parser::SetVerboseLogging(bool verbose)
841 {
842 s_verbose_logging = verbose;
843 }
844 /* End of File snapshot_parser.cpp */
845