VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/log/tracelogreader.cpp@ 78098

Last change on this file since 78098 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 60.4 KB
Line 
1/* $Id: tracelogreader.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * IPRT - Trace log reader.
4 */
5
6/*
7 * Copyright (C) 2018-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "internal/iprt.h"
32#include <iprt/formats/tracelog.h>
33#include <iprt/tracelog.h>
34
35
36#include <iprt/asm.h>
37#include <iprt/assert.h>
38#include <iprt/err.h>
39#include <iprt/file.h>
40#include <iprt/list.h>
41#include <iprt/log.h>
42#include <iprt/mem.h>
43#include <iprt/semaphore.h>
44#include <iprt/string.h>
45#include <iprt/strcache.h>
46#include <iprt/time.h>
47
48#include "internal/magics.h"
49
50
51/*********************************************************************************************************************************
52* Structures and Typedefs *
53*********************************************************************************************************************************/
54
55/** The trace log is malformed. */
56#define VERR_TRACELOG_READER_MALFORMED_LOG (-25700)
57/** The trace log version is not supported. */
58#define VERR_TRACELOG_READER_LOG_UNSUPPORTED (-25701)
59/** The trace log reader iterator reached the end of the event list. */
60#define VERR_TRACELOG_READER_ITERATOR_END (-25702)
61
62/** Pointer to a trace log reader instance. */
63typedef struct RTTRACELOGRDRINT *PRTTRACELOGRDRINT;
64
65/**
66 * State enums the trace log reader can be in.
67 */
68typedef enum RTTRACELOGRDRSTATE
69{
70 /** Invalid state. */
71 RTTRACELOGRDRSTATE_INVALID = 0,
72 /** The header is currently being received. */
73 RTTRACELOGRDRSTATE_RECV_HDR,
74 /** The header description is being received (if available). */
75 RTTRACELOGRDRSTATE_RECV_HDR_DESC,
76 /** the magic is being received to decide what to do next. */
77 RTTRACELOGRDRSTATE_RECV_MAGIC,
78 /** The event descriptor is being received. */
79 RTTRACELOGRDRSTATE_RECV_EVT_DESC,
80 /** The event descriptor ID is being received. */
81 RTTRACELOGRDRSTATE_RECV_EVT_DESC_ID,
82 /** The event descriptor description is being received. */
83 RTTRACELOGRDRSTATE_RECV_EVT_DESC_DESC,
84 /** The event item descriptor is being received. */
85 RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC,
86 /** The event item descriptor name is being received. */
87 RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC_NAME,
88 /** The event item descriptor description is being received. */
89 RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC_DESC,
90 /** The event marker is being received. */
91 RTTRACELOGRDRSTATE_RECV_EVT_MARKER,
92 /** The event data is being received. */
93 RTTRACELOGRDRSTATE_RECV_EVT_DATA,
94 /** 32bit hack. */
95 RTTRACELOGRDRSTATE_32BIT_HACK = 0x7fffffff
96} RTTRACELOGRDRSTATE;
97
98
99/** Pointer to internal trace log reader event descriptor. */
100typedef struct RTTRACELOGRDREVTDESC *PRTTRACELOGRDREVTDESC;
101/** Pointer to const internal trace log reader event descriptor. */
102typedef const RTTRACELOGRDREVTDESC *PCRTTRACELOGRDREVTDESC;
103
104
105/**
106 * Trace log reader event.
107 */
108typedef struct RTTRACELOGRDREVTINT
109{
110 /** List node for the global list of events. */
111 RTLISTANCHOR NdGlob;
112 /** The trace log reader instance the event belongs to. */
113 PRTTRACELOGRDRINT pRdr;
114 /** Trace log sequence number. */
115 uint64_t u64SeqNo;
116 /** Marker time stamp. */
117 uint64_t u64Ts;
118 /** Pointer to the event descriptor, describing the data layout. */
119 PCRTTRACELOGRDREVTDESC pEvtDesc;
120 /** Parent group ID if assigned. */
121 RTTRACELOGEVTGRPID idGrpParent;
122 /** Group ID this event belongs to. */
123 RTTRACELOGEVTGRPID idGrp;
124 /** Pointer to the array holding the non static raw data size values. */
125 size_t *pacbRawData;
126 /** Overall event data size in bytes, including non static data. */
127 size_t cbEvtData;
128 /** Event data, variable in size. */
129 uint8_t abEvtData[1];
130} RTTRACELOGRDREVTINT;
131/** Pointer to a trace log reader event. */
132typedef RTTRACELOGRDREVTINT *PRTTRACELOGRDREVTINT;
133/** Pointer to a const trace log reader event. */
134typedef const RTTRACELOGRDREVTINT *PCRTTRACELOGRDREVTINT;
135
136
137/**
138 * Trace log reader internal event descriptor.
139 */
140typedef struct RTTRACELOGRDREVTDESC
141{
142 /** Overall size of the event data not counting variable raw data items. */
143 size_t cbEvtData;
144 /** Number of non static raw binary items in the descriptor. */
145 uint32_t cRawDataNonStatic;
146 /** Current event item descriptor to work on. */
147 uint32_t idxEvtItemCur;
148 /** Size of the name of the current item to work on. */
149 size_t cbStrItemName;
150 /** Size of the description of the current item to work on. */
151 size_t cbStrItemDesc;
152 /** Size of the ID in bytes including the terminator. */
153 size_t cbStrId;
154 /** Size of the description in bytes including the terminator. */
155 size_t cbStrDesc;
156 /** Embedded event descriptor. */
157 RTTRACELOGEVTDESC EvtDesc;
158 /** Array of event item descriptors, variable in size. */
159 RTTRACELOGEVTITEMDESC aEvtItemDesc[1];
160} RTTRACELOGRDREVTDESC;
161
162
163/**
164 * Trace log reader instance data.
165 */
166typedef struct RTTRACELOGRDRINT
167{
168 /** Magic for identification. */
169 uint32_t u32Magic;
170 /** Stream out callback. */
171 PFNRTTRACELOGRDRSTREAM pfnStreamIn;
172 /** Stream close callback .*/
173 PFNRTTRACELOGSTREAMCLOSE pfnStreamClose;
174 /** Opaque user data passed to the stream callback. */
175 void *pvUser;
176 /** Mutex protecting the structure. */
177 RTSEMMUTEX hMtx;
178 /** Current state the reader is in. */
179 RTTRACELOGRDRSTATE enmState;
180 /** Flag whether to convert all inputs to the host endianess. */
181 bool fConvEndianess;
182 /** String cache for descriptions and IDs. */
183 RTSTRCACHE hStrCache;
184 /** Size of the description in characters. */
185 size_t cchDesc;
186 /** Pointer to the description if set. */
187 const char *pszDesc;
188 /** List of received events. */
189 RTLISTANCHOR LstEvts;
190 /** Number of event descriptors known. */
191 uint32_t cEvtDescsCur;
192 /** Maximum number of event descriptors currently fitting into the array. */
193 uint32_t cEvtDescsMax;
194 /** Pointer to the array of event descriptor pointers. */
195 PRTTRACELOGRDREVTDESC *papEvtDescs;
196 /** Current event descriptor being initialised. */
197 PRTTRACELOGRDREVTDESC pEvtDescCur;
198 /** The current event being received. */
199 PRTTRACELOGRDREVTINT pEvtCur;
200 /** Last seen sequence number. */
201 uint64_t u64SeqNoLast;
202 /** Size of the scratch buffer holding the received data. */
203 size_t cbScratch;
204 /** Pointer to the scratch buffer. */
205 uint8_t *pbScratch;
206 /** Current offset into the scratch buffer to write fetched data to. */
207 uint32_t offScratch;
208 /** Number of bytes left to receive until processing the data. */
209 size_t cbRecvLeft;
210 /** Starting timestamp fetched from the header. */
211 uint64_t u64TsStart;
212 /** Size of the pointer type in the trace log. */
213 size_t cbTypePtr;
214 /** Size of the size_t type in the trace log. */
215 size_t cbTypeSize;
216} RTTRACELOGRDRINT;
217
218
219/**
220 * Internal reader iterator instance data.
221 */
222typedef struct RTTRACELOGRDRITINT
223{
224 /** The reader instance this iterator belongs to. */
225 PRTTRACELOGRDRINT pRdr;
226 /** The current event. */
227 PRTTRACELOGRDREVTINT pEvt;
228} RTTRACELOGRDRITINT;
229/** Pointer to an internal reader iterator instance. */
230typedef RTTRACELOGRDRITINT *PRTTRACELOGRDRITINT;
231
232
233/**
234 * Trace log handler state callback.
235 *
236 * @returns IPRT status code.
237 * @param pThis The trace log reader instance.
238 * @param penmEvt Where to store the event indicator if a user visible event happened.
239 * @param pfContinuePoll Where to store the flag whether to continue polling.
240 */
241typedef DECLCALLBACK(int) FNRTTRACELOGRDRSTATEHANDLER(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
242 bool *pfContinuePoll);
243/** Pointer to a trace log reader state handler. */
244typedef FNRTTRACELOGRDRSTATEHANDLER *PFNRTTRACELOGRDRSTATEHANDLER;
245
246
247/*********************************************************************************************************************************
248* Defined Constants And Macros *
249*********************************************************************************************************************************/
250
251static DECLCALLBACK(int) rtTraceLogRdrHdrRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
252static DECLCALLBACK(int) rtTraceLogRdrHdrDescRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
253static DECLCALLBACK(int) rtTraceLogRdrMagicRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
254static DECLCALLBACK(int) rtTraceLogRdrEvtDescRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
255static DECLCALLBACK(int) rtTraceLogRdrEvtDescIdRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
256static DECLCALLBACK(int) rtTraceLogRdrEvtDescDescriptionRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
257static DECLCALLBACK(int) rtTraceLogRdrEvtItemDescRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
258static DECLCALLBACK(int) rtTraceLogRdrEvtItemDescNameRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
259static DECLCALLBACK(int) rtTraceLogRdrEvtItemDescDescriptionRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
260static DECLCALLBACK(int) rtTraceLogRdrEvtMarkerRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
261static DECLCALLBACK(int) rtTraceLogRdrEvtDataRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt, bool *pfContinuePoll);
262
263/**
264 * State handlers.
265 */
266static PFNRTTRACELOGRDRSTATEHANDLER g_apfnStateHandlers[] =
267{
268 NULL,
269 rtTraceLogRdrHdrRecvd,
270 rtTraceLogRdrHdrDescRecvd,
271 rtTraceLogRdrMagicRecvd,
272 rtTraceLogRdrEvtDescRecvd,
273 rtTraceLogRdrEvtDescIdRecvd,
274 rtTraceLogRdrEvtDescDescriptionRecvd,
275 rtTraceLogRdrEvtItemDescRecvd,
276 rtTraceLogRdrEvtItemDescNameRecvd,
277 rtTraceLogRdrEvtItemDescDescriptionRecvd,
278 rtTraceLogRdrEvtMarkerRecvd,
279 rtTraceLogRdrEvtDataRecvd,
280 NULL
281};
282
283/**
284 * Wrapper around the stream in callback.
285 *
286 * @returns IPRT status code returned by the stream callback.
287 * @param pThis The trace log reader instance.
288 * @param pvBuf The data to stream.
289 * @param cbBuf Number of bytes to read in.
290 * @param pcbRead Where to store the amount of data read.
291 * @param cMsTimeout How long to wait for something to arrive.
292 */
293DECLINLINE(int) rtTraceLogRdrStreamRead(PRTTRACELOGRDRINT pThis, void *pvBuf, size_t cbBuf,
294 size_t *pcbRead, RTMSINTERVAL cMsTimeout)
295{
296 return pThis->pfnStreamIn(pThis->pvUser, pvBuf, cbBuf, pcbRead, cMsTimeout);
297}
298
299
300/**
301 * Converts the header endianess to the host endianess.
302 *
303 * @returns nothing.
304 * @param pHdr The trace log header to convert.
305 */
306static void rtTraceLogRdrHdrEndianessConv(PTRACELOGHDR pHdr)
307{
308 pHdr->u32Endianess = RT_BSWAP_U32(pHdr->u32Endianess);
309 pHdr->u32Version = RT_BSWAP_U32(pHdr->u32Version);
310 pHdr->fFlags = RT_BSWAP_U32(pHdr->fFlags);
311 pHdr->cbStrDesc = RT_BSWAP_U32(pHdr->cbStrDesc);
312 pHdr->u64TsStart = RT_BSWAP_U64(pHdr->u64TsStart);
313}
314
315
316/**
317 * Converts the event descriptor endianess to the host endianess.
318 *
319 * @returns nothing.
320 * @param pEvtDesc The trace log event descriptor to convert.
321 */
322static void rtTraceLogRdrEvtDescEndianessConv(PTRACELOGEVTDESC pEvtDesc)
323{
324 pEvtDesc->u32Id = RT_BSWAP_U32(pEvtDesc->u32Id);
325 pEvtDesc->u32Severity = RT_BSWAP_U32(pEvtDesc->u32Severity);
326 pEvtDesc->cbStrId = RT_BSWAP_U32(pEvtDesc->cbStrId);
327 pEvtDesc->cbStrDesc = RT_BSWAP_U32(pEvtDesc->cbStrDesc);
328 pEvtDesc->cEvtItems = RT_BSWAP_U32(pEvtDesc->cEvtItems);
329}
330
331
332/**
333 * Converts the event item descriptor endianess to host endianess.
334 *
335 * @returns nothing.
336 * @param pEvtItemDesc The trace log event item descriptor to convert.
337 */
338static void rtTraceLogRdrEvtItemDescEndianessConv(PTRACELOGEVTITEMDESC pEvtItemDesc)
339{
340 pEvtItemDesc->cbStrName = RT_BSWAP_U32(pEvtItemDesc->cbStrName);
341 pEvtItemDesc->cbStrDesc = RT_BSWAP_U32(pEvtItemDesc->cbStrDesc);
342 pEvtItemDesc->u32Type = RT_BSWAP_U32(pEvtItemDesc->u32Type);
343 pEvtItemDesc->cbRawData = RT_BSWAP_U32(pEvtItemDesc->cbRawData);
344}
345
346
347/**
348 * Converts the event marker endianess to host endianess.
349 *
350 * @returns nothing.
351 * @param pEvt The trace log event marker to convert.
352 */
353static void rtTraceLogRdrEvtEndianessConv(PTRACELOGEVT pEvt)
354{
355 pEvt->u64SeqNo = RT_BSWAP_U64(pEvt->u64SeqNo);
356 pEvt->u64Ts = RT_BSWAP_U64(pEvt->u64Ts);
357 pEvt->u64EvtGrpId = RT_BSWAP_U64(pEvt->u64EvtGrpId);
358 pEvt->u64EvtParentGrpId = RT_BSWAP_U64(pEvt->u64EvtParentGrpId);
359 pEvt->fFlags = RT_BSWAP_U32(pEvt->fFlags);
360 pEvt->u32EvtDescId = RT_BSWAP_U32(pEvt->u32EvtDescId);
361 pEvt->cbEvtData = RT_BSWAP_U32(pEvt->cbEvtData);
362 pEvt->cRawEvtDataSz = RT_BSWAP_U32(pEvt->cRawEvtDataSz);
363}
364
365
366/**
367 * Converts severity field from stream to API value.
368 *
369 * @returns API severity enum, RTTRACELOGEVTSEVERITY_INVALID if the supplied stream value
370 * is invalid.
371 * @param u32Severity The severity value from the stream.
372 */
373static RTTRACELOGEVTSEVERITY rtTraceLogRdrConvSeverity(uint32_t u32Severity)
374{
375 RTTRACELOGEVTSEVERITY enmSeverity = RTTRACELOGEVTSEVERITY_INVALID;
376
377 switch (u32Severity)
378 {
379 case TRACELOG_EVTDESC_SEVERITY_INFO:
380 enmSeverity = RTTRACELOGEVTSEVERITY_INFO;
381 break;
382 case TRACELOG_EVTDESC_SEVERITY_WARNING:
383 enmSeverity = RTTRACELOGEVTSEVERITY_WARNING;
384 break;
385 case TRACELOG_EVTDESC_SEVERITY_ERROR:
386 enmSeverity = RTTRACELOGEVTSEVERITY_ERROR;
387 break;
388 case TRACELOG_EVTDESC_SEVERITY_FATAL:
389 enmSeverity = RTTRACELOGEVTSEVERITY_FATAL;
390 break;
391 case TRACELOG_EVTDESC_SEVERITY_DEBUG:
392 enmSeverity = RTTRACELOGEVTSEVERITY_DEBUG;
393 break;
394 default:
395 enmSeverity = RTTRACELOGEVTSEVERITY_INVALID;
396 }
397
398 return enmSeverity;
399}
400
401
402/**
403 * Converts type field from stream to API value.
404 *
405 * @returns API type enum, RTTRACELOGTYPE_INVALID if the supplied stream value
406 * is invalid.
407 * @param u32Type The type value from the stream.
408 */
409static RTTRACELOGTYPE rtTraceLogRdrConvType(uint32_t u32Type)
410{
411 RTTRACELOGTYPE enmType = RTTRACELOGTYPE_INVALID;
412
413 switch (u32Type)
414 {
415 case TRACELOG_EVTITEMDESC_TYPE_BOOL:
416 enmType = RTTRACELOGTYPE_BOOL;
417 break;
418 case TRACELOG_EVTITEMDESC_TYPE_UINT8:
419 enmType = RTTRACELOGTYPE_UINT8;
420 break;
421 case TRACELOG_EVTITEMDESC_TYPE_INT8:
422 enmType = RTTRACELOGTYPE_INT8;
423 break;
424 case TRACELOG_EVTITEMDESC_TYPE_UINT16:
425 enmType = RTTRACELOGTYPE_UINT16;
426 break;
427 case TRACELOG_EVTITEMDESC_TYPE_INT16:
428 enmType = RTTRACELOGTYPE_INT16;
429 break;
430 case TRACELOG_EVTITEMDESC_TYPE_UINT32:
431 enmType = RTTRACELOGTYPE_UINT32;
432 break;
433 case TRACELOG_EVTITEMDESC_TYPE_INT32:
434 enmType = RTTRACELOGTYPE_INT32;
435 break;
436 case TRACELOG_EVTITEMDESC_TYPE_UINT64:
437 enmType = RTTRACELOGTYPE_UINT64;
438 break;
439 case TRACELOG_EVTITEMDESC_TYPE_INT64:
440 enmType = RTTRACELOGTYPE_INT64;
441 break;
442 case TRACELOG_EVTITEMDESC_TYPE_FLOAT32:
443 enmType = RTTRACELOGTYPE_FLOAT32;
444 break;
445 case TRACELOG_EVTITEMDESC_TYPE_FLOAT64:
446 enmType = RTTRACELOGTYPE_FLOAT64;
447 break;
448 case TRACELOG_EVTITEMDESC_TYPE_RAWDATA:
449 enmType = RTTRACELOGTYPE_RAWDATA;
450 break;
451 case TRACELOG_EVTITEMDESC_TYPE_POINTER:
452 enmType = RTTRACELOGTYPE_POINTER;
453 break;
454 case TRACELOG_EVTITEMDESC_TYPE_SIZE:
455 enmType = RTTRACELOGTYPE_SIZE;
456 break;
457 default:
458 enmType = RTTRACELOGTYPE_INVALID;
459 }
460
461 return enmType;
462}
463
464
465/**
466 * Converts the type enum to the size of the the event item data in bytes.
467 *
468 * @returns Event item data size in bytes.
469 * @param pThis The trace log reader instance.
470 * @param pEvtItemDesc The event item descriptor.
471 */
472static size_t rtTraceLogRdrGetEvtItemDataSz(PRTTRACELOGRDRINT pThis, PCRTTRACELOGEVTITEMDESC pEvtItemDesc)
473{
474 size_t cb = 0;
475
476 switch (pEvtItemDesc->enmType)
477 {
478 case RTTRACELOGTYPE_BOOL:
479 case RTTRACELOGTYPE_UINT8:
480 case RTTRACELOGTYPE_INT8:
481 {
482 cb = 1;
483 break;
484 }
485 case RTTRACELOGTYPE_UINT16:
486 case RTTRACELOGTYPE_INT16:
487 {
488 cb = 2;
489 break;
490 }
491 case RTTRACELOGTYPE_UINT32:
492 case RTTRACELOGTYPE_INT32:
493 case RTTRACELOGTYPE_FLOAT32:
494 {
495 cb = 4;
496 break;
497 }
498 case RTTRACELOGTYPE_UINT64:
499 case RTTRACELOGTYPE_INT64:
500 case RTTRACELOGTYPE_FLOAT64:
501 {
502 cb = 8;
503 break;
504 }
505 case RTTRACELOGTYPE_RAWDATA:
506 {
507 cb = pEvtItemDesc->cbRawData;
508 break;
509 }
510 case RTTRACELOGTYPE_POINTER:
511 {
512 cb = pThis->cbTypePtr;
513 break;
514 }
515 case RTTRACELOGTYPE_SIZE:
516 {
517 cb = pThis->cbTypeSize;
518 break;
519 }
520 default:
521 AssertMsgFailed(("Invalid type %d\n", pEvtItemDesc->enmType));
522 }
523
524 return cb;
525}
526
527
528/**
529 * Calculates the overall event data size from the items in the event descriptor.
530 *
531 * @returns nothing.
532 * @param pThis The trace log reader instance.
533 * @param pEvtDesc The event descriptor.
534 */
535static void rtTraceLogRdrEvtCalcEvtDataSz(PRTTRACELOGRDRINT pThis, PRTTRACELOGRDREVTDESC pEvtDesc)
536{
537 pEvtDesc->cbEvtData = 0;
538 pEvtDesc->cRawDataNonStatic = 0;
539
540 for (unsigned i = 0; i < pEvtDesc->EvtDesc.cEvtItems; i++)
541 {
542 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = &pEvtDesc->aEvtItemDesc[i];
543
544 pEvtDesc->cbEvtData += rtTraceLogRdrGetEvtItemDataSz(pThis, pEvtItemDesc);
545 if ( pEvtItemDesc->enmType == RTTRACELOGTYPE_RAWDATA
546 && pEvtItemDesc->cbRawData == 0)
547 pEvtDesc->cRawDataNonStatic++;
548 }
549}
550
551
552/**
553 * Ensures that the scratch buffer can hold at least the given amount of data.
554 *
555 * @returns IPRT status code.
556 * @param pThis The trace log reader instance.
557 * @param cbScratch New size of the scratch buffer in bytes.
558 */
559static int rtTraceLogRdrScratchEnsureSz(PRTTRACELOGRDRINT pThis, size_t cbScratch)
560{
561 int rc = VINF_SUCCESS;
562
563 if (pThis->cbScratch < cbScratch)
564 {
565 cbScratch = RT_ALIGN_Z(cbScratch, 64);
566 uint8_t *pbScratchNew = (uint8_t *)RTMemRealloc(pThis->pbScratch, cbScratch);
567 if (RT_LIKELY(pbScratchNew))
568 {
569 pThis->cbScratch = cbScratch;
570 pThis->pbScratch = pbScratchNew;
571 }
572 else
573 rc = VERR_NO_MEMORY;
574 }
575
576 return rc;
577}
578
579
580/**
581 * Advances to the next state resetting the scratch/receive buffers to the given state.
582 *
583 * @returns IPRT status.
584 * @param pThis The trace log reader instance.
585 * @param enmState The next state.
586 * @param cbRecv How much to receive before processing the new data.
587 * @param offScratch Offset to set the receive buffer to (used
588 * when the magic was received which should still be saved).
589 */
590static int rtTraceLogRdrStateAdvanceEx(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRSTATE enmState, size_t cbRecv,
591 uint32_t offScratch)
592{
593 Assert(cbRecv >= offScratch);
594
595 pThis->enmState = enmState;
596 pThis->cbRecvLeft = cbRecv - offScratch;
597 pThis->offScratch = offScratch;
598 int rc = rtTraceLogRdrScratchEnsureSz(pThis, cbRecv);
599
600 /* Zero out scratch buffer (don't care whether growing it failed, the old buffer is still there). */
601 memset(pThis->pbScratch + offScratch, 0, pThis->cbScratch - offScratch);
602
603 return rc;
604}
605
606
607/**
608 * Advances to the next state resetting the scratch/receive buffers.
609 *
610 * @returns IPRT status.
611 * @param pThis The trace log reader instance.
612 * @param enmState The next state.
613 * @param cbRecv How much to receive before processing the new data.
614 */
615static int rtTraceLogRdrStateAdvance(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRSTATE enmState, size_t cbRecv)
616{
617 return rtTraceLogRdrStateAdvanceEx(pThis, enmState, cbRecv, 0);
618}
619
620
621/**
622 * Marks a received event descriptor as completed and adds it to the array of known descriptors.
623 *
624 * @returns IPRT status code.
625 * @param pThis The trace log reader instance.
626 * @param pEvtDesc The event descriptor which completed.
627 */
628static int rtTraceLogRdrEvtDescComplete(PRTTRACELOGRDRINT pThis, PRTTRACELOGRDREVTDESC pEvtDesc)
629{
630 int rc = VINF_SUCCESS;
631
632 rtTraceLogRdrEvtCalcEvtDataSz(pThis, pEvtDesc);
633 /* Insert into array of known event descriptors. */
634 if (pThis->cEvtDescsCur == pThis->cEvtDescsMax)
635 {
636 uint32_t cEvtDescsNew = pThis->cEvtDescsMax + 10;
637 size_t cbNew = cEvtDescsNew * sizeof(PRTTRACELOGRDREVTDESC *);
638 PRTTRACELOGRDREVTDESC *papEvtDescsNew = (PRTTRACELOGRDREVTDESC *)RTMemRealloc(pThis->papEvtDescs, cbNew);
639 if (RT_LIKELY(papEvtDescsNew))
640 {
641 pThis->papEvtDescs = papEvtDescsNew;
642 pThis->cEvtDescsMax = cEvtDescsNew;
643 }
644 else
645 rc = VERR_NO_MEMORY;
646 }
647
648 if (RT_SUCCESS(rc))
649 {
650 pThis->papEvtDescs[pThis->cEvtDescsCur++] = pEvtDesc;
651 pThis->pEvtDescCur = NULL;
652 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_MAGIC, TRACELOG_MAGIC_SZ);
653 }
654
655 return rc;
656}
657
658
659/**
660 * Decides which state to enter next after one event item descriptor was completed successfully.
661 *
662 * @returns IPRT status code.
663 * @param pThis The trace log reader instance.
664 * @param penmEvt Where to store the event indicator if a user visible event happened.
665 * @param pfContinuePoll Where to store the flag whether to continue polling.
666 */
667static int rtTraceLogRdrEvtItemDescComplete(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
668 bool *pfContinuePoll)
669{
670 RT_NOREF(penmEvt, pfContinuePoll);
671
672 int rc = VINF_SUCCESS;
673 PRTTRACELOGRDREVTDESC pEvtDesc = pThis->pEvtDescCur;
674 pEvtDesc->idxEvtItemCur++;
675
676 /* If this event descriptor is complete add it to the array of known descriptors. */
677 if (pEvtDesc->idxEvtItemCur == pEvtDesc->EvtDesc.cEvtItems)
678 rc = rtTraceLogRdrEvtDescComplete(pThis, pEvtDesc);
679 else
680 {
681 /* Not done yet. */
682 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC, sizeof(TRACELOGEVTITEMDESC));
683 }
684
685 return rc;
686}
687
688
689/**
690 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received header.}
691 */
692static DECLCALLBACK(int) rtTraceLogRdrHdrRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
693 bool *pfContinuePoll)
694{
695 RT_NOREF(penmEvt, pfContinuePoll);
696 int rc = VINF_SUCCESS;
697 PTRACELOGHDR pHdr = (PTRACELOGHDR)pThis->pbScratch;
698
699 /* Verify magic. */
700 if (!memcmp(&pHdr->szMagic[0], TRACELOG_HDR_MAGIC, sizeof(pHdr->szMagic)))
701 {
702 /* Check endianess. */
703 if (pHdr->u32Endianess == TRACELOG_HDR_ENDIANESS)
704 pThis->fConvEndianess = false;
705 else if (RT_BSWAP_U32(pHdr->u32Endianess) == TRACELOG_HDR_ENDIANESS)
706 {
707 pThis->fConvEndianess = true;
708 rtTraceLogRdrHdrEndianessConv(pHdr);
709 }
710 else
711 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
712
713 if (RT_SUCCESS(rc))
714 {
715 Assert(pHdr->u32Endianess == TRACELOG_HDR_ENDIANESS);
716
717 /* Enforce strict limits to avoid exhausting memory. */
718 if ( pHdr->u32Version == TRACELOG_VERSION
719 && pHdr->cbStrDesc < _1K
720 && pHdr->cbTypePtr <= 8
721 && (pHdr->cbTypeSize == 8 || pHdr->cbTypeSize == 4))
722 {
723 pThis->u64TsStart = pHdr->u64TsStart;
724 pThis->cbTypePtr = pHdr->cbTypePtr;
725 pThis->cbTypeSize = pHdr->cbTypeSize;
726 pThis->cchDesc = pHdr->cbStrDesc;
727 pThis->cEvtDescsMax = 10;
728
729 /* Allocate array to hold event descriptors later on. */
730 pThis->papEvtDescs = (PRTTRACELOGRDREVTDESC *)RTMemAllocZ(pThis->cEvtDescsMax * sizeof(PRTTRACELOGRDREVTDESC));
731 if (RT_LIKELY(pThis->papEvtDescs))
732 {
733 /* Switch to the next state. */
734 if (pHdr->cbStrDesc)
735 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_HDR_DESC, pHdr->cbStrDesc);
736 else
737 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_MAGIC, TRACELOG_MAGIC_SZ);
738
739 if (RT_SUCCESS(rc))
740 {
741 *penmEvt = RTTRACELOGRDRPOLLEVT_HDR_RECVD;
742 *pfContinuePoll = false;
743 }
744 }
745 else
746 rc = VERR_NO_MEMORY;
747 }
748 else
749 rc = VERR_TRACELOG_READER_LOG_UNSUPPORTED;
750 }
751 }
752 else
753 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
754
755 return rc;
756}
757
758
759/**
760 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received log description.}
761 */
762static DECLCALLBACK(int) rtTraceLogRdrHdrDescRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
763 bool *pfContinuePoll)
764{
765 RT_NOREF(penmEvt, pfContinuePoll);
766 int rc = VINF_SUCCESS;
767 char *pszDesc = (char *)pThis->pbScratch;
768
769 RTStrPurgeEncoding(pszDesc);
770 pThis->pszDesc = RTStrCacheEnterN(pThis->hStrCache, pszDesc, pThis->cchDesc);
771 if (pThis->pszDesc)
772 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_MAGIC, TRACELOG_MAGIC_SZ);
773 else
774 rc = VERR_NO_STR_MEMORY;
775 return rc;
776}
777
778
779/**
780 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received magic.}
781 */
782static DECLCALLBACK(int) rtTraceLogRdrMagicRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
783 bool *pfContinuePoll)
784{
785 RT_NOREF(penmEvt, pfContinuePoll);
786 int rc = VINF_SUCCESS;
787 char *pszMagic = (char *)pThis->pbScratch;
788
789 if (!memcmp(pszMagic, TRACELOG_EVTDESC_MAGIC, TRACELOG_MAGIC_SZ))
790 rc = rtTraceLogRdrStateAdvanceEx(pThis, RTTRACELOGRDRSTATE_RECV_EVT_DESC,
791 sizeof(TRACELOGEVTDESC), TRACELOG_MAGIC_SZ);
792 else if (!memcmp(pszMagic, TRACELOG_EVT_MAGIC, TRACELOG_MAGIC_SZ))
793 rc = rtTraceLogRdrStateAdvanceEx(pThis, RTTRACELOGRDRSTATE_RECV_EVT_MARKER,
794 sizeof(TRACELOGEVT), TRACELOG_MAGIC_SZ);
795
796 return rc;
797}
798
799
800/**
801 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event descriptor.}
802 */
803static DECLCALLBACK(int) rtTraceLogRdrEvtDescRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
804 bool *pfContinuePoll)
805{
806 RT_NOREF(penmEvt, pfContinuePoll);
807 int rc = VINF_SUCCESS;
808 PTRACELOGEVTDESC pEvtDesc = (PTRACELOGEVTDESC)pThis->pbScratch;
809 if (pThis->fConvEndianess)
810 rtTraceLogRdrEvtDescEndianessConv(pEvtDesc);
811
812 if ( !memcmp(&pEvtDesc->szMagic[0], TRACELOG_EVTDESC_MAGIC, sizeof(pEvtDesc->szMagic))
813 && pEvtDesc->u32Id == pThis->cEvtDescsCur
814 && (pEvtDesc->cbStrId >= 1 && pEvtDesc->cbStrId < 128)
815 && pEvtDesc->cbStrDesc < _1K
816 && pEvtDesc->cEvtItems < 128)
817 {
818 RTTRACELOGEVTSEVERITY enmSeverity = rtTraceLogRdrConvSeverity(pEvtDesc->u32Severity);
819 if (RT_LIKELY(enmSeverity != RTTRACELOGEVTSEVERITY_INVALID))
820 {
821 /* Allocate new internal event descriptor state. */
822 size_t cbEvtDesc = RT_UOFFSETOF_DYN(RTTRACELOGRDREVTDESC, aEvtItemDesc[pEvtDesc->cEvtItems]);
823 PRTTRACELOGRDREVTDESC pEvtDescInt = (PRTTRACELOGRDREVTDESC)RTMemAllocZ(cbEvtDesc);
824 if (RT_LIKELY(pEvtDesc))
825 {
826 pEvtDescInt->cbStrId = pEvtDesc->cbStrId;
827 pEvtDescInt->cbStrDesc = pEvtDesc->cbStrDesc;
828 pEvtDescInt->EvtDesc.enmSeverity = enmSeverity;
829 pEvtDescInt->EvtDesc.cEvtItems = pEvtDesc->cEvtItems;
830 pEvtDescInt->EvtDesc.paEvtItemDesc = &pEvtDescInt->aEvtItemDesc[0];
831
832 pThis->pEvtDescCur = pEvtDescInt;
833 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_DESC_ID, pEvtDescInt->cbStrId);
834 }
835 else
836 rc = VERR_NO_MEMORY;
837 }
838 else
839 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
840 }
841 else
842 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
843
844 return rc;
845}
846
847
848/**
849 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event descriptor ID.}
850 */
851static DECLCALLBACK(int) rtTraceLogRdrEvtDescIdRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
852 bool *pfContinuePoll)
853{
854 RT_NOREF(penmEvt, pfContinuePoll);
855
856 int rc = VINF_SUCCESS;
857 pThis->pEvtDescCur->EvtDesc.pszId = RTStrCacheEnterN(pThis->hStrCache, (const char *)pThis->pbScratch,
858 pThis->pEvtDescCur->cbStrId);
859 if (RT_LIKELY(pThis->pEvtDescCur->EvtDesc.pszId))
860 {
861 if (pThis->pEvtDescCur->cbStrDesc)
862 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_DESC_DESC, pThis->pEvtDescCur->cbStrDesc);
863 else if (pThis->pEvtDescCur->EvtDesc.cEvtItems > 0)
864 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC, sizeof(TRACELOGEVTITEMDESC));
865 else
866 rc = rtTraceLogRdrEvtDescComplete(pThis, pThis->pEvtDescCur);
867 }
868 else
869 rc = VERR_NO_STR_MEMORY;
870
871 return rc;
872}
873
874
875/**
876 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event descriptor description.}
877 */
878static DECLCALLBACK(int) rtTraceLogRdrEvtDescDescriptionRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
879 bool *pfContinuePoll)
880{
881 RT_NOREF(penmEvt, pfContinuePoll);
882 int rc = VINF_SUCCESS;
883 pThis->pEvtDescCur->EvtDesc.pszDesc = RTStrCacheEnterN(pThis->hStrCache, (const char *)pThis->pbScratch,
884 pThis->pEvtDescCur->cbStrDesc);
885 if (RT_LIKELY(pThis->pEvtDescCur->EvtDesc.pszDesc))
886 {
887 if (pThis->pEvtDescCur->EvtDesc.cEvtItems > 0)
888 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC, sizeof(TRACELOGEVTITEMDESC));
889 else
890 rc = rtTraceLogRdrEvtDescComplete(pThis, pThis->pEvtDescCur);
891 }
892 else
893 rc = VERR_NO_STR_MEMORY;
894
895 return rc;
896}
897
898
899/**
900 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event item descriptor.}
901 */
902static DECLCALLBACK(int) rtTraceLogRdrEvtItemDescRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
903 bool *pfContinuePoll)
904{
905 RT_NOREF(penmEvt, pfContinuePoll);
906 int rc = VINF_SUCCESS;
907 PTRACELOGEVTITEMDESC pEvtItemDesc = (PTRACELOGEVTITEMDESC)pThis->pbScratch;
908 if (pThis->fConvEndianess)
909 rtTraceLogRdrEvtItemDescEndianessConv(pEvtItemDesc);
910
911 if ( !memcmp(&pEvtItemDesc->szMagic[0], TRACELOG_EVTITEMDESC_MAGIC, sizeof(pEvtItemDesc->szMagic))
912 && (pEvtItemDesc->cbStrName >= 1 && pEvtItemDesc->cbStrName < 128)
913 && pEvtItemDesc->cbStrDesc < _1K
914 && pEvtItemDesc->cbRawData < _1M)
915 {
916 RTTRACELOGTYPE enmType = rtTraceLogRdrConvType(pEvtItemDesc->u32Type);
917 if (RT_LIKELY(enmType != RTTRACELOGTYPE_INVALID))
918 {
919 PRTTRACELOGEVTITEMDESC pEvtDesc = &pThis->pEvtDescCur->aEvtItemDesc[pThis->pEvtDescCur->idxEvtItemCur];
920
921 pThis->pEvtDescCur->cbStrItemName = pEvtItemDesc->cbStrName;
922 pThis->pEvtDescCur->cbStrItemDesc = pEvtItemDesc->cbStrDesc;
923
924 pEvtDesc->enmType = enmType;
925 pEvtDesc->cbRawData = pEvtItemDesc->cbRawData;
926 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC_NAME, pEvtItemDesc->cbStrName);
927 }
928 else
929 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
930 }
931 else
932 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
933
934 return rc;
935}
936
937
938/**
939 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event item descriptor name.}
940 */
941static DECLCALLBACK(int) rtTraceLogRdrEvtItemDescNameRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
942 bool *pfContinuePoll)
943{
944 int rc = VINF_SUCCESS;
945 PRTTRACELOGEVTITEMDESC pEvtDesc = &pThis->pEvtDescCur->aEvtItemDesc[pThis->pEvtDescCur->idxEvtItemCur];
946 pEvtDesc->pszName = RTStrCacheEnterN(pThis->hStrCache, (const char *)pThis->pbScratch, pThis->pEvtDescCur->cbStrItemName);
947 if (RT_LIKELY(pEvtDesc->pszName))
948 {
949 if (pThis->pEvtDescCur->cbStrItemDesc)
950 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC_DESC, pThis->pEvtDescCur->cbStrItemDesc);
951 else
952 rc = rtTraceLogRdrEvtItemDescComplete(pThis, penmEvt, pfContinuePoll);
953 }
954 else
955 rc = VERR_NO_STR_MEMORY;
956
957 return rc;
958}
959
960
961/**
962 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event item description.}
963 */
964static DECLCALLBACK(int) rtTraceLogRdrEvtItemDescDescriptionRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
965 bool *pfContinuePoll)
966{
967 int rc = VINF_SUCCESS;
968 PRTTRACELOGEVTITEMDESC pEvtDesc = &pThis->pEvtDescCur->aEvtItemDesc[pThis->pEvtDescCur->idxEvtItemCur];
969 pEvtDesc->pszDesc = RTStrCacheEnterN(pThis->hStrCache, (const char *)pThis->pbScratch, pThis->pEvtDescCur->cbStrItemDesc);
970 if (RT_LIKELY(pEvtDesc->pszDesc))
971 rc = rtTraceLogRdrEvtItemDescComplete(pThis, penmEvt, pfContinuePoll);
972 else
973 rc = VERR_NO_STR_MEMORY;
974
975 return rc;
976}
977
978
979/**
980 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event marker.}
981 */
982static DECLCALLBACK(int) rtTraceLogRdrEvtMarkerRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
983 bool *pfContinuePoll)
984{
985 int rc = VINF_SUCCESS;
986 PTRACELOGEVT pEvtStrm = (PTRACELOGEVT)pThis->pbScratch;
987 if (pThis->fConvEndianess)
988 rtTraceLogRdrEvtEndianessConv(pEvtStrm);
989
990 if ( (pEvtStrm->u64SeqNo == pThis->u64SeqNoLast + 1)
991 && !(pEvtStrm->fFlags & ~TRACELOG_EVT_F_VALID)
992 && pEvtStrm->u32EvtDescId < pThis->cEvtDescsCur)
993 {
994 PRTTRACELOGRDREVTDESC pEvtDesc = pThis->papEvtDescs[pEvtStrm->u32EvtDescId];
995 if ( ( !pEvtDesc->cRawDataNonStatic
996 && pEvtStrm->cbEvtData == pEvtDesc->cbEvtData)
997 || ( pEvtDesc->cRawDataNonStatic
998 && pEvtStrm->cbEvtData >= pEvtDesc->cbEvtData
999 && pEvtStrm->cRawEvtDataSz == pEvtDesc->cRawDataNonStatic))
1000 {
1001 size_t cbEvt = RT_UOFFSETOF_DYN(RTTRACELOGRDREVTINT, abEvtData[pEvtStrm->cbEvtData]);
1002 cbEvt += pEvtDesc->cRawDataNonStatic * sizeof(size_t);
1003 PRTTRACELOGRDREVTINT pEvt = (PRTTRACELOGRDREVTINT)RTMemAllocZ(cbEvt);
1004 if (RT_LIKELY(pEvt))
1005 {
1006 pEvt->pRdr = pThis;
1007 pEvt->u64SeqNo = pEvtStrm->u64SeqNo;
1008 pEvt->u64Ts = pEvtStrm->u64Ts;
1009 pEvt->pEvtDesc = pEvtDesc;
1010 pEvt->cbEvtData = pEvtStrm->cbEvtData;
1011 pEvt->pacbRawData = pEvtDesc->cRawDataNonStatic ? (size_t *)&pEvt->abEvtData[pEvtStrm->cbEvtData] : NULL;
1012 /** @todo Group handling and parenting. */
1013
1014 pThis->pEvtCur = pEvt;
1015 size_t cbEvtDataRecv = pEvtStrm->cRawEvtDataSz * pThis->cbTypeSize + pEvtStrm->cbEvtData;
1016 if (cbEvtDataRecv)
1017 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_DATA, cbEvtDataRecv);
1018 else
1019 {
1020 pThis->pEvtCur = NULL;
1021 RTSemMutexRequest(pThis->hMtx, RT_INDEFINITE_WAIT);
1022 pThis->u64SeqNoLast = pEvt->u64SeqNo;
1023 RTListAppend(&pThis->LstEvts, &pEvt->NdGlob);
1024 RTSemMutexRelease(pThis->hMtx);
1025 *penmEvt = RTTRACELOGRDRPOLLEVT_TRACE_EVENT_RECVD;
1026 *pfContinuePoll = false;
1027 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_MAGIC, TRACELOG_MAGIC_SZ);
1028 }
1029 }
1030 else
1031 rc = VERR_NO_MEMORY;
1032 }
1033 else
1034 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
1035 }
1036 else
1037 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
1038
1039 return rc;
1040}
1041
1042
1043/**
1044 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles received event data.}
1045 */
1046static DECLCALLBACK(int) rtTraceLogRdrEvtDataRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
1047 bool *pfContinuePoll)
1048{
1049 RT_NOREF(penmEvt, pfContinuePoll);
1050
1051 int rc = VINF_SUCCESS;
1052 PRTTRACELOGRDREVTINT pEvt = pThis->pEvtCur;
1053 PCRTTRACELOGRDREVTDESC pEvtDesc = pEvt->pEvtDesc;
1054 uint8_t *pbData = pThis->pbScratch;
1055 size_t cbRawDataNonStatic = 0;
1056
1057 /* Retrieve any raw data size indicators first. */
1058 for (unsigned i = 0; i < pEvtDesc->cRawDataNonStatic; i++)
1059 {
1060 size_t cb = 0;
1061 if (pThis->cbTypeSize == 4)
1062 {
1063 cb = RT_BSWAP_U32(*(uint32_t *)pbData);
1064 pbData += 4;
1065 }
1066 else if (pThis->cbTypeSize == 8)
1067 {
1068 cb = RT_BSWAP_U64(*(uint64_t *)pbData);
1069 pbData += 8;
1070 }
1071 else
1072 AssertMsgFailed(("Invalid size_t size %u\n", pThis->cbTypeSize));
1073
1074 pEvt->pacbRawData[i] = cb;
1075 cbRawDataNonStatic += cb;
1076 }
1077
1078 /* Verify that sizes add up. */
1079 if (pEvt->cbEvtData == pEvtDesc->cbEvtData + cbRawDataNonStatic)
1080 {
1081 /* Copy the data over. */
1082 memcpy(&pEvt->abEvtData[0], pbData, pEvt->cbEvtData);
1083
1084 /* Done add event to global list and generate event. */
1085 pThis->pEvtCur = NULL;
1086 RTSemMutexRequest(pThis->hMtx, RT_INDEFINITE_WAIT);
1087 pThis->u64SeqNoLast = pEvt->u64SeqNo;
1088 RTListAppend(&pThis->LstEvts, &pEvt->NdGlob);
1089 RTSemMutexRelease(pThis->hMtx);
1090 *penmEvt = RTTRACELOGRDRPOLLEVT_TRACE_EVENT_RECVD;
1091 *pfContinuePoll = false;
1092 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_MAGIC, TRACELOG_MAGIC_SZ);
1093 }
1094 else
1095 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
1096
1097 return rc;
1098}
1099
1100
1101/**
1102 * @copydoc FNRTTRACELOGRDRSTREAM
1103 */
1104static DECLCALLBACK(int) rtTraceLogRdrFileStream(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbRead,
1105 RTMSINTERVAL cMsTimeout)
1106{
1107 RT_NOREF(cMsTimeout);
1108 RTFILE hFile = (RTFILE)pvUser;
1109 return RTFileRead(hFile, pvBuf, cbBuf, pcbRead);
1110}
1111
1112
1113/**
1114 * @copydoc FNRTTRACELOGSTREAMCLOSE
1115 */
1116static DECLCALLBACK(int) rtTraceLogRdrFileStreamClose(void *pvUser)
1117{
1118 RTFILE hFile = (RTFILE)pvUser;
1119 return RTFileClose(hFile);
1120}
1121
1122
1123/**
1124 * Returns the size of the data for the given event item descriptor.
1125 *
1126 * @returns Size in bytes for the given event item descriptor.
1127 * @param pThis The trace log rader instance.
1128 * @param pEvtItemDesc The event item descriptor.
1129 * @param pacbRawData The raw data size array for he associated event to get the size for non static raw data items.
1130 * @param pidxRawData The index into the raw data size array for the next item to use.
1131 */
1132static size_t rtTraceLogRdrEvtItemGetSz(PRTTRACELOGRDRINT pThis, PCRTTRACELOGEVTITEMDESC pEvtItemDesc,
1133 size_t *pacbRawData, unsigned *pidxRawData)
1134{
1135 size_t cbRet = 0;
1136
1137 switch (pEvtItemDesc->enmType)
1138 {
1139 case RTTRACELOGTYPE_BOOL:
1140 cbRet = sizeof(bool);
1141 break;
1142 case RTTRACELOGTYPE_UINT8:
1143 cbRet = sizeof(uint8_t);
1144 break;
1145 case RTTRACELOGTYPE_INT8:
1146 cbRet = sizeof(int8_t);
1147 break;
1148 case RTTRACELOGTYPE_UINT16:
1149 cbRet = sizeof(uint16_t);
1150 break;
1151 case RTTRACELOGTYPE_INT16:
1152 cbRet = sizeof(int16_t);
1153 break;
1154 case RTTRACELOGTYPE_UINT32:
1155 cbRet = sizeof(uint32_t);
1156 break;
1157 case RTTRACELOGTYPE_INT32:
1158 cbRet = sizeof(int32_t);
1159 break;
1160 case RTTRACELOGTYPE_UINT64:
1161 cbRet = sizeof(uint64_t);
1162 break;
1163 case RTTRACELOGTYPE_INT64:
1164 cbRet = sizeof(int64_t);
1165 break;
1166 case RTTRACELOGTYPE_FLOAT32:
1167 cbRet = sizeof(float);
1168 break;
1169 case RTTRACELOGTYPE_FLOAT64:
1170 cbRet = sizeof(double);
1171 break;
1172 case RTTRACELOGTYPE_RAWDATA:
1173 if (pEvtItemDesc->cbRawData == 0)
1174 {
1175 cbRet = pacbRawData[*pidxRawData];
1176 *pidxRawData++;
1177 }
1178 else
1179 cbRet = pEvtItemDesc->cbRawData;
1180 break;
1181 case RTTRACELOGTYPE_POINTER:
1182 cbRet = pThis->cbTypePtr;
1183 break;
1184 case RTTRACELOGTYPE_SIZE:
1185 cbRet = pThis->cbTypeSize;
1186 break;
1187 default:
1188 AssertMsgFailed(("Invalid type given %d\n", pEvtItemDesc->enmType));
1189 }
1190
1191 return cbRet;
1192}
1193
1194
1195/**
1196 * Resolves the offset of the field with the given name returning the offset and data type.
1197 *
1198 * @returns IPRT status code.
1199 * @param pEvt The event to fetch the data for.
1200 * @param pszName The field to fetch.
1201 * @param poffData Where to store the offset to the data on success.
1202 * @param pcbEvtData Where to store the size of the size of the event data.
1203 * @param ppEvtItemDesc Where to store the event item descriptor.
1204 */
1205static int rtTraceLogRdrEvtResolveData(PRTTRACELOGRDREVTINT pEvt, const char *pszName, uint32_t *poffData,
1206 size_t *pcbEvtData, PPCRTTRACELOGEVTITEMDESC ppEvtItemDesc)
1207{
1208 PCRTTRACELOGRDREVTDESC pEvtDesc = pEvt->pEvtDesc;
1209 uint32_t offData = 0;
1210 unsigned idxRawData = 0;
1211
1212 for (unsigned i = 0; i < pEvtDesc->EvtDesc.cEvtItems; i++)
1213 {
1214 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = &pEvtDesc->aEvtItemDesc[i];
1215
1216 if (!RTStrCmp(pszName, pEvtItemDesc->pszName))
1217 {
1218 *poffData = offData;
1219 *pcbEvtData = rtTraceLogRdrEvtItemGetSz(pEvt->pRdr, pEvtItemDesc, pEvt->pacbRawData, &idxRawData);
1220 *ppEvtItemDesc = pEvtItemDesc;
1221 return VINF_SUCCESS;
1222 }
1223
1224 offData += (uint32_t)rtTraceLogRdrEvtItemGetSz(pEvt->pRdr, pEvtItemDesc, pEvt->pacbRawData, &idxRawData);
1225 }
1226
1227 return VERR_NOT_FOUND;
1228}
1229
1230
1231/**
1232 * Fills a value with the given event data.
1233 *
1234 * @returns IPRT status code.
1235 * @param pEvt The event to fetch the data for.
1236 * @param offData Offset the data is located in the event.
1237 * @param cbData Number of bytes for the data.
1238 * @param pEvtItemDesc The event item descriptor.
1239 * @param pVal The value to fill.
1240 */
1241static int rtTraceLogRdrEvtFillVal(PRTTRACELOGRDREVTINT pEvt, uint32_t offData, size_t cbData, PCRTTRACELOGEVTITEMDESC pEvtItemDesc,
1242 PRTTRACELOGEVTVAL pVal)
1243{
1244 PRTTRACELOGRDRINT pThis = pEvt->pRdr;
1245 uint8_t *pbData = &pEvt->abEvtData[offData];
1246
1247 pVal->pItemDesc = pEvtItemDesc;
1248 switch (pEvtItemDesc->enmType)
1249 {
1250 case RTTRACELOGTYPE_BOOL:
1251 pVal->u.f = *(bool *)pbData;
1252 break;
1253 case RTTRACELOGTYPE_UINT8:
1254 pVal->u.u8 = *pbData;
1255 break;
1256 case RTTRACELOGTYPE_INT8:
1257 pVal->u.i8 = *(int8_t *)pbData;
1258 break;
1259 case RTTRACELOGTYPE_UINT16:
1260 {
1261 uint16_t u16Tmp = *(uint16_t *)pbData;
1262 if (pThis->fConvEndianess)
1263 pVal->u.u16 = RT_BSWAP_U16(u16Tmp);
1264 else
1265 pVal->u.u16 = u16Tmp;
1266 break;
1267 }
1268 case RTTRACELOGTYPE_INT16:
1269 {
1270 uint8_t abData[2];
1271 if (pThis->fConvEndianess)
1272 {
1273 abData[0] = pbData[1];
1274 abData[1] = pbData[0];
1275 }
1276 else
1277 {
1278 abData[0] = pbData[0];
1279 abData[1] = pbData[1];
1280 }
1281
1282 pVal->u.i16 = *(int16_t *)&abData[0];
1283 break;
1284 }
1285 case RTTRACELOGTYPE_UINT32:
1286 {
1287 uint32_t u32Tmp = *(uint32_t *)pbData;
1288 if (pThis->fConvEndianess)
1289 pVal->u.u32 = RT_BSWAP_U32(u32Tmp);
1290 else
1291 pVal->u.u32 = u32Tmp;
1292 break;
1293 }
1294 case RTTRACELOGTYPE_INT32:
1295 {
1296 uint8_t abData[4];
1297 if (pThis->fConvEndianess)
1298 {
1299 abData[0] = pbData[3];
1300 abData[1] = pbData[2];
1301 abData[2] = pbData[1];
1302 abData[3] = pbData[0];
1303 }
1304 else
1305 {
1306 abData[0] = pbData[0];
1307 abData[1] = pbData[1];
1308 abData[2] = pbData[2];
1309 abData[3] = pbData[3];
1310 }
1311
1312 pVal->u.i32 = *(int32_t *)&abData[0];
1313 break;
1314 }
1315 case RTTRACELOGTYPE_UINT64:
1316 {
1317 uint64_t u64Tmp = *(uint64_t *)pbData;
1318 if (pThis->fConvEndianess)
1319 pVal->u.u64 = RT_BSWAP_U64(u64Tmp);
1320 else
1321 pVal->u.u64 = u64Tmp;
1322 break;
1323 }
1324 case RTTRACELOGTYPE_INT64:
1325 {
1326 uint8_t abData[8];
1327 if (pThis->fConvEndianess)
1328 {
1329 abData[0] = pbData[7];
1330 abData[1] = pbData[6];
1331 abData[2] = pbData[5];
1332 abData[3] = pbData[4];
1333 abData[4] = pbData[3];
1334 abData[5] = pbData[2];
1335 abData[6] = pbData[1];
1336 abData[7] = pbData[0];
1337 }
1338 else
1339 {
1340 abData[0] = pbData[0];
1341 abData[1] = pbData[1];
1342 abData[2] = pbData[2];
1343 abData[3] = pbData[3];
1344 abData[4] = pbData[4];
1345 abData[5] = pbData[5];
1346 abData[6] = pbData[6];
1347 abData[7] = pbData[7];
1348 }
1349
1350 pVal->u.i32 = *(int64_t *)&abData[0];
1351 break;
1352 }
1353 case RTTRACELOGTYPE_FLOAT32:
1354 {
1355 uint8_t abData[4];
1356 if (pThis->fConvEndianess)
1357 {
1358 abData[0] = pbData[3];
1359 abData[1] = pbData[2];
1360 abData[2] = pbData[1];
1361 abData[3] = pbData[0];
1362 }
1363 else
1364 {
1365 abData[0] = pbData[0];
1366 abData[1] = pbData[1];
1367 abData[2] = pbData[2];
1368 abData[3] = pbData[3];
1369 }
1370
1371 pVal->u.f32 = *(float *)&abData[0];
1372 break;
1373 }
1374 case RTTRACELOGTYPE_FLOAT64:
1375 {
1376 uint8_t abData[8];
1377 if (pThis->fConvEndianess)
1378 {
1379 abData[0] = pbData[7];
1380 abData[1] = pbData[6];
1381 abData[2] = pbData[5];
1382 abData[3] = pbData[4];
1383 abData[4] = pbData[3];
1384 abData[5] = pbData[2];
1385 abData[6] = pbData[1];
1386 abData[7] = pbData[0];
1387 }
1388 else
1389 {
1390 abData[0] = pbData[0];
1391 abData[1] = pbData[1];
1392 abData[2] = pbData[2];
1393 abData[3] = pbData[3];
1394 abData[4] = pbData[4];
1395 abData[5] = pbData[5];
1396 abData[6] = pbData[6];
1397 abData[7] = pbData[7];
1398 }
1399
1400 pVal->u.f64 = *(double *)&abData[0];
1401 break;
1402 }
1403 case RTTRACELOGTYPE_RAWDATA:
1404 pVal->u.RawData.pb = pbData;
1405 if (pEvtItemDesc->cbRawData == 0)
1406 pVal->u.RawData.cb = cbData;
1407 else
1408 pVal->u.RawData.cb = pEvtItemDesc->cbRawData;
1409 break;
1410 case RTTRACELOGTYPE_POINTER:
1411 {
1412 if (pThis->cbTypePtr == 4)
1413 {
1414 if (pThis->fConvEndianess)
1415 pVal->u.uPtr = RT_BSWAP_U32(*(uint32_t *)pbData);
1416 else
1417 pVal->u.uPtr = *(uint32_t *)pbData;
1418 }
1419 else if (pThis->cbTypePtr == 8)
1420 {
1421 if (pThis->fConvEndianess)
1422 pVal->u.uPtr = RT_BSWAP_U64(*(uint64_t *)pbData);
1423 else
1424 pVal->u.uPtr = *(uint64_t *)pbData;
1425 }
1426 else
1427 AssertMsgFailed(("Invalid pointer size %d, should not happen!\n", pThis->cbTypePtr));
1428 break;
1429 }
1430 case RTTRACELOGTYPE_SIZE:
1431 {
1432 if (pThis->cbTypeSize == 4)
1433 {
1434 if (pThis->fConvEndianess)
1435 pVal->u.sz = RT_BSWAP_U32(*(uint32_t *)pbData);
1436 else
1437 pVal->u.sz = *(uint32_t *)pbData;
1438 }
1439 else if (pThis->cbTypeSize == 8)
1440 {
1441 if (pThis->fConvEndianess)
1442 pVal->u.sz = RT_BSWAP_U64(*(uint64_t *)pbData);
1443 else
1444 pVal->u.sz = *(uint64_t *)pbData;
1445 }
1446 else
1447 AssertMsgFailed(("Invalid size_t size %d, should not happen!\n", pThis->cbTypeSize));
1448 break;
1449 }
1450 default:
1451 AssertMsgFailed(("Invalid type given %d\n", pEvtItemDesc->enmType));
1452 }
1453
1454 return VINF_SUCCESS;
1455}
1456
1457
1458RTDECL(int) RTTraceLogRdrCreate(PRTTRACELOGRDR phTraceLogRdr, PFNRTTRACELOGRDRSTREAM pfnStreamIn,
1459 PFNRTTRACELOGSTREAMCLOSE pfnStreamClose, void *pvUser)
1460{
1461 AssertPtrReturn(phTraceLogRdr, VERR_INVALID_POINTER);
1462 AssertPtrReturn(pfnStreamIn, VERR_INVALID_POINTER);
1463 AssertPtrReturn(pfnStreamClose, VERR_INVALID_POINTER);
1464 int rc = VINF_SUCCESS;
1465 PRTTRACELOGRDRINT pThis = (PRTTRACELOGRDRINT)RTMemAllocZ(sizeof(*pThis));
1466 if (pThis)
1467 {
1468 rc = RTSemMutexCreate(&pThis->hMtx);
1469 if (RT_SUCCESS(rc))
1470 {
1471 rc = RTStrCacheCreate(&pThis->hStrCache, "TRACELOGRDR");
1472 if (RT_SUCCESS(rc))
1473 {
1474 RTListInit(&pThis->LstEvts);
1475 pThis->u32Magic = RTTRACELOGRDR_MAGIC;
1476 pThis->pfnStreamIn = pfnStreamIn;
1477 pThis->pfnStreamClose = pfnStreamClose;
1478 pThis->pvUser = pvUser;
1479 pThis->enmState = RTTRACELOGRDRSTATE_RECV_HDR;
1480 pThis->fConvEndianess = false;
1481 pThis->pszDesc = NULL;
1482 pThis->cEvtDescsCur = 0;
1483 pThis->cEvtDescsMax = 0;
1484 pThis->papEvtDescs = NULL;
1485 pThis->pEvtDescCur = NULL;
1486 pThis->u64SeqNoLast = 0;
1487 pThis->cbScratch = sizeof(TRACELOGHDR);
1488 pThis->offScratch = 0;
1489 pThis->cbRecvLeft = sizeof(TRACELOGHDR);
1490 pThis->pbScratch = (uint8_t *)RTMemAllocZ(pThis->cbScratch);
1491 if (RT_LIKELY(pThis->pbScratch))
1492 {
1493 *phTraceLogRdr = pThis;
1494 return VINF_SUCCESS;
1495 }
1496 else
1497 rc = VERR_NO_MEMORY;
1498
1499 RTStrCacheDestroy(pThis->hStrCache);
1500 }
1501
1502 RTSemMutexDestroy(pThis->hMtx);
1503 }
1504 RTMemFree(pThis);
1505 }
1506 else
1507 rc = VERR_NO_MEMORY;
1508
1509 return rc;
1510}
1511
1512
1513RTDECL(int) RTTraceLogRdrCreateFromFile(PRTTRACELOGRDR phTraceLogRdr, const char *pszFilename)
1514{
1515 AssertPtrReturn(phTraceLogRdr, VERR_INVALID_POINTER);
1516 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
1517
1518 RTFILE hFile = NIL_RTFILE;
1519 int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
1520 if (RT_SUCCESS(rc))
1521 {
1522 rc = RTTraceLogRdrCreate(phTraceLogRdr, rtTraceLogRdrFileStream, rtTraceLogRdrFileStreamClose, hFile);
1523 if (RT_FAILURE(rc))
1524 {
1525 RTFileClose(hFile);
1526 RTFileDelete(pszFilename);
1527 }
1528 }
1529
1530 return rc;
1531}
1532
1533
1534RTDECL(int) RTTraceLogRdrDestroy(RTTRACELOGRDR hTraceLogRdr)
1535{
1536 PRTTRACELOGRDRINT pThis = hTraceLogRdr;
1537 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1538
1539 pThis->u32Magic = RTTRACELOGRDR_MAGIC_DEAD;
1540 pThis->pfnStreamClose(pThis->pvUser);
1541 for (unsigned i = 0; i < pThis->cEvtDescsCur; i++)
1542 RTMemFree(pThis->papEvtDescs[i]);
1543 if (pThis->papEvtDescs)
1544 RTMemFree(pThis->papEvtDescs);
1545 RTSemMutexDestroy(pThis->hMtx);
1546 RTMemFree(pThis->pbScratch);
1547 RTStrCacheDestroy(pThis->hStrCache);
1548 RTMemFree(pThis);
1549 return VINF_SUCCESS;
1550}
1551
1552
1553RTDECL(int) RTTraceLogRdrEvtPoll(RTTRACELOGRDR hTraceLogRdr, RTTRACELOGRDRPOLLEVT *penmEvt, RTMSINTERVAL cMsTimeout)
1554{
1555 PRTTRACELOGRDRINT pThis = hTraceLogRdr;
1556 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1557 AssertPtrReturn(penmEvt, VERR_INVALID_POINTER);
1558
1559 int rc = VINF_SUCCESS;
1560 bool fContinue = true;
1561 while ( RT_SUCCESS(rc)
1562 && fContinue)
1563 {
1564 size_t cbRecvd = 0;
1565
1566 rc = rtTraceLogRdrStreamRead(pThis, &pThis->pbScratch[pThis->offScratch],
1567 pThis->cbRecvLeft, &cbRecvd, cMsTimeout);
1568 if (RT_SUCCESS(rc))
1569 {
1570 if (cbRecvd == pThis->cbRecvLeft)
1571 {
1572 /* Act according to the current state. */
1573 rc = g_apfnStateHandlers[pThis->enmState](pThis, penmEvt, &fContinue);
1574 }
1575 else
1576 pThis->cbRecvLeft -= cbRecvd;
1577 }
1578 }
1579
1580 return rc;
1581}
1582
1583
1584RTDECL(int) RTTraceLogRdrQueryLastEvt(RTTRACELOGRDR hTraceLogRdr, PRTTRACELOGRDREVT phRdrEvt)
1585{
1586 PRTTRACELOGRDRINT pThis = hTraceLogRdr;
1587 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1588 AssertPtrReturn(phRdrEvt, VERR_INVALID_POINTER);
1589
1590 int rc = VINF_SUCCESS;
1591 RTSemMutexRequest(pThis->hMtx, RT_INDEFINITE_WAIT);
1592 PRTTRACELOGRDREVTINT pEvt = RTListGetLast(&pThis->LstEvts, RTTRACELOGRDREVTINT, NdGlob);
1593 *phRdrEvt = pEvt;
1594 if (!pEvt)
1595 rc = VERR_NOT_FOUND;
1596 RTSemMutexRelease(pThis->hMtx);
1597
1598 return rc;
1599}
1600
1601
1602RTDECL(int) RTTraceLogRdrQueryIterator(RTTRACELOGRDR hTraceLogRdr, PRTTRACELOGRDRIT phIt)
1603{
1604 PRTTRACELOGRDRINT pThis = hTraceLogRdr;
1605 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1606 AssertPtrReturn(phIt, VERR_INVALID_POINTER);
1607
1608 int rc = VINF_SUCCESS;
1609 PRTTRACELOGRDRITINT pIt = (PRTTRACELOGRDRITINT)RTMemAllocZ(sizeof(*pIt));
1610 if (RT_LIKELY(pIt))
1611 {
1612 pIt->pRdr = pThis;
1613 pIt->pEvt = RTListGetFirst(&pThis->LstEvts, RTTRACELOGRDREVTINT, NdGlob);
1614 }
1615 else
1616 rc = VERR_NO_MEMORY;
1617
1618 return rc;
1619}
1620
1621
1622RTDECL(void) RTTraceLogRdrIteratorFree(RTTRACELOGRDRIT hIt)
1623{
1624 PRTTRACELOGRDRITINT pIt = hIt;
1625 AssertPtrReturnVoid(pIt);
1626
1627 RTMemFree(pIt);
1628}
1629
1630
1631RTDECL(int) RTTraceLogRdrIteratorNext(RTTRACELOGRDRIT hIt)
1632{
1633 PRTTRACELOGRDRITINT pIt = hIt;
1634 AssertPtrReturn(pIt, VERR_INVALID_HANDLE);
1635
1636 if (!pIt->pEvt)
1637 return VERR_TRACELOG_READER_ITERATOR_END;
1638
1639 int rc = VINF_SUCCESS;
1640 PRTTRACELOGRDREVTINT pEvtNext = RTListGetNext(&pIt->pRdr->LstEvts, pIt->pEvt, RTTRACELOGRDREVTINT, NdGlob);
1641
1642 if (pEvtNext)
1643 pIt->pEvt = pEvtNext;
1644 else
1645 rc = VERR_TRACELOG_READER_ITERATOR_END;
1646
1647 return rc;
1648}
1649
1650
1651RTDECL(int) RTTraceLogRdrIteratorQueryEvent(RTTRACELOGRDRIT hIt, PRTTRACELOGRDREVT phRdrEvt)
1652{
1653 PRTTRACELOGRDRITINT pIt = hIt;
1654 AssertPtrReturn(pIt, VERR_INVALID_HANDLE);
1655 AssertPtrReturn(phRdrEvt, VERR_INVALID_POINTER);
1656
1657 *phRdrEvt = pIt->pEvt;
1658 return VINF_SUCCESS;
1659}
1660
1661
1662RTDECL(uint64_t) RTTraceLogRdrEvtGetSeqNo(RTTRACELOGRDREVT hRdrEvt)
1663{
1664 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1665 AssertPtrReturn(pEvt, 0);
1666
1667 return pEvt->u64SeqNo;
1668}
1669
1670
1671RTDECL(uint64_t) RTTraceLogRdrEvtGetTs(RTTRACELOGRDREVT hRdrEvt)
1672{
1673 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1674 AssertPtrReturn(pEvt, 0);
1675
1676 return pEvt->u64Ts;
1677}
1678
1679
1680RTDECL(bool) RTTraceLogRdrEvtIsGrouped(RTTRACELOGRDREVT hRdrEvt)
1681{
1682 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1683 AssertPtrReturn(pEvt, false);
1684
1685 return pEvt->idGrp != 0;
1686}
1687
1688
1689RTDECL(PCRTTRACELOGEVTDESC) RTTraceLogRdrEvtGetDesc(RTTRACELOGRDREVT hRdrEvt)
1690{
1691 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1692 AssertPtrReturn(pEvt, NULL);
1693
1694 return &pEvt->pEvtDesc->EvtDesc;
1695}
1696
1697
1698RTDECL(int) RTTraceLogRdrEvtQueryVal(RTTRACELOGRDREVT hRdrEvt, const char *pszName, PRTTRACELOGEVTVAL pVal)
1699{
1700 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1701 AssertPtrReturn(pEvt, VERR_INVALID_HANDLE);
1702
1703 uint32_t offData = 0;
1704 size_t cbData = 0;
1705 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = NULL;
1706 int rc = rtTraceLogRdrEvtResolveData(pEvt, pszName, &offData, &cbData, &pEvtItemDesc);
1707 if (RT_SUCCESS(rc))
1708 rc = rtTraceLogRdrEvtFillVal(pEvt, offData, cbData, pEvtItemDesc, pVal);
1709 return rc;
1710}
1711
1712
1713RTDECL(int) RTTraceLogRdrEvtFillVals(RTTRACELOGRDREVT hRdrEvt, unsigned idxItemStart, PRTTRACELOGEVTVAL paVals,
1714 unsigned cVals, unsigned *pcVals)
1715{
1716 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1717 AssertPtrReturn(pEvt, VERR_INVALID_HANDLE);
1718
1719 PCRTTRACELOGRDREVTDESC pEvtDesc = pEvt->pEvtDesc;
1720 AssertReturn(idxItemStart < pEvtDesc->EvtDesc.cEvtItems, VERR_INVALID_PARAMETER);
1721
1722 /* Advance to the item the caller wants to fill in. */
1723 uint32_t offData = 0;
1724 unsigned idxRawData = 0;
1725
1726 for (unsigned i = 0; i < idxItemStart; i++)
1727 {
1728 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = &pEvtDesc->aEvtItemDesc[i];
1729 offData += (uint32_t)rtTraceLogRdrEvtItemGetSz(pEvt->pRdr, pEvtItemDesc, pEvt->pacbRawData, &idxRawData);
1730 }
1731
1732 int rc = VINF_SUCCESS;
1733 unsigned idxItemEnd = RT_MIN(idxItemStart + cVals, pEvtDesc->EvtDesc.cEvtItems);
1734 for (unsigned i = idxItemStart; i < idxItemEnd && RT_SUCCESS(rc); i++)
1735 {
1736 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = &pEvtDesc->aEvtItemDesc[i];
1737 size_t cbData = rtTraceLogRdrEvtItemGetSz(pEvt->pRdr, pEvtItemDesc, pEvt->pacbRawData, &idxRawData);
1738
1739 rc = rtTraceLogRdrEvtFillVal(pEvt, offData, cbData, pEvtItemDesc, &paVals[i - idxItemStart]);
1740 offData += (uint32_t)cbData;
1741 }
1742
1743 *pcVals = idxItemEnd - idxItemStart;
1744
1745 return rc;
1746}
1747
Note: See TracBrowser for help on using the repository browser.

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