VirtualBox

Changeset 104892 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Jun 12, 2024 1:51:26 PM (8 months ago)
Author:
vboxsync
Message:

Runtime/RTTraceLogTool: Add support for loading decoder plugins which can do further analysis on trace log events, bugref:10701

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/tools/RTTraceLogTool.cpp

    r98103 r104892  
    4040*********************************************************************************************************************************/
    4141#include <iprt/tracelog.h>
     42#include <iprt/tracelog-decoder-plugin.h>
    4243
    4344#include <iprt/assert.h>
     
    4546#include <iprt/getopt.h>
    4647#include <iprt/initterm.h>
     48#include <iprt/ldr.h>
    4749#include <iprt/message.h>
    4850#include <iprt/mem.h>
     
    5153#include <iprt/string.h>
    5254#include <iprt/tcp.h>
     55
     56
     57/**
     58 * Loaded tracelog decoders.
     59 */
     60typedef struct RTTRACELOGDECODERS
     61{
     62    /** Pointer to the array of registered decoders. */
     63    PRTTRACELOGDECODERDECODEEVENT paDecodeEvts;
     64    /** Number of entries in the decoder array. */
     65    uint32_t                      cDecoders;
     66    /** Allocation size of the decoder array. */
     67    uint32_t                      cDecodersAlloc;
     68} RTTRACELOGDECODERS;
     69typedef RTTRACELOGDECODERS *PRTTRACELOGDECODERS;
    5370
    5471
     
    174191
    175192
     193static DECLCALLBACK(int) rtTraceLogToolRegisterDecoders(void *pvUser, PCRTTRACELOGDECODERDECODEEVENT paDecoders, uint32_t cDecoders)
     194{
     195    PRTTRACELOGDECODERS pDecoderState = (PRTTRACELOGDECODERS)pvUser;
     196
     197    if (pDecoderState->cDecodersAlloc - pDecoderState->cDecoders <= cDecoders)
     198    {
     199        PRTTRACELOGDECODERDECODEEVENT paNew = (PRTTRACELOGDECODERDECODEEVENT)RTMemRealloc(pDecoderState->paDecodeEvts,
     200                                                                                          (pDecoderState->cDecodersAlloc + cDecoders) * sizeof(*paDecoders));
     201        if (!paNew)
     202            return VERR_NO_MEMORY;
     203
     204        pDecoderState->paDecodeEvts    = paNew;
     205        pDecoderState->cDecodersAlloc += cDecoders;
     206    }
     207
     208    memcpy(&pDecoderState->paDecodeEvts[pDecoderState->cDecoders], paDecoders, cDecoders * sizeof(*paDecoders));
     209    pDecoderState->cDecoders += cDecoders;
     210    return VINF_SUCCESS;
     211}
     212
     213
    176214int main(int argc, char **argv)
    177215{
     
    185223    static const RTGETOPTDEF s_aOptions[] =
    186224    {
    187         { "--input",    'i', RTGETOPT_REQ_STRING },
    188         { "--save",     's', RTGETOPT_REQ_STRING },
    189         { "--help",     'h', RTGETOPT_REQ_NOTHING },
    190         { "--version",  'V', RTGETOPT_REQ_NOTHING },
     225        { "--input",        'i', RTGETOPT_REQ_STRING },
     226        { "--save",         's', RTGETOPT_REQ_STRING },
     227        { "--load-decoder", 'l', RTGETOPT_REQ_STRING },
     228        { "--help",         'h', RTGETOPT_REQ_NOTHING },
     229        { "--version",      'V', RTGETOPT_REQ_NOTHING },
    191230    };
    192231
    193     RTEXITCODE      rcExit   = RTEXITCODE_SUCCESS;
    194     const char     *pszInput = NULL;
    195     const char     *pszSave  = NULL;
     232    RTEXITCODE          rcExit   = RTEXITCODE_SUCCESS;
     233    const char         *pszInput = NULL;
     234    const char         *pszSave  = NULL;
     235    RTTRACELOGDECODERS  Decoders; RT_ZERO(Decoders);
    196236
    197237    RTGETOPTUNION   ValueUnion;
     
    210250                         "  -s,--save=file\n"
    211251                         "      Save the input to a file for later use\n"
     252                         "  -l,--load-decoder=<plugin path>\n"
     253                         "      Loads the given decoder library used for decoding events\n"
    212254                         "  -h, -?, --help\n"
    213255                         "      Display this help text and exit successfully.\n"
     
    226268                pszSave = ValueUnion.psz;
    227269                break;
     270            case 'l':
     271            {
     272                RTLDRMOD hLdrMod;
     273                rc = RTLdrLoadEx(ValueUnion.psz, &hLdrMod, RTLDRLOAD_FLAGS_NO_UNLOAD, NULL);
     274                if (RT_SUCCESS(rc))
     275                {
     276                    PFNTRACELOGDECODERPLUGINLOAD pfnLoad = NULL;
     277                    rc = RTLdrGetSymbol(hLdrMod, RT_TRACELOG_DECODER_PLUGIN_LOAD, (void **)&pfnLoad);
     278                    if (RT_SUCCESS(rc))
     279                    {
     280                        RTTRACELOGDECODERREGISTER RegCb;
     281
     282                        RegCb.u32Version          = RT_TRACELOG_DECODERREG_CB_VERSION;
     283                        RegCb.pfnRegisterDecoders = rtTraceLogToolRegisterDecoders;
     284
     285                        rc = pfnLoad(&Decoders, &RegCb);
     286                        if (RT_FAILURE(rc))
     287                            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to register decoders %Rrc\n", rc);
     288                    }
     289                    else
     290                        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to lretrieve entry point '%s' %Rrc\n",
     291                                              RT_TRACELOG_DECODER_PLUGIN_LOAD, rc);
     292
     293                    RTLdrClose(hLdrMod);
     294                }
     295                else
     296                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to load decoder library %Rrc\n", rc);
     297                break;
     298            }
    228299            default:
    229300                return RTGetOptPrintError(rc, &ValueUnion);
     
    266337                                      RTTraceLogRdrEvtGetTs(hTraceLogEvt),
    267338                                      pEvtDesc->pszId);
    268                             for (unsigned i = 0; i < pEvtDesc->cEvtItems; i++)
     339
     340                            /*
     341                             * Look through our registered decoders and pass the decoding on to it.
     342                             * If there is no decoder registered just dump the raw values.
     343                             */
     344                            PCRTTRACELOGDECODERDECODEEVENT pDecodeEvt = NULL;
     345                            for (uint32_t i = 0; i < Decoders.cDecoders; i++)
     346                                if (!strcmp(Decoders.paDecodeEvts[i].pszId, pEvtDesc->pszId))
     347                                {
     348                                    pDecodeEvt = &Decoders.paDecodeEvts[i];
     349                                    break;
     350                                }
     351
     352                            if (pDecodeEvt)
    269353                            {
    270                                 RTTRACELOGEVTVAL Val;
    271                                 unsigned cVals = 0;
    272                                 rc = RTTraceLogRdrEvtFillVals(hTraceLogEvt, i, &Val, 1, &cVals);
    273                                 if (RT_SUCCESS(rc))
     354                                /** @todo Dynamic value allocation (too lazy right now). */
     355                                RTTRACELOGEVTVAL aVals[32];
     356                                uint32_t cVals = 0;
     357                                rc = RTTraceLogRdrEvtFillVals(hTraceLogEvt, 0, &aVals[0], RT_ELEMENTS(aVals),
     358                                                              &cVals);
     359                                if (   RT_SUCCESS(rc)
     360                                    || cVals != pEvtDesc->cEvtItems)
    274361                                {
    275                                     switch (Val.pItemDesc->enmType)
    276                                     {
    277                                         case RTTRACELOGTYPE_BOOL:
    278                                             RTMsgInfo("    %s: %s\n", Val.pItemDesc->pszName, Val.u.f ? "true" : "false");
    279                                             break;
    280                                         case RTTRACELOGTYPE_UINT8:
    281                                             RTMsgInfo("    %s: %u\n", Val.pItemDesc->pszName, Val.u.u8);
    282                                             break;
    283                                         case RTTRACELOGTYPE_INT8:
    284                                             RTMsgInfo("    %s: %d\n", Val.pItemDesc->pszName, Val.u.i8);
    285                                             break;
    286                                         case RTTRACELOGTYPE_UINT16:
    287                                             RTMsgInfo("    %s: %u\n", Val.pItemDesc->pszName, Val.u.u16);
    288                                             break;
    289                                         case RTTRACELOGTYPE_INT16:
    290                                             RTMsgInfo("    %s: %d\n", Val.pItemDesc->pszName, Val.u.i16);
    291                                             break;
    292                                         case RTTRACELOGTYPE_UINT32:
    293                                             RTMsgInfo("    %s: %u\n", Val.pItemDesc->pszName, Val.u.u32);
    294                                             break;
    295                                         case RTTRACELOGTYPE_INT32:
    296                                             RTMsgInfo("    %s: %d\n", Val.pItemDesc->pszName, Val.u.i32);
    297                                             break;
    298                                         case RTTRACELOGTYPE_UINT64:
    299                                             RTMsgInfo("    %s: %llu\n", Val.pItemDesc->pszName, Val.u.u64);
    300                                             break;
    301                                         case RTTRACELOGTYPE_INT64:
    302                                             RTMsgInfo("    %s: %lld\n", Val.pItemDesc->pszName, Val.u.i64);
    303                                             break;
    304                                         case RTTRACELOGTYPE_RAWDATA:
    305                                             RTMsgInfo("    %s:\n"
    306                                                       "%.*Rhxd\n", Val.pItemDesc->pszName, Val.u.RawData.cb, Val.u.RawData.pb);
    307                                             break;
    308                                         case RTTRACELOGTYPE_FLOAT32:
    309                                         case RTTRACELOGTYPE_FLOAT64:
    310                                             RTMsgInfo("    %s: Float32 and Float64 data not supported yet\n", Val.pItemDesc->pszName);
    311                                             break;
    312                                         case RTTRACELOGTYPE_POINTER:
    313                                             RTMsgInfo("    %s: %#llx\n", Val.pItemDesc->pszName, Val.u.uPtr);
    314                                             break;
    315                                         case RTTRACELOGTYPE_SIZE:
    316                                             RTMsgInfo("    %s: %llu\n", Val.pItemDesc->pszName, Val.u.sz);
    317                                             break;
    318                                         default:
    319                                             RTMsgError("    %s: Invalid type given %d\n", Val.pItemDesc->pszName, Val.pItemDesc->enmType);
    320                                     }
     362                                    rc = pDecodeEvt->pfnDecode(hTraceLogEvt, pEvtDesc, &aVals[0], cVals);
     363                                    if (RT_FAILURE(rc))
     364                                        RTMsgError("Failed to decode event with ID '%s' -> %Rrc\n", pEvtDesc->pszId, rc);
    321365                                }
    322366                                else
    323                                     RTMsgInfo("    Failed to retrieve event data with %Rrc\n", rc);
     367                                    RTMsgError("Failed to fill values for event with ID '%s' -> %Rrc (cVals=%u vs. cEvtItems=%u)\n",
     368                                               pEvtDesc->pszId, rc, cVals, pEvtDesc->cEvtItems);
    324369                            }
     370                            else
     371                                for (unsigned i = 0; i < pEvtDesc->cEvtItems; i++)
     372                                {
     373                                    RTTRACELOGEVTVAL Val;
     374                                    unsigned cVals = 0;
     375                                    rc = RTTraceLogRdrEvtFillVals(hTraceLogEvt, i, &Val, 1, &cVals);
     376                                    if (RT_SUCCESS(rc))
     377                                    {
     378                                        switch (Val.pItemDesc->enmType)
     379                                        {
     380                                            case RTTRACELOGTYPE_BOOL:
     381                                                RTMsgInfo("    %s: %s\n", Val.pItemDesc->pszName, Val.u.f ? "true" : "false");
     382                                                break;
     383                                            case RTTRACELOGTYPE_UINT8:
     384                                                RTMsgInfo("    %s: %u\n", Val.pItemDesc->pszName, Val.u.u8);
     385                                                break;
     386                                            case RTTRACELOGTYPE_INT8:
     387                                                RTMsgInfo("    %s: %d\n", Val.pItemDesc->pszName, Val.u.i8);
     388                                                break;
     389                                            case RTTRACELOGTYPE_UINT16:
     390                                                RTMsgInfo("    %s: %u\n", Val.pItemDesc->pszName, Val.u.u16);
     391                                                break;
     392                                            case RTTRACELOGTYPE_INT16:
     393                                                RTMsgInfo("    %s: %d\n", Val.pItemDesc->pszName, Val.u.i16);
     394                                                break;
     395                                            case RTTRACELOGTYPE_UINT32:
     396                                                RTMsgInfo("    %s: %u\n", Val.pItemDesc->pszName, Val.u.u32);
     397                                                break;
     398                                            case RTTRACELOGTYPE_INT32:
     399                                                RTMsgInfo("    %s: %d\n", Val.pItemDesc->pszName, Val.u.i32);
     400                                                break;
     401                                            case RTTRACELOGTYPE_UINT64:
     402                                                RTMsgInfo("    %s: %llu\n", Val.pItemDesc->pszName, Val.u.u64);
     403                                                break;
     404                                            case RTTRACELOGTYPE_INT64:
     405                                                RTMsgInfo("    %s: %lld\n", Val.pItemDesc->pszName, Val.u.i64);
     406                                                break;
     407                                            case RTTRACELOGTYPE_RAWDATA:
     408                                                RTMsgInfo("    %s:\n"
     409                                                          "%.*Rhxd\n", Val.pItemDesc->pszName, Val.u.RawData.cb, Val.u.RawData.pb);
     410                                                break;
     411                                            case RTTRACELOGTYPE_FLOAT32:
     412                                            case RTTRACELOGTYPE_FLOAT64:
     413                                                RTMsgInfo("    %s: Float32 and Float64 data not supported yet\n", Val.pItemDesc->pszName);
     414                                                break;
     415                                            case RTTRACELOGTYPE_POINTER:
     416                                                RTMsgInfo("    %s: %#llx\n", Val.pItemDesc->pszName, Val.u.uPtr);
     417                                                break;
     418                                            case RTTRACELOGTYPE_SIZE:
     419                                                RTMsgInfo("    %s: %llu\n", Val.pItemDesc->pszName, Val.u.sz);
     420                                                break;
     421                                            default:
     422                                                RTMsgError("    %s: Invalid type given %d\n", Val.pItemDesc->pszName, Val.pItemDesc->enmType);
     423                                        }
     424                                    }
     425                                    else
     426                                        RTMsgInfo("    Failed to retrieve event data with %Rrc\n", rc);
     427                                }
    325428                        }
    326429                        break;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette