VirtualBox

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

Last change on this file since 106580 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

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