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