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/include/common | |
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/include/common')
26 files changed, 4249 insertions, 0 deletions
diff --git a/decoder/include/common/comp_attach_notifier_i.h b/decoder/include/common/comp_attach_notifier_i.h new file mode 100644 index 0000000..e0062ef --- /dev/null +++ b/decoder/include/common/comp_attach_notifier_i.h @@ -0,0 +1,63 @@ +/*! + * \file comp_attach_notifier_i.h + * \brief OpenCSD : Component attach point notifier interface. + * + * \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_COMP_ATTACH_NOTIFIER_I_H_INCLUDED +#define ARM_COMP_ATTACH_NOTIFIER_I_H_INCLUDED + +/*! + * @class IComponentAttachNotifier + * @addtogroup ocsd_infrastructure + * @brief Notification interface for attachment. + * + * Interface to the componentAttachPt classes that allow notification on component + * connect and disconnect. + */ +class IComponentAttachNotifier { +public: + IComponentAttachNotifier() {}; /**< Default interface constructor */ + virtual ~IComponentAttachNotifier() {}; /**< Default interface destructor */ + + /*! + * Callback called by the componentAttachPt() classes when a component is attached + * to or detached from the attach point. + * + * @param num_attached : number of remaining components attached to the point after the + * operation that triggered the notification. + */ + virtual void attachNotify(const int num_attached) = 0; +}; + +#endif // ARM_COMP_ATTACH_NOTIFIER_I_H_INCLUDED + +/* End of File comp_attach_notifier_i.h */ diff --git a/decoder/include/common/comp_attach_pt_t.h b/decoder/include/common/comp_attach_pt_t.h new file mode 100644 index 0000000..71f4c84 --- /dev/null +++ b/decoder/include/common/comp_attach_pt_t.h @@ -0,0 +1,240 @@ +/*! + * \file comp_attach_pt_t.h + * \brief OpenCSD : Component attachment point interface class. + * + * \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_COMP_ATTACH_PT_T_H_INCLUDED +#define ARM_COMP_ATTACH_PT_T_H_INCLUDED + +#include <vector> +#include "opencsd/ocsd_if_types.h" + +/** @defgroup ocsd_infrastructure OpenCSD Library : Library Component Infrastructure + + @brief Classes providing library infrastructure and auxilary functionality +@{*/ + +#include "comp_attach_notifier_i.h" + +/*! + * @class componentAttachPt + * @brief Single component interface pointer attachment point. + * + * This is a class template to standardise the connections between decode components. + * + * An attachment point connects a component interface pointer to the component providing the + * attachment point. + * + * This attachment point implementation allows a single interface to be connected. + * + */ +template <class T> +class componentAttachPt { +public: + componentAttachPt(); /**< Default constructor */ + virtual ~componentAttachPt(); /**< Default destructor */ + + /*! + * Attach an interface of type T to the attachment point. + * + * @param component : interface to attach. + * + * @return ocsd_err_t : OCSD_OK if successful, OCSD_ERR_ATTACH_TOO_MANY if too many connections. + */ + virtual ocsd_err_t attach(T* component); + + /*! + * Detach component from the attachment point. + * + * @param component : Component to detach. + * + * @return virtual ocsd_err_t : OCSD_OK if successful, OCSD_ERR_ATTACH_COMP_NOT_FOUND if no match to component. + */ + virtual ocsd_err_t detach(T* component); + + + // detach current first if anything attached, connect supplied pointer, remain unattached if pointer 0 + virtual ocsd_err_t replace_first(T* component); + + /*! + * Detach all components. + */ + virtual void detach_all(); + + /*! + * Return the current (first) attached interface pointer. + * Will return 0 if nothing attached or the attachment point is disabled. + * + * @return T* : Current Interface pointer of type T or 0. + */ + virtual T* first(); + + /*! + * Return the next attached interface. + * The componentAttachPt base implmentation will always return 0 as only a single attachment is possible + * + * @return T* : Always returns 0. + */ + virtual T* next(); + + /*! + * Returns the number of interface pointers attached to this attachment point. + * + * @return int : number of component interfaces attached. + */ + virtual int num_attached(); + + /*! + * Attach a notifier interface to the attachment point. Will call back on this interface whenever + * a component is attached or detached. + * + * @param *notifier : pointer to the IComponentAttachNotifier interface. + */ + void set_notifier(IComponentAttachNotifier *notifier); + + /* enable state does not affect attach / detach, but can be used to filter access to interfaces */ + const bool enabled() const; /**< return the enabled flag. */ + void set_enabled(const bool enable); + + + /*! + * Check to see if any attachements. Will return attach state independent of enable state. + * + * @return const bool : true if attachment. + */ + const bool hasAttached() const { return m_hasAttached; }; + + + /*! + * Return both the attachment and enabled state. + * + * @return const bool : true if both has attachment and is enabled. + */ + const bool hasAttachedAndEnabled() const { return m_hasAttached && m_enabled; }; + +protected: + bool m_enabled; /**< Flag to indicate if the attachment point is enabled. */ + bool m_hasAttached; /**< Flag indicating at least one attached interface */ + IComponentAttachNotifier *m_notifier; /**< Optional attachement notifier interface. */ + T *m_comp; /**< pointer to the single attached interface */ +}; + + + +template<class T> componentAttachPt<T>::componentAttachPt() +{ + m_comp = 0; + m_notifier = 0; + m_enabled = true; + m_hasAttached = false; +} + +template<class T> componentAttachPt<T>::~componentAttachPt() +{ + detach_all(); +} + + +template<class T> ocsd_err_t componentAttachPt<T>::attach(T* component) +{ + if(m_comp != 0) + return OCSD_ERR_ATTACH_TOO_MANY; + m_comp = component; + if(m_notifier) m_notifier->attachNotify(1); + m_hasAttached = true; + return OCSD_OK; +} + +template<class T> ocsd_err_t componentAttachPt<T>::replace_first(T* component) +{ + if(m_hasAttached) + detach(m_comp); + + if(component == 0) + return OCSD_OK; + + return attach(component); +} + +template<class T> ocsd_err_t componentAttachPt<T>::detach(T* component) +{ + if(m_comp != component) + return OCSD_ERR_ATTACH_COMP_NOT_FOUND; + m_comp = 0; + m_hasAttached = false; + if(m_notifier) m_notifier->attachNotify(0); + return OCSD_OK; +} + +template<class T> T* componentAttachPt<T>::first() +{ + return (m_enabled) ? m_comp : 0; +} + +template<class T> T* componentAttachPt<T>::next() +{ + return 0; +} + +template<class T> int componentAttachPt<T>::num_attached() +{ + return ((m_comp != 0) ? 1 : 0); +} + +template<class T> void componentAttachPt<T>::detach_all() +{ + m_comp = 0; + m_hasAttached = false; + if(m_notifier) m_notifier->attachNotify(0); +} + +template<class T> void componentAttachPt<T>::set_notifier(IComponentAttachNotifier *notifier) +{ + m_notifier = notifier; +} + +template<class T> const bool componentAttachPt<T>::enabled() const +{ + return m_enabled; +} + +template<class T> void componentAttachPt<T>::set_enabled(const bool enable) +{ + m_enabled = enable; +} + + +/** @}*/ + +#endif // ARM_COMP_ATTACH_PT_T_H_INCLUDED + +/* End of File comp_attach_pt_t.h */ diff --git a/decoder/include/common/ocsd_code_follower.h b/decoder/include/common/ocsd_code_follower.h new file mode 100644 index 0000000..b024aa0 --- /dev/null +++ b/decoder/include/common/ocsd_code_follower.h @@ -0,0 +1,237 @@ +/* + * \file ocsd_code_follower.h + * \brief OpenCSD : Code follower for instruction trace decode + * + * \copyright Copyright (c) 2016, 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_OCSD_CODE_FOLLOWER_H_INCLUDED +#define ARM_OCSD_CODE_FOLLOWER_H_INCLUDED + +#include "opencsd/ocsd_if_types.h" +#include "opencsd/trc_pkt_types.h" +#include "comp_attach_pt_t.h" +#include "interfaces/trc_tgt_mem_access_i.h" +#include "interfaces/trc_instr_decode_i.h" + +/*! + * @class OcsdCodeFollower + * @brief The code follower looks for waypoints or addresses. + * + * Code follower used to determine the trace ranges for Atom or other waypoint + * elements. Uses memory accessor and I decoder to follow the code path. + * + */ +class OcsdCodeFollower +{ +public: + OcsdCodeFollower(); + ~OcsdCodeFollower(); + +//*********** setup API + void initInterfaces(componentAttachPt<ITargetMemAccess> *pMemAccess, componentAttachPt<IInstrDecode> *pIDecode); + +// set information for decode operation - static or occasionally changing settings +// per decode values are passed as parameters into the decode API calls. + void setArchProfile(const ocsd_arch_profile_t profile); //!< core profile + void setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule); //!< memory space to use for access (filtered by S/NS, EL etc). + void setMemSpaceCSID(const uint8_t csid); //!< memory spaces might be partitioned by CSID + void setISA(const ocsd_isa isa); //!< set the ISA for the decode. + void setDSBDMBasWP(); //!< DSB and DMB can be treated as WP in some archs. + +//********** code following API + + // standard WP search - for program flow trace + //ocsd_err_t followToAtomWP(idec_res_t &op_result, const ocsd_vaddr_t addrStart, const ocsd_atm_val A); + + // PTM exception code may require follow to an address + //ocsd_err_t followToAddress(idec_res_t &op_result, const ocsd_vaddr_t addrStart, const ocsd_atm_val A, const ocsd_vaddr_t addrMatch); + + // single instruction atom format such as ETMv3 + ocsd_err_t followSingleAtom(const ocsd_vaddr_t addrStart, const ocsd_atm_val A); + + // follow N instructions + // ocsd_err_t followNInstructions(idec_res_t &op_result) // ETMv4 Q elements + +//*********************** results API + const ocsd_vaddr_t getRangeSt() const; //!< inclusive start address of decoded range (value passed in) + const ocsd_vaddr_t getRangeEn() const; //!< exclusive end address of decoded range (first instruction _not_ executed / potential next instruction). + const bool hasRange() const; //!< we have a valid range executed (may be false if nacc). + + const bool hasNextAddr() const; //!< we have calulated the next address - otherwise this is needed from trace packets. + const ocsd_vaddr_t getNextAddr() const; //!< next address - valid if hasNextAddr() true. + + // information on last instruction executed in range. + const ocsd_instr_type getInstrType() const; //!< last instruction type + const ocsd_instr_subtype getInstrSubType() const; //!< last instruction sub-type + const bool isCondInstr() const; //!< is a conditional instruction + const bool isLink() const; //!< is a link (branch with link etc) + const bool ISAChanged() const; //!< next ISA different from input ISA. + const ocsd_isa nextISA() const; //!< ISA for next instruction + const uint8_t getInstrSize() const; //!< Get the last instruction size. + + // information on error conditions + const bool isNacc() const; //!< true if Memory Not Accessible (nacc) error occurred + void clearNacc(); //!< clear the nacc error flag + const ocsd_vaddr_t getNaccAddr() const; //!< get the nacc error address. + +private: + bool initFollowerState(); //!< clear all the o/p data and flags, check init valid. + + ocsd_err_t decodeSingleOpCode(); //!< decode single opcode address from current m_inst_info packet + + ocsd_instr_info m_instr_info; + + ocsd_vaddr_t m_st_range_addr; //!< start of excuted range - inclusive address. + ocsd_vaddr_t m_en_range_addr; //!< end of executed range - exclusive address. + ocsd_vaddr_t m_next_addr; //!< calcuated next address (could be eo range of branch address, not set for indirect branches) + bool m_b_next_valid; //!< true if next address valid, false if need address from trace packets. + + //! memory space rule to use when accessing memory. + ocsd_mem_space_acc_t m_mem_acc_rule; + //! memory space csid to use when accessing memory. + uint8_t m_mem_space_csid; + + ocsd_vaddr_t m_nacc_address; //!< memory address that was inaccessible - failed read @ start, or during follow operation + bool m_b_nacc_err; //!< memory NACC error - required address was unavailable. + + //! pointers to the memory access and i decode interfaces. + componentAttachPt<ITargetMemAccess> *m_pMemAccess; + componentAttachPt<IInstrDecode> *m_pIDecode; + +}; + +#endif // ARM_OCSD_CODE_FOLLOWER_H_INCLUDED + +//*********** setup API +inline void OcsdCodeFollower::setArchProfile(const ocsd_arch_profile_t profile) +{ + m_instr_info.pe_type = profile; +} + +inline void OcsdCodeFollower::setMemSpaceAccess(const ocsd_mem_space_acc_t mem_acc_rule) +{ + m_mem_acc_rule = mem_acc_rule; +} + +inline void OcsdCodeFollower::setMemSpaceCSID(const uint8_t csid) +{ + m_mem_space_csid = csid; +} + +inline void OcsdCodeFollower::setISA(const ocsd_isa isa) +{ + m_instr_info.isa = isa; +} + +inline void OcsdCodeFollower::setDSBDMBasWP() +{ + m_instr_info.dsb_dmb_waypoints = 1; +} + +//**************************************** results API +inline const ocsd_vaddr_t OcsdCodeFollower::getRangeSt() const +{ + return m_st_range_addr; +} + +inline const ocsd_vaddr_t OcsdCodeFollower::getRangeEn() const +{ + return m_en_range_addr; +} + +inline const bool OcsdCodeFollower::hasRange() const +{ + return m_st_range_addr < m_en_range_addr; +} + +inline const bool OcsdCodeFollower::hasNextAddr() const +{ + return m_b_next_valid; +} + +inline const ocsd_vaddr_t OcsdCodeFollower::getNextAddr() const +{ + return m_next_addr; +} + +// information on last instruction executed in range. +inline const ocsd_instr_type OcsdCodeFollower::getInstrType() const +{ + return m_instr_info.type; +} + +inline const ocsd_instr_subtype OcsdCodeFollower::getInstrSubType() const +{ + return m_instr_info.sub_type; +} + +inline const uint8_t OcsdCodeFollower::getInstrSize() const +{ + return m_instr_info.instr_size; +} + +inline const bool OcsdCodeFollower::isCondInstr() const +{ + return (bool)(m_instr_info.is_conditional == 1); +} + +inline const bool OcsdCodeFollower::isLink() const +{ + return (bool)(m_instr_info.is_link == 1); +} + +inline const bool OcsdCodeFollower::ISAChanged() const +{ + return (bool)(m_instr_info.isa != m_instr_info.next_isa); +} + +inline const ocsd_isa OcsdCodeFollower::nextISA() const +{ + return m_instr_info.next_isa; +} + +// information on error conditions +inline const bool OcsdCodeFollower::isNacc() const +{ + return m_b_nacc_err; +} + +inline void OcsdCodeFollower::clearNacc() +{ + m_b_nacc_err = false; +} + +inline const ocsd_vaddr_t OcsdCodeFollower::getNaccAddr() const +{ + return m_nacc_address; +} + +/* End of File ocsd_code_follower.h */ diff --git a/decoder/include/common/ocsd_dcd_mngr.h b/decoder/include/common/ocsd_dcd_mngr.h new file mode 100644 index 0000000..34c4ef1 --- /dev/null +++ b/decoder/include/common/ocsd_dcd_mngr.h @@ -0,0 +1,445 @@ +/* + * \file ocsd_dcd_mngr.h + * \brief OpenCSD : Decoder manager base class. + * + * \copyright Copyright (c) 2016, 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_OCSD_DCD_MNGR_H_INCLUDED +#define ARM_OCSD_DCD_MNGR_H_INCLUDED + +#include "opencsd/ocsd_if_types.h" +#include "common/ocsd_dcd_mngr_i.h" +#include "common/ocsd_lib_dcd_register.h" +#include "common/trc_pkt_decode_base.h" +#include "common/trc_pkt_proc_base.h" + +template <class P, class Pt, class Pc> +class DecoderMngrBase : public IDecoderMngr +{ +public: + DecoderMngrBase(const std::string &decoderTypeName, ocsd_trace_protocol_t builtInProtocol); + virtual ~DecoderMngrBase() {}; + + // create decoder interface. + virtual ocsd_err_t createDecoder(const int create_flags, const int instID, const CSConfig *p_config, TraceComponent **p_component); + virtual ocsd_err_t destroyDecoder(TraceComponent *p_component); + + virtual const ocsd_trace_protocol_t getProtocolType() const { return m_builtInProtocol; } + +// common + virtual ocsd_err_t attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog); + +// pkt decoder + virtual ocsd_err_t attachInstrDecoder(TraceComponent *pComponent, IInstrDecode *pIInstrDec); + virtual ocsd_err_t attachMemAccessor(TraceComponent *pComponent, ITargetMemAccess *pMemAccessor); + virtual ocsd_err_t attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink); + +// pkt processor + virtual ocsd_err_t attachPktMonitor(TraceComponent *pComponent, ITrcTypedBase *pPktRawDataMon); + virtual ocsd_err_t attachPktIndexer(TraceComponent *pComponent, ITrcTypedBase *pPktIndexer); + virtual ocsd_err_t attachPktSink(TraceComponent *pComponent, ITrcTypedBase *pPktDataInSink); + +// data input connection interface + virtual ocsd_err_t getDataInputI(TraceComponent *pComponent, ITrcDataIn **ppDataIn); + +// generate a Config object from opaque config struct pointer. + virtual ocsd_err_t createConfigFromDataStruct(CSConfig **pConfigBase, const void *pDataStruct); + +// implemented by decoder handler derived classes + virtual TraceComponent *createPktProc(const bool useInstID, const int instID) = 0; + virtual TraceComponent *createPktDecode(const bool useInstID, const int instID) { return 0; }; + virtual CSConfig *createConfig(const void *pDataStruct) = 0; + + +private: + const ocsd_trace_protocol_t m_builtInProtocol; //!< Protocol ID if built in type. +}; + +template <class P, class Pt, class Pc> + DecoderMngrBase<P,Pt,Pc>::DecoderMngrBase(const std::string &decoderTypeName, ocsd_trace_protocol_t builtInProtocol) : + m_builtInProtocol(builtInProtocol) +{ + OcsdLibDcdRegister *pDcdReg = OcsdLibDcdRegister::getDecoderRegister(); + if(pDcdReg) + pDcdReg->registerDecoderTypeByName(decoderTypeName,this); +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::createDecoder(const int create_flags, const int instID, const CSConfig *pConfig, TraceComponent **ppTrcComp) +{ + TraceComponent *pkt_proc = 0; + TraceComponent *pkt_dcd = 0; + bool bUseInstID = (create_flags & OCSD_CREATE_FLG_INST_ID) != 0; + bool bDecoder = (create_flags & OCSD_CREATE_FLG_FULL_DECODER) != 0; + bool bUnConfigured = (pConfig == 0); + + const Pc *pConf = dynamic_cast< const Pc * >(pConfig); + + // check inputs valid... + if((pConf == 0) && !bUnConfigured) + return OCSD_ERR_INVALID_PARAM_TYPE; + + if((create_flags & (OCSD_CREATE_FLG_PACKET_PROC | OCSD_CREATE_FLG_FULL_DECODER)) == 0) + return OCSD_ERR_INVALID_PARAM_VAL; + + // always need a packet processor + pkt_proc = createPktProc(bUseInstID, instID); + if(!pkt_proc) + return OCSD_ERR_MEM; + + // set the op mode flags + pkt_proc->setComponentOpMode(create_flags & (OCSD_OPFLG_COMP_MODE_MASK | OCSD_OPFLG_PKTPROC_COMMON)); + + // set the configuration + TrcPktProcBase<P,Pt,Pc> *pProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> *>(pkt_proc); + if(pProcBase == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + if(!bUnConfigured) + pProcBase->setProtocolConfig(pConf); + + *ppTrcComp = pkt_proc; + + // may need a packet decoder + if(bDecoder) + { + // create the decoder + pkt_dcd = createPktDecode(bUseInstID, instID); + if(!pkt_dcd) + return OCSD_ERR_MEM; + + // set the op mode flags + pkt_dcd->setComponentOpMode(create_flags & (OCSD_OPFLG_COMP_MODE_MASK | OCSD_OPFLG_PKTDEC_COMMON)); + + // get the decoder base + TrcPktDecodeBase<P,Pc> *pBase = dynamic_cast< TrcPktDecodeBase<P,Pc> *>(pkt_dcd); + if(pBase == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + if(!bUnConfigured) + pBase->setProtocolConfig(pConf); + + // associate decoder with packet processor + // -> this means a TraceComponent with an associated component is a packet decoder. + // the associated component is the connected packet processor. + pkt_dcd->setAssocComponent(pkt_proc); + + // connect packet processor and decoder + pProcBase->getPacketOutAttachPt()->attach(pBase); + + *ppTrcComp = pkt_dcd; + } + return OCSD_OK; +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::destroyDecoder(TraceComponent *pComponent) +{ + if(pComponent->getAssocComponent() != 0) + delete pComponent->getAssocComponent(); + delete pComponent; + return OCSD_OK; +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog) +{ + return pComponent->getErrorLogAttachPt()->replace_first(pIErrorLog); +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachInstrDecoder(TraceComponent *pComponent, IInstrDecode *pIInstrDec) +{ + ocsd_err_t err = OCSD_ERR_DCD_INTERFACE_UNUSED; + + if(pComponent->getAssocComponent() == 0) // no associated component - so this is a packet processor + return OCSD_ERR_INVALID_PARAM_TYPE; + + TrcPktDecodeI *pDcdI = dynamic_cast< TrcPktDecodeI * >(pComponent); + if(pDcdI == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + if(pDcdI->getUsesIDecode()) + err = pDcdI->getInstrDecodeAttachPt()->replace_first(pIInstrDec); + + return err; +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachMemAccessor(TraceComponent *pComponent, ITargetMemAccess *pMemAccessor) +{ + ocsd_err_t err = OCSD_ERR_DCD_INTERFACE_UNUSED; + + if(pComponent->getAssocComponent() == 0) // no associated component - so this is a packet processor + return OCSD_ERR_INVALID_PARAM_TYPE; + + TrcPktDecodeI *pDcdI = dynamic_cast< TrcPktDecodeI * >(pComponent); + if(pDcdI == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + if(pDcdI->getUsesMemAccess()) + err = pDcdI->getMemoryAccessAttachPt()->replace_first(pMemAccessor); + + return err; +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink) +{ + ocsd_err_t err = OCSD_ERR_INVALID_PARAM_TYPE; + + if(pComponent->getAssocComponent() == 0) // no associated component - so this is a packet processor + return err; + + TrcPktDecodeI *pDcdI = dynamic_cast< TrcPktDecodeI * >(pComponent); + if(pDcdI == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + err = pDcdI->getTraceElemOutAttachPt()->replace_first(pOutSink); + + return err; +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::getDataInputI(TraceComponent *pComponent, ITrcDataIn **ppDataIn) +{ + // find the packet processor + TraceComponent *pPktProc = pComponent; + if(pComponent->getAssocComponent() != 0) + pPktProc = pComponent->getAssocComponent(); + + TrcPktProcI *pPPI = dynamic_cast< TrcPktProcI * >(pPktProc); + if(pPPI == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + *ppDataIn = pPPI; + + return OCSD_OK; +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachPktMonitor(TraceComponent *pComponent, ITrcTypedBase *pPktRawDataMon) +{ + // find the packet processor + TraceComponent *pPktProc = pComponent; + if(pComponent->getAssocComponent() != 0) + pPktProc = pComponent->getAssocComponent(); + + // get the packet processor + TrcPktProcBase<P,Pt,Pc> *pPktProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> * >(pPktProc); + if(pPktProcBase == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + // get the interface + IPktRawDataMon<P> *p_If = dynamic_cast< IPktRawDataMon<P> * >(pPktRawDataMon); + if(p_If == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + return pPktProcBase->getRawPacketMonAttachPt()->replace_first(p_If); +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachPktIndexer(TraceComponent *pComponent, ITrcTypedBase *pPktIndexer) +{ + // find the packet processor + TraceComponent *pPktProc = pComponent; + if(pComponent->getAssocComponent() != 0) + pPktProc = pComponent->getAssocComponent(); + + // get the packet processor + TrcPktProcBase<P,Pt,Pc> *pPktProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> * >(pPktProc); + if(pPktProcBase == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + // get the interface + ITrcPktIndexer<Pt> *p_If = dynamic_cast< ITrcPktIndexer<Pt> * >(pPktIndexer); + if(p_If == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + return pPktProcBase->getTraceIDIndexerAttachPt()->replace_first(p_If); +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::attachPktSink(TraceComponent *pComponent, ITrcTypedBase *pPktDataInSink) +{ + // must be solo packet processor + if(pComponent->getAssocComponent() != 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + // interface must be the correct one. + IPktDataIn<P> *pkt_in_i = dynamic_cast< IPktDataIn<P> * >(pPktDataInSink); + if(pkt_in_i == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + // get the packet processor + TrcPktProcBase<P,Pt,Pc> *pPktProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> * >(pComponent); + if(pPktProcBase == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + // attach + return pPktProcBase->getPacketOutAttachPt()->replace_first(pkt_in_i); +} + +template <class P, class Pt, class Pc> +ocsd_err_t DecoderMngrBase<P,Pt,Pc>::createConfigFromDataStruct(CSConfig **pConfigBase, const void *pDataStruct) +{ + CSConfig *pConfig = createConfig(pDataStruct); + if(!pConfig) + return OCSD_ERR_MEM; + *pConfigBase = pConfig; + return OCSD_OK; +} + +/****************************************************************************************************/ +/* Full decoder / packet process pair, templated base for creating decoder objects */ +/****************************************************************************************************/ + +template< class P, // Packet class. + class Pt, // Packet enum type ID. + class Pc, // Processor config class. + class PcSt, // Processor config struct type + class PktProc, // Packet processor class. + class PktDcd> // Packet decoder class. +class DecodeMngrFullDcd : public DecoderMngrBase<P,Pt,Pc> +{ +public: + DecodeMngrFullDcd (const std::string &name, ocsd_trace_protocol_t builtInProtocol) + : DecoderMngrBase<P,Pt,Pc>(name,builtInProtocol) {}; + + virtual ~DecodeMngrFullDcd() {}; + + virtual TraceComponent *createPktProc(const bool useInstID, const int instID) + { + TraceComponent *pComp; + if(useInstID) + pComp = new (std::nothrow) PktProc(instID); + else + pComp = new (std::nothrow) PktProc(); + return pComp; + } + + virtual TraceComponent *createPktDecode(const bool useInstID, const int instID) + { + TraceComponent *pComp; + if(useInstID) + pComp = new (std::nothrow)PktDcd(instID); + else + pComp = new (std::nothrow)PktDcd(); + return pComp; + } + + virtual CSConfig *createConfig(const void *pDataStruct) + { + return new (std::nothrow) Pc((PcSt *)pDataStruct); + } +}; + +/* full decode - extended config object - base + derived. */ +template< class P, // Packet class. + class Pt, // Packet enum type ID. + class Pc, // Processor config base class. + class PcEx, // Processor config derived class + class PcSt, // Processor config struct type + class PktProc, // Packet processor class. + class PktDcd> // Packet decoder class. + class DecodeMngrFullDcdExCfg : public DecoderMngrBase<P, Pt, Pc> +{ +public: + DecodeMngrFullDcdExCfg(const std::string &name, ocsd_trace_protocol_t builtInProtocol) + : DecoderMngrBase<P, Pt, Pc>(name, builtInProtocol) {}; + + virtual ~DecodeMngrFullDcdExCfg() {}; + + virtual TraceComponent *createPktProc(const bool useInstID, const int instID) + { + TraceComponent *pComp; + if (useInstID) + pComp = new (std::nothrow) PktProc(instID); + else + pComp = new (std::nothrow) PktProc(); + return pComp; + } + + virtual TraceComponent *createPktDecode(const bool useInstID, const int instID) + { + TraceComponent *pComp; + if (useInstID) + pComp = new (std::nothrow)PktDcd(instID); + else + pComp = new (std::nothrow)PktDcd(); + return pComp; + } + + virtual CSConfig *createConfig(const void *pDataStruct) + { + return new (std::nothrow) PcEx((PcSt *)pDataStruct); + } +}; + + +/****************************************************************************************************/ +/* Packet processor only, templated base for creating decoder objects */ +/****************************************************************************************************/ + +template< class P, // Packet class. + class Pt, // Packet enum type ID. + class Pc, // Processor config class. + class PcSt, // Processor config struct type + class PktProc> // Packet processor class. +class DecodeMngrPktProc : public DecoderMngrBase<P,Pt,Pc> +{ +public: + DecodeMngrPktProc (const std::string &name, ocsd_trace_protocol_t builtInProtocol) + : DecoderMngrBase<P,Pt,Pc>(name,builtInProtocol) {}; + + virtual ~DecodeMngrPktProc() {}; + + virtual TraceComponent *createPktProc(const bool useInstID, const int instID) + { + TraceComponent *pComp; + if(useInstID) + pComp = new (std::nothrow) PktProc(instID); + else + pComp = new (std::nothrow) PktProc(); + return pComp; + } + + virtual CSConfig *createConfig(const void *pDataStruct) + { + return new (std::nothrow) Pc((PcSt *)pDataStruct); + } +}; + + + +#endif // ARM_OCSD_DCD_MNGR_H_INCLUDED + +/* End of File ocsd_dcd_mngr.h */ diff --git a/decoder/include/common/ocsd_dcd_mngr_i.h b/decoder/include/common/ocsd_dcd_mngr_i.h new file mode 100644 index 0000000..5ecbe31 --- /dev/null +++ b/decoder/include/common/ocsd_dcd_mngr_i.h @@ -0,0 +1,98 @@ +/* + * \file ocsd_dcd_mngr_i.h + * \brief OpenCSD : Decoder manager interface. + * + * \copyright Copyright (c) 2016, 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_OCSD_DCD_MNGR_I_H_INCLUDED +#define ARM_OCSD_DCD_MNGR_I_H_INCLUDED + +#include "opencsd/ocsd_if_types.h" +#include "common/trc_cs_config.h" +#include "common/trc_component.h" + +#include "interfaces/trc_error_log_i.h" +#include "interfaces/trc_data_raw_in_i.h" +#include "interfaces/trc_instr_decode_i.h" +#include "interfaces/trc_tgt_mem_access_i.h" +#include "interfaces/trc_gen_elem_in_i.h" +#include "interfaces/trc_abs_typed_base_i.h" + +class IDecoderMngr +{ +public: + IDecoderMngr() {}; + virtual ~IDecoderMngr() {}; + +// create and destroy decoders + virtual ocsd_err_t createDecoder(const int create_flags, const int instID, const CSConfig *p_config, TraceComponent **ppComponent) = 0; + virtual ocsd_err_t destroyDecoder(TraceComponent *pComponent) = 0; + + //! Get the built in protocol type ID managed by this instance - extern for custom decoders + virtual const ocsd_trace_protocol_t getProtocolType() const = 0; + +// connect decoders to other components - (replace current / 0 pointer value to detach ); +// compatible with all decoders + //!attach error logger to ptk-processor, or both of pkt processor and pkt decoder pair + virtual ocsd_err_t attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog) = 0; + +// pkt decoder only + //! attach instruction decoder to pkt decoder + virtual ocsd_err_t attachInstrDecoder(TraceComponent *pComponent, IInstrDecode *pIInstrDec) = 0; + + //! attach memory accessor to pkt decoder + virtual ocsd_err_t attachMemAccessor(TraceComponent *pComponent, ITargetMemAccess *pMemAccessor) = 0; + + //! attach generic output interface to pkt decoder + virtual ocsd_err_t attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink) = 0; + +// pkt processor only + //! attach a raw packet monitor to pkt processor (solo pkt processor, or pkt processor part of pair) + virtual ocsd_err_t attachPktMonitor(TraceComponent *pComponent, ITrcTypedBase *pPktRawDataMon) = 0; + + //! attach a packet indexer to pkt processor (solo pkt processor, or pkt processor part of pair) + virtual ocsd_err_t attachPktIndexer(TraceComponent *pComponent, ITrcTypedBase *pPktIndexer) = 0; + + //! attach a packet data sink to pkt processor output (solo pkt processor only - instead of decoder when pkt processor only created.) + virtual ocsd_err_t attachPktSink(TraceComponent *pComponent, ITrcTypedBase *pPktDataInSink) = 0; + +// data input connection interface + //! get raw data input interface from packet processor + virtual ocsd_err_t getDataInputI(TraceComponent *pComponent, ITrcDataIn **ppDataIn) = 0; + +// create configuration from data structure + virtual ocsd_err_t createConfigFromDataStruct(CSConfig **pConfigBase, const void *pDataStruct) = 0; + +}; + +#endif // ARM_OCSD_DCD_MNGR_I_H_INCLUDED + +/* End of File ocsd_dcd_mngr.h */
\ No newline at end of file diff --git a/decoder/include/common/ocsd_dcd_tree.h b/decoder/include/common/ocsd_dcd_tree.h new file mode 100644 index 0000000..b1c3dc6 --- /dev/null +++ b/decoder/include/common/ocsd_dcd_tree.h @@ -0,0 +1,453 @@ +/*! + * \file ocsd_dcd_tree.h + * \brief OpenCSD : Trace Decode Tree. + * + * \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_OCSD_DCD_TREE_H_INCLUDED +#define ARM_OCSD_DCD_TREE_H_INCLUDED + +#include <vector> +#include <list> + +#include "opencsd.h" +#include "ocsd_dcd_tree_elem.h" + +/** @defgroup dcd_tree OpenCSD Library : Trace Decode Tree. + @brief Create a multi source decode tree for a single trace capture buffer. + + Use to create a connected set of decoder objects to decode a trace buffer. + There may be multiple trace sources within the capture buffer. + +@{*/ + +/*! + * @class DecodeTree + * @brief Class to manage the decoding of data from a single trace sink . + * + * Provides functionality to build a tree of decode objects capable of decoding + * multiple trace sources within a single trace sink (capture buffer). + * + */ +class DecodeTree : public ITrcDataIn +{ +public: +/** @name Creation and Destruction +@{*/ + DecodeTree(); //!< default constructor + ~DecodeTree(); //!< default destructor + + /*! + * @brief Create a decode tree. + * Automatically creates a trace frame deformatter if required and a default error log component. + * + * @param src_type : Data stream source type, can be CoreSight frame formatted trace, or single demuxed trace data stream, + * @param formatterCfgFlags : Configuration flags for trace de-formatter. + * + * @return DecodeTree * : pointer to the decode tree, 0 if creation failed. + */ + static DecodeTree *CreateDecodeTree(const ocsd_dcd_tree_src_t src_type, const uint32_t formatterCfgFlags); + + /** @brief Destroy a decode tree */ + static void DestroyDecodeTree(DecodeTree *p_dcd_tree); + +/** @}*/ + + +/** @name Error and element Logging +@{*/ + /** @brief The library default error logger */ + static ocsdDefaultErrorLogger* getDefaultErrorLogger() { return &s_error_logger; }; + + /** the current error logging interface in use */ + static ITraceErrorLog *getCurrentErrorLogI() { return s_i_error_logger; }; + + /** set an alternate error logging interface. */ + static void setAlternateErrorLogger(ITraceErrorLog *p_error_logger); + + /** get the list of packet printers for this decode tree */ + std::vector<ItemPrinter *> &getPrinterList() { return m_printer_list; }; + + /** add a protocol packet printer */ + ocsd_err_t addPacketPrinter(uint8_t CSID, bool bMonitor, ItemPrinter **ppPrinter); + + /** add a raw frame printer */ + ocsd_err_t addRawFramePrinter(RawFramePrinter **ppPrinter, uint32_t flags); + + /** add a generic element output printer */ + ocsd_err_t addGenElemPrinter(TrcGenericElementPrinter **ppPrinter); + + + +/** @}*/ + + +/** @name Trace Data Path +@{*/ + /** @brief Trace Data input interface (ITrcDataIn) + + Decode tree implements the data in interface : ITrcDataIn . + Captured raw trace data is passed into the deformatter and decoders via this method. + */ + virtual ocsd_datapath_resp_t TraceDataIn( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed); + + /*! + * @brief Decoded Trace output. + * + * Client trace analysis program attaches a generic trace element interface to + * receive the output from the trace decode operations. + * + * @param *i_gen_trace_elem : Pointer to the interface. + */ + void setGenTraceElemOutI(ITrcGenElemIn *i_gen_trace_elem); + + /*! @brief Return the connected generic element interface */ + ITrcGenElemIn *getGenTraceElemOutI() const { return m_i_gen_elem_out; }; + +/** @}*/ + +/** @name Decoder Management +@{*/ + + /*! + * Creates a decoder that is registered with the library under the supplied name. + * createFlags determine if a full packet processor / packet decoder pair or + * packet processor only is created. + * Uses the supplied configuration structure. + * + * @param &decoderName : registered name of decoder + * @param createFlags : Decoder creation options. + * @param *pConfig : Pointer to a valid configuration structure for the named decoder. + * + * @return ocsd_err_t : Library error code or OCSD_OK if successful. + */ + ocsd_err_t createDecoder(const std::string &decoderName, const int createFlags, const CSConfig *pConfig); + + /* */ + /*! + * Remove a decoder / packet processor attached to an Trace ID output on the frame de-mux. + * + * Once removed another decoder can be created that has a CSConfig using that ID. + * + * @param CSID : Trace ID to remove. + * + * @return ocsd_err_t : Library error code or OCSD_OK if successful. + */ + ocsd_err_t removeDecoder(const uint8_t CSID); + + /*! + * Get the stats block for the channel indicated. + * Caller must check p_stats_block->version to esure that the block + * is filled in a compatible manner. + * + * @param CSID : Configured CoreSight trace ID for the decoder. + * @param p_stats_block: block pointer to set to reference the stats block. + * + * @return ocsd_err_t : Library error code - OCSD_OK if valid block pointer returned, + * OCSD_ERR_NOTINIT if decoder does not support stats counting. + */ + ocsd_err_t getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block); + + /*! + * Reset the stats block for the chosens decode channel. + * stats block is reset independently of the decoder reset to allow counts across + * multiple decode runs. + * + * @param handle : Handle to decode tree. + * @param CSID : Configured CoreSight trace ID for the decoder. + * + * @return ocsd_err_t : Library error code - OCSD_OK if successful. + */ + ocsd_err_t resetDecoderStats(const uint8_t CSID); + +/* get decoder elements currently in use */ + + /*! + * Find a decode tree element associated with a specific CoreSight trace ID. * + */ + DecodeTreeElement *getDecoderElement(const uint8_t CSID) const; + /* iterate decoder elements */ + + /*! + * Decode tree iteration. Return the first tree element 0 if no elements avaiable. + * + * @param &elemID : CoreSight Trace ID associated with this element + */ + DecodeTreeElement *getFirstElement(uint8_t &elemID); + /*! + * Return the next tree element - or 0 if no futher elements avaiable. + * + * @param &elemID : CoreSight Trace ID associated with this element + */ + DecodeTreeElement *getNextElement(uint8_t &elemID); + +/* set key interfaces - attach / replace on any existing tree components */ + + /*! + * Set an ARM instruction opcode decoder. + * + * @param *i_instr_decode : Pointer to the interface. + */ + void setInstrDecoder(IInstrDecode *i_instr_decode); + /*! + * Set a target memory access interface - used to access program image memory for instruction + * trace decode. + * + * @param *i_mem_access : Pointer to the interface. + */ + void setMemAccessI(ITargetMemAccess *i_mem_access); + + +/** @}*/ + +/** @name Memory Access Mapper + + A memory mapper is used to organise a collection of memory accessor objects that contain the + memory images for different areas of traced instruction memory. These areas could be the executed + program and a set of loaded .so libraries for example - each of which would have code sections in + different memory locations. + + A memory accessor represents a snapshot of an area of memory as it appeared during trace capture, + for a given memory space. Memory spaces are described by the ocsd_mem_space_acc_t enum. The most + general memory space is OCSD_MEM_SPACE_ANY. This represents memory that can be secure or none-secure, + available at any exception level. + + The memory mapper will not allow two accessors to overlap in the same memory space. + + The trace decdoer will access memory with a memory space parameter that represents the current core + state - the mapper will find the closest memory space match for the address. + + e.g. if the core is accessing secure EL3, then the most specialised matching space will be accessed. + If an EL3 space matches that will be used, otherwise the any secure, and finally _ANY. + + It is no necessary for clients to register memory accessors for all spaces - _ANY will be sufficient + in many cases. + + +@{*/ + + /* */ + /*! + * This creates a memory mapper within the decode tree. + * + * @param type : defaults to MEMACC_MAP_GLOBAL (only type available at present) + * + * @return ocsd_err_t : Library error code or OCSD_OK if successful. + */ + ocsd_err_t createMemAccMapper(memacc_mapper_t type = MEMACC_MAP_GLOBAL); + + /*! + * Get a pointer to the memory mapper. Allows a client to add memory accessors directly to the mapper. + * @return TrcMemAccMapper : Pointer to the mapper. + */ + TrcMemAccMapper *getMemAccMapper() const { return m_default_mapper; }; + + /*! + * Set an external mapper rather than create a mapper in the decode tree. + * Setting this will also destroy any internal mapper that was previously created. + * + * @param pMapper : pointer to the mapper to add. + */ + void setExternMemAccMapper(TrcMemAccMapper * pMapper); + + /*! + * Return true if a mapper has been set (internal or external + */ + const bool hasMemAccMapper() const { return (bool)(m_default_mapper != 0); }; + + void logMappedRanges(); //!< Log the mapped memory ranges to the default message logger. + +/** @}*/ + +/** @name Memory Accessors + A memory accessor represents a snapshot of an area of memory as it appeared during trace capture. + + Memory spaces represent either common global memory, or Secure / none-secure and EL specific spaces. + +@{*/ + + /*! + * Creates a memory accessor for a memory block in the supplied buffer and adds to the current mapper. + * + * @param address : Start address for the memory block in the memory map. + * @param mem_space : Memory space + * @param *p_mem_buffer : start of the buffer. + * @param mem_length : length of the buffer. + * + * @return ocsd_err_t : Library error code or OCSD_OK if successful. + */ + ocsd_err_t addBufferMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t *p_mem_buffer, const uint32_t mem_length); + + /*! + * Creates a memory accessor for a memory block supplied as a contiguous binary data file, and adds to the current mapper. + * + * @param address : Start address for the memory block in the memory map. + * @param mem_space : Memory space + * @param &filepath : Path to the binary data file + * + * @return ocsd_err_t : Library error code or OCSD_OK if successful. + */ + ocsd_err_t addBinFileMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const std::string &filepath); + + /*! + * Creates a memory accessor for a memory block supplied as a one or more memory regions in a binary file. + * Region structures are created that describe the memory start address, the offset within the binary file + * for that address, and the length of the region. This accessor can be used to point to the code section + * in a program file for example. + * + * @param *region_array : array of valid memory regions in the file. + * @param num_regions : number of regions + * @param mem_space : Memory space + * @param &filepath : Path to the binary data file + * + * @return ocsd_err_t : Library error code or OCSD_OK if successful. + */ + ocsd_err_t addBinFileRegionMemAcc(const ocsd_file_mem_region_t *region_array, const int num_regions, const ocsd_mem_space_acc_t mem_space, const std::string &filepath); + + + /*! + * Updates/adds to a memory accessor for a memory block supplied as a one or more memory regions in a binary file. + * Region structures are created that describe the memory start address, the offset within the binary file + * for that address, and the length of the region. This accessor can be used to point to the code section + * in a program file for example. + * + * @param *region_array : array of valid memory regions in the file. + * @param num_regions : number of regions + * @param mem_space : Memory space + * @param &filepath : Path to the binary data file + * + * @return ocsd_err_t : Library error code or OCSD_OK if successful. + */ + ocsd_err_t updateBinFileRegionMemAcc(const ocsd_file_mem_region_t *region_array, const int num_regions, const ocsd_mem_space_acc_t mem_space, const std::string &filepath); + + /*! + * This memory accessor allows the client to supply a callback function for the region + * defined by the start and end addresses. This can be used to supply a custom memory accessor, + * or to directly access memory if the decode is running live on a target system. + * + * @param st_address : start address of region. + * @param en_address : end address of region. + * @param mem_space : Memory space + * @param p_cb_func : Callback function + * @param *p_context : client supplied context information + * + * @return ocsd_err_t : Library error code or OCSD_OK if successful. + */ + ocsd_err_t addCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, Fn_MemAcc_CB p_cb_func, const void *p_context); + ocsd_err_t addCallbackIDMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, Fn_MemAccID_CB p_cb_func, const void *p_context); + + /*! + * Remove the memory accessor from the map, that begins at the given address, for the memory space provided. + * + * @param address : Start address of the memory accessor. + * @param mem_space : Memory space for the memory accessor. + * + * @return ocsd_err_t : Library error code or OCSD_OK if successful. + */ + ocsd_err_t removeMemAccByAddress(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space); + +/** @}*/ + +/** @name CoreSight Trace Frame De-mux +@{*/ + + //! Get the Trace Frame de-mux. + TraceFormatterFrameDecoder *getFrameDeformatter() const { return m_frame_deformatter_root; }; + + + /*! @brief ID filtering - sets the output filter on the trace deformatter. + + Only supplied IDs will be decoded. + + No effect if no decoder attached for the ID + + @param ids : Vector of CS Trace IDs + */ + ocsd_err_t setIDFilter(std::vector<uint8_t> &ids); // only supplied IDs will be decoded + + ocsd_err_t clearIDFilter(); //!< remove filter, all IDs will be decoded + +/** @}*/ + +private: + bool initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCfgFlags); + const bool usingFormatter() const { return (bool)(m_dcd_tree_type == OCSD_TRC_SRC_FRAME_FORMATTED); }; + void setSingleRoot(TrcPktProcI *pComp); + ocsd_err_t createDecodeElement(const uint8_t CSID); + void destroyDecodeElement(const uint8_t CSID); + void destroyMemAccMapper(); + ocsd_err_t initCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, + const ocsd_mem_space_acc_t mem_space, void *p_cb_func, bool IDfn, const void *p_context); + TrcPktProcI *getPktProcI(const uint8_t CSID); + + ocsd_dcd_tree_src_t m_dcd_tree_type; + + IInstrDecode *m_i_instr_decode; + ITargetMemAccess *m_i_mem_access; + ITrcGenElemIn *m_i_gen_elem_out; //!< Output interface for generic elements from decoder. + + ITrcDataIn* m_i_decoder_root; /*!< root decoder object interface - either deformatter or single packet processor */ + + TraceFormatterFrameDecoder *m_frame_deformatter_root; + + DecodeTreeElement *m_decode_elements[0x80]; + + uint8_t m_decode_elem_iter; + + TrcMemAccMapper *m_default_mapper; //!< the mem acc mapper to use + bool m_created_mapper; //!< true if created by decode tree object + + std::vector<ItemPrinter *> m_printer_list; //!< list of packet printers. + + /* global error logger - all sources */ + static ITraceErrorLog *s_i_error_logger; + static std::list<DecodeTree *> s_trace_dcd_trees; + + /**! default error logger */ + static ocsdDefaultErrorLogger s_error_logger; + + /**! default instruction decoder */ + static TrcIDecode s_instruction_decoder; + + /**! demux stats block */ + ocsd_demux_stats_t m_demux_stats; +}; + +/** @}*/ + +#endif // ARM_OCSD_DCD_TREE_H_INCLUDED + +/* End of File ocsd_dcd_tree.h */ diff --git a/decoder/include/common/ocsd_dcd_tree_elem.h b/decoder/include/common/ocsd_dcd_tree_elem.h new file mode 100644 index 0000000..2b609fb --- /dev/null +++ b/decoder/include/common/ocsd_dcd_tree_elem.h @@ -0,0 +1,112 @@ +/*! + * \file ocsd_dcd_tree_elem.h + * \brief OpenCSD : Decode tree element. + * + * \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_OCSD_DCD_TREE_ELEM_H_INCLUDED +#define ARM_OCSD_DCD_TREE_ELEM_H_INCLUDED + +#include "common/ocsd_dcd_mngr_i.h" +#include "common/trc_component.h" + +/** @addtogroup dcd_tree +@{*/ + +/*! @struct _decoder_elements + * @brief Decode tree element base structure. + * + * Element describes the protocol supported for this element and + * contains pointers to the decoder manager interface and component handle. + */ +typedef struct _decoder_elements +{ + std::string dcd_name; //!< Registered name of the decoder + TraceComponent *dcd_handle; //!< handle to the decoder object + IDecoderMngr *dcd_mngr; //!< pointer to the decoder manager interface for the decodcer + ocsd_trace_protocol_t protocol;//!< protocol type + bool created; /**< decode tree created this element (destroy it on tree destruction) */ +} decoder_element; + +/*! + * @class DecodeTreeElement + * @brief Decode tree element + * + * Decoder tree elements are references to individual decoders in the tree. + * These allow iteration of all decoders in the tree to perform common operations. + * + * The DecodeTree contains a list of elements. + */ +class DecodeTreeElement : protected decoder_element +{ +public: + DecodeTreeElement(); + ~DecodeTreeElement() {}; + + void SetDecoderElement(const std::string &name, IDecoderMngr *dcdMngr, TraceComponent *pHandle, bool bCreated); + void DestroyElem(); + + const std::string &getDecoderTypeName() { return dcd_name; }; + IDecoderMngr *getDecoderMngr() { return dcd_mngr; }; + ocsd_trace_protocol_t getProtocol() const { return protocol; }; + TraceComponent *getDecoderHandle() { return dcd_handle; }; +}; + +inline DecodeTreeElement::DecodeTreeElement() +{ + dcd_name = "unknown"; + dcd_mngr = 0; + dcd_handle = 0; + protocol = OCSD_PROTOCOL_END; + created = false; +} + +inline void DecodeTreeElement::SetDecoderElement(const std::string &name, IDecoderMngr *dcdMngr, TraceComponent *pHandle, bool bCreated) +{ + dcd_name = name; + dcd_mngr = dcdMngr; + dcd_handle = pHandle; + protocol = OCSD_PROTOCOL_UNKNOWN; + if(dcd_mngr) + protocol = dcd_mngr->getProtocolType(); + created = bCreated; +} + +inline void DecodeTreeElement::DestroyElem() +{ + if(created && (dcd_mngr != 0) && (dcd_handle != 0)) + dcd_mngr->destroyDecoder(dcd_handle); +} + +/** @}*/ +#endif // ARM_OCSD_DCD_TREE_ELEM_H_INCLUDED + +/* End of File ocsd_dcd_tree_elem.h */ diff --git a/decoder/include/common/ocsd_error.h b/decoder/include/common/ocsd_error.h new file mode 100644 index 0000000..7c6ed3a --- /dev/null +++ b/decoder/include/common/ocsd_error.h @@ -0,0 +1,127 @@ +/*! + * \file ocsd_error.h + * \brief OpenCSD : Library Error class + * + * \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_OCSD_ERROR_H_INCLUDED +#define ARM_OCSD_ERROR_H_INCLUDED + +#include "opencsd/ocsd_if_types.h" +#include <string> +/** @ingroup ocsd_infrastructure +@{*/ + +/*! + * @class ocsdError + * + * This class is the error object for the Ocsd. + * + * Errors are created with a severity (ocsd_err_severity_t) and a standard ocsd_err_t error code. + * Errors can optionally be created with a trace index (offset from start of capture buffer), and + * trace CoreSight source channel ID. + * + * A custom error message can be appended to the error. + * + * The ocsdError class contains a static function to output a formatted string representation of an error. + * + */ +class ocsdError { +public: + ocsdError(const ocsd_err_severity_t sev_type, const ocsd_err_t code); /**< Default error constructor with severity and error code. */ + ocsdError(const ocsd_err_severity_t sev_type, const ocsd_err_t code, const ocsd_trc_index_t idx); /**< Constructor with optional trace index. */ + ocsdError(const ocsd_err_severity_t sev_type, const ocsd_err_t code, const ocsd_trc_index_t idx, const uint8_t chan_id); /**< Constructor with optional trace index and channel ID. */ + ocsdError(const ocsd_err_severity_t sev_type, const ocsd_err_t code, const std::string &msg); /**< Default error constructor with severity and error code - plus message. */ + ocsdError(const ocsd_err_severity_t sev_type, const ocsd_err_t code, const ocsd_trc_index_t idx, const std::string &msg); /**< Constructor with optional trace index - plus message. */ + ocsdError(const ocsd_err_severity_t sev_type, const ocsd_err_t code, const ocsd_trc_index_t idx, const uint8_t chan_id, const std::string &msg); /**< Constructor with optional trace index and channel ID - plus message. */ + + ocsdError(const ocsdError *pError); /**< Copy constructor */ + ocsdError(const ocsdError &Error); /**< Copy constructor */ + ~ocsdError(); /**< Destructor */ + + ocsdError& operator=(const ocsdError *p_err); + ocsdError& operator=(const ocsdError &err); + + void setMessage(const std::string &msg) { m_err_message = msg; }; /**< Set custom error message */ + const std::string &getMessage() const { return m_err_message; }; /**< Get custom error message */ + + const ocsd_err_t getErrorCode() const { return m_error_code; }; /**< Get error code. */ + const ocsd_err_severity_t getErrorSeverity() const { return m_sev; }; /**< Get error severity. */ + const ocsd_trc_index_t getErrorIndex() const { return m_idx; }; /**< Get trace index associated with the error. */ + const uint8_t getErrorChanID() const { return m_chan_ID; }; /**< Get the trace source channel ID associated with the error. */ + + static const std::string getErrorString(const ocsdError &error); /**< Generate a formatted error string for the supplied error. */ + +private: + static void appendErrorDetails(std::string &errStr, const ocsdError &error); /**< build the error string. */ + ocsdError(); /**< Make no parameter default constructor inaccessible. */ + + ocsd_err_t m_error_code; /**< Error code for this error */ + ocsd_err_severity_t m_sev; /**< severity for this error */ + ocsd_trc_index_t m_idx; /**< Trace buffer index associated with this error (optional) */ + uint8_t m_chan_ID; /**< trace source ID associated with this error (optional) */ + + std::string m_err_message; /**< Additional text associated with this error (optional) */ +}; + +inline ocsdError& ocsdError::operator=(const ocsdError *p_err) +{ + this->m_error_code = p_err->getErrorCode(); + this->m_sev = p_err->getErrorSeverity(); + this->m_idx = p_err->getErrorIndex(); + this->m_chan_ID = p_err->getErrorChanID(); + this->m_err_message = p_err->getMessage(); + return *this; +} + +inline ocsdError& ocsdError::operator=(const ocsdError &err) +{ + return (*this = &err); +} + +/* class to get data path response values as strings */ +class ocsdDataRespStr +{ +public: + ocsdDataRespStr(ocsd_datapath_resp_t type) { m_type = type; } + ~ocsdDataRespStr() {}; + + const char* getStr(); +private: + ocsd_datapath_resp_t m_type; +}; + +/** @}*/ + +#endif // ARM_OCSD_ERROR_H_INCLUDED + +/* End of File ocsd_error.h */ diff --git a/decoder/include/common/ocsd_error_logger.h b/decoder/include/common/ocsd_error_logger.h new file mode 100644 index 0000000..3badd33 --- /dev/null +++ b/decoder/include/common/ocsd_error_logger.h @@ -0,0 +1,89 @@ +/*! + * \file ocsd_error_logger.h + * \brief OpenCSD : Library error logger. + * + * \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_OCSD_ERROR_LOGGER_H_INCLUDED +#define ARM_OCSD_ERROR_LOGGER_H_INCLUDED + +#include <string> +#include <vector> +//#include <fstream> + +#include "interfaces/trc_error_log_i.h" +#include "ocsd_error.h" +#include "ocsd_msg_logger.h" + +class ocsdDefaultErrorLogger : public ITraceErrorLog +{ +public: + ocsdDefaultErrorLogger(); + virtual ~ocsdDefaultErrorLogger(); + + bool initErrorLogger(const ocsd_err_severity_t verbosity, bool bCreateOutputLogger = false); //!< Initialise the error logger with a severity filter, optionally create an output logger on stderr. + + virtual ocsdMsgLogger *getOutputLogger() { return m_output_logger; }; + virtual void setOutputLogger(ocsdMsgLogger *pLogger); + + virtual const ocsd_hndl_err_log_t RegisterErrorSource(const std::string &component_name); + + virtual void LogError(const ocsd_hndl_err_log_t handle, const ocsdError *Error); + virtual void LogMessage(const ocsd_hndl_err_log_t handle, const ocsd_err_severity_t filter_level, const std::string &msg ); + + virtual const ocsd_err_severity_t GetErrorLogVerbosity() const { return m_Verbosity; }; + + virtual ocsdError *GetLastError() { return m_lastErr; }; + virtual ocsdError *GetLastIDError(const uint8_t chan_id) + { + if(OCSD_IS_VALID_CS_SRC_ID(chan_id)) + return m_lastErrID[chan_id]; + return 0; + }; + +private: + void CreateErrorObj(ocsdError **ppErr, const ocsdError *p_from); + + ocsdError *m_lastErr; + ocsdError *m_lastErrID[0x80]; + + ocsd_err_severity_t m_Verbosity; + + ocsdMsgLogger *m_output_logger; // pointer to a standard message output logger; + bool m_created_output_logger; // true if this class created it's own logger; + + std::vector<std::string> m_error_sources; +}; + + +#endif // ARM_OCSD_ERROR_LOGGER_H_INCLUDED + +/* End of File ocsd_error_logger.h */ diff --git a/decoder/include/common/ocsd_gen_elem_list.h b/decoder/include/common/ocsd_gen_elem_list.h new file mode 100644 index 0000000..2dab240 --- /dev/null +++ b/decoder/include/common/ocsd_gen_elem_list.h @@ -0,0 +1,153 @@ +/* + * \file ocsd_gen_elem_list.h + * \brief OpenCSD : Generic element output list. + * + * \copyright Copyright (c) 2016, 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 <list> +#include "trc_gen_elem.h" +#include "comp_attach_pt_t.h" +#include "interfaces/trc_gen_elem_in_i.h" + +/*! + * @class OcsdGenElemList + * @brief Maintain a list of elements to be output + * + * Each incoming packet can result in multiple output elements. + * These are stacked in this class prior to entering the output phase of processing. + * + * This should remove some of the requirement on the packet processing to be re-enterant, + * simplifying this code. + * + * Last element(s) on this list can be marked pending to allow for later cancellation. + * (This required for cancel element in ETMv3 exeception branch). + * + * The "list" is actually a ring buffer - maintaining pointers to indicate current valid elements. + * This buffer can increase on demand, but will only be released at the end of a decode session. + */ +class OcsdGenElemList +{ +public: + OcsdGenElemList(); + ~OcsdGenElemList(); + + void initSendIf(componentAttachPt<ITrcGenElemIn> *pGenElemIf); + void initCSID(const uint8_t CSID) { m_CSID = CSID; }; + + void reset(); //!< reset the element list. + + OcsdTraceElement *getNextElem(const ocsd_trc_index_t trc_pkt_idx); //!< get next free element on the stack (add one to the output) + const int getNumElem() const; //!< return the total number of elements on the stack (inlcuding any pended ones). + + const ocsd_gen_trc_elem_t getElemType(const int entryN) const; //!< get the type for the nth element in the stack (0 indexed) + + void pendLastNElem(int numPend); //!< Last element to be pended prior to cancel/commit decision. + void commitAllPendElem(); //!< commit all pended elements. + void cancelPendElem(); //!< cancel the last pended element on the stack. + const int numPendElem() const; //!< return the number of pended elements. + + /*! Send all of the none pended elements + Stop sending when all sent or _CONT response. + */ + ocsd_datapath_resp_t sendElements(); + const bool elemToSend() const; //!< true if any none-pending elements left to send. + +private: + + void growArray(); + const int getAdjustedIdx(int idxIn) const; //!< get adjusted index into circular buffer. + + + // list element contains pointer and byte index in trace stream + typedef struct _elemPtr { + OcsdTraceElement *pElem; //!< pointer to the listed trace element + ocsd_trc_index_t trc_pkt_idx; //!< packet index in the trace stream + } elemPtr_t; + + elemPtr_t *m_pElemArray; //!< an array of pointers to elements. + int m_elemArraySize; //!< number of element pointers in the array + + int m_firstElemIdx; //!< internal index in array of first element in use. + int m_numUsed; //!< number of elements in use + int m_numPend; //!< internal count of pended elements. + + uint8_t m_CSID; + + componentAttachPt<ITrcGenElemIn> *m_sendIf; //!< element send interface. +}; + +inline const int OcsdGenElemList::getAdjustedIdx(int idxIn) const +{ + if(idxIn >= m_elemArraySize) + idxIn -= m_elemArraySize; + return idxIn; +} + +inline const int OcsdGenElemList::getNumElem() const +{ + return m_numUsed; +} + +inline const int OcsdGenElemList::numPendElem() const +{ + return m_numPend; +} + +inline void OcsdGenElemList::pendLastNElem(int numPend) +{ + if(numPend >= getNumElem()) + m_numPend = numPend; +} + +inline void OcsdGenElemList::commitAllPendElem() +{ + m_numPend = 0; +} + +inline void OcsdGenElemList::cancelPendElem() +{ + if(m_numPend > 0) + { + m_numUsed -= m_numPend; + } +} + +inline const bool OcsdGenElemList::elemToSend() const +{ + return ((getNumElem() - m_numPend) > 0); +} + +inline void OcsdGenElemList::initSendIf(componentAttachPt<ITrcGenElemIn> *pGenElemIf) +{ + m_sendIf = pGenElemIf; +} + +/* End of File ocsd_gen_elem_list.h */ diff --git a/decoder/include/common/ocsd_gen_elem_stack.h b/decoder/include/common/ocsd_gen_elem_stack.h new file mode 100644 index 0000000..64c525d --- /dev/null +++ b/decoder/include/common/ocsd_gen_elem_stack.h @@ -0,0 +1,109 @@ +/* +* \file ocsd_gen_elem_stack.h +* \brief OpenCSD : Generic element output stack. +* +* \copyright Copyright (c) 2020, 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 "trc_gen_elem.h" +#include "comp_attach_pt_t.h" +#include "interfaces/trc_gen_elem_in_i.h" + +/* element stack to handle cases where a trace element can generate multiple output packets + + maintains the "current" element, which might be sent independently of this stack, and also + ensures that persistent data in the output elements is maintained between elements. +*/ +class OcsdGenElemStack +{ +public: + OcsdGenElemStack(); + ~OcsdGenElemStack(); + + void initSendIf(componentAttachPt<ITrcGenElemIn> *pGenElemIf); + void initCSID(const uint8_t CSID) { m_CSID = CSID; }; + + OcsdTraceElement &getCurrElem(); //!< get the current element. + ocsd_err_t resetElemStack(); //!< set pointers to base of stack + ocsd_err_t addElem(const ocsd_trc_index_t trc_pkt_idx); //!< add elem to stack and set current. + void setCurrElemIdx(const ocsd_trc_index_t trc_pkt_idx); //!< packet index for this element + ocsd_err_t addElemType(const ocsd_trc_index_t trc_pkt_idx, ocsd_gen_trc_elem_t elem_type); + + ocsd_datapath_resp_t sendElements(); //!< send elements on the stack + const int numElemToSend() const; + +private: + typedef struct _elemPtr { + OcsdTraceElement *pElem; //!< pointer to the listed trace element + ocsd_trc_index_t trc_pkt_idx; //!< packet index in the trace stream + } elemPtr_t; + + const bool isInit(); //!< check correctly initialised. + + ocsd_err_t growArray(); + void copyPersistentData(int src, int dst); //!< copy across persistent state data between elements + void resetIndexes(); //!< clear down all indexes - reset or send complete. + + elemPtr_t *m_pElemArray; //!< an array of pointers to elements. + int m_elemArraySize; //!< number of element pointers in the array + + int m_elem_to_send; //!< number of live elements in the stack - init to 1. + int m_curr_elem_idx; //!< index into the element array. + int m_send_elem_idx; //!< next element to send. + + //!< send packet info + uint8_t m_CSID; + componentAttachPt<ITrcGenElemIn> *m_sendIf; //!< element send interface. + + bool m_is_init; +}; + +inline const int OcsdGenElemStack::numElemToSend() const +{ + return m_elem_to_send; +} + +inline void OcsdGenElemStack::initSendIf(componentAttachPt<ITrcGenElemIn> *pGenElemIf) +{ + m_sendIf = pGenElemIf; +} + +inline void OcsdGenElemStack::setCurrElemIdx(const ocsd_trc_index_t trc_pkt_idx) +{ + m_pElemArray[m_curr_elem_idx].trc_pkt_idx = trc_pkt_idx; +} + +inline OcsdTraceElement &OcsdGenElemStack::getCurrElem() +{ + return *(m_pElemArray[m_curr_elem_idx].pElem); +} + + +/* End of File ocsd_gen_elem_stack.h */ diff --git a/decoder/include/common/ocsd_lib_dcd_register.h b/decoder/include/common/ocsd_lib_dcd_register.h new file mode 100644 index 0000000..6ba4cf8 --- /dev/null +++ b/decoder/include/common/ocsd_lib_dcd_register.h @@ -0,0 +1,131 @@ +/* + * \file ocsd_lib_dcd_register.h + * \brief OpenCSD : Library decoder registration and management. + * + * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved. + */ + +#ifndef ARM_OCSD_LIB_DCD_REGISTER_H_INCLUDED +#define ARM_OCSD_LIB_DCD_REGISTER_H_INCLUDED + + +/* + * 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 <map> + +#include "opencsd/ocsd_if_types.h" +#include "common/ocsd_dcd_mngr_i.h" + +/*! + * @class OcsdLibDcdRegister : Registers decoders with the library + * + * library decoder register class allows decoders to be registered by name, and the register allows clients to access + * the list of names of registerd decoders. + * + * The decoders in the library are accessed through the decoder manager interface. This provides a set of functions to allow + * the creation, manipulation and destruction of registered decoders + * + */ +class OcsdLibDcdRegister +{ +public: + static OcsdLibDcdRegister *getDecoderRegister(); + + static void deregisterAllDecoders(); //!< library cleanup - deregisters decoder managers and destroys the register object. + static const ocsd_trace_protocol_t getNextCustomProtocolID(); + static void releaseLastCustomProtocolID(); + + const ocsd_err_t registerDecoderTypeByName(const std::string &name, IDecoderMngr *p_decoder_fact); //!< register a decoder manager interface + const ocsd_err_t getDecoderMngrByName(const std::string &name, IDecoderMngr **p_decoder_mngr); + const ocsd_err_t getDecoderMngrByType(const ocsd_trace_protocol_t decoderType, IDecoderMngr **p_decoder_mngr); + + const bool isRegisteredDecoder(const std::string &name); + const bool getFirstNamedDecoder(std::string &name); + const bool getNextNamedDecoder(std::string &name); + + const bool isRegisteredDecoderType(const ocsd_trace_protocol_t decoderType); + +private: + void registerBuiltInDecoders(); //!< register the list of build in decoder managers on first access of getDecoderMngrByName. + void deRegisterCustomDecoders(); //!< delete all custom decoders registered with the library. + + std::map<const std::string, IDecoderMngr *> m_decoder_mngrs; //!< map linking names to decoder manager interfaces. + std::map<const std::string, IDecoderMngr *>::const_iterator m_iter; //!< iterator for name search. + + std::map<const ocsd_trace_protocol_t, IDecoderMngr *> m_typed_decoder_mngrs; //!< map linking decoder managers to protocol type ID + + // cache last found by type to speed up repeated quries on same object. + IDecoderMngr *m_pLastTypedDecoderMngr; //!< last manager we found by type + + + + // singleton pattern - need just one of these in the library - ensure all default constructors are private. + OcsdLibDcdRegister(); + OcsdLibDcdRegister(OcsdLibDcdRegister const &) {}; + OcsdLibDcdRegister& operator=(OcsdLibDcdRegister const &){ return *this; }; + ~OcsdLibDcdRegister(); + + static OcsdLibDcdRegister *m_p_libMngr; + static bool m_b_registeredBuiltins; + static ocsd_trace_protocol_t m_nextCustomProtocolID; +}; + +/*! + * Typedef of function signature to create a decoder manager. + * + * @param *name : Registered name of the decoder. + */ +typedef IDecoderMngr *(*CreateMngr)(const std::string &name); + +/*! + * Template function to create a specific decoder manager class object. + * + * @param &name : Registered name of the decoder. + * + * @return IDecoderMngr * : pointer to the decoder manager base class interface. + */ +template <typename T> IDecoderMngr *createManagerInst(const std::string &name) +{ + return new (std::nothrow)T(name); +} + +/*! Structure to contain the information needed to create and register a builtin decoder + * manager with the library + */ +typedef struct built_in_decoder_info { + IDecoderMngr *pMngr; //!< pointer to created decoder manager + CreateMngr PFn; //!< function to create the decoder manager. + const char *name; //!< registered name of the decoder. +} built_in_decoder_info_t; + +//! Define to use to fill in an array of built_in_decoder_info_t structures. +#define CREATE_BUILTIN_ENTRY(C,N) { 0, createManagerInst<C>, N } + +#endif // ARM_OCSD_LIB_DCD_REGISTER_H_INCLUDED + +/* End of File ocsd_lib_dcd_register.h */ diff --git a/decoder/include/common/ocsd_msg_logger.h b/decoder/include/common/ocsd_msg_logger.h new file mode 100644 index 0000000..d83a022 --- /dev/null +++ b/decoder/include/common/ocsd_msg_logger.h @@ -0,0 +1,87 @@ +/*! + * \file ocsd_msg_logger.h + * \brief OpenCSD : Generic Message logger / printer + * + * \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_OCSD_MSG_LOGGER_H_INCLUDED +#define ARM_OCSD_MSG_LOGGER_H_INCLUDED + +#include <string> +#include <fstream> + +class ocsdMsgLogStrOutI +{ +public: + ocsdMsgLogStrOutI() {}; + virtual ~ocsdMsgLogStrOutI() {}; + + virtual void printOutStr(const std::string &outStr) = 0; +}; + +class ocsdMsgLogger +{ +public: + ocsdMsgLogger(); + ~ocsdMsgLogger(); + + /** Typedef enum providing flags to define the output methods for the message logger. + */ + typedef enum { + OUT_NONE = 0, /*!< No output from logger*/ + OUT_FILE = 1, /*!< Output to file */ + OUT_STDERR = 2, /*!< Output to stderr */ + OUT_STDOUT = 4, /*!< Output to stdout */ + OUT_STR_CB = 8 /*!< output to external string callback interface */ + } output_dest; + + void setLogOpts(int logOpts); //!< set the output logging flags. + const int getLogOpts() const //! get the current output logging flags value. + { return m_outFlags; }; + + void setLogFileName(const char *fileName); //!< Set the output log filename, and enable logging to file. + void setStrOutFn(ocsdMsgLogStrOutI *p_IstrOut); //!< Set the output log string callback and enable logging to callback. + + void LogMsg(const std::string &msg); //!< Log a message to the current set output channels. + + const bool isLogging() const; //!< true if logging active + +private: + int m_outFlags; + + std::string m_logFileName; + std::fstream m_out_file; + ocsdMsgLogStrOutI *m_pOutStrI; +}; + +#endif // ARM_OCSD_MSG_LOGGER_H_INCLUDED + +/* End of File ocsd_msg_logger.h */ diff --git a/decoder/include/common/ocsd_pe_context.h b/decoder/include/common/ocsd_pe_context.h new file mode 100644 index 0000000..797881c --- /dev/null +++ b/decoder/include/common/ocsd_pe_context.h @@ -0,0 +1,116 @@ +/* + * \file ocsd_pe_context.h + * \brief OpenCSD : Wrapper class for PE context + * + * \copyright Copyright (c) 2016, 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_OCSD_PE_CONTEXT_H_INCLUDED +#define ARM_OCSD_PE_CONTEXT_H_INCLUDED + +#include "opencsd/ocsd_if_types.h" + +/*! @class OcsdPeContext + * @brief Handler for the ocsd_pe_context structure. + * + * Reads and writes structure values, enforcing interaction rules between values + * and flags. + */ +class OcsdPeContext +{ +public: + OcsdPeContext(); + OcsdPeContext(const ocsd_pe_context *context); + ~OcsdPeContext() {}; + + OcsdPeContext &operator =(const OcsdPeContext &ctxt); + OcsdPeContext &operator =(const ocsd_pe_context *context); + + void resetCtxt(); + + void setSecLevel(const ocsd_sec_level sl) { m_context.security_level = sl; }; + void setEL(const ocsd_ex_level el) { m_context.exception_level = el; m_context.el_valid = el > ocsd_EL_unknown ? 1 : 0; }; + void setCtxtID(const uint32_t id) { m_context.context_id = id; m_context.ctxt_id_valid = 1; }; + void setVMID(const uint32_t id) { m_context.vmid = id; m_context.vmid_valid = 1; }; + void set64bit(const bool is64bit) { m_context.bits64 = is64bit ? 1 : 0; }; + + const ocsd_sec_level getSecLevel() const { return m_context.security_level; }; + const ocsd_ex_level getEL() const { return m_context.exception_level; }; + const bool ELvalid() const { return (m_context.el_valid == 1); }; + const uint32_t getCtxtID() const { return (m_context.ctxt_id_valid == 1) ? m_context.context_id : 0; }; + const bool ctxtIDvalid() const { return (m_context.ctxt_id_valid == 1); }; + const uint32_t getVMID() const { return (m_context.vmid_valid == 1) ? m_context.vmid : 0; }; + const bool VMIDvalid() const { return (m_context.vmid_valid == 1); }; + + // only allow an immutable copy of the structure out to C-API land. + operator const ocsd_pe_context &() const { return m_context; }; + +private: + ocsd_pe_context m_context; +}; + +inline OcsdPeContext::OcsdPeContext() +{ + resetCtxt(); +} + +inline OcsdPeContext::OcsdPeContext(const ocsd_pe_context *context) +{ + m_context = *context; +} + +inline void OcsdPeContext::resetCtxt() +{ + // initialise the context + m_context.bits64 = 0; + m_context.context_id = 0; + m_context.ctxt_id_valid = 0; + m_context.el_valid = 0; + m_context.exception_level = ocsd_EL_unknown; + m_context.security_level = ocsd_sec_secure; + m_context.vmid = 0; + m_context.vmid_valid = 0; +} + +inline OcsdPeContext & OcsdPeContext::operator =(const OcsdPeContext &ctxt) +{ + m_context = ctxt; + return *this; +} + +inline OcsdPeContext & OcsdPeContext::operator =(const ocsd_pe_context *context) +{ + m_context = *context; + return *this; +} + + +#endif // ARM_OCSD_PE_CONTEXT_H_INCLUDED + +/* End of File ocsd_pe_context.h */ diff --git a/decoder/include/common/ocsd_version.h b/decoder/include/common/ocsd_version.h new file mode 100644 index 0000000..b68c85f --- /dev/null +++ b/decoder/include/common/ocsd_version.h @@ -0,0 +1,46 @@ +/* + * \file ocsd_version.h + * \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. + */ +#ifndef ARM_OCSD_VERSION_H_INCLUDED +#define ARM_OCSD_VERSION_H_INCLUDED + +class ocsdVersion +{ +public: + static const uint32_t vers_num(); + static const char *vers_str(); +}; + +#endif // ARM_OCSD_VERSION_H_INCLUDED + +/* End of File ocsd_version.h */ diff --git a/decoder/include/common/trc_component.h b/decoder/include/common/trc_component.h new file mode 100644 index 0000000..6096ac7 --- /dev/null +++ b/decoder/include/common/trc_component.h @@ -0,0 +1,149 @@ +/*! + * \file trc_component.h + * \brief OpenCSD : Base trace decode component. + * + * \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_TRC_COMPONENT_H_INCLUDED +#define ARM_TRC_COMPONENT_H_INCLUDED + +#include <string> +#include "comp_attach_pt_t.h" +#include "interfaces/trc_error_log_i.h" +#include "ocsd_error.h" + +class errLogAttachMonitor; + +/** @addtogroup ocsd_infrastructure +@{*/ + +/*! + * @class TraceComponent + * @brief Base class for all decode components in the library. + * + * Provides error logging attachment point and component type and instance naming + * Interface for handling of component operational mode. + */ +class TraceComponent +{ +public: + TraceComponent(const std::string &name); + TraceComponent(const std::string &name, int instIDNum); + virtual ~TraceComponent(); /**< Default Destructor */ + + const std::string &getComponentName() const { return m_name; }; + void setComponentName(const std::string &name) { m_name = name; }; + + /** Error logger attachment point.*/ + componentAttachPt<ITraceErrorLog> *getErrorLogAttachPt() { return &m_error_logger; }; + + /*! + * Set the operational mode for the component. + * This controls the way the component behaves under error conditions etc. + * These flags may also control output formats or data. + * Operation mode flags used are component specific and defined by derived classes. + * + * @param op_flags : Set of operation mode flags. + * + * @return ocsd_err_t : OCSD_OK if flags supported by this component, error if unsuppored + */ + ocsd_err_t setComponentOpMode(uint32_t op_flags); + + /*! + * Return the current operational mode flags values + * + * @return const uint32_t : Op Mode flags. + */ + const uint32_t getComponentOpMode() const { return m_op_flags; }; + + /*! + * Get the supported operational mode flags for this component. + * Base class will return nothing supported. + * Derived class must set the value correctly for the component. + * + * @return const uint32_t : Supported flags values. + */ + const uint32_t getSupportedOpModes() const { return m_supported_op_flags; }; + + /*! + * Set associated trace component - used by generic code to track + * packet processor / packet decoder pairs. + * + * @param *assocComp : pointer to the associated component + */ + void setAssocComponent(TraceComponent *assocComp) { m_assocComp = assocComp; }; + + + /*! + * get associated trace component pointer + * + * @return TraceComponent *: associated component. + */ + TraceComponent *getAssocComponent() { return m_assocComp; }; + + /*! + * Log a message at the default severity on this component. + */ + void LogDefMessage(const std::string &msg) + { + LogMessage(m_errVerbosity, msg); + } + +protected: + friend class errLogAttachMonitor; + + void LogError(const ocsdError &Error); + void LogMessage(const ocsd_err_severity_t filter_level, const std::string &msg); + const ocsd_err_severity_t getErrorLogLevel() const { return m_errVerbosity; }; + const bool isLoggingErrorLevel(const ocsd_err_severity_t level) const { return level <= m_errVerbosity; }; + void updateErrorLogLevel(); + + void do_attach_notify(const int num_attached); + void Init(const std::string &name); + + uint32_t m_op_flags; //!< current component operational mode flags. + uint32_t m_supported_op_flags; //!< supported component operational mode flags - derived class to intialise. + +private: + componentAttachPt<ITraceErrorLog> m_error_logger; + ocsd_hndl_err_log_t m_errLogHandle; + ocsd_err_severity_t m_errVerbosity; + errLogAttachMonitor *m_pErrAttachMon; + + std::string m_name; + + TraceComponent *m_assocComp; //!< associated component -> if this is a pkt decoder, associated pkt processor. +}; +/** @}*/ +#endif // ARM_TRC_COMPONENT_H_INCLUDED + +/* End of File trc_component.h */ diff --git a/decoder/include/common/trc_core_arch_map.h b/decoder/include/common/trc_core_arch_map.h new file mode 100644 index 0000000..aa976c3 --- /dev/null +++ b/decoder/include/common/trc_core_arch_map.h @@ -0,0 +1,77 @@ +/*! + * \file trc_core_arch_map.h + * \brief OpenCSD : Map core name strings to architecture profile constants. + * + * \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_TRC_CORE_ARCH_MAP_H_INCLUDED +#define ARM_TRC_CORE_ARCH_MAP_H_INCLUDED + +#include <map> +#include <string> +#include "opencsd/ocsd_if_types.h" + +/** @class CoreArchProfileMap + * + * @brief Map core / arch name to profile for decoder. + * + * Helper class for library clients to map core or architecture version names onto + * a profile / arch version pair suitable for use with the decode library. + * + * Valid core names are:- + * - Cortex-Axx : where xx = 5,7,12,15,17,32,35,53,55,57,65,72,73,75,76,77; + * - Cortex-Rxx : where xx = 5,7,8,52; + * - Cortex-Mxx : where xx = 0,0+,3,4,23,33; + * + * Valid architecture profile names are:- + * - ARMv7-A, ARMv7-R, ARMv7-M; + * - ARMv8-A, ARMv8.x-A, ARMv8-R, ARMv8-M; + * - ARM-AA64, ARM-aa64 + * + */ +class CoreArchProfileMap +{ +public: + CoreArchProfileMap(); + ~CoreArchProfileMap() {}; + + ocsd_arch_profile_t getArchProfile(const std::string &coreName); + +private: + ocsd_arch_profile_t getPatternMatchCoreName(const std::string &coreName); + + std::map<std::string, ocsd_arch_profile_t> core_profiles; + std::map<std::string, ocsd_arch_profile_t> arch_profiles; +}; + +#endif // ARM_TRC_CORE_ARCH_MAP_H_INCLUDED + +/* End of File trc_core_arch_map.h */ diff --git a/decoder/include/common/trc_cs_config.h b/decoder/include/common/trc_cs_config.h new file mode 100644 index 0000000..9b2c130 --- /dev/null +++ b/decoder/include/common/trc_cs_config.h @@ -0,0 +1,62 @@ +/* + * \file trc_cs_config.h + * \brief OpenCSD : Trace component config base class. + * + * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved. + */ +#ifndef ARM_TRC_CS_CONFIG_H_INCLUDED +#define ARM_TRC_CS_CONFIG_H_INCLUDED + + +/* + * 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. + */ + +/** @addtogroup ocsd_protocol_cfg +@{*/ + +/*! + * @class CSConfig + * @brief Base class for configuration data on CoreSight trace component. + * + * Defines common access functionality, common to all components. + * (e.g. trace ID). + * + */ +class CSConfig +{ +public: + CSConfig() {}; + virtual ~CSConfig() {}; + + virtual const uint8_t getTraceID() const = 0; //!< CoreSight Trace ID for this device. +}; + +/** @}*/ + +#endif // ARM_TRC_CS_CONFIG_H_INCLUDED + +/* End of File trc_cs_config.h */
\ No newline at end of file diff --git a/decoder/include/common/trc_frame_deformatter.h b/decoder/include/common/trc_frame_deformatter.h new file mode 100644 index 0000000..cb2960f --- /dev/null +++ b/decoder/include/common/trc_frame_deformatter.h @@ -0,0 +1,104 @@ +/*! + * \file trc_frame_deformatter.h + * \brief OpenCSD : De-format CoreSight formatted trace frame. + * + * \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_TRC_FRAME_DEFORMATTER_H_INCLUDED +#define ARM_TRC_FRAME_DEFORMATTER_H_INCLUDED + +#include "opencsd/ocsd_if_types.h" + +#include "interfaces/trc_data_raw_in_i.h" +#include "comp_attach_pt_t.h" + +class ITrcRawFrameIn; +class ITrcDataMixIDIn; +class ITrcSrcIndexCreator; +class ITraceErrorLog; +class TraceFmtDcdImpl; + +/** @defgroup ocsd_deformatter OpenCSD Library : Trace Frame Deformatter + @brief CoreSight Formatted Trace Frame - deformatting functionality. +@{*/ + +class TraceFormatterFrameDecoder : public ITrcDataIn +{ +public: + TraceFormatterFrameDecoder(); + TraceFormatterFrameDecoder(int instNum); + virtual ~TraceFormatterFrameDecoder(); + + /* the data input interface from the reader */ + virtual ocsd_datapath_resp_t TraceDataIn( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed); + + /* attach a data processor to a stream ID output */ + componentAttachPt<ITrcDataIn> *getIDStreamAttachPt(uint8_t ID); + + /* attach a data processor to the raw frame output */ + componentAttachPt<ITrcRawFrameIn> *getTrcRawFrameAttachPt(); + + componentAttachPt<ITrcSrcIndexCreator> *getTrcSrcIndexAttachPt(); + + componentAttachPt<ITraceErrorLog> *getErrLogAttachPt(); + + /* init decoder implementation object */ + ocsd_err_t Init(); + + /* configuration - set operational mode for incoming stream (has FSYNCS etc) */ + ocsd_err_t Configure(uint32_t cfg_flags); + const uint32_t getConfigFlags() const; + + /* enable / disable ID streams - default as all enabled */ + ocsd_err_t OutputFilterIDs(std::vector<uint8_t> &id_list, bool bEnable); + ocsd_err_t OutputFilterAllIDs(bool bEnable); + + /* decode control */ + ocsd_datapath_resp_t Reset(); /* reset the decode to the start state, drop partial data - propogate to attached components */ + ocsd_datapath_resp_t Flush(); /* flush existing data if possible, retain state - propogate to attached components */ + + /* demux stats */ + void SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock); + +private: + TraceFmtDcdImpl *m_pDecoder; + int m_instNum; + +}; + +/** @}*/ + +#endif // ARM_TRC_FRAME_DEFORMATTER_H_INCLUDED + +/* End of File trc_frame_deformatter.h */
\ No newline at end of file diff --git a/decoder/include/common/trc_gen_elem.h b/decoder/include/common/trc_gen_elem.h new file mode 100644 index 0000000..25be807 --- /dev/null +++ b/decoder/include/common/trc_gen_elem.h @@ -0,0 +1,228 @@ +/*! + * \file trc_gen_elem.h + * \brief OpenCSD : Decoder Generic trace element output class. + * + * \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_TRC_GEN_ELEM_H_INCLUDED +#define ARM_TRC_GEN_ELEM_H_INCLUDED + +#include "opencsd/trc_gen_elem_types.h" +#include "trc_printable_elem.h" +#include "ocsd_pe_context.h" + +/** @addtogroup gen_trc_elem +@{*/ + +/*! + * @class OcsdTraceElement + * @brief Generic trace element class + * + */ +class OcsdTraceElement : public trcPrintableElem, public ocsd_generic_trace_elem +{ +public: + OcsdTraceElement(); + OcsdTraceElement(ocsd_gen_trc_elem_t type); + virtual ~OcsdTraceElement() {}; + + void init(); + +// set elements API + + void setType(const ocsd_gen_trc_elem_t type); //!< set type and init flags + void updateType(const ocsd_gen_trc_elem_t type); //!< change type only - no init + + void setContext(const ocsd_pe_context &new_context) { context = new_context; }; + void setISA(const ocsd_isa isa_update); + + void setCycleCount(const uint32_t cycleCount); + void setEvent(const event_t ev_type, const uint16_t number); + void setTS(const uint64_t ts, const bool freqChange = false); + + void setExcepMarker() { excep_data_marker = 1; }; + void setExceptionNum(uint32_t excepNum) { exception_number = excepNum; }; + void setTraceOnReason(const trace_on_reason_t reason); + void setUnSyncEOTReason(const unsync_info_t reason); + void setTransactionType(const trace_memtrans_t trans) { mem_trans = trans; }; + + void setAddrRange(const ocsd_vaddr_t st_addr, const ocsd_vaddr_t en_addr, const int num_instr = 1); + void setLastInstrInfo(const bool exec, const ocsd_instr_type last_i_type, const ocsd_instr_subtype last_i_subtype, const uint8_t size); + void setAddrStart(const ocsd_vaddr_t st_addr) { this->st_addr = st_addr; }; + void setLastInstrCond(const int is_cond) { this->last_instr_cond = is_cond; }; + + void setSWTInfo(const ocsd_swt_info_t swt_info) { sw_trace_info = swt_info; }; + void setExtendedDataPtr(const void *data_ptr); + + void setSyncMarker(const trace_marker_payload_t &marker); + +// stringize the element + + virtual void toString(std::string &str) const; + +// get elements API + + OcsdTraceElement &operator =(const ocsd_generic_trace_elem* p_elem); + + const ocsd_gen_trc_elem_t getType() const { return elem_type; }; + + // return current context + const ocsd_pe_context &getContext() const { return context; }; + + void copyPersistentData(const OcsdTraceElement &src); + +private: + void printSWInfoPkt(std::ostringstream &oss) const; + void clearPerPktData(); //!< clear flags that indicate validity / have values on a per packet basis + +}; + +inline OcsdTraceElement::OcsdTraceElement(ocsd_gen_trc_elem_t type) +{ + elem_type = type; +} + +inline OcsdTraceElement::OcsdTraceElement() +{ + elem_type = OCSD_GEN_TRC_ELEM_UNKNOWN; +} + +inline void OcsdTraceElement::setCycleCount(const uint32_t cycleCount) +{ + cycle_count = cycleCount; + has_cc = 1; +} + +inline void OcsdTraceElement::setEvent(const event_t ev_type, const uint16_t number) +{ + trace_event.ev_type = (uint16_t)ev_type; + trace_event.ev_number = ev_type == EVENT_NUMBERED ? number : 0; +} + +inline void OcsdTraceElement::setAddrRange(const ocsd_vaddr_t st_addr, const ocsd_vaddr_t en_addr, const int num_instr /* = 1 */) +{ + this->st_addr = st_addr; + this->en_addr = en_addr; + this->num_instr_range = num_instr; +} + +inline void OcsdTraceElement::setLastInstrInfo(const bool exec, const ocsd_instr_type last_i_type, const ocsd_instr_subtype last_i_subtype, const uint8_t size) +{ + last_instr_exec = exec ? 1 : 0; + last_instr_sz = size & 0x7; + this->last_i_type = last_i_type; + this->last_i_subtype = last_i_subtype; +} + +inline void OcsdTraceElement::setType(const ocsd_gen_trc_elem_t type) +{ + // set the type and clear down the per element flags + elem_type = type; + + clearPerPktData(); +} + +inline void OcsdTraceElement::updateType(const ocsd_gen_trc_elem_t type) +{ + elem_type = type; +} + +inline void OcsdTraceElement::init() +{ + st_addr = en_addr = (ocsd_vaddr_t)-1; + isa = ocsd_isa_unknown; + + cycle_count = 0; + timestamp = 0; + + context.ctxt_id_valid = 0; + context.vmid_valid = 0; + context.el_valid = 0; + + last_i_type = OCSD_INSTR_OTHER; + last_i_subtype = OCSD_S_INSTR_NONE; + + clearPerPktData(); +} + +inline void OcsdTraceElement::clearPerPktData() +{ + flag_bits = 0; // bit-field with various flags. + exception_number = 0; // union with trace_on_reason / trace_event + ptr_extended_data = 0; // extended data pointer +} + +inline void OcsdTraceElement::setTraceOnReason(const trace_on_reason_t reason) +{ + trace_on_reason = reason; +} + +inline void OcsdTraceElement::setUnSyncEOTReason(const unsync_info_t reason) +{ + unsync_eot_info = reason; +} + +inline void OcsdTraceElement::setISA(const ocsd_isa isa_update) +{ + isa = isa_update; + if(isa > ocsd_isa_unknown) + isa = ocsd_isa_unknown; +} + +inline void OcsdTraceElement::setTS(const uint64_t ts, const bool freqChange /*= false*/) +{ + timestamp = ts; + cpu_freq_change = freqChange ? 1 : 0; + has_ts = 1; +} + +inline void OcsdTraceElement::setExtendedDataPtr(const void *data_ptr) +{ + extended_data = 1; + ptr_extended_data = data_ptr; +} + +inline void OcsdTraceElement::setSyncMarker(const trace_marker_payload_t &marker) +{ + sync_marker = marker; +} + +// set persistent data between output packets. +inline void OcsdTraceElement::copyPersistentData(const OcsdTraceElement &src) +{ + isa = src.isa; + context = src.context; +} + +/** @}*/ + +#endif // ARM_TRC_GEN_ELEM_H_INCLUDED + +/* End of File trc_gen_elem.h */ diff --git a/decoder/include/common/trc_pkt_decode_base.h b/decoder/include/common/trc_pkt_decode_base.h new file mode 100644 index 0000000..24ea2b0 --- /dev/null +++ b/decoder/include/common/trc_pkt_decode_base.h @@ -0,0 +1,317 @@ +/*! + * \file trc_pkt_decode_base.h + * \brief OpenCSD : Trace Packet decoder base class. + * + * \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_TRC_PKT_DECODE_BASE_H_INCLUDED +#define ARM_TRC_PKT_DECODE_BASE_H_INCLUDED + +#include "trc_component.h" +#include "comp_attach_pt_t.h" + +#include "interfaces/trc_pkt_in_i.h" +#include "interfaces/trc_gen_elem_in_i.h" +#include "interfaces/trc_tgt_mem_access_i.h" +#include "interfaces/trc_instr_decode_i.h" + +/** @defgroup ocsd_pkt_decode OpenCSD Library : Packet Decoders. + + @brief Classes providing Protocol Packet Decoding capability. + + Packet decoders convert incoming protocol packets from a packet processor, + into generic trace elements to be output to an analysis program. + + Packet decoders can be:- + - PE decoders - converting ETM or PTM packets into instruction and data trace elements + - SW stimulus decoder - converting STM or ITM packets into software generated trace elements. + - Bus decoders - converting HTM packets into bus transaction elements. + +@{*/ + + +class TrcPktDecodeI : public TraceComponent +{ +public: + TrcPktDecodeI(const char *component_name); + TrcPktDecodeI(const char *component_name, int instIDNum); + virtual ~TrcPktDecodeI() {}; + + componentAttachPt<ITrcGenElemIn> *getTraceElemOutAttachPt() { return &m_trace_elem_out; }; + componentAttachPt<ITargetMemAccess> *getMemoryAccessAttachPt() { return &m_mem_access; }; + componentAttachPt<IInstrDecode> *getInstrDecodeAttachPt() { return &m_instr_decode; }; + + void setUsesMemAccess(bool bUsesMemaccess) { m_uses_memaccess = bUsesMemaccess; }; + const bool getUsesMemAccess() const { return m_uses_memaccess; }; + + void setUsesIDecode(bool bUsesIDecode) { m_uses_idecode = bUsesIDecode; }; + const bool getUsesIDecode() const { return m_uses_idecode; }; + +protected: + + /* implementation packet decoding interface */ + virtual ocsd_datapath_resp_t processPacket() = 0; + virtual ocsd_datapath_resp_t onEOT() = 0; + virtual ocsd_datapath_resp_t onReset() = 0; + virtual ocsd_datapath_resp_t onFlush() = 0; + virtual ocsd_err_t onProtocolConfig() = 0; + virtual const uint8_t getCoreSightTraceID() = 0; + + /* init handling */ + const bool checkInit(); + /* Called on first init confirmation */ + virtual void onFirstInitOK() {}; + + /* data output */ + ocsd_datapath_resp_t outputTraceElement(const OcsdTraceElement &elem); // use current index + ocsd_datapath_resp_t outputTraceElementIdx(ocsd_trc_index_t idx, const OcsdTraceElement &elem); // use supplied index (where decoder caches elements) + + /* target access */ + ocsd_err_t accessMemory(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, uint32_t *num_bytes, uint8_t *p_buffer); + ocsd_err_t invalidateMemAccCache(); + + /* instruction decode */ + ocsd_err_t instrDecode(ocsd_instr_info *instr_info); + + componentAttachPt<ITrcGenElemIn> m_trace_elem_out; + componentAttachPt<ITargetMemAccess> m_mem_access; + componentAttachPt<IInstrDecode> m_instr_decode; + + ocsd_trc_index_t m_index_curr_pkt; + + bool m_decode_init_ok; //!< set true if all attachments in place for decode. (remove checks in main throughput paths) + bool m_config_init_ok; //!< set true if config set. + + std::string init_err_msg; //!< error message for init error + + bool m_uses_memaccess; + bool m_uses_idecode; + +}; + +inline TrcPktDecodeI::TrcPktDecodeI(const char *component_name) : + TraceComponent(component_name), + m_index_curr_pkt(0), + m_decode_init_ok(false), + m_config_init_ok(false), + m_uses_memaccess(true), + m_uses_idecode(true) +{ +} + +inline TrcPktDecodeI::TrcPktDecodeI(const char *component_name, int instIDNum) : + TraceComponent(component_name, instIDNum), + m_index_curr_pkt(0), + m_decode_init_ok(false), + m_config_init_ok(false), + m_uses_memaccess(true), + m_uses_idecode(true) +{ +} + +inline const bool TrcPktDecodeI::checkInit() +{ + if(!m_decode_init_ok) + { + if(!m_config_init_ok) + init_err_msg = "No decoder configuration information"; + else if(!m_trace_elem_out.hasAttachedAndEnabled()) + init_err_msg = "No element output interface attached and enabled"; + else if(m_uses_memaccess && !m_mem_access.hasAttachedAndEnabled()) + init_err_msg = "No memory access interface attached and enabled"; + else if(m_uses_idecode && !m_instr_decode.hasAttachedAndEnabled()) + init_err_msg = "No instruction decoder interface attached and enabled"; + else + m_decode_init_ok = true; + if (m_decode_init_ok) + onFirstInitOK(); + } + return m_decode_init_ok; +} + +inline ocsd_datapath_resp_t TrcPktDecodeI::outputTraceElement(const OcsdTraceElement &elem) +{ + return m_trace_elem_out.first()->TraceElemIn(m_index_curr_pkt,getCoreSightTraceID(), elem); +} + +inline ocsd_datapath_resp_t TrcPktDecodeI::outputTraceElementIdx(ocsd_trc_index_t idx, const OcsdTraceElement &elem) +{ + return m_trace_elem_out.first()->TraceElemIn(idx, getCoreSightTraceID(), elem); +} + +inline ocsd_err_t TrcPktDecodeI::instrDecode(ocsd_instr_info *instr_info) +{ + if(m_uses_idecode) + return m_instr_decode.first()->DecodeInstruction(instr_info); + return OCSD_ERR_DCD_INTERFACE_UNUSED; +} + +inline ocsd_err_t TrcPktDecodeI::accessMemory(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, uint32_t *num_bytes, uint8_t *p_buffer) +{ + if(m_uses_memaccess) + return m_mem_access.first()->ReadTargetMemory(address,getCoreSightTraceID(),mem_space, num_bytes,p_buffer); + return OCSD_ERR_DCD_INTERFACE_UNUSED; +} + +inline ocsd_err_t TrcPktDecodeI::invalidateMemAccCache() +{ + if (!m_uses_memaccess) + return OCSD_ERR_DCD_INTERFACE_UNUSED; + m_mem_access.first()->InvalidateMemAccCache(getCoreSightTraceID()); + return OCSD_OK; +} + +/**********************************************************************/ +template <class P, class Pc> +class TrcPktDecodeBase : public TrcPktDecodeI, public IPktDataIn<P> +{ +public: + TrcPktDecodeBase(const char *component_name); + TrcPktDecodeBase(const char *component_name, int instIDNum); + virtual ~TrcPktDecodeBase(); + + virtual ocsd_datapath_resp_t PacketDataIn( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index_sop, + const P *p_packet_in); + + + /* protocol configuration */ + ocsd_err_t setProtocolConfig(const Pc *config); + const Pc * getProtocolConfig() const { return m_config; }; + +protected: + void ClearConfigObj(); + + /* the protocol configuration */ + Pc * m_config; + /* the current input packet */ + const P * m_curr_packet_in; + +}; + + +template <class P, class Pc> TrcPktDecodeBase<P, Pc>::TrcPktDecodeBase(const char *component_name) : + TrcPktDecodeI(component_name), + m_config(0) +{ +} + +template <class P, class Pc> TrcPktDecodeBase<P, Pc>::TrcPktDecodeBase(const char *component_name, int instIDNum) : + TrcPktDecodeI(component_name,instIDNum), + m_config(0) +{ +} + +template <class P, class Pc> TrcPktDecodeBase<P, Pc>::~TrcPktDecodeBase() +{ + ClearConfigObj(); +} + +template <class P, class Pc> ocsd_datapath_resp_t TrcPktDecodeBase<P, Pc>::PacketDataIn( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index_sop, + const P *p_packet_in) +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + if(!checkInit()) + { + LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_NOT_INIT,init_err_msg)); + return OCSD_RESP_FATAL_NOT_INIT; + } + + switch(op) + { + case OCSD_OP_DATA: + if(p_packet_in == 0) + { + LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL)); + resp = OCSD_RESP_FATAL_INVALID_PARAM; + } + else + { + m_curr_packet_in = p_packet_in; + m_index_curr_pkt = index_sop; + resp = processPacket(); + } + break; + + case OCSD_OP_EOT: + resp = onEOT(); + break; + + case OCSD_OP_FLUSH: + resp = onFlush(); + break; + + case OCSD_OP_RESET: + resp = onReset(); + break; + + default: + LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL)); + resp = OCSD_RESP_FATAL_INVALID_OP; + break; + } + return resp; +} + + /* protocol configuration */ +template <class P, class Pc> ocsd_err_t TrcPktDecodeBase<P, Pc>::setProtocolConfig(const Pc *config) +{ + ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL; + if(config != 0) + { + ClearConfigObj(); // remove any current config + m_config = new (std::nothrow) Pc(*config); // make a copy of the config - don't rely on the object passed in being valid outside the context of the call. + if(m_config != 0) + { + err = onProtocolConfig(); + if(err == OCSD_OK) + m_config_init_ok = true; + } + else + err = OCSD_ERR_MEM; + } + return err; +} + +template <class P, class Pc> void TrcPktDecodeBase<P, Pc>::ClearConfigObj() +{ + if(m_config) + { + delete m_config; + m_config = 0; + } +} + +/** @}*/ +#endif // ARM_TRC_PKT_DECODE_BASE_H_INCLUDED + +/* End of File trc_pkt_decode_base.h */ diff --git a/decoder/include/common/trc_pkt_elem_base.h b/decoder/include/common/trc_pkt_elem_base.h new file mode 100644 index 0000000..07604a6 --- /dev/null +++ b/decoder/include/common/trc_pkt_elem_base.h @@ -0,0 +1,49 @@ +/* + * \file trc_pkt_elem_base.h + * \brief Reference CoreSight Trace Decoder : + * + * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved. + */ +#ifndef ARM_TRC_PKT_ELEM_BASE_H_INCLUDED +#define ARM_TRC_PKT_ELEM_BASE_H_INCLUDED + +/* + * 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. + */ + +class TrcPacketBase +{ +public: + TrcPacketBase() {}; + virtual ~TrcPacketBase() {} + + //! return the underlying C API packet structure + virtual const void *c_pkt() const = 0; +}; + +#endif // ARM_TRC_PKT_ELEM_BASE_H_INCLUDED + +/* End of File trc_pkt_elem_base.h */
\ No newline at end of file diff --git a/decoder/include/common/trc_pkt_proc_base.h b/decoder/include/common/trc_pkt_proc_base.h new file mode 100644 index 0000000..8ed7d83 --- /dev/null +++ b/decoder/include/common/trc_pkt_proc_base.h @@ -0,0 +1,456 @@ +/*! + * \file trc_pkt_proc_base.h + * \brief OpenCSD : Trace packet processor base class. + * + * \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_TRC_PKT_PROC_BASE_H_INCLUDED +#define ARM_TRC_PKT_PROC_BASE_H_INCLUDED + +#include "interfaces/trc_data_raw_in_i.h" +#include "interfaces/trc_pkt_in_i.h" +#include "interfaces/trc_pkt_raw_in_i.h" +#include "interfaces/trc_indexer_pkt_i.h" + +#include "trc_component.h" +#include "comp_attach_pt_t.h" +#include "opencsd/ocsd_if_version.h" + +/** @defgroup ocsd_pkt_proc OpenCSD Library : Packet Processors. + @brief Classes providing Protocol Packet Processing capability. + + Packet processors take an incoming byte stream and convert into discrete packets for the + required trace protocol. +@{*/ + + + +/*! + * @class TrcPktProcI + * @brief Base Packet processing interface + * + * Defines the packet processing methods that protocol specific processors must + * implement. + * + */ +class TrcPktProcI : public TraceComponent, public ITrcDataIn +{ +public: + TrcPktProcI(const char *component_name); + TrcPktProcI(const char *component_name, int instIDNum); + virtual ~TrcPktProcI() {}; + + /** Trace byte data input interface - from ITrcDataIn. + */ + virtual ocsd_datapath_resp_t TraceDataIn( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed) = 0; + + virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats) = 0; + virtual void resetStats() = 0; +protected: + + /* implementation packet processing interface */ + + /*! @brief Implementation function for the OCSD_OP_DATA operation */ + virtual ocsd_datapath_resp_t processData( const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed) = 0; + + virtual ocsd_datapath_resp_t onEOT() = 0; //!< Implementation function for the OCSD_OP_EOT operation + virtual ocsd_datapath_resp_t onReset() = 0; //!< Implementation function for the OCSD_OP_RESET operation + virtual ocsd_datapath_resp_t onFlush() = 0; //!< Implementation function for the OCSD_OP_FLUSH operation + virtual ocsd_err_t onProtocolConfig() = 0; //!< Called when the configuration object is passed to the decoder. + virtual const bool isBadPacket() const = 0; //!< check if the current packet is an error / bad packet +}; + +inline TrcPktProcI::TrcPktProcI(const char *component_name) : + TraceComponent(component_name) +{ +} + +inline TrcPktProcI::TrcPktProcI(const char *component_name, int instIDNum) : + TraceComponent(component_name,instIDNum) +{ +} + +/*! + * @class TrcPktProcBase + * @brief Packet Processor base class. Provides common infrastructure and interconnections for packet processors. + * + * The class is a templated base class. + * - P - this is the packet object class. + * - Pt - this is the packet type class. + * - Pc - this is the packet configuration class. + * + * implementations will provide concrete classes for each of these to operate under the common infrastructures. + * The base provides the trace data in (ITrcDataIn) interface and operates on the incoming operation type. + * + * Implementions override the 'onFn()' and data process functions defined in TrcPktProcI, + * with the base class ensuring consistent ordering of operations. + * + */ +template <class P, class Pt, class Pc> +class TrcPktProcBase : public TrcPktProcI +{ +public: + TrcPktProcBase(const char *component_name); + TrcPktProcBase(const char *component_name, int instIDNum); + virtual ~TrcPktProcBase(); + + /** Byte trace data input interface defined in ITrcDataIn + + The base class implementation processes the operation to call the + interface functions on TrcPktProcI. + */ + virtual ocsd_datapath_resp_t TraceDataIn( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed); + + +/* component attachment points */ + + //! Attachement point for the protocol packet output + componentAttachPt<IPktDataIn<P>> *getPacketOutAttachPt() { return &m_pkt_out_i; }; + //! Attachment point for the protocol packet monitor + componentAttachPt<IPktRawDataMon<P>> *getRawPacketMonAttachPt() { return &m_pkt_raw_mon_i; }; + + //! Attachment point for a packet indexer + componentAttachPt<ITrcPktIndexer<Pt>> *getTraceIDIndexerAttachPt() { return &m_pkt_indexer_i; }; + +/* protocol configuration */ + //!< Set the protocol specific configuration for the decoder. + virtual ocsd_err_t setProtocolConfig(const Pc *config); + //!< Get the configuration for the decoder. + virtual const Pc *getProtocolConfig() const { return m_config; }; + +/* stats block access - derived class must init stats for the block to be returned. */ + virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats); + virtual void resetStats(); /* reset the counts - operates separately from decoder reset. */ + +protected: + + /* data output functions */ + ocsd_datapath_resp_t outputDecodedPacket(const ocsd_trc_index_t index_sop, const P *pkt); + + void outputRawPacketToMonitor( const ocsd_trc_index_t index_sop, + const P *pkt, + const uint32_t size, + const uint8_t *p_data); + + void indexPacket(const ocsd_trc_index_t index_sop, const Pt *packet_type); + + ocsd_datapath_resp_t outputOnAllInterfaces(const ocsd_trc_index_t index_sop, const P *pkt, const Pt *pkt_type, std::vector<uint8_t> &pktdata); + + ocsd_datapath_resp_t outputOnAllInterfaces(const ocsd_trc_index_t index_sop, const P *pkt, const Pt *pkt_type, const uint8_t *pktdata, uint32_t pktlen); + + /*! Let the derived class figure out if it needs to collate and send raw data. + can improve wait for sync performance if we do not need to save and send unsynced data. + */ + const bool hasRawMon() const; + + /* the protocol configuration */ + const Pc *m_config; + + void ClearConfigObj(); // remove our copy of the config + + const bool checkInit(); // return true if init (configured and at least one output sink attached), false otherwise. + + /* stats block updates - called by derived protocol specific decoder */ + void statsAddTotalCount(const uint64_t count) { m_stats.channel_total += count; }; + void statsAddUnsyncCount(const uint64_t count) { m_stats.channel_unsynced += count; }; + void statsAddBadSeqCount(const uint32_t count) { m_stats.bad_sequence_errs += count; }; + void statsAddBadHdrCount(const uint32_t count) { m_stats.bad_header_errs += count; }; + void statsInit() { m_stats_init = true; }; /* mark stats as in use */ + + +private: + /* decode control */ + ocsd_datapath_resp_t Reset(const ocsd_trc_index_t index); + ocsd_datapath_resp_t Flush(); + ocsd_datapath_resp_t EOT(); + + componentAttachPt<IPktDataIn<P>> m_pkt_out_i; + componentAttachPt<IPktRawDataMon<P>> m_pkt_raw_mon_i; + + componentAttachPt<ITrcPktIndexer<Pt>> m_pkt_indexer_i; + + bool m_b_is_init; + + /* decode statistics block */ + ocsd_decode_stats_t m_stats; + bool m_stats_init; /*< true if the specific decoder is using the stats */ + +}; + +template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name) : + TrcPktProcI(component_name), + m_config(0), + m_b_is_init(false), + m_stats_init(false) +{ + resetStats(); +} + +template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name, int instIDNum) : + TrcPktProcI(component_name, instIDNum), + m_config(0), + m_b_is_init(false), + m_stats_init(false) +{ + resetStats(); +} + +template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::~TrcPktProcBase() +{ + ClearConfigObj(); +} + +template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::TraceDataIn( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed) +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + + switch(op) + { + case OCSD_OP_DATA: + if((dataBlockSize == 0) || (pDataBlock == 0) || (numBytesProcessed == 0)) + { + if(numBytesProcessed) + *numBytesProcessed = 0; // ensure processed bytes value set to 0. + LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL,"Packet Processor: Zero length data block or NULL pointer error\n")); + resp = OCSD_RESP_FATAL_INVALID_PARAM; + } + else + resp = processData(index,dataBlockSize,pDataBlock,numBytesProcessed); + break; + + case OCSD_OP_EOT: + resp = EOT(); + break; + + case OCSD_OP_FLUSH: + resp = Flush(); + break; + + case OCSD_OP_RESET: + resp = Reset(index); + break; + + default: + LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL,"Packet Processor : Unknown Datapath operation\n")); + resp = OCSD_RESP_FATAL_INVALID_OP; + break; + } + return resp; +} + + +template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::Reset(const ocsd_trc_index_t index) +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + + // reset the trace decoder attachment on main data path. + if(m_pkt_out_i.hasAttachedAndEnabled()) + resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_RESET,index,0); + + // reset the packet processor implmentation + if(!OCSD_DATA_RESP_IS_FATAL(resp)) + resp = onReset(); + + // packet monitor + if(m_pkt_raw_mon_i.hasAttachedAndEnabled()) + m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_RESET,index,0,0,0); + + return resp; +} + +template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::Flush() +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + ocsd_datapath_resp_t resplocal = OCSD_RESP_CONT; + + // the trace decoder attachment on main data path. + if(m_pkt_out_i.hasAttachedAndEnabled()) + resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_FLUSH,0,0); // flush up the data path first. + + // if the connected components are flushed, not flush this one. + if(OCSD_DATA_RESP_IS_CONT(resp)) + resplocal = onFlush(); // local flush + + return (resplocal > resp) ? resplocal : resp; +} + +template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::EOT() +{ + ocsd_datapath_resp_t resp = onEOT(); // local EOT - mark any part packet as incomplete type and prepare to send + + // the trace decoder attachment on main data path. + if(m_pkt_out_i.hasAttachedAndEnabled() && !OCSD_DATA_RESP_IS_FATAL(resp)) + resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_EOT,0,0); + + // packet monitor + if(m_pkt_raw_mon_i.hasAttachedAndEnabled()) + m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_EOT,0,0,0,0); + + return resp; +} + +template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::outputDecodedPacket(const ocsd_trc_index_t index, const P *pkt) +{ + ocsd_datapath_resp_t resp = OCSD_RESP_CONT; + + // bad packet filter. + if((getComponentOpMode() & OCSD_OPFLG_PKTPROC_NOFWD_BAD_PKTS) && isBadPacket()) + return resp; + + // send a complete packet over the primary data path + if(m_pkt_out_i.hasAttachedAndEnabled()) + resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_DATA,index,pkt); + return resp; +} + +template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::outputRawPacketToMonitor( + const ocsd_trc_index_t index_sop, + const P *pkt, + const uint32_t size, + const uint8_t *p_data) +{ + // never output 0 sized packets. + if(size == 0) + return; + + // bad packet filter. + if((getComponentOpMode() & OCSD_OPFLG_PKTPROC_NOMON_BAD_PKTS) && isBadPacket()) + return; + + // packet monitor - this cannot return CONT / WAIT, but does get the raw packet data. + if(m_pkt_raw_mon_i.hasAttachedAndEnabled()) + m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_DATA,index_sop,pkt,size,p_data); +} + +template<class P,class Pt, class Pc> const bool TrcPktProcBase<P, Pt, Pc>::hasRawMon() const +{ + return m_pkt_raw_mon_i.hasAttachedAndEnabled(); +} + +template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::indexPacket(const ocsd_trc_index_t index_sop, const Pt *packet_type) +{ + // packet indexer - cannot return CONT / WAIT, just gets the current index and type. + if(m_pkt_indexer_i.hasAttachedAndEnabled()) + m_pkt_indexer_i.first()->TracePktIndex(index_sop,packet_type); +} + +template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::outputOnAllInterfaces(const ocsd_trc_index_t index_sop, const P *pkt, const Pt *pkt_type, std::vector<uint8_t> &pktdata) +{ + indexPacket(index_sop,pkt_type); + if(pktdata.size() > 0) // prevent out of range errors for 0 length vector. + outputRawPacketToMonitor(index_sop,pkt,(uint32_t)pktdata.size(),&pktdata[0]); + return outputDecodedPacket(index_sop,pkt); +} + +template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::outputOnAllInterfaces(const ocsd_trc_index_t index_sop, const P *pkt, const Pt *pkt_type, const uint8_t *pktdata, uint32_t pktlen) +{ + indexPacket(index_sop,pkt_type); + outputRawPacketToMonitor(index_sop,pkt,pktlen,pktdata); + return outputDecodedPacket(index_sop,pkt); +} + +template<class P,class Pt, class Pc> ocsd_err_t TrcPktProcBase<P, Pt, Pc>::setProtocolConfig(const Pc *config) +{ + ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL; + if(config != 0) + { + ClearConfigObj(); + m_config = new (std::nothrow) Pc(*config); + if(m_config != 0) + err = onProtocolConfig(); + else + err = OCSD_ERR_MEM; + } + return err; +} + +template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::ClearConfigObj() +{ + if(m_config) + { + delete m_config; + m_config = 0; + } +} + +template<class P,class Pt, class Pc> const bool TrcPktProcBase<P, Pt, Pc>::checkInit() +{ + if(!m_b_is_init) + { + if( (m_config != 0) && + (m_pkt_out_i.hasAttached() || m_pkt_raw_mon_i.hasAttached()) + ) + m_b_is_init = true; + } + return m_b_is_init; +} + +template<class P,class Pt, class Pc> ocsd_err_t TrcPktProcBase<P, Pt, Pc>::getStatsBlock(ocsd_decode_stats_t **pp_stats) +{ + + *pp_stats = &m_stats; + return m_stats_init ? OCSD_OK : OCSD_ERR_NOT_INIT; +} + +template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::resetStats() +{ + m_stats.version = OCSD_VER_NUM; + m_stats.revision = OCSD_STATS_REVISION; + m_stats.channel_total = 0; + m_stats.channel_unsynced = 0; + m_stats.bad_header_errs = 0; + m_stats.bad_sequence_errs = 0; + m_stats.demux.frame_bytes = 0; + m_stats.demux.no_id_bytes = 0; + m_stats.demux.valid_id_bytes = 0; +} + +/** @}*/ + +#endif // ARM_TRC_PKT_PROC_BASE_H_INCLUDED + +/* End of File trc_pkt_proc_base.h */ diff --git a/decoder/include/common/trc_printable_elem.h b/decoder/include/common/trc_printable_elem.h new file mode 100644 index 0000000..92a47e8 --- /dev/null +++ b/decoder/include/common/trc_printable_elem.h @@ -0,0 +1,91 @@ +/*! + * \file trc_printable_elem.h + * \brief OpenCSD : Standard printable element base class. + * + * \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_TRC_PRINTABLE_ELEM_H_INCLUDED +#define ARM_TRC_PRINTABLE_ELEM_H_INCLUDED + +#include <string> +#include <cstdint> + +/** @addtogroup ocsd_infrastructure +@{*/ + +/*! + * @class trcPrintableElem + * @brief Class to provide trace element strings for printing + * + * Provide a standard interface to the trace packet classes to allow the packets + * to be printed in logging or tools. + * + * Provides some standard formatting functionality + * + */ +class trcPrintableElem +{ +public: + trcPrintableElem() {}; + virtual ~trcPrintableElem() {}; + virtual void toString(std::string &str) const; + virtual void toStringFmt(const uint32_t fmtFlags, std::string &str) const; + + // print formatting utilities + static void getValStr(std::string &valStr, const int valTotalBitSize, const int valValidBits, const uint64_t value, const bool asHex = true, const int updateBits = 0); + +}; + +inline void trcPrintableElem::toString(std::string &str) const +{ + str = "Trace Element : print not implemented"; +} + +inline void trcPrintableElem::toStringFmt(const uint32_t /*fmtFlags*/, std::string &str) const +{ + toString(str); +} + +/** static template string function - used in "C" API to provide generic printing */ +template<class Pc, class Pt> +void trcPrintElemToString(const void *p_pkt, std::string &str) +{ + Pc pktClass; + pktClass = static_cast<const Pt *>(p_pkt); + pktClass.toString(str); +} + +/** @}*/ + +#endif // ARM_TRC_PRINTABLE_ELEM_H_INCLUDED + +/* End of File trc_printable_elem.h */ diff --git a/decoder/include/common/trc_raw_buffer.h b/decoder/include/common/trc_raw_buffer.h new file mode 100644 index 0000000..67b8d24 --- /dev/null +++ b/decoder/include/common/trc_raw_buffer.h @@ -0,0 +1,96 @@ +/* +* \file trc_raw_buffer.h +* \brief OpenCSD : Trace raw data byte buffer +* +* \copyright Copyright (c) 2019, 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_TRC_RAW_BUFFER_H_INCLUDED +#define ARM_TRC_RAW_BUFFER_H_INCLUDED + +#include <vector> + +class TraceRawBuffer +{ +public: + TraceRawBuffer() : + m_bufSize(0), + m_bufProcessed(0), + m_pBuffer(0), + pkt(0) + {}; + ~TraceRawBuffer() {}; + + // init the buffer + void init(const uint32_t size, const uint8_t *rawtrace, std::vector<uint8_t> *out_packet); + void copyByteToPkt(); // move a byte to the packet buffer + uint8_t peekNextByte(); // value of next byte in buffer. + + bool empty() { return m_bufProcessed == m_bufSize; }; + // bytes processed. + uint32_t processed() { return m_bufProcessed; }; + // buffer size; + uint32_t size() { return m_bufSize; } + +private: + uint32_t m_bufSize; + uint32_t m_bufProcessed; + const uint8_t *m_pBuffer; + std::vector<uint8_t> *pkt; + +}; + +// init the buffer +inline void TraceRawBuffer::init(const uint32_t size, const uint8_t *rawtrace, std::vector<uint8_t> *out_packet) +{ + m_bufSize = size; + m_bufProcessed = 0; + m_pBuffer = rawtrace; + pkt = out_packet; +} + +inline void TraceRawBuffer::copyByteToPkt() +{ + if (!empty()) { + pkt->push_back(m_pBuffer[m_bufProcessed]); + m_bufProcessed++; + } +} + +inline uint8_t TraceRawBuffer::peekNextByte() +{ + uint8_t val = 0; + if (!empty()) + val = m_pBuffer[m_bufProcessed]; + return val; +} + +#endif // ARM_TRC_RAW_BUFFER_H_INCLUDED + diff --git a/decoder/include/common/trc_ret_stack.h b/decoder/include/common/trc_ret_stack.h new file mode 100644 index 0000000..a7f53d1 --- /dev/null +++ b/decoder/include/common/trc_ret_stack.h @@ -0,0 +1,114 @@ +/* +* \file trc_ret_stack.h +* \brief OpenCSD : trace decoder return stack feature. +* +* \copyright Copyright (c) 2017, 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_TRC_RET_STACK_H_INCLUDED +#define ARM_TRC_RET_STACK_H_INCLUDED + +#include "opencsd/ocsd_if_types.h" + +// uncomment below for return stack logging +// #define TRC_RET_STACK_DEBUG + +#ifdef TRC_RET_STACK_DEBUG +class TraceComponent; +#endif + +typedef struct _retStackElement +{ + ocsd_vaddr_t ret_addr; + ocsd_isa ret_isa; +} retStackElement; + +class TrcAddrReturnStack +{ +public: + TrcAddrReturnStack(); + ~TrcAddrReturnStack() {}; + + void set_active(bool active) + { + m_active = active; + }; + + bool is_active() const + { + return m_active; + }; + + void push(const ocsd_vaddr_t addr, const ocsd_isa isa); + ocsd_vaddr_t pop(ocsd_isa &isa); + void flush(); + + bool overflow() const + { + return (bool)(num_entries < 0); + }; + + void set_pop_pending() + { + if (m_active) + m_pop_pending = true; + } + + void clear_pop_pending() + { + m_pop_pending = false; + } + + bool pop_pending() const + { + return m_pop_pending; + }; + +private: + bool m_active; + bool m_pop_pending; // flag for decoder to indicate a pop might be needed depending on the next packet (ETMv4) + + int head_idx; + int num_entries; + retStackElement m_stack[16]; + +#ifdef TRC_RET_STACK_DEBUG +public: + void set_dbg_logger(TraceComponent *pLogger) { m_p_debug_logger = pLogger; }; +private: + void LogOp(const char *pszOpString, ocsd_vaddr_t addr, int head_off, ocsd_isa isa); + + TraceComponent *m_p_debug_logger; +#endif // TRC_RET_STACK_DEBUG +}; + +#endif // ARM_TRC_RET_STACK_H_INCLUDED + +/* End of File trc_ret_stack.h */ |