Add class to library to handle return stack feature in trace for PTM and ETMv4.
Return stack allows return addresses to be saved on an internal hardware stack, and reused if matching on an indirect branch. This reduces the need for explicit address packets on indirect branches.
The return stack object maintains a stack of at least the size required by the protocols, as a circular buffer as old, unused values fall off the end. the object allows for push() and pop() operations, a check for overflow and also a flag to allow the decoder to mark pop as pending. This is where the decision to pop() may be dependent on a following packet.
Compile time debug option allows test and debug of the stack operations.
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/build/linux/ref_trace_decode_lib/makefile | 1 + .../ref_trace_decode_lib.vcxproj | 2 + .../ref_trace_decode_lib.vcxproj.filters | 6 ++ decoder/include/common/trc_ret_stack.h | 114 +++++++++++++++++++++ decoder/source/trc_ret_stack.cpp | 106 +++++++++++++++++++ 5 files changed, 229 insertions(+) create mode 100644 decoder/include/common/trc_ret_stack.h create mode 100644 decoder/source/trc_ret_stack.cpp
diff --git a/decoder/build/linux/ref_trace_decode_lib/makefile b/decoder/build/linux/ref_trace_decode_lib/makefile index 748bab1..ed947e7 100644 --- a/decoder/build/linux/ref_trace_decode_lib/makefile +++ b/decoder/build/linux/ref_trace_decode_lib/makefile @@ -104,6 +104,7 @@ OBJECTS=$(BUILD_DIR)/ocsd_code_follower.o \ $(BUILD_DIR)/trc_frame_deformatter.o \ $(BUILD_DIR)/trc_gen_elem.o \ $(BUILD_DIR)/trc_printable_elem.o \ + $(BUILD_DIR)/trc_ret_stack.o \ $(ETMV3OBJ) \ $(ETMV4OBJ) \ $(IDECOBJ) \ diff --git a/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj b/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj index 709f031..e9f231d 100644 --- a/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj +++ b/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj @@ -334,6 +334,7 @@ <ClInclude Include="..\..\..\include\common\trc_pkt_elem_base.h" /> <ClInclude Include="..\..\..\include\common\trc_pkt_proc_base.h" /> <ClInclude Include="..\..\..\include\common\trc_printable_elem.h" /> + <ClInclude Include="..\..\..\include\common\trc_ret_stack.h" /> <ClInclude Include="..\..\..\include\etmv3\etmv3_decoder.h" /> <ClInclude Include="..\..\..\include\etmv3\trc_cmp_cfg_etmv3.h" /> <ClInclude Include="..\..\..\include\etmv3\trc_dcd_mngr_etmv3.h" /> @@ -441,6 +442,7 @@ <ClCompile Include="..\..\..\source\trc_frame_deformatter.cpp" /> <ClCompile Include="..\..\..\source\trc_gen_elem.cpp" /> <ClCompile Include="..\..\..\source\trc_printable_elem.cpp" /> + <ClCompile Include="..\..\..\source\trc_ret_stack.cpp" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> diff --git a/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters b/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters index 2ee0f50..a3f3558 100644 --- a/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters +++ b/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters @@ -353,6 +353,9 @@ <ClInclude Include="..\..\..\include\pkt_printers\trc_print_fact.h"> <Filter>Header Files\pkt_printers</Filter> </ClInclude> + <ClInclude Include="..\..\..\include\common\trc_ret_stack.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\..\source\trc_component.cpp"> @@ -475,5 +478,8 @@ <ClCompile Include="..\..\..\source\pkt_printers\trc_print_fact.cpp"> <Filter>Source Files\pkt_printers</Filter> </ClCompile> + <ClCompile Include="..\..\..\source\trc_ret_stack.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> </Project> \ No newline at end of file diff --git a/decoder/include/common/trc_ret_stack.h b/decoder/include/common/trc_ret_stack.h new file mode 100644 index 0000000..2cc8595 --- /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 "ocsd_if_types.h" + +// uncomment below for return stack logging +//#define TRC_RET_STACK_DEBUG + +#ifdef TRC_RET_STACK_DEBUG +class TraceComponent; +#endif + +class TrcAddrReturnStack +{ +public: + TrcAddrReturnStack(); + ~TrcAddrReturnStack() {}; + + void set_active(bool active) + { + m_active = active; + }; + + bool is_active() const + { + return m_active; + }; + + void push(ocsd_vaddr_t addr); + ocsd_vaddr_t pop(); + + void flush() + { + num_entries = 0; + m_pop_pending = false; + }; + + 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; + }; + +#ifdef TRC_RET_STACK_DEBUG + void set_dbg_logger(TraceComponent *pLogger) { m_p_debug_logger = pLogger; }; +#endif + +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; + ocsd_vaddr_t m_stack[16]; + +#ifdef TRC_RET_STACK_DEBUG + void LogOp(const char *pszOpString, ocsd_vaddr_t addr, int head_off); + + TraceComponent *m_p_debug_logger; +#endif // TRC_RET_STACK_DEBUG +}; + +#endif // ARM_TRC_RET_STACK_H_INCLUDED + +/* End of File trc_ret_stack.h */ diff --git a/decoder/source/trc_ret_stack.cpp b/decoder/source/trc_ret_stack.cpp new file mode 100644 index 0000000..4cae29e --- /dev/null +++ b/decoder/source/trc_ret_stack.cpp @@ -0,0 +1,106 @@ +/* +* \file trc_ret_stack.cpp +* \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. +*/ +#include "common/trc_ret_stack.h" + +#ifdef TRC_RET_STACK_DEBUG +#include <sstream> +#include "common/trc_component.h" + +#define LOG_POP(A,O) LogOp("Pop",A,O) +#define LOG_PUSH(A,O) LogOp("Push",A,O) +#else +#define LOG_POP(A,O) +#define LOG_PUSH(A,O) +#endif + +TrcAddrReturnStack::TrcAddrReturnStack() : + m_active(false), + m_pop_pending(false), + head_idx(0), + num_entries(0) +{ +#ifdef TRC_RET_STACK_DEBUG + m_p_debug_logger = 0; +#endif +} + +void TrcAddrReturnStack::push(ocsd_vaddr_t addr) +{ + if (is_active()) + { + head_idx++; + head_idx &= 0xF; + m_stack[head_idx] = addr; + num_entries++; + if (num_entries > 16) + num_entries = 16; + LOG_PUSH(addr,0); + m_pop_pending = false; + } +} + +ocsd_vaddr_t TrcAddrReturnStack::pop() +{ + ocsd_vaddr_t addr = (ocsd_vaddr_t)-1; + if (is_active()) + { + if (num_entries > 0) + { + addr = m_stack[head_idx]; + head_idx--; + head_idx &= 0xF; + } + num_entries--; + LOG_POP(addr,1); + m_pop_pending = false; + } + return addr; +} + +#ifdef TRC_RET_STACK_DEBUG +void TrcAddrReturnStack::LogOp(const char * pszOpString, ocsd_vaddr_t addr, int head_off) +{ + if (m_p_debug_logger) + { + std::ostringstream oss; + oss << "Return stack " << pszOpString << "[" << std::dec << (head_idx+head_off) << "](0x" << std::hex << addr << ");"; + oss << "current entries = " << std::dec << num_entries << ";"; + oss << "new head idx = " << head_idx << ";"; + oss << "pop pend (pre op) = " << (m_pop_pending ? "true\n" : "false\n"); + m_p_debug_logger->LogDefMessage(oss.str()); + } +} +#endif + +/* End of File trc_ret_stack.cpp */