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 */ 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 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 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 106 CustomDcdMngrWrapper::CustomDcdMngrWrapper() 107 { 108 m_dcd_fact.protocol_id = OCSD_PROTOCOL_END; 109 } 110 111 112 // set the C-API decoder factory interface 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 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 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 172 const ocsd_trace_protocol_t CustomDcdMngrWrapper::getProtocolType() const 173 { 174 return m_dcd_fact.protocol_id; 175 } 176 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 */ 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 376 CustomDecoderWrapper::~CustomDecoderWrapper() 377 { 378 } 379 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 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 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 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 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