• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * \file       ss_to_dcdtree.cpp
3  * \brief      OpenCSD :
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 "ss_to_dcdtree.h"
36 #include "ss_key_value_names.h"
37 
38 
CreateDcdTreeFromSnapShot()39 CreateDcdTreeFromSnapShot::CreateDcdTreeFromSnapShot() :
40     m_bInit(false),
41     m_pDecodeTree(0),
42     m_pReader(0),
43     m_pErrLogInterface(0),
44     m_bPacketProcOnly(false),
45     m_BufferFileName("")
46 {
47     m_errlog_handle = 0;
48 }
49 
~CreateDcdTreeFromSnapShot()50 CreateDcdTreeFromSnapShot::~CreateDcdTreeFromSnapShot()
51 {
52     destroyDecodeTree();
53 }
54 
initialise(SnapShotReader * pReader,ITraceErrorLog * pErrLogInterface)55 void CreateDcdTreeFromSnapShot::initialise(SnapShotReader *pReader, ITraceErrorLog *pErrLogInterface)
56 {
57     if((pErrLogInterface != 0) && (pReader != 0))
58     {
59         m_pReader = pReader;
60         m_pErrLogInterface = pErrLogInterface;
61         m_errlog_handle = m_pErrLogInterface->RegisterErrorSource("ss2_dcdtree");
62         m_bInit = true;
63     }
64 }
65 
createDecodeTree(const std::string & SourceName,bool bPacketProcOnly)66 bool CreateDcdTreeFromSnapShot::createDecodeTree(const std::string &SourceName, bool bPacketProcOnly)
67 {
68     if(m_bInit)
69     {
70         if(!m_pReader->snapshotReadOK())
71         {
72             LogError("Supplied snapshot reader has not correctly read the snapshot.\n");
73             return false;
74         }
75 
76         m_bPacketProcOnly = bPacketProcOnly;
77         Parser::TraceBufferSourceTree tree;
78 
79         if(m_pReader->getTraceBufferSourceTree(SourceName, tree))
80         {
81             int numDecodersCreated = 0; // count how many we create - if none then give up.
82             uint32_t formatter_flags = OCSD_DFRMTR_FRAME_MEM_ALIGN;
83 
84             /* make a note of the trace binary file name + path to ss directory */
85             m_BufferFileName = m_pReader->getSnapShotDir() + tree.buffer_info.dataFileName;
86 
87             ocsd_dcd_tree_src_t src_format = tree.buffer_info.dataFormat == "source_data" ? OCSD_TRC_SRC_SINGLE : OCSD_TRC_SRC_FRAME_FORMATTED;
88 
89             if (tree.buffer_info.dataFormat == "dstream_coresight")
90                 formatter_flags = OCSD_DFRMTR_HAS_FSYNCS;
91 
92             /* create the initial device tree */
93             // TBD:     handle syncs / hsyncs data from TPIU
94             m_pDecodeTree = DecodeTree::CreateDecodeTree(src_format, formatter_flags);
95             if(m_pDecodeTree == 0)
96             {
97                 LogError("Failed to create decode tree object\n");
98                 return false;
99             }
100 
101             // use our error logger - don't use the tree default.
102             m_pDecodeTree->setAlternateErrorLogger(m_pErrLogInterface);
103 
104             if(!bPacketProcOnly)
105             {
106                 m_pDecodeTree->createMemAccMapper();
107             }
108 
109             /* run through each protocol source to this buffer... */
110             std::map<std::string, std::string>::iterator it = tree.source_core_assoc.begin();
111 
112             while(it != tree.source_core_assoc.end())
113             {
114                 Parser::Parsed *etm_dev, *core_dev;
115                 if(m_pReader->getDeviceData(it->first,&etm_dev))
116                 {
117                     // found the device data for this device.
118 
119                     // see if we have a core name (STM / ITM not associated with a core);
120                     std::string coreDevName = it->second;
121                     if(coreDevName.size() > 0)
122                     {
123                         if(m_pReader->getDeviceData(coreDevName,&core_dev))
124                         {
125                             if(createPEDecoder(core_dev->deviceTypeName,etm_dev))
126                             {
127                                 numDecodersCreated++;
128                                 if(!bPacketProcOnly &&(core_dev->dumpDefs.size() > 0))
129                                 {
130                                     processDumpfiles(core_dev->dumpDefs);
131                                 }
132                             }
133                             else
134                             {
135                                 std::ostringstream oss;
136                                 oss << "Failed to create decoder for source " << it->first << ".\n";
137                                 LogError(oss.str());
138                             }
139                         }
140                         else
141                         {
142                             // Could not find the device data for the core.
143                             // unexpected - since we created the associations.
144                             std::ostringstream oss;
145                             oss << "Failed to get device data for source " << it->first << ".\n";
146                             LogError(oss.str());
147                         }
148                     }
149                     else
150                     {
151                         // none-core source
152                         if(createSTDecoder(etm_dev))
153                         {
154                              numDecodersCreated++;
155                         }
156                         else
157                         {
158                             std::ostringstream oss;
159                             oss << "Failed to create decoder for none core source " << it->first << ".\n";
160                             LogError(oss.str());
161                         }
162                     }
163                 }
164                 else
165                 {
166                     // TBD: could not find the device data for the source.
167                     // again unexpected - suggests ss format error.
168                     std::ostringstream oss;
169                     oss << "Failed to find device data for source " << it->first << ".\n";
170                     LogError(oss.str());
171                 }
172                 if(src_format == OCSD_TRC_SRC_SINGLE)
173                     it = tree.source_core_assoc.end();
174                 else
175                     it++;
176             }
177 
178             if(numDecodersCreated == 0)
179             {
180                 // nothing useful found
181                 destroyDecodeTree();
182             }
183         }
184         else
185         {
186             std::ostringstream oss;
187             oss << "Failed to get parsed source tree for buffer " << SourceName << ".\n";
188             LogError(oss.str());
189         }
190     }
191     return (bool)(m_pDecodeTree != 0);
192 }
193 
destroyDecodeTree()194 void CreateDcdTreeFromSnapShot::destroyDecodeTree()
195 {
196     if(m_pDecodeTree)
197         DecodeTree::DestroyDecodeTree(m_pDecodeTree);
198     m_pDecodeTree = 0;
199     m_pReader = 0;
200     m_pErrLogInterface = 0;
201     m_errlog_handle = 0;
202     m_BufferFileName = "";
203 }
204 
LogError(const std::string & msg)205 void  CreateDcdTreeFromSnapShot::LogError(const std::string &msg)
206 {
207     ocsdError err(OCSD_ERR_SEV_ERROR,OCSD_ERR_TEST_SS_TO_DECODER,msg);
208     m_pErrLogInterface->LogError(m_errlog_handle,&err);
209 }
210 
LogError(const ocsdError & err)211 void CreateDcdTreeFromSnapShot::LogError(const ocsdError &err)
212 {
213     m_pErrLogInterface->LogError(m_errlog_handle,&err);
214 }
215 
createPEDecoder(const std::string & coreName,Parser::Parsed * devSrc)216 bool CreateDcdTreeFromSnapShot::createPEDecoder(const std::string &coreName, Parser::Parsed *devSrc)
217 {
218     bool bCreatedDecoder = false;
219     std::string devTypeName = devSrc->deviceTypeName;
220 
221     // split off .x from type name.
222     std::string::size_type pos = devTypeName.find_first_of('.');
223     if(pos != std::string::npos)
224         devTypeName = devTypeName.substr(0,pos);
225 
226     // split according to protocol
227     if(devTypeName == ETMv4Protocol)
228     {
229         bCreatedDecoder = createETMv4Decoder(coreName,devSrc);
230     }
231     else if(devTypeName == ETMv3Protocol)
232     {
233         bCreatedDecoder = createETMv3Decoder(coreName,devSrc);
234     }
235     else if(devTypeName == PTMProtocol || devTypeName == PFTProtocol)
236     {
237         bCreatedDecoder = createPTMDecoder(coreName,devSrc);
238     }
239 
240     return bCreatedDecoder;
241 }
242 
243 // create an ETMv4 decoder based on the deviceN.ini file.
createETMv4Decoder(const std::string & coreName,Parser::Parsed * devSrc,const bool bDataChannel)244 bool CreateDcdTreeFromSnapShot::createETMv4Decoder(const std::string &coreName, Parser::Parsed *devSrc, const bool bDataChannel /* = false*/)
245 {
246     bool createdDecoder = false;
247     bool configOK = true;
248 
249     // generate the config data from the device data.
250     ocsd_etmv4_cfg config;
251 
252     regs_to_access_t regs_to_access[] = {
253         { ETMv4RegCfg, true, &config.reg_configr, 0 },
254         { ETMv4RegIDR, true, &config.reg_traceidr, 0 },
255         { ETMv4RegIDR0, true, &config.reg_idr0, 0 },
256         { ETMv4RegIDR1, false, &config.reg_idr1, 0x4100F403 },
257         { ETMv4RegIDR2, true, &config.reg_idr2, 0 },
258         { ETMv4RegIDR8, false, &config.reg_idr8, 0 },
259         { ETMv4RegIDR9, false, &config.reg_idr9, 0 },
260         { ETMv4RegIDR10, false, &config.reg_idr10, 0 },
261         { ETMv4RegIDR11, false, &config.reg_idr11, 0 },
262         { ETMv4RegIDR12, false, &config.reg_idr12, 0 },
263         { ETMv4RegIDR13,false, &config.reg_idr13, 0 },
264     };
265 
266     // extract registers
267     configOK = getRegisters(devSrc->regDefs,sizeof(regs_to_access)/sizeof(regs_to_access_t), regs_to_access);
268 
269     // extract core profile
270     if(configOK)
271         configOK = getCoreProfile(coreName,config.arch_ver,config.core_prof);
272 
273     // good config - generate the decoder on the tree.
274     if(configOK)
275     {
276         ocsd_err_t err = OCSD_OK;
277         EtmV4Config configObj(&config);
278         const char *decoderName = bDataChannel ? OCSD_BUILTIN_DCD_ETMV4D : OCSD_BUILTIN_DCD_ETMV4I;
279 
280         err = m_pDecodeTree->createDecoder(decoderName, m_bPacketProcOnly ? OCSD_CREATE_FLG_PACKET_PROC : OCSD_CREATE_FLG_FULL_DECODER,&configObj);
281 
282         if(err ==  OCSD_OK)
283             createdDecoder = true;
284         else
285         {
286             std::string msg = "Snapshot processor : failed to create " +  (std::string)decoderName + " decoder on decode tree.";
287             LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,msg));
288         }
289     }
290 
291     return createdDecoder;
292 }
293 
294 // create an ETMv3 decoder based on the register values in the deviceN.ini file.
createETMv3Decoder(const std::string & coreName,Parser::Parsed * devSrc)295 bool CreateDcdTreeFromSnapShot::createETMv3Decoder(const std::string &coreName, Parser::Parsed *devSrc)
296 {
297     bool createdDecoder = false;
298     bool configOK = true;
299 
300     // generate the config data from the device data.
301     ocsd_etmv3_cfg cfg_regs;
302 
303     regs_to_access_t regs_to_access[] = {
304         { ETMv3PTMRegIDR, true, &cfg_regs.reg_idr, 0 },
305         { ETMv3PTMRegCR, true, &cfg_regs.reg_ctrl, 0 },
306         { ETMv3PTMRegCCER, true, &cfg_regs.reg_ccer, 0 },
307         { ETMv3PTMRegTraceIDR, true, &cfg_regs.reg_trc_id, 0}
308     };
309 
310     // extract registers
311     configOK = getRegisters(devSrc->regDefs,sizeof(regs_to_access)/sizeof(regs_to_access_t), regs_to_access);
312 
313     // extract core profile
314     if(configOK)
315         configOK = getCoreProfile(coreName,cfg_regs.arch_ver,cfg_regs.core_prof);
316 
317     // good config - generate the decoder on the tree.
318     if(configOK)
319     {
320         EtmV3Config config(&cfg_regs);
321         ocsd_err_t err = OCSD_OK;
322         err = m_pDecodeTree->createDecoder(OCSD_BUILTIN_DCD_ETMV3, m_bPacketProcOnly ? OCSD_CREATE_FLG_PACKET_PROC : OCSD_CREATE_FLG_FULL_DECODER,&config);
323 
324         if(err ==  OCSD_OK)
325             createdDecoder = true;
326         else
327             LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Snapshot processor : failed to create ETMV3 decoder on decode tree."));
328     }
329     return createdDecoder;
330 }
331 
createPTMDecoder(const std::string & coreName,Parser::Parsed * devSrc)332 bool CreateDcdTreeFromSnapShot::createPTMDecoder(const std::string &coreName, Parser::Parsed *devSrc)
333 {
334     bool createdDecoder = false;
335     bool configOK = true;
336 
337     // generate the config data from the device data.
338 
339     ocsd_ptm_cfg config;
340 
341     regs_to_access_t regs_to_access[] = {
342         { ETMv3PTMRegIDR, true, &config.reg_idr, 0 },
343         { ETMv3PTMRegCR, true, &config.reg_ctrl, 0 },
344         { ETMv3PTMRegCCER, true, &config.reg_ccer, 0 },
345         { ETMv3PTMRegTraceIDR, true, &config.reg_trc_id, 0}
346     };
347 
348     // extract registers
349     configOK = getRegisters(devSrc->regDefs,sizeof(regs_to_access)/sizeof(regs_to_access_t), regs_to_access);
350 
351     // extract core profile
352     if(configOK)
353         configOK = getCoreProfile(coreName,config.arch_ver,config.core_prof);
354 
355     // good config - generate the decoder on the tree.
356     if(configOK)
357     {
358         PtmConfig configObj(&config);
359         ocsd_err_t err = OCSD_OK;
360         err = m_pDecodeTree->createDecoder(OCSD_BUILTIN_DCD_PTM, m_bPacketProcOnly ? OCSD_CREATE_FLG_PACKET_PROC : OCSD_CREATE_FLG_FULL_DECODER,&configObj);
361 
362         if(err ==  OCSD_OK)
363             createdDecoder = true;
364         else
365             LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Snapshot processor : failed to create PTM decoder on decode tree."));
366     }
367     return createdDecoder;
368 }
369 
createSTDecoder(Parser::Parsed * devSrc)370 bool CreateDcdTreeFromSnapShot::createSTDecoder(Parser::Parsed *devSrc)
371 {
372     bool bCreatedDecoder = false;
373     std::string devTypeName = devSrc->deviceTypeName;
374 
375     // split off .x from type name.
376     std::string::size_type pos = devTypeName.find_first_of('.');
377     if(pos != std::string::npos)
378         devTypeName = devTypeName.substr(0,pos);
379 
380     if(devTypeName == STMProtocol)
381     {
382         bCreatedDecoder = createSTMDecoder(devSrc);
383     }
384 
385     return bCreatedDecoder;
386 }
387 
createSTMDecoder(Parser::Parsed * devSrc)388 bool CreateDcdTreeFromSnapShot::createSTMDecoder(Parser::Parsed *devSrc)
389 {
390     bool createdDecoder = false;
391     bool configOK = true;
392 
393     // generate the config data from the device data.
394 
395     ocsd_stm_cfg config;
396 
397     regs_to_access_t regs_to_access[] = {
398         { STMRegTCSR, true, &config.reg_tcsr, 0 }
399     };
400 
401     configOK = getRegisters(devSrc->regDefs,sizeof(regs_to_access)/sizeof(regs_to_access_t), regs_to_access);
402     if(configOK)
403     {
404         ocsd_err_t err = OCSD_OK;
405         STMConfig configObj(&config);
406 
407         err = m_pDecodeTree->createDecoder(OCSD_BUILTIN_DCD_STM, m_bPacketProcOnly ? OCSD_CREATE_FLG_PACKET_PROC : OCSD_CREATE_FLG_FULL_DECODER,&configObj);
408 
409         if(err ==  OCSD_OK)
410             createdDecoder = true;
411         else
412             LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Snapshot processor : failed to create STM decoder on decode tree."));
413     }
414 
415     return createdDecoder;
416 }
417 
418 
419 
420 // get a set of register values.
getRegisters(std::map<std::string,std::string,Util::CaseInsensitiveLess> & regDefs,int numRegs,regs_to_access_t * reg_access_array)421 bool CreateDcdTreeFromSnapShot::getRegisters(std::map<std::string, std::string, Util::CaseInsensitiveLess> &regDefs, int numRegs, regs_to_access_t *reg_access_array)
422 {
423     bool regsOK = true;
424 
425     for(int rv = 0; rv < numRegs; rv++)
426     {
427         if(!getRegByPrefix( regDefs,reg_access_array[rv]))
428             regsOK = false;
429     }
430     return regsOK;
431 }
432 
433 // strip out any parts with brackets
getRegByPrefix(std::map<std::string,std::string,Util::CaseInsensitiveLess> & regDefs,regs_to_access_t & reg_accessor)434 bool CreateDcdTreeFromSnapShot::getRegByPrefix(std::map<std::string, std::string, Util::CaseInsensitiveLess> &regDefs,
435     regs_to_access_t &reg_accessor)
436 {
437     std::ostringstream oss;
438     bool bFound = false;
439     std::map<std::string, std::string, Util::CaseInsensitiveLess>::iterator it;
440     std::string prefix_cmp;
441     std::string::size_type pos;
442     std::string strval;
443 
444     *reg_accessor.value = 0;
445 
446     it = regDefs.begin();
447     while((it != regDefs.end()) && !bFound)
448     {
449         prefix_cmp = it->first;
450         pos = prefix_cmp.find_first_of('(');
451         if(pos != std::string::npos)
452         {
453             prefix_cmp = prefix_cmp.substr(0, pos);
454         }
455         if(prefix_cmp == reg_accessor.pszName)
456         {
457             strval = it->second;
458             bFound = true;
459         }
460         it++;
461     }
462 
463     if(bFound)
464         *reg_accessor.value = strtoul(strval.c_str(),0,0);
465     else
466     {
467         ocsd_err_severity_t sev = OCSD_ERR_SEV_ERROR;
468         if(reg_accessor.failIfMissing)
469         {
470             oss << "Error:";
471         }
472         else
473         {
474             // no fail if missing - set any default and just warn.
475             bFound = true;
476             oss << "Warning: Default set for register. ";
477             sev = OCSD_ERR_SEV_WARN;
478             *reg_accessor.value = reg_accessor.val_default;
479         }
480         oss << "Missing " << reg_accessor.pszName << "\n";
481         m_pErrLogInterface->LogMessage(m_errlog_handle, sev, oss.str());
482     }
483     return bFound;
484 }
485 
getCoreProfile(const std::string & coreName,ocsd_arch_version_t & arch_ver,ocsd_core_profile_t & core_prof)486 bool CreateDcdTreeFromSnapShot::getCoreProfile(const std::string &coreName, ocsd_arch_version_t &arch_ver, ocsd_core_profile_t &core_prof)
487 {
488     bool profileOK = true;
489     ocsd_arch_profile_t ap = m_arch_profiles.getArchProfile(coreName);
490     if(ap.arch != ARCH_UNKNOWN)
491     {
492         arch_ver = ap.arch;
493         core_prof = ap.profile;
494     }
495     else
496     {
497         std::ostringstream oss;
498         oss << "Unrecognized Core name " << coreName << ". Cannot evaluate profile or architecture.";
499         LogError(oss.str());
500         profileOK = false;
501     }
502     return profileOK;
503 }
504 
processDumpfiles(std::vector<Parser::DumpDef> & dumps)505 void CreateDcdTreeFromSnapShot::processDumpfiles(std::vector<Parser::DumpDef> &dumps)
506 {
507     std::string dumpFilePathName;
508     std::vector<Parser::DumpDef>::const_iterator it;
509 
510     it = dumps.begin();
511     while(it != dumps.end())
512     {
513         dumpFilePathName = m_pReader->getSnapShotDir() + it->path;
514         ocsd_file_mem_region_t region;
515         ocsd_err_t err = OCSD_OK;
516 
517         region.start_address = it->address;
518         region.file_offset = it->offset;
519         region.region_size = it->length;
520 
521         // ensure we respect optional length and offset parameter and
522         // allow multiple dump entries with same file name to define regions
523         if (!TrcMemAccessorFile::isExistingFileAccessor(dumpFilePathName))
524             err = m_pDecodeTree->addBinFileRegionMemAcc(&region, 1, OCSD_MEM_SPACE_ANY, dumpFilePathName);
525         else
526             err = m_pDecodeTree->updateBinFileRegionMemAcc(&region, 1, OCSD_MEM_SPACE_ANY, dumpFilePathName);
527         if(err != OCSD_OK)
528         {
529             std::ostringstream oss;
530             oss << "Failed to create memory accessor for file " << dumpFilePathName << ".";
531             LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,oss.str()));
532         }
533         it++;
534     }
535 }
536 
537 /* End of File ss_to_dcdtree.cpp */
538