You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
8.7 KiB
238 lines
8.7 KiB
/*
|
|
* \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 */
|