1 /*
2 * \file ocsd_c_api_custom_obj.cpp
3 * \brief OpenCSD :
4 *
5 * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved.
6 */
7
8 /*
9 * Redistribution and use in source and binary forms, with or without modification,
10 * are permitted provided that the following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the copyright holder nor the names of its contributors
20 * may be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /* pull in the C++ decode library */
36 #include "opencsd.h"
37
38 #include "opencsd/c_api/opencsd_c_api.h"
39 #include "ocsd_c_api_custom_obj.h"
40 #include "common/ocsd_lib_dcd_register.h"
41
42 /***************** C-API functions ********************************/
43
44 /** register a custom decoder with the library */
ocsd_register_custom_decoder(const char * name,ocsd_extern_dcd_fact_t * p_dcd_fact)45 OCSD_C_API ocsd_err_t ocsd_register_custom_decoder(const char *name, ocsd_extern_dcd_fact_t *p_dcd_fact)
46 {
47 ocsd_err_t err = OCSD_OK;
48 OcsdLibDcdRegister *pRegister = OcsdLibDcdRegister::getDecoderRegister();
49
50 // check not already registered
51 if(pRegister->isRegisteredDecoder(name))
52 return OCSD_ERR_DCDREG_NAME_REPEAT;
53
54 // validate the factory interface structure
55 if((p_dcd_fact->createDecoder == 0) ||
56 (p_dcd_fact->destroyDecoder == 0) ||
57 (p_dcd_fact->csidFromConfig == 0)
58 )
59 return OCSD_ERR_INVALID_PARAM_VAL;
60
61 // create a wrapper.
62 CustomDcdMngrWrapper *pWrapper = new (std::nothrow) CustomDcdMngrWrapper();
63 if(pRegister == 0)
64 return OCSD_ERR_MEM;
65
66 p_dcd_fact->protocol_id = OcsdLibDcdRegister::getNextCustomProtocolID();
67 if(p_dcd_fact->protocol_id < OCSD_PROTOCOL_END)
68 {
69 // fill out the wrapper and register it
70 pWrapper->setAPIDcdFact(p_dcd_fact);
71 err = pRegister->registerDecoderTypeByName(name,pWrapper);
72 if(err != OCSD_OK)
73 OcsdLibDcdRegister::releaseLastCustomProtocolID();
74 }
75 else
76 err = OCSD_ERR_DCDREG_TOOMANY; // too many decoders
77
78 if(err != OCSD_OK)
79 delete pWrapper;
80
81 return err;
82 }
83
ocsd_deregister_decoders()84 OCSD_C_API ocsd_err_t ocsd_deregister_decoders()
85 {
86 // destroys all builtin and custom decoders & library registration object.
87 OcsdLibDcdRegister::deregisterAllDecoders();
88 return OCSD_OK;
89 }
90
ocsd_cust_protocol_to_str(const ocsd_trace_protocol_t pkt_protocol,const void * trc_pkt,char * buffer,const int buflen)91 OCSD_C_API ocsd_err_t ocsd_cust_protocol_to_str(const ocsd_trace_protocol_t pkt_protocol, const void *trc_pkt, char *buffer, const int buflen)
92 {
93 OcsdLibDcdRegister *pRegister = OcsdLibDcdRegister::getDecoderRegister();
94 IDecoderMngr *p_mngr = 0;
95 if (OCSD_PROTOCOL_IS_CUSTOM(pkt_protocol) && (pRegister->getDecoderMngrByType(pkt_protocol, &p_mngr) == OCSD_OK))
96 {
97 CustomDcdMngrWrapper *pWrapper = static_cast<CustomDcdMngrWrapper *>(p_mngr);
98 pWrapper->pktToString(trc_pkt, buffer, buflen);
99 return OCSD_OK;
100 }
101 return OCSD_ERR_NO_PROTOCOL;
102 }
103
104 /***************** Decode Manager Wrapper *****************************/
105
CustomDcdMngrWrapper()106 CustomDcdMngrWrapper::CustomDcdMngrWrapper()
107 {
108 m_dcd_fact.protocol_id = OCSD_PROTOCOL_END;
109 }
110
111
112 // set the C-API decoder factory interface
setAPIDcdFact(ocsd_extern_dcd_fact_t * p_dcd_fact)113 void CustomDcdMngrWrapper::setAPIDcdFact(ocsd_extern_dcd_fact_t *p_dcd_fact)
114 {
115 m_dcd_fact = *p_dcd_fact;
116 }
117
118 // create and destroy decoders
createDecoder(const int create_flags,const int instID,const CSConfig * p_config,TraceComponent ** ppComponent)119 ocsd_err_t CustomDcdMngrWrapper::createDecoder(const int create_flags, const int instID, const CSConfig *p_config, TraceComponent **ppComponent)
120 {
121 ocsd_err_t err = OCSD_OK;
122 if(m_dcd_fact.protocol_id == OCSD_PROTOCOL_END)
123 return OCSD_ERR_NOT_INIT;
124
125 CustomDecoderWrapper *pComp = new (std::nothrow) CustomDecoderWrapper();
126 *ppComponent = pComp;
127 if (pComp == 0)
128 return OCSD_ERR_MEM;
129
130 ocsd_extern_dcd_cb_fns lib_callbacks;
131 CustomDecoderWrapper::SetCallbacks(lib_callbacks);
132 lib_callbacks.lib_context = pComp;
133 lib_callbacks.packetCBFlags = 0;
134
135 ocsd_extern_dcd_inst_t *pDecodeInst = pComp->getDecoderInstInfo();
136
137 err = m_dcd_fact.createDecoder( create_flags,
138 ((CustomConfigWrapper *)p_config)->getConfig(),
139 &lib_callbacks,
140 pDecodeInst);
141
142 if (err == OCSD_OK)
143 {
144 // validate the decoder
145 if ((pDecodeInst->fn_data_in == 0) ||
146 (pDecodeInst->fn_update_pkt_mon == 0) ||
147 (pDecodeInst->cs_id == 0) ||
148 (pDecodeInst->decoder_handle == 0) ||
149 (pDecodeInst->p_decoder_name == 0)
150 )
151 {
152 err = OCSD_ERR_INVALID_PARAM_VAL;
153 }
154 }
155
156 if (err != OCSD_OK)
157 delete pComp;
158 else
159 pComp->updateNameFromDcdInst();
160 return err;
161 }
162
destroyDecoder(TraceComponent * pComponent)163 ocsd_err_t CustomDcdMngrWrapper::destroyDecoder(TraceComponent *pComponent)
164 {
165 CustomDecoderWrapper *pCustWrap = dynamic_cast<CustomDecoderWrapper *>(pComponent);
166 if(m_dcd_fact.protocol_id != OCSD_PROTOCOL_END)
167 m_dcd_fact.destroyDecoder(pCustWrap->getDecoderInstInfo()->decoder_handle);
168 delete pCustWrap;
169 return OCSD_OK;
170 }
171
getProtocolType() const172 const ocsd_trace_protocol_t CustomDcdMngrWrapper::getProtocolType() const
173 {
174 return m_dcd_fact.protocol_id;
175 }
176
createConfigFromDataStruct(CSConfig ** pConfigBase,const void * pDataStruct)177 ocsd_err_t CustomDcdMngrWrapper::createConfigFromDataStruct(CSConfig **pConfigBase, const void *pDataStruct)
178 {
179 ocsd_err_t err = OCSD_OK;
180 CustomConfigWrapper *pConfig = new (std::nothrow) CustomConfigWrapper(pDataStruct);
181 if(!pConfig)
182 return OCSD_ERR_MEM;
183
184 if(m_dcd_fact.csidFromConfig == 0)
185 return OCSD_ERR_NOT_INIT;
186
187 unsigned char csid;
188 err = m_dcd_fact.csidFromConfig(pDataStruct,&csid);
189 if(err == OCSD_OK)
190 {
191 pConfig->setCSID(csid);
192 *pConfigBase = pConfig;
193 }
194 return err;
195 }
196
getDataInputI(TraceComponent * pComponent,ITrcDataIn ** ppDataIn)197 ocsd_err_t CustomDcdMngrWrapper::getDataInputI(TraceComponent *pComponent, ITrcDataIn **ppDataIn)
198 {
199 CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
200 if(pDecoder == 0)
201 return OCSD_ERR_INVALID_PARAM_TYPE;
202
203 *ppDataIn = pDecoder;
204 return OCSD_OK;
205 }
206
207 // component connections
208 // all
attachErrorLogger(TraceComponent * pComponent,ITraceErrorLog * pIErrorLog)209 ocsd_err_t CustomDcdMngrWrapper::attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog)
210 {
211 CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
212 if (pDecoder == 0)
213 return OCSD_ERR_INVALID_PARAM_TYPE;
214 pDecoder->getErrorLogAttachPt()->replace_first(pIErrorLog);
215 return OCSD_OK;
216 }
217
218 // full decoder
attachInstrDecoder(TraceComponent * pComponent,IInstrDecode * pIInstrDec)219 ocsd_err_t CustomDcdMngrWrapper::attachInstrDecoder(TraceComponent *pComponent, IInstrDecode *pIInstrDec)
220 {
221 CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
222 if(pDecoder == 0)
223 return OCSD_ERR_INVALID_PARAM_TYPE;
224 pDecoder->attachInstrDecI(pIInstrDec);
225 return OCSD_OK;
226 }
227
attachMemAccessor(TraceComponent * pComponent,ITargetMemAccess * pMemAccessor)228 ocsd_err_t CustomDcdMngrWrapper::attachMemAccessor(TraceComponent *pComponent, ITargetMemAccess *pMemAccessor)
229 {
230 CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
231 if(pDecoder == 0)
232 return OCSD_ERR_INVALID_PARAM_TYPE;
233 pDecoder->attachMemAccI(pMemAccessor);
234 return OCSD_OK;
235 }
236
attachOutputSink(TraceComponent * pComponent,ITrcGenElemIn * pOutSink)237 ocsd_err_t CustomDcdMngrWrapper::attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink)
238 {
239 CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
240 if(pDecoder == 0)
241 return OCSD_ERR_INVALID_PARAM_TYPE;
242 pDecoder->attachGenElemI(pOutSink);
243 return OCSD_OK;
244 }
245
246 // pkt processor only
attachPktMonitor(TraceComponent * pComponent,ITrcTypedBase * pPktRawDataMon)247 ocsd_err_t CustomDcdMngrWrapper::attachPktMonitor(TraceComponent *pComponent, ITrcTypedBase *pPktRawDataMon)
248 {
249 CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
250 if(pDecoder == 0)
251 return OCSD_ERR_INVALID_PARAM_TYPE;
252 IPktRawDataMon<void> *pIF = 0;
253 if (pPktRawDataMon)
254 {
255 pIF = dynamic_cast<IPktRawDataMon<void> *>(pPktRawDataMon);
256 if (!pIF)
257 return OCSD_ERR_INVALID_PARAM_TYPE;
258 }
259 pDecoder->attachPtkMonI(pIF);
260 return OCSD_OK;
261 }
262
attachPktIndexer(TraceComponent * pComponent,ITrcTypedBase * pPktIndexer)263 ocsd_err_t CustomDcdMngrWrapper::attachPktIndexer(TraceComponent *pComponent, ITrcTypedBase *pPktIndexer)
264 {
265 // indexers for external custom will also be external and custom.
266 return OCSD_ERR_DCD_INTERFACE_UNUSED;
267 }
268
attachPktSink(TraceComponent * pComponent,ITrcTypedBase * pPktDataInSink)269 ocsd_err_t CustomDcdMngrWrapper::attachPktSink(TraceComponent *pComponent, ITrcTypedBase *pPktDataInSink)
270 {
271 CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
272 if(pDecoder == 0)
273 return OCSD_ERR_INVALID_PARAM_TYPE;
274 IPktDataIn<void> *pIF = 0;
275 if (pPktDataInSink)
276 {
277 pIF = dynamic_cast<IPktDataIn<void> *>(pPktDataInSink);
278 if(!pIF)
279 return OCSD_ERR_INVALID_PARAM_TYPE;
280 }
281 pDecoder->attachPtkSinkI(pIF);
282 return OCSD_OK;
283 }
284
pktToString(const void * pkt,char * pStrBuffer,int bufSize)285 void CustomDcdMngrWrapper::pktToString(const void *pkt, char *pStrBuffer, int bufSize)
286 {
287 if (m_dcd_fact.pktToString)
288 m_dcd_fact.pktToString(pkt, pStrBuffer, bufSize);
289 else
290 snprintf(pStrBuffer, bufSize, "CUSTOM_PKT[]: print unsupported; protocol(%d).",m_dcd_fact.protocol_id);
291 }
292
293 /************************** Decoder instance wrapper **************************************/
294
295 /* callback functions */
GenElemOpCB(const void * lib_context,const ocsd_trc_index_t index_sop,const uint8_t trc_chan_id,const ocsd_generic_trace_elem * elem)296 ocsd_datapath_resp_t GenElemOpCB( const void *lib_context,
297 const ocsd_trc_index_t index_sop,
298 const uint8_t trc_chan_id,
299 const ocsd_generic_trace_elem *elem)
300 {
301 if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pGenElemIn)
302 return ((CustomDecoderWrapper *)lib_context)->m_pGenElemIn->TraceElemIn(index_sop,trc_chan_id,*(OcsdTraceElement *)elem);
303 return OCSD_RESP_FATAL_NOT_INIT;
304 }
305
LogErrorCB(const void * lib_context,const ocsd_err_severity_t filter_level,const ocsd_err_t code,const ocsd_trc_index_t idx,const uint8_t chan_id,const char * pMsg)306 void LogErrorCB(const void *lib_context, const ocsd_err_severity_t filter_level, const ocsd_err_t code, const ocsd_trc_index_t idx, const uint8_t chan_id, const char *pMsg)
307 {
308 if (lib_context)
309 {
310 if(pMsg)
311 ((CustomDecoderWrapper *)lib_context)->LogError(ocsdError(filter_level, code, idx, chan_id, std::string(pMsg)));
312 else
313 ((CustomDecoderWrapper *)lib_context)->LogError(ocsdError(filter_level, code, idx, chan_id));
314 }
315 }
316
LogMsgCB(const void * lib_context,const ocsd_err_severity_t filter_level,const char * msg)317 void LogMsgCB(const void *lib_context, const ocsd_err_severity_t filter_level, const char *msg)
318 {
319 if (lib_context && msg)
320 ((CustomDecoderWrapper *)lib_context)->LogMessage(filter_level, std::string(msg));
321 }
322
DecodeArmInstCB(const void * lib_context,ocsd_instr_info * instr_info)323 ocsd_err_t DecodeArmInstCB(const void *lib_context, ocsd_instr_info *instr_info)
324 {
325 if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pIInstrDec)
326 return ((CustomDecoderWrapper *)lib_context)->m_pIInstrDec->DecodeInstruction(instr_info);
327 return OCSD_ERR_ATTACH_INVALID_PARAM;
328 }
329
MemAccessCB(const void * lib_context,const ocsd_vaddr_t address,const uint8_t cs_trace_id,const ocsd_mem_space_acc_t mem_space,uint32_t * num_bytes,uint8_t * p_buffer)330 ocsd_err_t MemAccessCB(const void *lib_context,
331 const ocsd_vaddr_t address,
332 const uint8_t cs_trace_id,
333 const ocsd_mem_space_acc_t mem_space,
334 uint32_t *num_bytes,
335 uint8_t *p_buffer)
336 {
337 if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pMemAccessor)
338 return ((CustomDecoderWrapper *)lib_context)->m_pMemAccessor->ReadTargetMemory(address, cs_trace_id, mem_space, num_bytes, p_buffer);
339 return OCSD_ERR_INVALID_PARAM_VAL;
340 }
341
PktMonCB(const void * lib_context,const ocsd_datapath_op_t op,const ocsd_trc_index_t index_sop,const void * pkt,const uint32_t size,const uint8_t * p_data)342 void PktMonCB(const void *lib_context,
343 const ocsd_datapath_op_t op,
344 const ocsd_trc_index_t index_sop,
345 const void *pkt,
346 const uint32_t size,
347 const uint8_t *p_data)
348 {
349 if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pPktMon)
350 ((CustomDecoderWrapper *)lib_context)->m_pPktMon->RawPacketDataMon(op, index_sop, pkt, size, p_data);
351 }
352
PktDataSinkCB(const void * lib_context,const ocsd_datapath_op_t op,const ocsd_trc_index_t index_sop,const void * pkt)353 ocsd_datapath_resp_t PktDataSinkCB(const void *lib_context,
354 const ocsd_datapath_op_t op,
355 const ocsd_trc_index_t index_sop,
356 const void *pkt)
357 {
358 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
359 if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pPktIn)
360 resp = ((CustomDecoderWrapper *)lib_context)->m_pPktIn->PacketDataIn(op, index_sop, pkt);
361 return resp;
362 }
363
364
365
366 /** decoder instance object */
CustomDecoderWrapper()367 CustomDecoderWrapper::CustomDecoderWrapper() : TraceComponent("extern_wrapper"),
368 m_pGenElemIn(0),
369 m_pIInstrDec(0),
370 m_pMemAccessor(0),
371 m_pPktMon(0),
372 m_pPktIn(0)
373 {
374 }
375
~CustomDecoderWrapper()376 CustomDecoderWrapper::~CustomDecoderWrapper()
377 {
378 }
379
TraceDataIn(const ocsd_datapath_op_t op,const ocsd_trc_index_t index,const uint32_t dataBlockSize,const uint8_t * pDataBlock,uint32_t * numBytesProcessed)380 ocsd_datapath_resp_t CustomDecoderWrapper::TraceDataIn( const ocsd_datapath_op_t op,
381 const ocsd_trc_index_t index,
382 const uint32_t dataBlockSize,
383 const uint8_t *pDataBlock,
384 uint32_t *numBytesProcessed)
385 {
386 if(m_decoder_inst.fn_data_in)
387 return m_decoder_inst.fn_data_in( m_decoder_inst.decoder_handle,
388 op,
389 index,
390 dataBlockSize,
391 pDataBlock,
392 numBytesProcessed);
393 return OCSD_RESP_FATAL_NOT_INIT;
394 }
395
attachPtkMonI(IPktRawDataMon<void> * pIF)396 void CustomDecoderWrapper::attachPtkMonI(IPktRawDataMon<void>* pIF)
397 {
398 m_pPktMon = pIF;
399 int flags = (m_pPktMon ? OCSD_CUST_DCD_PKT_CB_USE_MON : 0) | (m_pPktIn ? OCSD_CUST_DCD_PKT_CB_USE_SINK : 0);
400 m_decoder_inst.fn_update_pkt_mon(m_decoder_inst.decoder_handle, flags);
401 }
402
attachPtkSinkI(IPktDataIn<void> * pIF)403 void CustomDecoderWrapper::attachPtkSinkI(IPktDataIn<void>* pIF)
404 {
405 m_pPktIn = pIF;
406 int flags = (m_pPktMon ? OCSD_CUST_DCD_PKT_CB_USE_MON : 0) | (m_pPktIn ? OCSD_CUST_DCD_PKT_CB_USE_SINK : 0);
407 m_decoder_inst.fn_update_pkt_mon(m_decoder_inst.decoder_handle, flags);
408 }
409
updateNameFromDcdInst()410 void CustomDecoderWrapper::updateNameFromDcdInst()
411 {
412 // create a unique component name from the decoder name + cs-id.
413 std::string name_combined = m_decoder_inst.p_decoder_name;
414 char num_buffer[32];
415 sprintf(num_buffer, "_%04d", m_decoder_inst.cs_id);
416 name_combined += (std::string)num_buffer;
417 setComponentName(name_combined);
418 }
419
SetCallbacks(ocsd_extern_dcd_cb_fns & callbacks)420 void CustomDecoderWrapper::SetCallbacks(ocsd_extern_dcd_cb_fns & callbacks)
421 {
422 callbacks.fn_arm_instruction_decode = DecodeArmInstCB;
423 callbacks.fn_gen_elem_out = GenElemOpCB;
424 callbacks.fn_log_error = LogErrorCB;
425 callbacks.fn_log_msg = LogMsgCB;
426 callbacks.fn_memory_access = MemAccessCB;
427 callbacks.fn_packet_data_sink = PktDataSinkCB;
428 callbacks.fn_packet_mon = PktMonCB;
429 }
430
431 /* End of File ocsd_c_api_custom_obj.cpp */
432