diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 07:24:57 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 07:24:57 +0000 |
commit | 070852d8604cece0c31f28ff3eb8d21d9ba415fb (patch) | |
tree | 9097175a6a5b8b7e37af9a96269ac0b61a0189cd /decoder/tests/snapshot_parser_lib | |
parent | Initial commit. (diff) | |
download | libopencsd-070852d8604cece0c31f28ff3eb8d21d9ba415fb.tar.xz libopencsd-070852d8604cece0c31f28ff3eb8d21d9ba415fb.zip |
Adding upstream version 1.3.3.upstream/1.3.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'decoder/tests/snapshot_parser_lib')
16 files changed, 2927 insertions, 0 deletions
diff --git a/decoder/tests/snapshot_parser_lib/include/device_info.h b/decoder/tests/snapshot_parser_lib/include/device_info.h new file mode 100644 index 0000000..886aee6 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/include/device_info.h @@ -0,0 +1,62 @@ +/* + * \file device_info.h + * \brief OpenCSD : Snapshot parser library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DEVICE_INFO_H +#define DEVICE_INFO_H + +#include <string> + +class DeviceInfo +{ +public: + DeviceInfo() {}; + DeviceInfo(const unsigned int deviceNum, + const std::string &iniFile); + virtual ~DeviceInfo() {}; + + std::string getIniFile() const; + std::string getName(); + void setName(const std::string &n); + unsigned int getID() const; + +private: + unsigned int id; + std::string ini; + std::string name; +}; + +#endif + +/* End of File device_info.h */ diff --git a/decoder/tests/snapshot_parser_lib/include/device_parser.h b/decoder/tests/snapshot_parser_lib/include/device_parser.h new file mode 100644 index 0000000..4919501 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/include/device_parser.h @@ -0,0 +1,106 @@ +/* + * \file device_parser.h + * \brief OpenCSD : Snapshot parser library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DEVICE_PARSER_H +#define DEVICE_PARSER_H + +#include "device_info.h" +#include <memory> + +#include <map> +#include <istream> +#include <vector> +#include <cstdint> + +#include "snapshot_info.h" + +class DeviceParser +{ +public: + virtual ~DeviceParser() {}; + typedef std::shared_ptr<DeviceInfo> DevPtr; + virtual DevPtr getDevice(int devNo) =0; + virtual void getDeviceList(std::vector<int> &devices) const = 0; + virtual size_t getDeviceCount() const = 0; + +}; + +class SnapshotParser +{ +public: + virtual ~SnapshotParser() {}; + virtual std::string getDescription() const = 0; + virtual std::string getVersion() const = 0; +}; + +class ModernSnapshotParser : public DeviceParser, SnapshotParser +{ +public: + ModernSnapshotParser( std::istream &iss); + ModernSnapshotParser(); + virtual ~ModernSnapshotParser(); + + typedef std::shared_ptr<DeviceInfo> DevPtr; + DevPtr getDevice(int devNo); + void getDeviceList(std::vector<int> &devices) const; + + bool isInitialised() const; + size_t getDeviceCount() const; + + std::string getTraceMetadataFile() const; + + // Snapshot Info + std::string getDescription() const; + std::string getVersion() const; + + +private: + void addDevice(std::string rawName, std::string path); + uint32_t getUniqueDeviceID(std::string &rawName); + + void addSnapshotInfo(SnapshotInfo snap); + + SnapshotInfo snaphotInfo; + + // map stores deviceId and associated data + std::map<int, DevPtr> deviceMap; + bool initialised; + + std::string traceMetaDataIni; +}; + +#endif + +/* End of File device_parser.h */ diff --git a/decoder/tests/snapshot_parser_lib/include/ini_section_names.h b/decoder/tests/snapshot_parser_lib/include/ini_section_names.h new file mode 100644 index 0000000..a11fbc6 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/include/ini_section_names.h @@ -0,0 +1,88 @@ +/* + * \file ini_section_names.h + * \brief OpenCSD : Snapshot Parser Library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* based on original RDDI source file 'ini_section_names.h"*/ + +#ifndef INC_INI_SECTION_NAMES_H +#define INC_INI_SECTION_NAMES_H + +/* snapshot.ini keys */ +const char* const SnapshotSectionName("snapshot"); +const char* const VersionKey("version"); +const char* const DescriptionKey("description"); + +const char* const DeviceListSectionName("device_list"); + +const char* const TraceSectionName("trace"); +const char* const MetadataKey("metadata"); + +/* device .ini keys (device_N.ini or cpu_N.ini)*/ +const char* const DeviceSectionName("device"); +const char* const DeviceNameKey("name"); +const char* const DeviceClassKey("class"); +const char* const DeviceTypeKey("type"); + +const char* const SymbolicRegsSectionName("regs"); + +const char* const DumpFileSectionPrefix("dump"); +const size_t DumpFileSectionLen = 4; +const char* const DumpAddressKey("address"); +const char* const DumpLengthKey("length"); +const char* const DumpOffsetKey("offset"); +const char* const DumpFileKey("file"); +const char* const DumpSpaceKey("space"); + +/* trace.ini keys */ +const char * const TraceBuffersSectionName("trace_buffers"); +const char* const BufferListKey("buffers"); + +const char * const BufferSectionPrefix("buffer"); +const size_t BufferSectionLen = 6; +const char* const BufferNameKey("name"); +const char* const BufferFileKey("file"); +const char* const BufferFormatKey("format"); + +const char * const SourceBuffersSectionName("source_buffers"); +const char * const CoreSourcesSectionName("core_trace_sources"); + +/* deprecated / unused in trace decode */ +const char* const GlobalSectionName("global"); +const char* const CoreKey("core"); +const char* const ExtendedRegsSectionName("extendregs"); +const char* const ClustersSectionName("clusters"); + +#endif // INC_INI_SECTION_NAMES_H + +/* End of File ini_section_names.h */ diff --git a/decoder/tests/snapshot_parser_lib/include/snapshot_info.h b/decoder/tests/snapshot_parser_lib/include/snapshot_info.h new file mode 100644 index 0000000..b152c47 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/include/snapshot_info.h @@ -0,0 +1,50 @@ +/* + * \file snapshot_info.h + * \brief OpenCSD : Snapshot Parser Library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SNAPSHOT_INFO_H_ +#define SNAPSHOT_INFO_H_ + +#include <string> + +struct SnapshotInfo +{ + std::string version; + std::string description; +}; + + +#endif /* SNAPSHOT_INFO_H_ */ + +/* End of File snapshot_info.h */ diff --git a/decoder/tests/snapshot_parser_lib/include/snapshot_parser.h b/decoder/tests/snapshot_parser_lib/include/snapshot_parser.h new file mode 100644 index 0000000..9e5b371 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/include/snapshot_parser.h @@ -0,0 +1,152 @@ +/* + * \file snapshot_parser.h + * \brief OpenCSD : Snapshot Parser Library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_SNAPSHOT_PARSER_H_INCLUDED +#define ARM_SNAPSHOT_PARSER_H_INCLUDED + +#include <cstdint> +#include <sstream> +#include <exception> +#include <string> +#include <vector> +#include <map> +#include <istream> + +#include "snapshot_parser_util.h" +#include "snapshot_info.h" + +class ITraceErrorLog; // forward declare the OCSD error log interface. + +namespace Parser +{ + //! \brief Stores a parsed [dump] section + struct DumpDef + { + uint64_t address; + std::string path; + std::size_t length; + std::size_t offset; + std::string space; + }; + + + + //! \brief Stores the entire parsed device ini file + struct Parsed + { + Parsed() : foundGlobal() {} + + bool foundGlobal; + std::string core; + std::vector<DumpDef> dumpDefs; + std::map<std::string, + std::string, // register value is stored as a string initially to cope with > 64 bit registers + Util::CaseInsensitiveLess> regDefs; + std::map<uint32_t, uint32_t> extendRegDefs; + std::string deviceName; + std::string deviceClass; + std::string deviceTypeName; // Cortex-Ax or ETMvN + + + }; + /*! \brief Parse the device ini file and call back on the builder as appropriate. + * \param input the ini file + * \return parsed definitions + */ + Parsed ParseSingleDevice(std::istream& input); + + //! \brief Stores the entire device list + struct ParsedDevices + { + std::map<std::string, std::string> deviceList; + SnapshotInfo snapshotInfo; + std::string traceMetaDataName; + }; + + /*! \brief Parse the snapshot.ini file that contains the device list and call back on the builder as appropriate. + * \param input the ini file + * \return parsed definitions + */ + ParsedDevices ParseDeviceList(std::istream& input); + + // basic info about the buffer + struct TraceBufferInfo + { + std::string bufferName; + std::string dataFileName; + std::string dataFormat; + }; + + // list of buffers and associations as presented in the ini file. + struct ParsedTrace + { + std::vector<std::string> buffer_section_names; + std::vector<TraceBufferInfo> trace_buffers; + std::map<std::string, std::string> source_buffer_assoc; // trace source name -> trace buffer name assoc + std::map<std::string, std::string> cpu_source_assoc; // trace source name -> cpu_name assoc + }; + + // single buffer information containing just the assoc for the buffer + // -> created by processing the ini data for a single named buffer. + // this can then be used to create a decode tree in the decode library. + struct TraceBufferSourceTree + { + TraceBufferInfo buffer_info; + std::map<std::string, std::string> source_core_assoc; // list of source names attached to core device names (e.g. ETM_0:cpu_0) + }; + + // parse the trace metadata ini file. + ParsedTrace ParseTraceMetaData(std::istream& input); + + // build a source tree for a single buffer + bool ExtractSourceTree(const std::string &buffer_name, ParsedTrace &metadata, TraceBufferSourceTree &buffer_data); + + std::vector<std::string> GetBufferNameList(ParsedTrace &metadata); + + + //static ITraceErrorLog *s_pErrorLogger = 0; + //static ocsd_hndl_err_log_t s_errlog_handle = 0; + //static bool s_verbose_logging = true; + + void SetIErrorLogger(ITraceErrorLog *i_err_log); + void SetVerboseLogging(bool verbose); + ITraceErrorLog *GetIErrorLogger(); + void LogInfoStr(const std::string &logMsg); + + +} + +#endif // ARM_SNAPSHOT_PARSER_H_INCLUDED + +/* End of File snapshot_parser.h */ diff --git a/decoder/tests/snapshot_parser_lib/include/snapshot_parser_util.h b/decoder/tests/snapshot_parser_lib/include/snapshot_parser_util.h new file mode 100644 index 0000000..d4fd6cd --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/include/snapshot_parser_util.h @@ -0,0 +1,112 @@ +/* + * \file snapshot_parser_util.h + * \brief OpenCSD : Snapshot Parser Library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_SNAPSHOT_PARSER_UTIL_H_INCLUDED +#define ARM_SNAPSHOT_PARSER_UTIL_H_INCLUDED + +#include <algorithm> +#include <string> +#include <sstream> +#include <iomanip> +#include <cctype> +#include <cstdlib> +#include <cstdint> + +#include "common/ocsd_error.h" + +namespace Util +{ + //! format an address as '0xNNNNNNNN' + std::string MakeAddressString(uint32_t address); + //! format a an address as '0xNNNNNNNNNNNNNNNN' + std::string MakeAddressString(uint64_t address); + + //! remove leading garbage from a string + std::string TrimLeft(const std::string& s, const std::string& ws = " \t"); + + //! remove trailing garbage from a string + std::string TrimRight(const std::string& s, const std::string& ws = " \t"); + + //! remove leading and trailing garbage from a string + std::string Trim(const std::string& s, const std::string& ws = " \t"); + + //! Functions to decode an integer + // + inline void ThrowUnsignedConversionError(const std::string& s) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Could not parse '" + s + "' as unsigned integer"); + } + + template <class T> + T DecodeUnsigned(const std::string& s) + { + char *endptr(0); + // Address can be up to 64 bits, ensure there is enough storage +#ifdef WIN32 + uint64_t result(_strtoui64(s.c_str(), &endptr, 0)); +#else + uint64_t result(std::strtoull(s.c_str(), &endptr, 0)); +#endif + if (*endptr != '\0') + { + ThrowUnsignedConversionError(s); + return T(); // keep compiler happy + } + return static_cast<T>(result); + } + + class CaseInsensitiveLess + { + public: + bool operator() (const std::string& s1, const std::string& s2) const + { + return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), cmp); + } + + private: + static bool cmp(unsigned char c1, unsigned char c2) + { + return std::tolower(c1) < std::tolower(c2); + } + }; + + inline bool CaseInsensitiveEquals(const std::string& s1, const std::string& s2) + { + return !CaseInsensitiveLess()(s1, s2) && !CaseInsensitiveLess()(s2, s1); + } +} + +#endif // ARM_SNAPSHOT_PARSER_UTIL_H_INCLUDED + +/* End of File snapshot_parser_util.h */ diff --git a/decoder/tests/snapshot_parser_lib/include/snapshot_reader.h b/decoder/tests/snapshot_parser_lib/include/snapshot_reader.h new file mode 100644 index 0000000..0b3c7e5 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/include/snapshot_reader.h @@ -0,0 +1,99 @@ +/* + * \file snapshot_reader.h + * \brief OpenCSD : Snapshot Parser Library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_SNAPSHOT_READER_H_INCLUDED +#define ARM_SNAPSHOT_READER_H_INCLUDED + +#include <string> +#include <vector> + +#include "snapshot_parser.h" + +class ITraceErrorLog; + +class SnapShotReader +{ +public: + SnapShotReader(); + ~SnapShotReader(); + + void setSnapshotDir(const std::string &dir); + const std::string &getSnapShotDir() const { return m_snapshotPath; }; + + const bool readSnapShot(); // read the snapshot dir + + // true if the snapshot ini file can be found on the path. + const bool snapshotFound() const { return m_snapshot_found; }; + + const bool snapshotReadOK() const { return m_read_ok; }; + + void setErrorLogger(ITraceErrorLog *err_log); + void setVerboseOutput(const bool bVerbose) { m_verbose = bVerbose; }; + + bool getSourceBufferNameList(std::vector<std::string> &nameList); + bool getTraceBufferSourceTree(const std::string &traceBufferName, Parser::TraceBufferSourceTree &sourceTree); + + bool getDeviceData(const std::string &deviceName, Parser::Parsed **devData); + +private: + void checkPath(); // see if the ini file can be opened on the current path + void LogInfo(const std::string &msg); + void LogError(const std::string &msg); + + + std::string m_snapshotPath; // snapshot directory - default to cwd. + bool m_snapshot_found; // true if the path supplied can be opened. + ITraceErrorLog *m_i_err_log; + ocsd_hndl_err_log_t m_errlog_handle; + bool m_verbose; // true for verbose output. + bool m_read_ok; + + // list of parsed device ini files, mapped by device name . + // <device_name (ETM_0 | cpu_0)> : { <parsed_device_data> } + std::map<std::string, Parser::Parsed> m_parsed_device_list; + + Parser::ParsedTrace m_parsed_trace; // the parsed trace meta data + + // trace metadata rearranged as source trees, mapped by source name + // <source_buffer_name> : { buffer_info, {<ETM_0:cpu_0>,....} } + std::map<std::string, Parser::TraceBufferSourceTree> m_source_trees; +}; + +// the top level snapshot file name. +const char* const SnapshotINIFilename("snapshot.ini"); + +#endif // ARM_SNAPSHOT_READER_H_INCLUDED + +/* End of File snapshot_reader.h */ diff --git a/decoder/tests/snapshot_parser_lib/include/ss_key_value_names.h b/decoder/tests/snapshot_parser_lib/include/ss_key_value_names.h new file mode 100644 index 0000000..ad0823b --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/include/ss_key_value_names.h @@ -0,0 +1,80 @@ +/* + * \file ss_key_value_names.h + * \brief OpenCSD : Names and Value Strings needed to interpret snapshot .ini data + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_SS_KEY_VALUE_NAMES_H_INCLUDED +#define ARM_SS_KEY_VALUE_NAMES_H_INCLUDED + +/*** Core Profile Prefixes ***/ +const char * const CPUprofileA("Cortex-A"); +const char * const CPUprofileR("Cortex-R"); +const char * const CPUprofileM("Cortex-M"); + +/*** Trace Buffer formats ***/ +const char * const BuffFmtCS("coresight"); // coresight frame formatted. + +/***ETM v4 ***/ +const char * const ETMv4Protocol("ETM4"); +const char * const ETMv4RegCfg("TRCCONFIGR"); +const char * const ETMv4RegIDR("TRCTRACEIDR"); +const char * const ETMv4RegAuth("TRCAUTHSTATUS"); +const char * const ETMv4RegIDR0("TRCIDR0"); +const char * const ETMv4RegIDR1("TRCIDR1"); +const char * const ETMv4RegIDR2("TRCIDR2"); +const char * const ETMv4RegIDR8("TRCIDR8"); +const char * const ETMv4RegIDR9("TRCIDR9"); +const char * const ETMv4RegIDR10("TRCIDR10"); +const char * const ETMv4RegIDR11("TRCIDR11"); +const char * const ETMv4RegIDR12("TRCIDR12"); +const char * const ETMv4RegIDR13("TRCIDR13"); + +/*** ETE ***/ +const char *const ETEProtocol("ETE"); +const char *const ETERegDevArch("TRCDEVARCH"); + +/*** ETMv3/PTM ***/ +const char * const ETMv3Protocol("ETM3"); +const char * const PTMProtocol("PTM1"); +const char * const PFTProtocol("PFT1"); +const char * const ETMv3PTMRegIDR("ETMIDR"); +const char * const ETMv3PTMRegCR("ETMCR"); +const char * const ETMv3PTMRegCCER("ETMCCER"); +const char * const ETMv3PTMRegTraceIDR("ETMTRACEIDR"); + +/*** STM/ITM **/ +const char * const STMProtocol("STM"); +const char * const STMRegTCSR("STMTCSR"); + +#endif // ARM_SS_KEY_VALUE_NAMES_H_INCLUDED + +/* End of File ss_key_value_names.h */ diff --git a/decoder/tests/snapshot_parser_lib/include/ss_to_dcdtree.h b/decoder/tests/snapshot_parser_lib/include/ss_to_dcdtree.h new file mode 100644 index 0000000..3c85f9d --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/include/ss_to_dcdtree.h @@ -0,0 +1,112 @@ +/* + * \file ss_to_dcdtree.h + * \brief OpenCSD : Create a decode tree given a snapshot database. + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_SS_TO_DCDTREE_H_INCLUDED +#define ARM_SS_TO_DCDTREE_H_INCLUDED + +#include <string> + +#include "opencsd.h" +#include "snapshot_parser.h" +#include "snapshot_reader.h" + +class DecodeTree; +class ITraceErrorLog; + +class CreateDcdTreeFromSnapShot +{ +public: + CreateDcdTreeFromSnapShot(); + ~CreateDcdTreeFromSnapShot(); + + void initialise(SnapShotReader *m_pReader, ITraceErrorLog *m_pErrLogInterface); + + bool createDecodeTree(const std::string &SourceBufferName, bool bPacketProcOnly, uint32_t add_create_flags = 0); + void destroyDecodeTree(); + DecodeTree *getDecodeTree() const { return m_pDecodeTree; }; + const char *getBufferFileName() const { return m_BufferFileName.c_str(); }; + + // TBD: add in filters for ID list, first ID found. + +private: + // create a decoder related to a core source (ETM, PTM) + bool createPEDecoder(const std::string &coreName, Parser::Parsed *devSrc); + // protocol specific core source decoders + bool createETMv4Decoder(const std::string &coreName, Parser::Parsed *devSrc, const bool bDataChannel = false); + bool createETMv3Decoder(const std::string &coreName, Parser::Parsed *devSrc); + bool createPTMDecoder(const std::string &coreName, Parser::Parsed *devSrc); + bool createETEDecoder(const std::string &coreName, Parser::Parsed *devSrc); + // TBD add etmv4d + + // create a decoder related to a software trace source (ITM, STM) + bool createSTDecoder(Parser::Parsed *devSrc); + // protocol specific decoders + bool createSTMDecoder(Parser::Parsed *devSrc); + + typedef struct _regs_to_access { + const char *pszName; + bool failIfMissing; + uint32_t *value; + uint32_t val_default; + } regs_to_access_t; + + bool getRegisters(std::map<std::string, std::string, Util::CaseInsensitiveLess> ®Defs, int numRegs, regs_to_access_t *reg_access_array); + bool getRegByPrefix(std::map<std::string, std::string, Util::CaseInsensitiveLess> ®Defs, + regs_to_access_t ®_accessor); + bool getCoreProfile(const std::string &coreName, ocsd_arch_version_t &arch_ver, ocsd_core_profile_t &core_prof); + + void LogError(const std::string &msg); + void LogError(const ocsdError &err); + + void processDumpfiles(std::vector<Parser::DumpDef> &dumps); + + + uint32_t m_add_create_flags; + + bool m_bInit; + DecodeTree *m_pDecodeTree; + SnapShotReader *m_pReader; + ITraceErrorLog *m_pErrLogInterface; + ocsd_hndl_err_log_t m_errlog_handle; + + bool m_bPacketProcOnly; + std::string m_BufferFileName; + + CoreArchProfileMap m_arch_profiles; +}; + + +#endif // ARM_SS_TO_DCDTREE_H_INCLUDED + +/* End of File ss_to_dcdtree.h */ diff --git a/decoder/tests/snapshot_parser_lib/include/trace_snapshots.h b/decoder/tests/snapshot_parser_lib/include/trace_snapshots.h new file mode 100644 index 0000000..cec97a8 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/include/trace_snapshots.h @@ -0,0 +1,44 @@ +/* + * \file trace_snapshots.h + * \brief OpenCSD : Principal include file for snapshot read and parse library. + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM_TRACE_SNAPSHOTS_H_INCLUDED +#define ARM_TRACE_SNAPSHOTS_H_INCLUDED + +#include "snapshot_reader.h" +#include "snapshot_parser.h" +#include "ss_to_dcdtree.h" + +#endif // ARM_TRACE_SNAPSHOTS_H_INCLUDED + +/* End of File trace_snapshots.h */ diff --git a/decoder/tests/snapshot_parser_lib/source/device_info.cpp b/decoder/tests/snapshot_parser_lib/source/device_info.cpp new file mode 100644 index 0000000..c449441 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/source/device_info.cpp @@ -0,0 +1,70 @@ +/* + * \file device_info.cpp + * \brief OpenCSD : Snapshot Parser Library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "device_info.h" + +static unsigned int unknownCount = 0; +DeviceInfo::DeviceInfo(const unsigned int deviceNum, + const std::string &iniFile) + : ini(iniFile), id(deviceNum), name("") +{ + +} + +unsigned int DeviceInfo::getID() const +{ + return id; +} + +std::string DeviceInfo::getIniFile() const +{ + return ini; +} + +void DeviceInfo::setName(const std::string &n) +{ + name = n; +} + +std::string DeviceInfo::getName() +{ + if (name.empty()) + { + name = "UNKNOWN"; + } + return name; +} + + +/* End of File device_info.cpp */ diff --git a/decoder/tests/snapshot_parser_lib/source/device_parser.cpp b/decoder/tests/snapshot_parser_lib/source/device_parser.cpp new file mode 100644 index 0000000..3086e49 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/source/device_parser.cpp @@ -0,0 +1,157 @@ +/* + * \file device_parser.cpp + * \brief OpenCSD : Snapshot Parser Library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "device_parser.h" + +#include "snapshot_parser.h" + +#include <sstream> +#include <iostream> +#include <string> +#include <memory> +#include <cstdio> + +#include "common/ocsd_error.h" + +using namespace std; + +ModernSnapshotParser::ModernSnapshotParser() : initialised(false), traceMetaDataIni("") +{ +} + +ModernSnapshotParser::ModernSnapshotParser( std::istream &iss) : initialised(false), traceMetaDataIni("") +{ + Parser::ParsedDevices pd = Parser::ParseDeviceList(iss); + std::map<std::string, std::string> rawList = pd.deviceList; + std::map<std::string, std::string>::iterator it; + for (it = rawList.begin(); it != rawList.end(); ++it ) + { + addDevice(it->first, it->second); + } + snaphotInfo = pd.snapshotInfo; + this->traceMetaDataIni = pd.traceMetaDataName; + initialised = true; +} + +ModernSnapshotParser::~ModernSnapshotParser() +{ +} + +void ModernSnapshotParser::addDevice(std::string rawName, std::string path) +{ + uint32_t deviceID = getUniqueDeviceID(rawName); + deviceMap[deviceID] = DevPtr(new DeviceInfo(deviceID, path)); +} + +uint32_t ModernSnapshotParser::getUniqueDeviceID(std::string &rawName) +{ + size_t pos = rawName.find_first_of("0123456789"); + uint32_t candidate = 1; + if (pos != std::string::npos) + { + std::string numbers = rawName.substr(pos); + istringstream ist(numbers); + ist >> candidate; + } + while (true) + { + try + { + getDevice(candidate); + // didn't throw means already in list, so bad candidate + candidate++; + } + catch (ocsdError & /*e*/) + { + // threw, so unique ID, so this is good, leave loop + break; + } + } + return candidate; +} + +bool ModernSnapshotParser::isInitialised() const +{ + return initialised; +} + +size_t ModernSnapshotParser::getDeviceCount() const +{ + unsigned int deviceCount = 0; + if (isInitialised()) + deviceCount = deviceMap.size(); + return deviceCount; +} + +ModernSnapshotParser::DevPtr ModernSnapshotParser::getDevice(int id) +{ + map<int, DevPtr>::const_iterator it(deviceMap.find(id)); + if (it == deviceMap.end()) + { + std::ostringstream ost; + ost << "Unknown device:" << id; + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, ost.str()); + } + return it->second; +} + +void ModernSnapshotParser::addSnapshotInfo(SnapshotInfo snap) +{ + snaphotInfo = snap; +} + +void ModernSnapshotParser::getDeviceList(std::vector<int> &devices) const +{ + map<int, DevPtr>::const_iterator it; + //devices.clear(); + for (it = deviceMap.begin(); it != deviceMap.end(); ++it) + devices.push_back(it->first); +} + +std::string ModernSnapshotParser::getDescription() const +{ + return snaphotInfo.description; +} + +std::string ModernSnapshotParser::getVersion() const +{ + return snaphotInfo.version; +} + + +std::string ModernSnapshotParser::getTraceMetadataFile() const +{ + return traceMetaDataIni; +} + +/* End of File device_parser.cpp */ diff --git a/decoder/tests/snapshot_parser_lib/source/snapshot_parser.cpp b/decoder/tests/snapshot_parser_lib/source/snapshot_parser.cpp new file mode 100644 index 0000000..4570700 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/source/snapshot_parser.cpp @@ -0,0 +1,844 @@ +/* + * \file snapshot_parser.cpp + * \brief OpenCSD : Snapshot Parser Library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "snapshot_parser.h" + +#include <memory> +#include <algorithm> +#include <istream> +#include <iostream> +#include <string> +#include <utility> +using namespace std; + +#include "snapshot_parser_util.h" +#include "ini_section_names.h" +using namespace Util; +using namespace Parser; + +#include "opencsd.h" + +static ITraceErrorLog *s_pErrorLogger = 0; +static ocsd_hndl_err_log_t s_errlog_handle = 0; +static bool s_verbose_logging = true; + +/************************************************************************* + * Note, this file handles the parsring of the general (device specific) + * ini file and the (much smaller) device_list file + *************************************************************************/ + +namespace ParserPrivate +{ + //! Handle CRLF terminators and '#' and ';' comments + void CleanLine(string& line) + { + string::size_type endpos = line.find_first_of("\r;#"); + if (endpos != string::npos) + { + line.erase(endpos); + } + } + + //! Split foo=bar into pair <foo, bar> + pair<string, string> SplitKeyValue(const string& kv) + { + string::size_type eq(kv.find('=')); + if (eq == string::npos) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Couldn't parse '" + kv + "' as key=value"); + } + return make_pair(Trim(kv.substr(0, eq)), Trim(kv.substr(eq + 1))); + } + + //! Whether line is just tabs and spaces + bool IsEmpty(const string& line) + { + return TrimLeft(line) == ""; + } + + /*! \brief Whether line is of form '[header]' + * \param line the line + * \param sectionName if function returns true, returns the text between the brackets + */ + bool IsSectionHeader(const string& line, string& sectionName) + { + string::size_type openBracket(line.find('[')); + if (openBracket == string::npos) + { + return false; + } + string::size_type textStart(openBracket + 1); + string::size_type closeBracket(line.find(']', textStart)); + if (closeBracket == string::npos) + { + return false; + } + sectionName.assign(Trim(line.substr(textStart, closeBracket - textStart))); + return true; + } + + template <class M, class K, class V> + void AddUniqueKey(M& m, const K& key, const V& value, const std::string &keyStr ) + { + if (!m.insert(make_pair(key, value)).second) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Duplicate key: " + keyStr); + } + } + + void PreventDupes(bool& store, const string& key, const string& section) + { + if (store) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, + "Duplicate " + key + " key found in " + + section + " section"); + } + store = true; + } + + + /*! \class Section + * \brief Handle an ini file section begun with a section header ([header]) + */ + class Section + { + public: + virtual ~Section() {} + + //! Notify a key=value definition + virtual void Define(const string& k, const string& v) = 0; + + //! Notify end of section - we can't handle in dtor because misparses throw. + virtual void End() = 0; + }; + + //! The initial state + class NullSection : public Section + { + public: + void Define(const string& k, const string&) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Definition of '" + k + "' has no section header"); + } + void End() {} + }; + + //! Silently ignore sections that are undefined + class IgnoredSection : public Section + { + public: + void Define(const string& , const string&) + { + } + void End() {} + }; + + //! Handle a [global] section. + class GlobalSection : public Section + { + public: + GlobalSection(Parsed& result) : m_result(result), m_got_core() + { + if (m_result.foundGlobal) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, string("Only one ") + GlobalSectionName + " section allowed"); + } + m_result.foundGlobal = true; + } + + void Define(const string& k, const string& v) + { + if (k == CoreKey) + { + PreventDupes(m_got_core, CoreKey, GlobalSectionName); + m_result.core.assign(v); + } + else + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Unknown global option '" + k + '\''); + } + } + + void End() {} + + private: + Parsed& m_result; + bool m_got_core; + }; + + //! Handle a [dump] section + class DumpSection : public Section + { + public: + DumpSection(Parsed& result) + : m_result(result), + m_got_file(), m_got_address(), m_got_length(), m_got_offset(), m_got_space(), + m_address(), m_length(), m_offset(), m_file(), m_space() + {} + + void Define(const string& k, const string& v) + { + if (k == DumpAddressKey) + { + PreventDupes(m_got_address, DumpAddressKey, DumpFileSectionPrefix); + m_address = DecodeUnsigned<uint64_t>(v); + } + else if (k == DumpLengthKey) + { + PreventDupes(m_got_length, DumpLengthKey, DumpFileSectionPrefix); + m_length = DecodeUnsigned<size_t>(v); + } + else if (k == DumpOffsetKey) + { + PreventDupes(m_got_offset, DumpOffsetKey, DumpFileSectionPrefix); + m_offset = DecodeUnsigned<size_t>(v); + } + else if (k == DumpFileKey) + { + PreventDupes(m_got_file, DumpFileKey, DumpFileSectionPrefix); + m_file = Trim(v, "\"'"); // strip quotes + } + else if (k == DumpSpaceKey) + { + PreventDupes(m_got_space, DumpSpaceKey, DumpFileSectionPrefix); + m_space = Trim(v, "\"'"); // strip quotes + } + else + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Unknown dump section key '" + k + '\''); + } + } + + void End() + { + if (!m_got_address) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Dump section is missing mandatory address definition"); + } + if (!m_got_file) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Dump section is missing mandatory file definition"); + } + + struct DumpDef add = { m_address, m_file, m_length, m_offset, m_space}; + m_result.dumpDefs.push_back(add); + } + + private: + Parsed& m_result; + bool m_got_file; + bool m_got_address; + bool m_got_length; + bool m_got_offset; + bool m_got_space; + uint64_t m_address; + size_t m_length; + size_t m_offset; + string m_file; + string m_space; + }; + + //! Handle an [extendregs] section. + class ExtendRegsSection : public Section + { + public: + ExtendRegsSection(Parsed& result) : m_result(result) + {} + + void Define(const string& k, const string& v) + { + AddUniqueKey(m_result.extendRegDefs, DecodeUnsigned<uint32_t>(k), DecodeUnsigned<uint32_t>(v),k); + } + + void End() {} + + private: + Parsed& m_result; + }; + + // Handle a [regs] section + class SymbolicRegsSection : public Section + { + public: + SymbolicRegsSection(Parsed& result) : m_result(result) + {} + + void Define(const string& k, const string& v) + { + const string value = Trim(v, "\"'"); // strip quotes + AddUniqueKey(m_result.regDefs, k, value,k); + } + + void End() {} + + private: + Parsed& m_result; + }; + + // Handle a [device] section + class DeviceSection : public Section + { + public: + DeviceSection(Parsed& result) : m_result(result), gotName(false), gotClass(false), gotType(false) + {} + + void Define(const string& k, const string& v) + { + if (k == DeviceNameKey) + { + PreventDupes(gotName, k, DeviceSectionName); + m_result.deviceName = v; + } + else if(k == DeviceClassKey) + { + PreventDupes(gotClass, k, DeviceSectionName); + m_result.deviceClass = v; + } + else if(k == DeviceTypeKey) + { + PreventDupes(gotType, k, DeviceSectionName); + m_result.deviceTypeName = v; + } + } + + void End() {} + + private: + Parsed& m_result; + bool gotName; + bool gotClass; + bool gotType; + }; + + //! Instantiate the appropriate handler for the section name + auto_ptr<Section> NewSection( const string& sectionName, Parsed& result) + { + LogInfoStr( "Start of " + sectionName + " section\n"); + + if (sectionName == GlobalSectionName) + { + return auto_ptr<Section>(new GlobalSection(result)); + } + if (sectionName.substr(0,DumpFileSectionLen) == DumpFileSectionPrefix) + { + return auto_ptr<Section>(new DumpSection(result)); + } + else if (sectionName == ExtendedRegsSectionName) + { + return auto_ptr<Section>(new ExtendRegsSection(result)); + } + else if (sectionName == SymbolicRegsSectionName) + { + return auto_ptr<Section>(new SymbolicRegsSection(result)); + } + else if (sectionName == DeviceSectionName) + { + return auto_ptr<Section>(new DeviceSection(result)); + } + else + { + LogInfoStr("Unknown section ignored: " + sectionName + "\n"); + return auto_ptr<Section>(new IgnoredSection); + } + } + + /***** Device List file parsing *********************/ + //! Handle a [device_list] section. + class DeviceListSection : public Section + { + public: + DeviceListSection(ParsedDevices& result) : m_result(result), nextId(1) + {} + + void Define(const string& , const string& v) + { + // throw away supplied key - DTSL wants them monotonically increasing from 1 + std::ostringstream id; + id << nextId++; + m_result.deviceList[id.str()] = v; + } + + void End() {} + + private: + ParsedDevices& m_result; + uint32_t nextId; + }; + + //! Instantiate the appropriate handler for the section name + auto_ptr<Section> NewDeviceList(const string& sectionName, ParsedDevices& result) + { + LogInfoStr("Start of " + sectionName + " section\n"); + + if (sectionName == DeviceListSectionName) + { + return auto_ptr<Section>(new DeviceListSection(result)); + } + else + { + // ignore unexpected sections, there may be others like [trace] + // which RDDI doesn't care about + return auto_ptr<Section>(new NullSection); + } + } + + // Handle a [snapshot] section + class SnapshotSection : public Section + { + public: + SnapshotSection(SnapshotInfo& result) : m_result(result), m_gotDescription(false), m_gotVersion(false) + {} + + void Define(const string& k, const string& v) + { + if (k == VersionKey) + { + PreventDupes(m_gotVersion, k, SnapshotSectionName); + m_result.version = v; + // the only valid contents of this are 1.0, as this is the version that introduced the "snapshot" section + if (v != "1.0" && v != "1") + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Illegal snapshot file version: " + v); + } + else if (k == DescriptionKey) + { + PreventDupes(m_gotDescription, k, SnapshotSectionName); + m_result.description = v; + } + } + SnapshotInfo getSnapshotInfo() { return m_result; } + void End() {} + + private: + SnapshotInfo &m_result; + bool m_gotDescription; + bool m_gotVersion; + + }; + + //! Instantiate the appropriate handler for the section name + auto_ptr<Section> NewSnapshotInfo(const string& sectionName, ParsedDevices& result) + { + LogInfoStr((std::string)"Start of " + sectionName + (std::string)" section\n"); + + if (sectionName == SnapshotSectionName) + { + return auto_ptr<Section>(new SnapshotSection(result.snapshotInfo)); + } + else + { + // ignore unexpected sections, there may be others like [trace] + // which RDDI doesn't care about + return auto_ptr<Section>(new NullSection); + } + }; + + class TraceSection : public Section + { + public: + TraceSection(ParsedDevices& result) : m_result(result), gotName(false) + {} + + void Define(const string& k, const string& v) + { + if (k == MetadataKey) + { + PreventDupes(gotName, k, TraceSectionName); + m_result.traceMetaDataName = v; + } + } + + void End() {} + + private: + ParsedDevices& m_result; + bool gotName; + }; + + //! Instantiate the appropriate handler for the section name + auto_ptr<Section> NewTraceMetaData(const string& sectionName, ParsedDevices& result) + { + LogInfoStr((std::string)"Start of " + sectionName + (std::string)" section\n"); + + if (sectionName == TraceSectionName) + { + return auto_ptr<Section>(new TraceSection(result)); + } + else + { + // ignore unexpected sections, there may be others like [trace] + // which RDDI doesn't care about + return auto_ptr<Section>(new NullSection); + } + }; + + class TraceBufferListSection : public Section + { + public: + TraceBufferListSection(ParsedTrace& result) : m_result(result), gotList(false) + {} + + void Define(const string& k, const string& v) + { + if (k == BufferListKey) + { + PreventDupes(gotList, k, TraceBuffersSectionName); + std::string nameList = v; + std::string::size_type pos; + while((pos = nameList.find_first_of(',')) != std::string::npos) + { + m_result.buffer_section_names.push_back(nameList.substr(0,pos)); + nameList=nameList.substr(pos+1,std::string::npos); + } + m_result.buffer_section_names.push_back(nameList); + } + } + + void End() {} + + private: + ParsedTrace& m_result; + bool gotList; + }; + + //! Instantiate the appropriate handler for the section name + + + class TraceBufferSection : public Section + { + public: + TraceBufferSection(ParsedTrace& result, const std::string §ionName) : m_result(result), m_sectionName(sectionName), + name(""), file(""), format(""), gotName(false), gotFile(false), gotFormat(false) + {} + + void Define(const string& k, const string& v) + { + if (k == BufferNameKey) + { + PreventDupes(gotName, k, m_sectionName); + name = v; + } + else if (k == BufferFileKey) + { + PreventDupes(gotFile, k, m_sectionName); + file = v; + } + else if (k == BufferFormatKey) + { + PreventDupes(gotFormat, k, m_sectionName); + format = v; + } + } + + void End() + { + if (!gotName) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Trace Buffer section missing required buffer name"); + } + if (!gotFile) + { + throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Trace Buffer section is missing mandatory file definition"); + } + + struct TraceBufferInfo info = { name, file, format }; + m_result.trace_buffers.push_back(info); + } + + + private: + ParsedTrace& m_result; + std::string m_sectionName; + std::string name; + bool gotName; + std::string file; + bool gotFile; + std::string format; + bool gotFormat; + + }; + + class TraceSourceBuffersSection : public Section + { + public: + TraceSourceBuffersSection(ParsedTrace& result) : m_result(result) + {} + + void Define(const string& k, const string& v) + { + // k is the source name, v is the buffer name + m_result.source_buffer_assoc[k] = v; + } + + void End() {} + + private: + ParsedTrace& m_result; + }; + + class TraceCpuSourceSection : public Section + { + public: + TraceCpuSourceSection(ParsedTrace& result) : m_result(result) + {} + + void Define(const string& k, const string& v) + { + // k is the cpu name, v is the source name + m_result.cpu_source_assoc[v] = k; + } + + void End() {} + + private: + ParsedTrace& m_result; + }; + + auto_ptr<Section> NewTraceSection(const string& sectionName, ParsedTrace& result) + { + LogInfoStr((std::string)"Start of " + sectionName + (std::string)" section\n"); + + if (sectionName == TraceBuffersSectionName) + { + return auto_ptr<Section>(new TraceBufferListSection(result)); + } + else if(sectionName == SourceBuffersSectionName) + { + return auto_ptr<Section>(new TraceSourceBuffersSection(result)); + } + else if(sectionName == CoreSourcesSectionName) + { + return auto_ptr<Section>(new TraceCpuSourceSection(result)); + } + else + { + // check the list of buffer sections + std::vector<std::string>::iterator it = result.buffer_section_names.begin(); + bool matchedName = false; + while(it != result.buffer_section_names.end()) + { + if(sectionName == *it) + { + return auto_ptr<Section>(new TraceBufferSection(result, sectionName)); + } + it++; + } + // ignore unexpected sections, + return auto_ptr<Section>(new IgnoredSection); + } + }; + + +} + +using namespace ParserPrivate; + +Parser::Parsed Parser::ParseSingleDevice(istream& in) +{ + Parsed result; + + string line; + auto_ptr<Section> section(new NullSection); + + while (getline(in, line)) + { + CleanLine(line); // remove LF, comments + string sectionName; + + if (IsSectionHeader(line, sectionName)) + { + // Section ends with start of next section... + section->End(); + section = NewSection(sectionName, result); + } + else if (!IsEmpty(line)) + { + if (dynamic_cast<IgnoredSection *>(section.get()) == NULL) + { // NOT an ignored section, so process it + pair<string, string> kv(SplitKeyValue(line)); + section->Define(kv.first, kv.second); + } + } + } + // ... or end of file + section->End(); + return result; +} + +Parser::ParsedDevices Parser::ParseDeviceList(istream& in) +{ + ParsedDevices result; + result.snapshotInfo.description = ""; + // call the original format 0.0, the device_list format 0.1 and the flexible format (including version) 1.0 + result.snapshotInfo.version = "0.1"; + string line; + auto_ptr<Section> section(new NullSection); + + while (getline(in, line)) + { + CleanLine(line); // remove LF, comments + string sectionName; + + if (IsSectionHeader(line, sectionName)) + { + // Section ends with start of next section... + section->End(); + + if (sectionName == SnapshotSectionName) + section = NewSnapshotInfo(sectionName, result); + else if(sectionName == TraceSectionName) + section = NewTraceMetaData(sectionName, result); + else // else rather than elseif for closer compatibility with old tests + section = NewDeviceList(sectionName, result); + } + else if (!IsEmpty(line) && + ( dynamic_cast<DeviceListSection *>(section.get()) != NULL || + dynamic_cast<SnapshotSection *>(section.get()) != NULL || + dynamic_cast<TraceSection *>(section.get()) != NULL + ) + ) + { + pair<string, string> kv(SplitKeyValue(line)); + section->Define(kv.first, kv.second); + } + } + // ... or end of file + section->End(); + + return result; +} + + +// parse the trace metadata ini file. +ParsedTrace Parser::ParseTraceMetaData(std::istream& in) +{ + ParsedTrace result; + + string line; + auto_ptr<Section> section(new NullSection); + + while (getline(in, line)) + { + CleanLine(line); // remove LF, comments + string sectionName; + + if (IsSectionHeader(line, sectionName)) + { + // Section ends with start of next section... + section->End(); + section = NewTraceSection(sectionName, result); + } + else if (!IsEmpty(line)) + { + if (dynamic_cast<IgnoredSection *>(section.get()) == NULL) + { // NOT an ignored section, so process it + pair<string, string> kv(SplitKeyValue(line)); + section->Define(kv.first, kv.second); + } + } + } + // ... or end of file + section->End(); + return result; +} + + // build a source tree for a single buffer +bool Parser::ExtractSourceTree(const std::string &buffer_name, ParsedTrace &metadata, TraceBufferSourceTree &buffer_data) +{ + bool bFoundbuffer = false; + std::vector<TraceBufferInfo>::iterator it = metadata.trace_buffers.begin(); + + while((it != metadata.trace_buffers.end()) && !bFoundbuffer) + { + if(it->bufferName == buffer_name) + { + bFoundbuffer = true; + buffer_data.buffer_info = *it; + } + it++; + } + + if(bFoundbuffer) + { + std::map<std::string, std::string>::iterator sbit = metadata.source_buffer_assoc.begin(); + while(sbit != metadata.source_buffer_assoc.end()) + { + if(sbit->second == buffer_data.buffer_info.bufferName) + { + // found a source in this buffer... + buffer_data.source_core_assoc[sbit->first] = metadata.cpu_source_assoc[sbit->first]; + } + sbit++; + } + } + return bFoundbuffer; +} + +std::vector<std::string> Parser::GetBufferNameList(ParsedTrace &metadata) +{ + std::vector<std::string> nameList; + std::vector<TraceBufferInfo>::iterator it = metadata.trace_buffers.begin(); + while(it != metadata.trace_buffers.end()) + { + nameList.push_back(it->bufferName); + it++; + } + return nameList; +} + +void Parser::SetIErrorLogger(ITraceErrorLog *i_err_log) +{ + s_pErrorLogger = i_err_log; + if(s_pErrorLogger) + { + s_errlog_handle = s_pErrorLogger->RegisterErrorSource("snapshot_parser"); + } +} + +ITraceErrorLog *Parser::GetIErrorLogger() +{ + return s_pErrorLogger; +} + +void Parser::LogInfoStr(const std::string &logMsg) +{ + if(GetIErrorLogger() && s_verbose_logging) + GetIErrorLogger()->LogMessage(s_errlog_handle,OCSD_ERR_SEV_INFO,logMsg); +} + +void Parser::SetVerboseLogging(bool verbose) +{ + s_verbose_logging = verbose; +} +/* End of File snapshot_parser.cpp */ diff --git a/decoder/tests/snapshot_parser_lib/source/snapshot_parser_util.cpp b/decoder/tests/snapshot_parser_lib/source/snapshot_parser_util.cpp new file mode 100644 index 0000000..b5640c0 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/source/snapshot_parser_util.cpp @@ -0,0 +1,91 @@ +/* + * \file snapshot_parser_util.cpp + * \brief OpenCSD : Snapshot Parser Library + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "snapshot_parser_util.h" + +#include <string> +#include <sstream> +#include <iomanip> +#include <iterator> +using namespace std; + +//#include <boost/regex.hpp> + +// Make "0xNNNNNNNN" for use in user messages +string Util::MakeAddressString(uint32_t address) +{ + ostringstream oss; + oss << "0x" << hex << setw(8) << setfill('0') << address; + return oss.str(); +} + +// Make "0xNNNNNNNNNNNNNNNN" for use in user messages +string Util::MakeAddressString(uint64_t address) +{ + ostringstream oss; + oss << "0x" << hex << setw(16) << setfill('0') << address; + return oss.str(); +} + +string Util::TrimLeft(const std::string& s, const std::string& ws) +{ + string out(s); + return out.erase(0, s.find_first_not_of(ws)); +} + +string Util::TrimRight(const std::string& s, const std::string& ws) +{ + string out(s); + return out.erase(s.find_last_not_of(ws) + 1); +} + +string Util::Trim(const std::string& s, const std::string& ws) +{ + return TrimRight(TrimLeft(s, ws), ws); +} + +/*bool Util::DoRegexReplace(string& original, const string& re, + const string& replacement) +{ + const string before(original); + const boost::regex ex(re); + string after; + boost::regex_replace(back_inserter(after), before.begin(), before.end(), + ex, replacement); + original.assign(after); + return before != after; +}*/ + +/* End of File snapshot_parser_util.cpp */ diff --git a/decoder/tests/snapshot_parser_lib/source/snapshot_reader.cpp b/decoder/tests/snapshot_parser_lib/source/snapshot_reader.cpp new file mode 100644 index 0000000..4741e63 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/source/snapshot_reader.cpp @@ -0,0 +1,270 @@ +/* + * \file snapshot_reader.cpp + * \brief OpenCSD : + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "snapshot_reader.h" +#include "snapshot_parser.h" +#include "device_parser.h" + +#include "opencsd.h" + +#include <fstream> +#include <iterator> +#include <ios> +#include <iostream> + +#ifdef WIN32 +#define DIR_CHAR '\\' +#else +#define DIR_CHAR '/' +#endif + +using namespace Parser; + +SnapShotReader::SnapShotReader() : + m_snapshotPath(""), + m_snapshot_found(false), + m_i_err_log(0), + m_errlog_handle(0), + m_verbose(true), + m_read_ok(false) +{ + checkPath(); // see if default will work. +} + +SnapShotReader::~SnapShotReader() +{ +} + +void SnapShotReader::setSnapshotDir(const std::string &dir) +{ + m_snapshotPath = dir; + if(dir.size() > 0) + { + if(dir.at(dir.size()-1) != DIR_CHAR) + m_snapshotPath += DIR_CHAR; + } + m_read_ok = false; + checkPath(); +} + +const bool SnapShotReader::readSnapShot() +{ + bool bRead = true; + + std::string iniFile = m_snapshotPath + SnapshotINIFilename; + std::ifstream in(iniFile.c_str()); + std::ostringstream oss; + + if(in.is_open()) + { + Parser::SetVerboseLogging(m_verbose); + ModernSnapshotParser parser(in); + in.close(); + + if(m_verbose) + { + oss.str(""); + oss << "Parsed snapshot.ini." << std::endl; + oss << "Found " << parser.getDeviceCount() << " devices." << std::endl; + LogInfo(oss.str()); + } + + std::vector<int> device_list; + parser.getDeviceList(device_list); + + ModernSnapshotParser::DevPtr device; + + for(size_t i = 0; i < device_list.size(); i++) + { + device = parser.getDevice(device_list[i]); + if(m_verbose) + { + oss.str(""); + oss << "Device " << device.get()->getID() << ": Ini file = " << device.get()->getIniFile() << "; Name = " << device.get()->getName() << std::endl; + LogInfo(oss.str()); + } + iniFile = m_snapshotPath + device.get()->getIniFile(); + in.open(iniFile.c_str()); + if(in.is_open()) + { + Parser::Parsed pdev = Parser::ParseSingleDevice(in); + m_parsed_device_list[pdev.deviceName] = pdev; // map devices by name + in.close(); + + } + else + { + oss.str(""); + oss << "Failed to open device file : " << iniFile << std::endl; + LogError(oss.str()); + } + } + + if(parser.getTraceMetadataFile().length() > 0) + { + if(m_verbose) + { + oss.str(""); + oss << "Trace Metadata ini file found : " << parser.getTraceMetadataFile() << std::endl; + LogInfo(oss.str()); + } + + iniFile = m_snapshotPath + parser.getTraceMetadataFile(); + in.open(iniFile.c_str()); + if(in.is_open()) + { + m_parsed_trace = Parser::ParseTraceMetaData(in); + in.close(); + if(m_parsed_trace.trace_buffers.size()) // found one or more buffers + { + std::vector<std::string> bufferNames = GetBufferNameList(m_parsed_trace); + std::vector<std::string>::iterator bnit = bufferNames.begin(); + while(bnit != bufferNames.end()) + { + Parser::TraceBufferSourceTree tbst; + if(Parser::ExtractSourceTree(*bnit,m_parsed_trace,tbst)) + m_source_trees[*bnit] = tbst; + bnit++; + } + } + + } + else + { + oss.str(""); + oss << "Failed to trace ini file : " << iniFile << std::endl; + LogError(oss.str()); + } + } + else + { + oss.str(""); + oss << "Trace Metadata ini file not found." << std::endl; + LogError(oss.str()); + } + + if(m_verbose) + { + oss.str(""); + oss << "Done." << std::endl; + LogInfo(oss.str()); + } + } + else + { + oss.str(""); + oss << "Read Error : Failed to open " << iniFile << "." << std::endl; + LogError(oss.str()); + bRead = false; + } + m_read_ok = bRead; + return bRead; +} + +void SnapShotReader::checkPath() +{ + std::string iniFile = m_snapshotPath + SnapshotINIFilename; + std::ifstream in(iniFile.c_str()); + m_snapshot_found = false; + + if(in.is_open()) + { + in.close(); + m_snapshot_found = true; + } +} + +void SnapShotReader::setErrorLogger(ITraceErrorLog *err_log) +{ + if(err_log) + { + m_i_err_log = err_log; + m_errlog_handle = m_i_err_log->RegisterErrorSource("snapshot_reader"); + Parser::SetIErrorLogger(m_i_err_log); + } +} + +void SnapShotReader::LogInfo(const std::string &msg) +{ + if(m_i_err_log) + m_i_err_log->LogMessage(m_errlog_handle, OCSD_ERR_SEV_INFO, msg); +} + +void SnapShotReader::LogError(const std::string &msg) +{ + if(m_i_err_log) + { + ocsdError err(OCSD_ERR_SEV_ERROR,OCSD_ERR_TEST_SNAPSHOT_READ,msg); + m_i_err_log->LogError(m_errlog_handle,&err); + } +} + +bool SnapShotReader::getSourceBufferNameList(std::vector<std::string> &nameList) +{ + nameList.clear(); + if(snapshotFound()) + { + nameList = GetBufferNameList(m_parsed_trace); + } + return (bool)(nameList.size() > 0); +} + +bool SnapShotReader::getTraceBufferSourceTree(const std::string &traceBufferName, Parser::TraceBufferSourceTree &sourceTree) +{ + bool found = false; + std::map<std::string, Parser::TraceBufferSourceTree>::iterator it; + it = m_source_trees.find(traceBufferName); + if(it != m_source_trees.end()) + { + sourceTree = it->second; + found = true; + } + return found; +} + +bool SnapShotReader::getDeviceData(const std::string &deviceName, Parser::Parsed **devData) +{ + std::map<std::string, Parser::Parsed>::iterator it; + + *devData = 0; + it = m_parsed_device_list.find(deviceName); + if(it != m_parsed_device_list.end()) + { + *devData = &(it->second); + } + return (*devData != 0); +} + + +/* End of File snapshot_reader.cpp */ diff --git a/decoder/tests/snapshot_parser_lib/source/ss_to_dcdtree.cpp b/decoder/tests/snapshot_parser_lib/source/ss_to_dcdtree.cpp new file mode 100644 index 0000000..902ce56 --- /dev/null +++ b/decoder/tests/snapshot_parser_lib/source/ss_to_dcdtree.cpp @@ -0,0 +1,590 @@ +/* + * \file ss_to_dcdtree.cpp + * \brief OpenCSD : + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ss_to_dcdtree.h" +#include "ss_key_value_names.h" + + +CreateDcdTreeFromSnapShot::CreateDcdTreeFromSnapShot() : + m_bInit(false), + m_pDecodeTree(0), + m_pReader(0), + m_pErrLogInterface(0), + m_bPacketProcOnly(false), + m_BufferFileName("") +{ + m_errlog_handle = 0; + m_add_create_flags = 0; +} + +CreateDcdTreeFromSnapShot::~CreateDcdTreeFromSnapShot() +{ + destroyDecodeTree(); +} + +void CreateDcdTreeFromSnapShot::initialise(SnapShotReader *pReader, ITraceErrorLog *pErrLogInterface) +{ + if((pErrLogInterface != 0) && (pReader != 0)) + { + m_pReader = pReader; + m_pErrLogInterface = pErrLogInterface; + m_errlog_handle = m_pErrLogInterface->RegisterErrorSource("ss2_dcdtree"); + m_bInit = true; + } +} + +bool CreateDcdTreeFromSnapShot::createDecodeTree(const std::string &SourceName, bool bPacketProcOnly, uint32_t add_create_flags) +{ + m_add_create_flags = add_create_flags; + if(m_bInit) + { + if(!m_pReader->snapshotReadOK()) + { + LogError("Supplied snapshot reader has not correctly read the snapshot.\n"); + return false; + } + + m_bPacketProcOnly = bPacketProcOnly; + Parser::TraceBufferSourceTree tree; + + if(m_pReader->getTraceBufferSourceTree(SourceName, tree)) + { + int numDecodersCreated = 0; // count how many we create - if none then give up. + uint32_t formatter_flags = OCSD_DFRMTR_FRAME_MEM_ALIGN; + + /* make a note of the trace binary file name + path to ss directory */ + m_BufferFileName = m_pReader->getSnapShotDir() + tree.buffer_info.dataFileName; + + ocsd_dcd_tree_src_t src_format = tree.buffer_info.dataFormat == "source_data" ? OCSD_TRC_SRC_SINGLE : OCSD_TRC_SRC_FRAME_FORMATTED; + + if (tree.buffer_info.dataFormat == "dstream_coresight") + formatter_flags = OCSD_DFRMTR_HAS_FSYNCS; + + /* create the initial device tree */ + // TBD: handle syncs / hsyncs data from TPIU + m_pDecodeTree = DecodeTree::CreateDecodeTree(src_format, formatter_flags); + if(m_pDecodeTree == 0) + { + LogError("Failed to create decode tree object\n"); + return false; + } + + // use our error logger - don't use the tree default. + m_pDecodeTree->setAlternateErrorLogger(m_pErrLogInterface); + + if(!bPacketProcOnly) + { + m_pDecodeTree->createMemAccMapper(); + } + + /* run through each protocol source to this buffer... */ + std::map<std::string, std::string>::iterator it = tree.source_core_assoc.begin(); + + while(it != tree.source_core_assoc.end()) + { + Parser::Parsed *etm_dev, *core_dev; + if(m_pReader->getDeviceData(it->first,&etm_dev)) + { + // found the device data for this device. + + // see if we have a core name (STM / ITM not associated with a core); + std::string coreDevName = it->second; + if(coreDevName.size() > 0) + { + if(m_pReader->getDeviceData(coreDevName,&core_dev)) + { + if(createPEDecoder(core_dev->deviceTypeName,etm_dev)) + { + numDecodersCreated++; + if(!bPacketProcOnly &&(core_dev->dumpDefs.size() > 0)) + { + processDumpfiles(core_dev->dumpDefs); + } + } + else + { + std::ostringstream oss; + oss << "Failed to create decoder for source " << it->first << ".\n"; + LogError(oss.str()); + } + } + else + { + // Could not find the device data for the core. + // unexpected - since we created the associations. + std::ostringstream oss; + oss << "Failed to get device data for source " << it->first << ".\n"; + LogError(oss.str()); + } + } + else + { + // none-core source + if(createSTDecoder(etm_dev)) + { + numDecodersCreated++; + } + else + { + std::ostringstream oss; + oss << "Failed to create decoder for none core source " << it->first << ".\n"; + LogError(oss.str()); + } + } + } + else + { + // TBD: could not find the device data for the source. + // again unexpected - suggests ss format error. + std::ostringstream oss; + oss << "Failed to find device data for source " << it->first << ".\n"; + LogError(oss.str()); + } + if(src_format == OCSD_TRC_SRC_SINGLE) + it = tree.source_core_assoc.end(); + else + it++; + } + + if(numDecodersCreated == 0) + { + // nothing useful found + destroyDecodeTree(); + } + } + else + { + std::ostringstream oss; + oss << "Failed to get parsed source tree for buffer " << SourceName << ".\n"; + LogError(oss.str()); + } + } + return (bool)(m_pDecodeTree != 0); +} + +void CreateDcdTreeFromSnapShot::destroyDecodeTree() +{ + if(m_pDecodeTree) + DecodeTree::DestroyDecodeTree(m_pDecodeTree); + m_pDecodeTree = 0; + m_pReader = 0; + m_pErrLogInterface = 0; + m_errlog_handle = 0; + m_BufferFileName = ""; +} + +void CreateDcdTreeFromSnapShot::LogError(const std::string &msg) +{ + ocsdError err(OCSD_ERR_SEV_ERROR,OCSD_ERR_TEST_SS_TO_DECODER,msg); + m_pErrLogInterface->LogError(m_errlog_handle,&err); +} + +void CreateDcdTreeFromSnapShot::LogError(const ocsdError &err) +{ + m_pErrLogInterface->LogError(m_errlog_handle,&err); +} + +bool CreateDcdTreeFromSnapShot::createPEDecoder(const std::string &coreName, Parser::Parsed *devSrc) +{ + bool bCreatedDecoder = false; + std::string devTypeName = devSrc->deviceTypeName; + + // split off .x from type name. + std::string::size_type pos = devTypeName.find_first_of('.'); + if(pos != std::string::npos) + devTypeName = devTypeName.substr(0,pos); + + // split according to protocol + if(devTypeName == ETMv4Protocol) + { + bCreatedDecoder = createETMv4Decoder(coreName,devSrc); + } + else if(devTypeName == ETMv3Protocol) + { + bCreatedDecoder = createETMv3Decoder(coreName,devSrc); + } + else if(devTypeName == PTMProtocol || devTypeName == PFTProtocol) + { + bCreatedDecoder = createPTMDecoder(coreName,devSrc); + } + else if (devTypeName == ETEProtocol) + { + bCreatedDecoder = createETEDecoder(coreName, devSrc); + } + + return bCreatedDecoder; +} + +// create an ETMv4 decoder based on the deviceN.ini file. +bool CreateDcdTreeFromSnapShot::createETMv4Decoder(const std::string &coreName, Parser::Parsed *devSrc, const bool bDataChannel /* = false*/) +{ + bool createdDecoder = false; + bool configOK = true; + + // generate the config data from the device data. + ocsd_etmv4_cfg config; + + regs_to_access_t regs_to_access[] = { + { ETMv4RegCfg, true, &config.reg_configr, 0 }, + { ETMv4RegIDR, true, &config.reg_traceidr, 0 }, + { ETMv4RegIDR0, true, &config.reg_idr0, 0 }, + { ETMv4RegIDR1, false, &config.reg_idr1, 0x4100F403 }, + { ETMv4RegIDR2, true, &config.reg_idr2, 0 }, + { ETMv4RegIDR8, false, &config.reg_idr8, 0 }, + { ETMv4RegIDR9, false, &config.reg_idr9, 0 }, + { ETMv4RegIDR10, false, &config.reg_idr10, 0 }, + { ETMv4RegIDR11, false, &config.reg_idr11, 0 }, + { ETMv4RegIDR12, false, &config.reg_idr12, 0 }, + { ETMv4RegIDR13,false, &config.reg_idr13, 0 }, + }; + + // extract registers + configOK = getRegisters(devSrc->regDefs,sizeof(regs_to_access)/sizeof(regs_to_access_t), regs_to_access); + + // extract core profile + if(configOK) + configOK = getCoreProfile(coreName,config.arch_ver,config.core_prof); + + // good config - generate the decoder on the tree. + if(configOK) + { + ocsd_err_t err = OCSD_OK; + EtmV4Config configObj(&config); + const char *decoderName = bDataChannel ? OCSD_BUILTIN_DCD_ETMV4D : OCSD_BUILTIN_DCD_ETMV4I; + + err = m_pDecodeTree->createDecoder(decoderName, m_add_create_flags | (m_bPacketProcOnly ? OCSD_CREATE_FLG_PACKET_PROC : OCSD_CREATE_FLG_FULL_DECODER),&configObj); + + if(err == OCSD_OK) + createdDecoder = true; + else + { + std::string msg = "Snapshot processor : failed to create " + (std::string)decoderName + " decoder on decode tree."; + LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,msg)); + } + } + + return createdDecoder; +} + +bool CreateDcdTreeFromSnapShot::createETEDecoder(const std::string &coreName, Parser::Parsed *devSrc) +{ + bool createdDecoder = false; + bool configOK = true; + + // generate the config data from the device data. + ocsd_ete_cfg config; + + // ete regs are same names Etmv4 in places... + regs_to_access_t regs_to_access[] = { + { ETMv4RegCfg, true, &config.reg_configr, 0 }, + { ETMv4RegIDR, true, &config.reg_traceidr, 0 }, + { ETMv4RegIDR0, true, &config.reg_idr0, 0 }, + { ETMv4RegIDR1, false, &config.reg_idr1, 0x4100F403 }, + { ETMv4RegIDR2, true, &config.reg_idr2, 0 }, + { ETMv4RegIDR8, false, &config.reg_idr8, 0 }, + { ETERegDevArch, false, &config.reg_devarch, 0x47705A13 }, + }; + + // extract registers + configOK = getRegisters(devSrc->regDefs, sizeof(regs_to_access) / sizeof(regs_to_access_t), regs_to_access); + + // extract core profile + if (configOK) + configOK = getCoreProfile(coreName, config.arch_ver, config.core_prof); + + // good config - generate the decoder on the tree. + if (configOK) + { + ocsd_err_t err = OCSD_OK; + ETEConfig configObj(&config); + const char *decoderName = OCSD_BUILTIN_DCD_ETE; + + err = m_pDecodeTree->createDecoder(decoderName, m_add_create_flags | (m_bPacketProcOnly ? OCSD_CREATE_FLG_PACKET_PROC : OCSD_CREATE_FLG_FULL_DECODER), &configObj); + + if (err == OCSD_OK) + createdDecoder = true; + else + { + std::string msg = "Snapshot processor : failed to create " + (std::string)decoderName + " decoder on decode tree."; + LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, msg)); + } + } + + return createdDecoder; +} + +// create an ETMv3 decoder based on the register values in the deviceN.ini file. +bool CreateDcdTreeFromSnapShot::createETMv3Decoder(const std::string &coreName, Parser::Parsed *devSrc) +{ + bool createdDecoder = false; + bool configOK = true; + + // generate the config data from the device data. + ocsd_etmv3_cfg cfg_regs; + + regs_to_access_t regs_to_access[] = { + { ETMv3PTMRegIDR, true, &cfg_regs.reg_idr, 0 }, + { ETMv3PTMRegCR, true, &cfg_regs.reg_ctrl, 0 }, + { ETMv3PTMRegCCER, true, &cfg_regs.reg_ccer, 0 }, + { ETMv3PTMRegTraceIDR, true, &cfg_regs.reg_trc_id, 0} + }; + + // extract registers + configOK = getRegisters(devSrc->regDefs,sizeof(regs_to_access)/sizeof(regs_to_access_t), regs_to_access); + + // extract core profile + if(configOK) + configOK = getCoreProfile(coreName,cfg_regs.arch_ver,cfg_regs.core_prof); + + // good config - generate the decoder on the tree. + if(configOK) + { + EtmV3Config config(&cfg_regs); + ocsd_err_t err = OCSD_OK; + err = m_pDecodeTree->createDecoder(OCSD_BUILTIN_DCD_ETMV3, m_bPacketProcOnly ? OCSD_CREATE_FLG_PACKET_PROC : OCSD_CREATE_FLG_FULL_DECODER,&config); + + if(err == OCSD_OK) + createdDecoder = true; + else + LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Snapshot processor : failed to create ETMV3 decoder on decode tree.")); + } + return createdDecoder; +} + +bool CreateDcdTreeFromSnapShot::createPTMDecoder(const std::string &coreName, Parser::Parsed *devSrc) +{ + bool createdDecoder = false; + bool configOK = true; + + // generate the config data from the device data. + + ocsd_ptm_cfg config; + + regs_to_access_t regs_to_access[] = { + { ETMv3PTMRegIDR, true, &config.reg_idr, 0 }, + { ETMv3PTMRegCR, true, &config.reg_ctrl, 0 }, + { ETMv3PTMRegCCER, true, &config.reg_ccer, 0 }, + { ETMv3PTMRegTraceIDR, true, &config.reg_trc_id, 0} + }; + + // extract registers + configOK = getRegisters(devSrc->regDefs,sizeof(regs_to_access)/sizeof(regs_to_access_t), regs_to_access); + + // extract core profile + if(configOK) + configOK = getCoreProfile(coreName,config.arch_ver,config.core_prof); + + // good config - generate the decoder on the tree. + if(configOK) + { + PtmConfig configObj(&config); + ocsd_err_t err = OCSD_OK; + err = m_pDecodeTree->createDecoder(OCSD_BUILTIN_DCD_PTM, m_bPacketProcOnly ? OCSD_CREATE_FLG_PACKET_PROC : OCSD_CREATE_FLG_FULL_DECODER,&configObj); + + if(err == OCSD_OK) + createdDecoder = true; + else + LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Snapshot processor : failed to create PTM decoder on decode tree.")); + } + return createdDecoder; +} + +bool CreateDcdTreeFromSnapShot::createSTDecoder(Parser::Parsed *devSrc) +{ + bool bCreatedDecoder = false; + std::string devTypeName = devSrc->deviceTypeName; + + // split off .x from type name. + std::string::size_type pos = devTypeName.find_first_of('.'); + if(pos != std::string::npos) + devTypeName = devTypeName.substr(0,pos); + + if(devTypeName == STMProtocol) + { + bCreatedDecoder = createSTMDecoder(devSrc); + } + + return bCreatedDecoder; +} + +bool CreateDcdTreeFromSnapShot::createSTMDecoder(Parser::Parsed *devSrc) +{ + bool createdDecoder = false; + bool configOK = true; + + // generate the config data from the device data. + + ocsd_stm_cfg config; + + regs_to_access_t regs_to_access[] = { + { STMRegTCSR, true, &config.reg_tcsr, 0 } + }; + + configOK = getRegisters(devSrc->regDefs,sizeof(regs_to_access)/sizeof(regs_to_access_t), regs_to_access); + if(configOK) + { + ocsd_err_t err = OCSD_OK; + STMConfig configObj(&config); + + err = m_pDecodeTree->createDecoder(OCSD_BUILTIN_DCD_STM, m_bPacketProcOnly ? OCSD_CREATE_FLG_PACKET_PROC : OCSD_CREATE_FLG_FULL_DECODER,&configObj); + + if(err == OCSD_OK) + createdDecoder = true; + else + LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Snapshot processor : failed to create STM decoder on decode tree.")); + } + + return createdDecoder; +} + + + +// get a set of register values. +bool CreateDcdTreeFromSnapShot::getRegisters(std::map<std::string, std::string, Util::CaseInsensitiveLess> ®Defs, int numRegs, regs_to_access_t *reg_access_array) +{ + bool regsOK = true; + + for(int rv = 0; rv < numRegs; rv++) + { + if(!getRegByPrefix( regDefs,reg_access_array[rv])) + regsOK = false; + } + return regsOK; +} + +// strip out any parts with brackets +bool CreateDcdTreeFromSnapShot::getRegByPrefix(std::map<std::string, std::string, Util::CaseInsensitiveLess> ®Defs, + regs_to_access_t ®_accessor) +{ + std::ostringstream oss; + bool bFound = false; + std::map<std::string, std::string, Util::CaseInsensitiveLess>::iterator it; + std::string prefix_cmp; + std::string::size_type pos; + std::string strval; + + *reg_accessor.value = 0; + + it = regDefs.begin(); + while((it != regDefs.end()) && !bFound) + { + prefix_cmp = it->first; + pos = prefix_cmp.find_first_of('('); + if(pos != std::string::npos) + { + prefix_cmp = prefix_cmp.substr(0, pos); + } + if(prefix_cmp == reg_accessor.pszName) + { + strval = it->second; + bFound = true; + } + it++; + } + + if(bFound) + *reg_accessor.value = strtoul(strval.c_str(),0,0); + else + { + ocsd_err_severity_t sev = OCSD_ERR_SEV_ERROR; + if(reg_accessor.failIfMissing) + { + oss << "Error:"; + } + else + { + // no fail if missing - set any default and just warn. + bFound = true; + oss << "Warning: Default set for register. "; + sev = OCSD_ERR_SEV_WARN; + *reg_accessor.value = reg_accessor.val_default; + } + oss << "Missing " << reg_accessor.pszName << "\n"; + m_pErrLogInterface->LogMessage(m_errlog_handle, sev, oss.str()); + } + return bFound; +} + +bool CreateDcdTreeFromSnapShot::getCoreProfile(const std::string &coreName, ocsd_arch_version_t &arch_ver, ocsd_core_profile_t &core_prof) +{ + bool profileOK = true; + ocsd_arch_profile_t ap = m_arch_profiles.getArchProfile(coreName); + if(ap.arch != ARCH_UNKNOWN) + { + arch_ver = ap.arch; + core_prof = ap.profile; + } + else + { + std::ostringstream oss; + oss << "Unrecognized Core name " << coreName << ". Cannot evaluate profile or architecture."; + LogError(oss.str()); + profileOK = false; + } + return profileOK; +} + +void CreateDcdTreeFromSnapShot::processDumpfiles(std::vector<Parser::DumpDef> &dumps) +{ + std::string dumpFilePathName; + std::vector<Parser::DumpDef>::const_iterator it; + + it = dumps.begin(); + while(it != dumps.end()) + { + dumpFilePathName = m_pReader->getSnapShotDir() + it->path; + ocsd_file_mem_region_t region; + ocsd_err_t err = OCSD_OK; + + region.start_address = it->address; + region.file_offset = it->offset; + region.region_size = it->length; + + // ensure we respect optional length and offset parameter and + // allow multiple dump entries with same file name to define regions + if (!TrcMemAccessorFile::isExistingFileAccessor(dumpFilePathName)) + err = m_pDecodeTree->addBinFileRegionMemAcc(®ion, 1, OCSD_MEM_SPACE_ANY, dumpFilePathName); + else + err = m_pDecodeTree->updateBinFileRegionMemAcc(®ion, 1, OCSD_MEM_SPACE_ANY, dumpFilePathName); + if(err != OCSD_OK) + { + std::ostringstream oss; + oss << "Failed to create memory accessor for file " << dumpFilePathName << "."; + LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,oss.str())); + } + it++; + } +} + +/* End of File ss_to_dcdtree.cpp */ |