xref: /freebsd-src/contrib/opencsd/decoder/source/trc_gen_elem.cpp (revision c120c5646da1a1d2c4d90fd069a7e2a8d559eb46)
1*c120c564SAndrew Turner /*
2*c120c564SAndrew Turner  * \file       trc_gen_elem.cpp
3*c120c564SAndrew Turner  * \brief      OpenCSD :
4*c120c564SAndrew Turner  *
5*c120c564SAndrew Turner  * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
6*c120c564SAndrew Turner  */
7*c120c564SAndrew Turner 
8*c120c564SAndrew Turner /*
9*c120c564SAndrew Turner  * Redistribution and use in source and binary forms, with or without modification,
10*c120c564SAndrew Turner  * are permitted provided that the following conditions are met:
11*c120c564SAndrew Turner  *
12*c120c564SAndrew Turner  * 1. Redistributions of source code must retain the above copyright notice,
13*c120c564SAndrew Turner  * this list of conditions and the following disclaimer.
14*c120c564SAndrew Turner  *
15*c120c564SAndrew Turner  * 2. Redistributions in binary form must reproduce the above copyright notice,
16*c120c564SAndrew Turner  * this list of conditions and the following disclaimer in the documentation
17*c120c564SAndrew Turner  * and/or other materials provided with the distribution.
18*c120c564SAndrew Turner  *
19*c120c564SAndrew Turner  * 3. Neither the name of the copyright holder nor the names of its contributors
20*c120c564SAndrew Turner  * may be used to endorse or promote products derived from this software without
21*c120c564SAndrew Turner  * specific prior written permission.
22*c120c564SAndrew Turner  *
23*c120c564SAndrew Turner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24*c120c564SAndrew Turner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25*c120c564SAndrew Turner  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26*c120c564SAndrew Turner  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27*c120c564SAndrew Turner  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28*c120c564SAndrew Turner  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29*c120c564SAndrew Turner  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30*c120c564SAndrew Turner  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31*c120c564SAndrew Turner  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32*c120c564SAndrew Turner  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*c120c564SAndrew Turner  */
34*c120c564SAndrew Turner 
35*c120c564SAndrew Turner #include "common/trc_gen_elem.h"
36*c120c564SAndrew Turner 
37*c120c564SAndrew Turner #include <string>
38*c120c564SAndrew Turner #include <sstream>
39*c120c564SAndrew Turner #include <iomanip>
40*c120c564SAndrew Turner 
41*c120c564SAndrew Turner static const char *s_elem_descs[][2] =
42*c120c564SAndrew Turner {
43*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_UNKNOWN","Unknown trace element - default value or indicate error in stream to client."},
44*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_NO_SYNC","Waiting for sync - either at start of decode, or after overflow / bad packet"},
45*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_TRACE_ON","Start of trace - beginning of elements or restart after discontinuity (overflow, trace filtering)."},
46*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_EO_TRACE","End of the available trace in the buffer."},
47*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_PE_CONTEXT","PE status update / change (arch, ctxtid, vmid etc)."},
48*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_INSTR_RANGE","Traced N consecutive instructions from addr (no intervening events or data elements), may have data assoc key"},
49*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_ADDR_NACC","Tracing in inaccessible memory area."},
50*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN","Tracing unknown address area."},
51*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_EXCEPTION","Exception"},
52*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_EXCEPTION_RET","Exception return"},
53*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_TIMESTAMP","Timestamp - preceding elements happeded before this time."},
54*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_CYCLE_COUNT","Cycle count - cycles since last cycle count value - associated with a preceding instruction range."},
55*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_EVENT","Event - numbered event or trigger"},
56*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_SWTRACE","Software trace packet - may contain data payload."},
57*c120c564SAndrew Turner     {"OCSD_GEN_TRC_ELEM_CUSTOM","Fully custom packet type."}
58*c120c564SAndrew Turner };
59*c120c564SAndrew Turner 
60*c120c564SAndrew Turner static const char *instr_type[] = {
61*c120c564SAndrew Turner     "--- ",
62*c120c564SAndrew Turner     "BR  ",
63*c120c564SAndrew Turner     "iBR ",
64*c120c564SAndrew Turner     "ISB ",
65*c120c564SAndrew Turner     "DSB.DMB"
66*c120c564SAndrew Turner };
67*c120c564SAndrew Turner 
68*c120c564SAndrew Turner #define T_SIZE (sizeof(instr_type) / sizeof(const char *))
69*c120c564SAndrew Turner 
70*c120c564SAndrew Turner static const char *instr_sub_type[] = {
71*c120c564SAndrew Turner     "--- ",
72*c120c564SAndrew Turner     "b+link ",
73*c120c564SAndrew Turner     "A64:ret ",
74*c120c564SAndrew Turner     "A64:eret ",
75*c120c564SAndrew Turner     "V7:impl ret",
76*c120c564SAndrew Turner };
77*c120c564SAndrew Turner 
78*c120c564SAndrew Turner #define ST_SIZE (sizeof(instr_sub_type) / sizeof(const char *))
79*c120c564SAndrew Turner 
80*c120c564SAndrew Turner static const char *s_trace_on_reason[] = {
81*c120c564SAndrew Turner     "begin or filter",
82*c120c564SAndrew Turner     "overflow",
83*c120c564SAndrew Turner     "debug restart"
84*c120c564SAndrew Turner };
85*c120c564SAndrew Turner 
86*c120c564SAndrew Turner 
87*c120c564SAndrew Turner static const char *s_isa_str[] = {
88*c120c564SAndrew Turner    "A32",      /**< V7 ARM 32, V8 AArch32 */
89*c120c564SAndrew Turner    "T32",          /**< Thumb2 -> 16/32 bit instructions */
90*c120c564SAndrew Turner    "A64",      /**< V8 AArch64 */
91*c120c564SAndrew Turner    "TEE",          /**< Thumb EE - unsupported */
92*c120c564SAndrew Turner    "Jaz",      /**< Jazelle - unsupported in trace */
93*c120c564SAndrew Turner    "Cst",      /**< ISA custom */
94*c120c564SAndrew Turner    "Unk"       /**< ISA not yet known */
95*c120c564SAndrew Turner };
96*c120c564SAndrew Turner 
97*c120c564SAndrew Turner void OcsdTraceElement::toString(std::string &str) const
98*c120c564SAndrew Turner {
99*c120c564SAndrew Turner     std::ostringstream oss;
100*c120c564SAndrew Turner     int num_str = ((sizeof(s_elem_descs) / sizeof(const char *)) / 2);
101*c120c564SAndrew Turner     int typeIdx = (int)this->elem_type;
102*c120c564SAndrew Turner     if(typeIdx < num_str)
103*c120c564SAndrew Turner     {
104*c120c564SAndrew Turner         oss << s_elem_descs[typeIdx][0] << "(";
105*c120c564SAndrew Turner         switch(elem_type)
106*c120c564SAndrew Turner         {
107*c120c564SAndrew Turner         case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
108*c120c564SAndrew Turner             oss << "exec range=0x" << std::hex << st_addr << ":[0x" << en_addr << "] ";
109*c120c564SAndrew Turner             oss << "num_i(" << std::dec << num_instr_range << ") ";
110*c120c564SAndrew Turner             oss << "last_sz(" << last_instr_sz << ") ";
111*c120c564SAndrew Turner             oss << "(ISA=" << s_isa_str[(int)isa] << ") ";
112*c120c564SAndrew Turner             oss << ((last_instr_exec == 1) ? "E " : "N ");
113*c120c564SAndrew Turner             if((int)last_i_type < T_SIZE)
114*c120c564SAndrew Turner                 oss << instr_type[last_i_type];
115*c120c564SAndrew Turner             if((last_i_subtype != OCSD_S_INSTR_NONE) && ((int)last_i_subtype < ST_SIZE))
116*c120c564SAndrew Turner                 oss << instr_sub_type[last_i_subtype];
117*c120c564SAndrew Turner             if (last_instr_cond)
118*c120c564SAndrew Turner                 oss << " <cond>";
119*c120c564SAndrew Turner             break;
120*c120c564SAndrew Turner 
121*c120c564SAndrew Turner         case OCSD_GEN_TRC_ELEM_ADDR_NACC:
122*c120c564SAndrew Turner             oss << " 0x" << std::hex << st_addr << " ";
123*c120c564SAndrew Turner             break;
124*c120c564SAndrew Turner 
125*c120c564SAndrew Turner         case OCSD_GEN_TRC_ELEM_EXCEPTION:
126*c120c564SAndrew Turner             if (excep_ret_addr == 1)
127*c120c564SAndrew Turner             {
128*c120c564SAndrew Turner                 oss << "pref ret addr:0x" << std::hex << en_addr;
129*c120c564SAndrew Turner                 if (excep_ret_addr_br_tgt)
130*c120c564SAndrew Turner                 {
131*c120c564SAndrew Turner                     oss << " [addr also prev br tgt]";
132*c120c564SAndrew Turner                 }
133*c120c564SAndrew Turner                 oss << "; ";
134*c120c564SAndrew Turner             }
135*c120c564SAndrew Turner             oss << "excep num (0x" << std::setfill('0') << std::setw(2) << std::hex << exception_number << ") ";
136*c120c564SAndrew Turner             break;
137*c120c564SAndrew Turner 
138*c120c564SAndrew Turner         case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
139*c120c564SAndrew Turner             oss << "(ISA=" << s_isa_str[(int)isa] << ") ";
140*c120c564SAndrew Turner             if((context.exception_level > ocsd_EL_unknown) && (context.el_valid))
141*c120c564SAndrew Turner             {
142*c120c564SAndrew Turner                 oss << "EL" << std::dec << (int)(context.exception_level);
143*c120c564SAndrew Turner             }
144*c120c564SAndrew Turner             oss << (context.security_level == ocsd_sec_secure ? "S; " : "N; ") << (context.bits64 ? "64-bit; " : "32-bit; ");
145*c120c564SAndrew Turner             if(context.vmid_valid)
146*c120c564SAndrew Turner                 oss << "VMID=0x" << std::hex << context.vmid << "; ";
147*c120c564SAndrew Turner             if(context.ctxt_id_valid)
148*c120c564SAndrew Turner                 oss << "CTXTID=0x" << std::hex << context.context_id << "; ";
149*c120c564SAndrew Turner             break;
150*c120c564SAndrew Turner 
151*c120c564SAndrew Turner         case  OCSD_GEN_TRC_ELEM_TRACE_ON:
152*c120c564SAndrew Turner             oss << " [" << s_trace_on_reason[trace_on_reason] << "]";
153*c120c564SAndrew Turner             break;
154*c120c564SAndrew Turner 
155*c120c564SAndrew Turner         case OCSD_GEN_TRC_ELEM_TIMESTAMP:
156*c120c564SAndrew Turner             oss << " [ TS=0x" << std::setfill('0') << std::setw(12) << std::hex << timestamp << "]; ";
157*c120c564SAndrew Turner             break;
158*c120c564SAndrew Turner 
159*c120c564SAndrew Turner         case OCSD_GEN_TRC_ELEM_SWTRACE:
160*c120c564SAndrew Turner             printSWInfoPkt(oss);
161*c120c564SAndrew Turner             break;
162*c120c564SAndrew Turner 
163*c120c564SAndrew Turner         case OCSD_GEN_TRC_ELEM_EVENT:
164*c120c564SAndrew Turner             if(trace_event.ev_type == EVENT_TRIGGER)
165*c120c564SAndrew Turner                 oss << " Trigger; ";
166*c120c564SAndrew Turner             else if(trace_event.ev_type == EVENT_NUMBERED)
167*c120c564SAndrew Turner                 oss << " Numbered:" << std::dec << trace_event.ev_number << "; ";
168*c120c564SAndrew Turner             break;
169*c120c564SAndrew Turner 
170*c120c564SAndrew Turner         default: break;
171*c120c564SAndrew Turner         }
172*c120c564SAndrew Turner         if(has_cc)
173*c120c564SAndrew Turner             oss << std::dec << " [CC=" << cycle_count << "]; ";
174*c120c564SAndrew Turner         oss << ")";
175*c120c564SAndrew Turner     }
176*c120c564SAndrew Turner     else
177*c120c564SAndrew Turner     {
178*c120c564SAndrew Turner         oss << "OCSD_GEN_TRC_ELEM??: index out of range.";
179*c120c564SAndrew Turner     }
180*c120c564SAndrew Turner     str = oss.str();
181*c120c564SAndrew Turner }
182*c120c564SAndrew Turner 
183*c120c564SAndrew Turner OcsdTraceElement &OcsdTraceElement::operator =(const ocsd_generic_trace_elem* p_elem)
184*c120c564SAndrew Turner {
185*c120c564SAndrew Turner     *dynamic_cast<ocsd_generic_trace_elem*>(this) = *p_elem;
186*c120c564SAndrew Turner     return *this;
187*c120c564SAndrew Turner }
188*c120c564SAndrew Turner 
189*c120c564SAndrew Turner 
190*c120c564SAndrew Turner void OcsdTraceElement::printSWInfoPkt(std::ostringstream & oss) const
191*c120c564SAndrew Turner {
192*c120c564SAndrew Turner     if (!sw_trace_info.swt_global_err)
193*c120c564SAndrew Turner     {
194*c120c564SAndrew Turner         if (sw_trace_info.swt_id_valid)
195*c120c564SAndrew Turner         {
196*c120c564SAndrew Turner             oss << " (Ma:0x" << std::setfill('0') << std::setw(2) << std::hex << sw_trace_info.swt_master_id << "; ";
197*c120c564SAndrew Turner             oss << "Ch:0x" << std::setfill('0') << std::setw(2) << std::hex << sw_trace_info.swt_channel_id << ") ";
198*c120c564SAndrew Turner         }
199*c120c564SAndrew Turner         else
200*c120c564SAndrew Turner             oss << "(Ma:0x??; Ch:0x??" << ") ";
201*c120c564SAndrew Turner 
202*c120c564SAndrew Turner         if (sw_trace_info.swt_payload_pkt_bitsize > 0)
203*c120c564SAndrew Turner         {
204*c120c564SAndrew Turner             oss << "0x" << std::setfill('0') << std::hex;
205*c120c564SAndrew Turner             if (sw_trace_info.swt_payload_pkt_bitsize == 4)
206*c120c564SAndrew Turner             {
207*c120c564SAndrew Turner                 oss << std::setw(1);
208*c120c564SAndrew Turner                 oss << (uint16_t)(((uint8_t *)ptr_extended_data)[0] & 0xF);
209*c120c564SAndrew Turner             }
210*c120c564SAndrew Turner             else
211*c120c564SAndrew Turner             {
212*c120c564SAndrew Turner                 switch (sw_trace_info.swt_payload_pkt_bitsize)
213*c120c564SAndrew Turner                 {
214*c120c564SAndrew Turner                 case 8:
215*c120c564SAndrew Turner                     // force uint8 to uint16 so oss 'sees' them as something to be stringised, rather than absolute char values
216*c120c564SAndrew Turner                     oss << std::setw(2) << (uint16_t)((uint8_t *)ptr_extended_data)[0];
217*c120c564SAndrew Turner                     break;
218*c120c564SAndrew Turner                 case 16:
219*c120c564SAndrew Turner                     oss << std::setw(4) << ((uint16_t *)ptr_extended_data)[0];
220*c120c564SAndrew Turner                     break;
221*c120c564SAndrew Turner                 case 32:
222*c120c564SAndrew Turner                     oss << std::setw(8) << ((uint32_t *)ptr_extended_data)[0];
223*c120c564SAndrew Turner                     break;
224*c120c564SAndrew Turner                 case 64:
225*c120c564SAndrew Turner                     oss << std::setw(16) << ((uint64_t *)ptr_extended_data)[0];
226*c120c564SAndrew Turner                     break;
227*c120c564SAndrew Turner                 default:
228*c120c564SAndrew Turner                     oss << "{Data Error : unsupported bit width.}";
229*c120c564SAndrew Turner                     break;
230*c120c564SAndrew Turner                 }
231*c120c564SAndrew Turner             }
232*c120c564SAndrew Turner             oss << "; ";
233*c120c564SAndrew Turner         }
234*c120c564SAndrew Turner         if (sw_trace_info.swt_marker_packet)
235*c120c564SAndrew Turner             oss << "+Mrk ";
236*c120c564SAndrew Turner         if (sw_trace_info.swt_trigger_event)
237*c120c564SAndrew Turner             oss << "Trig ";
238*c120c564SAndrew Turner         if (sw_trace_info.swt_has_timestamp)
239*c120c564SAndrew Turner             oss << " [ TS=0x" << std::setfill('0') << std::setw(12) << std::hex << timestamp << "]; ";
240*c120c564SAndrew Turner         if (sw_trace_info.swt_frequency)
241*c120c564SAndrew Turner             oss << "Freq";
242*c120c564SAndrew Turner         if (sw_trace_info.swt_master_err)
243*c120c564SAndrew Turner             oss << "{Master Error.}";
244*c120c564SAndrew Turner     }
245*c120c564SAndrew Turner     else
246*c120c564SAndrew Turner     {
247*c120c564SAndrew Turner         oss << "{Global Error.}";
248*c120c564SAndrew Turner     }
249*c120c564SAndrew Turner }
250*c120c564SAndrew Turner 
251*c120c564SAndrew Turner /*
252*c120c564SAndrew Turner void OcsdTraceElement::toString(const ocsd_generic_trace_elem *p_elem, std::string &str)
253*c120c564SAndrew Turner {
254*c120c564SAndrew Turner     OcsdTraceElement elem;
255*c120c564SAndrew Turner     elem = p_elem;
256*c120c564SAndrew Turner     elem.toString(str);
257*c120c564SAndrew Turner }
258*c120c564SAndrew Turner */
259*c120c564SAndrew Turner /* End of File trc_gen_elem.cpp */
260