]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - decoder/tests/snapshot_parser_lib/source/snapshot_parser.cpp
Import OpenCSD -- an ARM CoreSight Trace Decode library.
[FreeBSD/FreeBSD.git] / decoder / tests / snapshot_parser_lib / source / snapshot_parser.cpp
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
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>
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
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      */
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> 
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
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:
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:
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         }
151         void End() {}
152     };
153
154     //! Silently ignore sections that are undefined
155     class IgnoredSection : public Section
156     {
157     public:
158         void Define(const string& , const string&)
159         {
160         }
161         void End() {}
162     };
163
164     //! Handle a [global] section.
165     class GlobalSection : public Section
166     {
167     public:
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
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
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:
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
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
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:
273         ExtendRegsSection(Parsed& result) : m_result(result)
274         {}
275
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
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:
291         SymbolicRegsSection(Parsed& result) : m_result(result)
292         {}
293
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
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:
310         DeviceSection(Parsed& result) : m_result(result), gotName(false),  gotClass(false), gotType(false)
311         {}
312
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
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
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:
378         DeviceListSection(ParsedDevices& result) : m_result(result), nextId(1)
379         {}
380
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
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
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:
417         SnapshotSection(SnapshotInfo& result) : m_result(result), m_gotDescription(false), m_gotVersion(false)
418         {}
419
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         }
436         SnapshotInfo getSnapshotInfo() { return m_result; }
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
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:
466         TraceSection(ParsedDevices& result) : m_result(result), gotName(false)
467         {}
468
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
478         void End() {}
479
480     private:
481         ParsedDevices&     m_result;
482         bool               gotName;
483     };
484
485     //! Instantiate the appropriate handler for the section name
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:
505         TraceBufferListSection(ParsedTrace& result) : m_result(result), gotList(false)
506         {}
507
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
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:
537         TraceBufferSection(ParsedTrace& result, const std::string &sectionName) : m_result(result), m_sectionName(sectionName),
538             name(""), file(""), format(""), gotName(false), gotFile(false), gotFormat(false)
539         {}
540
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
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:
591         TraceSourceBuffersSection(ParsedTrace& result) : m_result(result)
592         {}
593
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
600         void End() {}
601
602     private:
603         ParsedTrace&     m_result;
604     };
605
606     class TraceCpuSourceSection : public Section
607     {
608     public:
609         TraceCpuSourceSection(ParsedTrace& result) : m_result(result)
610         {}
611
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
618         void End() {}
619
620     private:
621         ParsedTrace&     m_result;
622     };
623
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
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
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.
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
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
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
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
825 ITraceErrorLog *Parser::GetIErrorLogger() 
826
827     return s_pErrorLogger; 
828 }
829
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
836 void Parser::SetVerboseLogging(bool verbose) 
837
838     s_verbose_logging = verbose; 
839 }
840 /* End of File snapshot_parser.cpp */