VirtualBox

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

Last change on this file since 96563 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 67.2 KB
Line 
1/* $Id: tracelogreader.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * IPRT - Trace log reader.
4 */
5
6/*
7 * Copyright (C) 2018-2022 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 * @returns nothing.
308 * @param pHdr The trace log header to convert.
309 */
310static void rtTraceLogRdrHdrEndianessConv(PTRACELOGHDR pHdr)
311{
312 pHdr->u32Endianess = RT_BSWAP_U32(pHdr->u32Endianess);
313 pHdr->u32Version = RT_BSWAP_U32(pHdr->u32Version);
314 pHdr->fFlags = RT_BSWAP_U32(pHdr->fFlags);
315 pHdr->cbStrDesc = RT_BSWAP_U32(pHdr->cbStrDesc);
316 pHdr->u64TsStart = RT_BSWAP_U64(pHdr->u64TsStart);
317}
318
319
320/**
321 * Converts the event descriptor endianess to the host endianess.
322 *
323 * @returns nothing.
324 * @param pEvtDesc The trace log event descriptor to convert.
325 */
326static void rtTraceLogRdrEvtDescEndianessConv(PTRACELOGEVTDESC pEvtDesc)
327{
328 pEvtDesc->u32Id = RT_BSWAP_U32(pEvtDesc->u32Id);
329 pEvtDesc->u32Severity = RT_BSWAP_U32(pEvtDesc->u32Severity);
330 pEvtDesc->cbStrId = RT_BSWAP_U32(pEvtDesc->cbStrId);
331 pEvtDesc->cbStrDesc = RT_BSWAP_U32(pEvtDesc->cbStrDesc);
332 pEvtDesc->cEvtItems = RT_BSWAP_U32(pEvtDesc->cEvtItems);
333}
334
335
336/**
337 * Converts the event item descriptor endianess to host endianess.
338 *
339 * @returns nothing.
340 * @param pEvtItemDesc The trace log event item descriptor to convert.
341 */
342static void rtTraceLogRdrEvtItemDescEndianessConv(PTRACELOGEVTITEMDESC pEvtItemDesc)
343{
344 pEvtItemDesc->cbStrName = RT_BSWAP_U32(pEvtItemDesc->cbStrName);
345 pEvtItemDesc->cbStrDesc = RT_BSWAP_U32(pEvtItemDesc->cbStrDesc);
346 pEvtItemDesc->u32Type = RT_BSWAP_U32(pEvtItemDesc->u32Type);
347 pEvtItemDesc->cbRawData = RT_BSWAP_U32(pEvtItemDesc->cbRawData);
348}
349
350
351/**
352 * Converts the event marker endianess to host endianess.
353 *
354 * @returns nothing.
355 * @param pEvt The trace log event marker to convert.
356 */
357static void rtTraceLogRdrEvtEndianessConv(PTRACELOGEVT pEvt)
358{
359 pEvt->u64SeqNo = RT_BSWAP_U64(pEvt->u64SeqNo);
360 pEvt->u64Ts = RT_BSWAP_U64(pEvt->u64Ts);
361 pEvt->u64EvtGrpId = RT_BSWAP_U64(pEvt->u64EvtGrpId);
362 pEvt->u64EvtParentGrpId = RT_BSWAP_U64(pEvt->u64EvtParentGrpId);
363 pEvt->fFlags = RT_BSWAP_U32(pEvt->fFlags);
364 pEvt->u32EvtDescId = RT_BSWAP_U32(pEvt->u32EvtDescId);
365 pEvt->cbEvtData = RT_BSWAP_U32(pEvt->cbEvtData);
366 pEvt->cRawEvtDataSz = RT_BSWAP_U32(pEvt->cRawEvtDataSz);
367}
368
369
370/**
371 * Converts severity field from stream to API value.
372 *
373 * @returns API severity enum, RTTRACELOGEVTSEVERITY_INVALID if the supplied stream value
374 * is invalid.
375 * @param u32Severity The severity value from the stream.
376 */
377static RTTRACELOGEVTSEVERITY rtTraceLogRdrConvSeverity(uint32_t u32Severity)
378{
379 RTTRACELOGEVTSEVERITY enmSeverity = RTTRACELOGEVTSEVERITY_INVALID;
380
381 switch (u32Severity)
382 {
383 case TRACELOG_EVTDESC_SEVERITY_INFO:
384 enmSeverity = RTTRACELOGEVTSEVERITY_INFO;
385 break;
386 case TRACELOG_EVTDESC_SEVERITY_WARNING:
387 enmSeverity = RTTRACELOGEVTSEVERITY_WARNING;
388 break;
389 case TRACELOG_EVTDESC_SEVERITY_ERROR:
390 enmSeverity = RTTRACELOGEVTSEVERITY_ERROR;
391 break;
392 case TRACELOG_EVTDESC_SEVERITY_FATAL:
393 enmSeverity = RTTRACELOGEVTSEVERITY_FATAL;
394 break;
395 case TRACELOG_EVTDESC_SEVERITY_DEBUG:
396 enmSeverity = RTTRACELOGEVTSEVERITY_DEBUG;
397 break;
398 default:
399 enmSeverity = RTTRACELOGEVTSEVERITY_INVALID;
400 }
401
402 return enmSeverity;
403}
404
405
406/**
407 * Converts type field from stream to API value.
408 *
409 * @returns API type enum, RTTRACELOGTYPE_INVALID if the supplied stream value
410 * is invalid.
411 * @param u32Type The type value from the stream.
412 */
413static RTTRACELOGTYPE rtTraceLogRdrConvType(uint32_t u32Type)
414{
415 RTTRACELOGTYPE enmType = RTTRACELOGTYPE_INVALID;
416
417 switch (u32Type)
418 {
419 case TRACELOG_EVTITEMDESC_TYPE_BOOL:
420 enmType = RTTRACELOGTYPE_BOOL;
421 break;
422 case TRACELOG_EVTITEMDESC_TYPE_UINT8:
423 enmType = RTTRACELOGTYPE_UINT8;
424 break;
425 case TRACELOG_EVTITEMDESC_TYPE_INT8:
426 enmType = RTTRACELOGTYPE_INT8;
427 break;
428 case TRACELOG_EVTITEMDESC_TYPE_UINT16:
429 enmType = RTTRACELOGTYPE_UINT16;
430 break;
431 case TRACELOG_EVTITEMDESC_TYPE_INT16:
432 enmType = RTTRACELOGTYPE_INT16;
433 break;
434 case TRACELOG_EVTITEMDESC_TYPE_UINT32:
435 enmType = RTTRACELOGTYPE_UINT32;
436 break;
437 case TRACELOG_EVTITEMDESC_TYPE_INT32:
438 enmType = RTTRACELOGTYPE_INT32;
439 break;
440 case TRACELOG_EVTITEMDESC_TYPE_UINT64:
441 enmType = RTTRACELOGTYPE_UINT64;
442 break;
443 case TRACELOG_EVTITEMDESC_TYPE_INT64:
444 enmType = RTTRACELOGTYPE_INT64;
445 break;
446 case TRACELOG_EVTITEMDESC_TYPE_FLOAT32:
447 enmType = RTTRACELOGTYPE_FLOAT32;
448 break;
449 case TRACELOG_EVTITEMDESC_TYPE_FLOAT64:
450 enmType = RTTRACELOGTYPE_FLOAT64;
451 break;
452 case TRACELOG_EVTITEMDESC_TYPE_RAWDATA:
453 enmType = RTTRACELOGTYPE_RAWDATA;
454 break;
455 case TRACELOG_EVTITEMDESC_TYPE_POINTER:
456 enmType = RTTRACELOGTYPE_POINTER;
457 break;
458 case TRACELOG_EVTITEMDESC_TYPE_SIZE:
459 enmType = RTTRACELOGTYPE_SIZE;
460 break;
461 default:
462 enmType = RTTRACELOGTYPE_INVALID;
463 }
464
465 return enmType;
466}
467
468
469/**
470 * Converts the type enum to the size of the the event item data in bytes.
471 *
472 * @returns Event item data size in bytes.
473 * @param pThis The trace log reader instance.
474 * @param pEvtItemDesc The event item descriptor.
475 */
476static size_t rtTraceLogRdrGetEvtItemDataSz(PRTTRACELOGRDRINT pThis, PCRTTRACELOGEVTITEMDESC pEvtItemDesc)
477{
478 size_t cb = 0;
479
480 switch (pEvtItemDesc->enmType)
481 {
482 case RTTRACELOGTYPE_BOOL:
483 case RTTRACELOGTYPE_UINT8:
484 case RTTRACELOGTYPE_INT8:
485 {
486 cb = 1;
487 break;
488 }
489 case RTTRACELOGTYPE_UINT16:
490 case RTTRACELOGTYPE_INT16:
491 {
492 cb = 2;
493 break;
494 }
495 case RTTRACELOGTYPE_UINT32:
496 case RTTRACELOGTYPE_INT32:
497 case RTTRACELOGTYPE_FLOAT32:
498 {
499 cb = 4;
500 break;
501 }
502 case RTTRACELOGTYPE_UINT64:
503 case RTTRACELOGTYPE_INT64:
504 case RTTRACELOGTYPE_FLOAT64:
505 {
506 cb = 8;
507 break;
508 }
509 case RTTRACELOGTYPE_RAWDATA:
510 {
511 cb = pEvtItemDesc->cbRawData;
512 break;
513 }
514 case RTTRACELOGTYPE_POINTER:
515 {
516 cb = pThis->cbTypePtr;
517 break;
518 }
519 case RTTRACELOGTYPE_SIZE:
520 {
521 cb = pThis->cbTypeSize;
522 break;
523 }
524 default:
525 AssertMsgFailed(("Invalid type %d\n", pEvtItemDesc->enmType));
526 }
527
528 return cb;
529}
530
531
532/**
533 * Calculates the overall event data size from the items in the event descriptor.
534 *
535 * @returns nothing.
536 * @param pThis The trace log reader instance.
537 * @param pEvtDesc The event descriptor.
538 */
539static void rtTraceLogRdrEvtCalcEvtDataSz(PRTTRACELOGRDRINT pThis, PRTTRACELOGRDREVTDESC pEvtDesc)
540{
541 pEvtDesc->cbEvtData = 0;
542 pEvtDesc->cRawDataNonStatic = 0;
543
544 for (unsigned i = 0; i < pEvtDesc->EvtDesc.cEvtItems; i++)
545 {
546 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = &pEvtDesc->aEvtItemDesc[i];
547
548 pEvtDesc->cbEvtData += rtTraceLogRdrGetEvtItemDataSz(pThis, pEvtItemDesc);
549 if ( pEvtItemDesc->enmType == RTTRACELOGTYPE_RAWDATA
550 && pEvtItemDesc->cbRawData == 0)
551 pEvtDesc->cRawDataNonStatic++;
552 }
553}
554
555
556/**
557 * Ensures that the scratch buffer can hold at least the given amount of data.
558 *
559 * @returns IPRT status code.
560 * @param pThis The trace log reader instance.
561 * @param cbScratch New size of the scratch buffer in bytes.
562 */
563static int rtTraceLogRdrScratchEnsureSz(PRTTRACELOGRDRINT pThis, size_t cbScratch)
564{
565 int rc = VINF_SUCCESS;
566
567 if (pThis->cbScratch < cbScratch)
568 {
569 cbScratch = RT_ALIGN_Z(cbScratch, 64);
570 uint8_t *pbScratchNew = (uint8_t *)RTMemRealloc(pThis->pbScratch, cbScratch);
571 if (RT_LIKELY(pbScratchNew))
572 {
573 pThis->cbScratch = cbScratch;
574 pThis->pbScratch = pbScratchNew;
575 }
576 else
577 rc = VERR_NO_MEMORY;
578 }
579
580 return rc;
581}
582
583
584/**
585 * Advances to the next state resetting the scratch/receive buffers to the given state.
586 *
587 * @returns IPRT status.
588 * @param pThis The trace log reader instance.
589 * @param enmState The next state.
590 * @param cbRecv How much to receive before processing the new data.
591 * @param offScratch Offset to set the receive buffer to (used
592 * when the magic was received which should still be saved).
593 */
594static int rtTraceLogRdrStateAdvanceEx(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRSTATE enmState, size_t cbRecv,
595 uint32_t offScratch)
596{
597 Assert(cbRecv >= offScratch);
598
599 pThis->enmState = enmState;
600 pThis->cbRecvLeft = cbRecv - offScratch;
601 pThis->offScratch = offScratch;
602 int rc = rtTraceLogRdrScratchEnsureSz(pThis, cbRecv);
603
604 /* Zero out scratch buffer (don't care whether growing it failed, the old buffer is still there). */
605 memset(pThis->pbScratch + offScratch, 0, pThis->cbScratch - offScratch);
606
607 return rc;
608}
609
610
611/**
612 * Advances to the next state resetting the scratch/receive buffers.
613 *
614 * @returns IPRT status.
615 * @param pThis The trace log reader instance.
616 * @param enmState The next state.
617 * @param cbRecv How much to receive before processing the new data.
618 */
619static int rtTraceLogRdrStateAdvance(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRSTATE enmState, size_t cbRecv)
620{
621 return rtTraceLogRdrStateAdvanceEx(pThis, enmState, cbRecv, 0);
622}
623
624
625/**
626 * Marks a received event descriptor as completed and adds it to the array of known descriptors.
627 *
628 * @returns IPRT status code.
629 * @param pThis The trace log reader instance.
630 * @param pEvtDesc The event descriptor which completed.
631 */
632static int rtTraceLogRdrEvtDescComplete(PRTTRACELOGRDRINT pThis, PRTTRACELOGRDREVTDESC pEvtDesc)
633{
634 int rc = VINF_SUCCESS;
635
636 rtTraceLogRdrEvtCalcEvtDataSz(pThis, pEvtDesc);
637 /* Insert into array of known event descriptors. */
638 if (pThis->cEvtDescsCur == pThis->cEvtDescsMax)
639 {
640 uint32_t cEvtDescsNew = pThis->cEvtDescsMax + 10;
641 size_t cbNew = cEvtDescsNew * sizeof(PRTTRACELOGRDREVTDESC *);
642 PRTTRACELOGRDREVTDESC *papEvtDescsNew = (PRTTRACELOGRDREVTDESC *)RTMemRealloc(pThis->papEvtDescs, cbNew);
643 if (RT_LIKELY(papEvtDescsNew))
644 {
645 pThis->papEvtDescs = papEvtDescsNew;
646 pThis->cEvtDescsMax = cEvtDescsNew;
647 }
648 else
649 rc = VERR_NO_MEMORY;
650 }
651
652 if (RT_SUCCESS(rc))
653 {
654 pThis->papEvtDescs[pThis->cEvtDescsCur++] = pEvtDesc;
655 pThis->pEvtDescCur = NULL;
656 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_MAGIC, TRACELOG_MAGIC_SZ);
657 }
658
659 return rc;
660}
661
662
663/**
664 * Decides which state to enter next after one event item descriptor was completed successfully.
665 *
666 * @returns IPRT status code.
667 * @param pThis The trace log reader instance.
668 * @param penmEvt Where to store the event indicator if a user visible event happened.
669 * @param pfContinuePoll Where to store the flag whether to continue polling.
670 */
671static int rtTraceLogRdrEvtItemDescComplete(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
672 bool *pfContinuePoll)
673{
674 RT_NOREF(penmEvt, pfContinuePoll);
675
676 int rc = VINF_SUCCESS;
677 PRTTRACELOGRDREVTDESC pEvtDesc = pThis->pEvtDescCur;
678 pEvtDesc->idxEvtItemCur++;
679
680 /* If this event descriptor is complete add it to the array of known descriptors. */
681 if (pEvtDesc->idxEvtItemCur == pEvtDesc->EvtDesc.cEvtItems)
682 rc = rtTraceLogRdrEvtDescComplete(pThis, pEvtDesc);
683 else
684 {
685 /* Not done yet. */
686 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC, sizeof(TRACELOGEVTITEMDESC));
687 }
688
689 return rc;
690}
691
692
693/**
694 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received header.}
695 */
696static DECLCALLBACK(int) rtTraceLogRdrHdrRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
697 bool *pfContinuePoll)
698{
699 RT_NOREF(penmEvt, pfContinuePoll);
700 int rc = VINF_SUCCESS;
701 PTRACELOGHDR pHdr = (PTRACELOGHDR)pThis->pbScratch;
702
703 /* Verify magic. */
704 if (!memcmp(&pHdr->szMagic[0], TRACELOG_HDR_MAGIC, sizeof(pHdr->szMagic)))
705 {
706 /* Check endianess. */
707 if (pHdr->u32Endianess == TRACELOG_HDR_ENDIANESS)
708 pThis->fConvEndianess = false;
709 else if (RT_BSWAP_U32(pHdr->u32Endianess) == TRACELOG_HDR_ENDIANESS)
710 {
711 pThis->fConvEndianess = true;
712 rtTraceLogRdrHdrEndianessConv(pHdr);
713 }
714 else
715 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
716
717 if (RT_SUCCESS(rc))
718 {
719 Assert(pHdr->u32Endianess == TRACELOG_HDR_ENDIANESS);
720
721 /* Enforce strict limits to avoid exhausting memory. */
722 if ( pHdr->u32Version == TRACELOG_VERSION
723 && pHdr->cbStrDesc < _1K
724 && pHdr->cbTypePtr <= 8
725 && (pHdr->cbTypeSize == 8 || pHdr->cbTypeSize == 4))
726 {
727 pThis->u64TsStart = pHdr->u64TsStart;
728 pThis->cbTypePtr = pHdr->cbTypePtr;
729 pThis->cbTypeSize = pHdr->cbTypeSize;
730 pThis->cchDesc = pHdr->cbStrDesc;
731 pThis->cEvtDescsMax = 10;
732
733 /* Allocate array to hold event descriptors later on. */
734 pThis->papEvtDescs = (PRTTRACELOGRDREVTDESC *)RTMemAllocZ(pThis->cEvtDescsMax * sizeof(PRTTRACELOGRDREVTDESC));
735 if (RT_LIKELY(pThis->papEvtDescs))
736 {
737 /* Switch to the next state. */
738 if (pHdr->cbStrDesc)
739 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_HDR_DESC, pHdr->cbStrDesc);
740 else
741 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_MAGIC, TRACELOG_MAGIC_SZ);
742
743 if (RT_SUCCESS(rc))
744 {
745 *penmEvt = RTTRACELOGRDRPOLLEVT_HDR_RECVD;
746 *pfContinuePoll = false;
747 }
748 }
749 else
750 rc = VERR_NO_MEMORY;
751 }
752 else
753 rc = VERR_TRACELOG_READER_LOG_UNSUPPORTED;
754 }
755 }
756 else
757 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
758
759 return rc;
760}
761
762
763/**
764 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received log description.}
765 */
766static DECLCALLBACK(int) rtTraceLogRdrHdrDescRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
767 bool *pfContinuePoll)
768{
769 RT_NOREF(penmEvt, pfContinuePoll);
770 int rc = VINF_SUCCESS;
771 char *pszDesc = (char *)pThis->pbScratch;
772
773 RTStrPurgeEncoding(pszDesc);
774 pThis->pszDesc = RTStrCacheEnterN(pThis->hStrCache, pszDesc, pThis->cchDesc);
775 if (pThis->pszDesc)
776 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_MAGIC, TRACELOG_MAGIC_SZ);
777 else
778 rc = VERR_NO_STR_MEMORY;
779 return rc;
780}
781
782
783/**
784 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received magic.}
785 */
786static DECLCALLBACK(int) rtTraceLogRdrMagicRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
787 bool *pfContinuePoll)
788{
789 RT_NOREF(penmEvt, pfContinuePoll);
790 int rc = VINF_SUCCESS;
791 char *pszMagic = (char *)pThis->pbScratch;
792
793 if (!memcmp(pszMagic, TRACELOG_EVTDESC_MAGIC, TRACELOG_MAGIC_SZ))
794 rc = rtTraceLogRdrStateAdvanceEx(pThis, RTTRACELOGRDRSTATE_RECV_EVT_DESC,
795 sizeof(TRACELOGEVTDESC), TRACELOG_MAGIC_SZ);
796 else if (!memcmp(pszMagic, TRACELOG_EVT_MAGIC, TRACELOG_MAGIC_SZ))
797 rc = rtTraceLogRdrStateAdvanceEx(pThis, RTTRACELOGRDRSTATE_RECV_EVT_MARKER,
798 sizeof(TRACELOGEVT), TRACELOG_MAGIC_SZ);
799
800 return rc;
801}
802
803
804/**
805 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event descriptor.}
806 */
807static DECLCALLBACK(int) rtTraceLogRdrEvtDescRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
808 bool *pfContinuePoll)
809{
810 RT_NOREF(penmEvt, pfContinuePoll);
811 int rc = VINF_SUCCESS;
812 PTRACELOGEVTDESC pEvtDesc = (PTRACELOGEVTDESC)pThis->pbScratch;
813 if (pThis->fConvEndianess)
814 rtTraceLogRdrEvtDescEndianessConv(pEvtDesc);
815
816 if ( !memcmp(&pEvtDesc->szMagic[0], TRACELOG_EVTDESC_MAGIC, sizeof(pEvtDesc->szMagic))
817 && pEvtDesc->u32Id == pThis->cEvtDescsCur
818 && (pEvtDesc->cbStrId >= 1 && pEvtDesc->cbStrId < 128)
819 && pEvtDesc->cbStrDesc < _1K
820 && pEvtDesc->cEvtItems < 128)
821 {
822 RTTRACELOGEVTSEVERITY enmSeverity = rtTraceLogRdrConvSeverity(pEvtDesc->u32Severity);
823 if (RT_LIKELY(enmSeverity != RTTRACELOGEVTSEVERITY_INVALID))
824 {
825 /* Allocate new internal event descriptor state. */
826 size_t cbEvtDesc = RT_UOFFSETOF_DYN(RTTRACELOGRDREVTDESC, aEvtItemDesc[pEvtDesc->cEvtItems]);
827 PRTTRACELOGRDREVTDESC pEvtDescInt = (PRTTRACELOGRDREVTDESC)RTMemAllocZ(cbEvtDesc);
828 if (RT_LIKELY(pEvtDescInt))
829 {
830 pEvtDescInt->cbStrId = pEvtDesc->cbStrId;
831 pEvtDescInt->cbStrDesc = pEvtDesc->cbStrDesc;
832 pEvtDescInt->EvtDesc.enmSeverity = enmSeverity;
833 pEvtDescInt->EvtDesc.cEvtItems = pEvtDesc->cEvtItems;
834 pEvtDescInt->EvtDesc.paEvtItemDesc = &pEvtDescInt->aEvtItemDesc[0];
835
836 pThis->pEvtDescCur = pEvtDescInt;
837 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_DESC_ID, pEvtDescInt->cbStrId);
838 }
839 else
840 rc = VERR_NO_MEMORY;
841 }
842 else
843 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
844 }
845 else
846 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
847
848 return rc;
849}
850
851
852/**
853 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event descriptor ID.}
854 */
855static DECLCALLBACK(int) rtTraceLogRdrEvtDescIdRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
856 bool *pfContinuePoll)
857{
858 RT_NOREF(penmEvt, pfContinuePoll);
859
860 int rc = VINF_SUCCESS;
861 pThis->pEvtDescCur->EvtDesc.pszId = RTStrCacheEnterN(pThis->hStrCache, (const char *)pThis->pbScratch,
862 pThis->pEvtDescCur->cbStrId);
863 if (RT_LIKELY(pThis->pEvtDescCur->EvtDesc.pszId))
864 {
865 if (pThis->pEvtDescCur->cbStrDesc)
866 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_DESC_DESC, pThis->pEvtDescCur->cbStrDesc);
867 else if (pThis->pEvtDescCur->EvtDesc.cEvtItems > 0)
868 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC, sizeof(TRACELOGEVTITEMDESC));
869 else
870 rc = rtTraceLogRdrEvtDescComplete(pThis, pThis->pEvtDescCur);
871 }
872 else
873 rc = VERR_NO_STR_MEMORY;
874
875 return rc;
876}
877
878
879/**
880 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event descriptor description.}
881 */
882static DECLCALLBACK(int) rtTraceLogRdrEvtDescDescriptionRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
883 bool *pfContinuePoll)
884{
885 RT_NOREF(penmEvt, pfContinuePoll);
886 int rc = VINF_SUCCESS;
887 pThis->pEvtDescCur->EvtDesc.pszDesc = RTStrCacheEnterN(pThis->hStrCache, (const char *)pThis->pbScratch,
888 pThis->pEvtDescCur->cbStrDesc);
889 if (RT_LIKELY(pThis->pEvtDescCur->EvtDesc.pszDesc))
890 {
891 if (pThis->pEvtDescCur->EvtDesc.cEvtItems > 0)
892 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC, sizeof(TRACELOGEVTITEMDESC));
893 else
894 rc = rtTraceLogRdrEvtDescComplete(pThis, pThis->pEvtDescCur);
895 }
896 else
897 rc = VERR_NO_STR_MEMORY;
898
899 return rc;
900}
901
902
903/**
904 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event item descriptor.}
905 */
906static DECLCALLBACK(int) rtTraceLogRdrEvtItemDescRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
907 bool *pfContinuePoll)
908{
909 RT_NOREF(penmEvt, pfContinuePoll);
910 int rc = VINF_SUCCESS;
911 PTRACELOGEVTITEMDESC pEvtItemDesc = (PTRACELOGEVTITEMDESC)pThis->pbScratch;
912 if (pThis->fConvEndianess)
913 rtTraceLogRdrEvtItemDescEndianessConv(pEvtItemDesc);
914
915 if ( !memcmp(&pEvtItemDesc->szMagic[0], TRACELOG_EVTITEMDESC_MAGIC, sizeof(pEvtItemDesc->szMagic))
916 && (pEvtItemDesc->cbStrName >= 1 && pEvtItemDesc->cbStrName < 128)
917 && pEvtItemDesc->cbStrDesc < _1K
918 && pEvtItemDesc->cbRawData < _1M)
919 {
920 RTTRACELOGTYPE enmType = rtTraceLogRdrConvType(pEvtItemDesc->u32Type);
921 if (RT_LIKELY(enmType != RTTRACELOGTYPE_INVALID))
922 {
923 PRTTRACELOGEVTITEMDESC pEvtDesc = &pThis->pEvtDescCur->aEvtItemDesc[pThis->pEvtDescCur->idxEvtItemCur];
924
925 pThis->pEvtDescCur->cbStrItemName = pEvtItemDesc->cbStrName;
926 pThis->pEvtDescCur->cbStrItemDesc = pEvtItemDesc->cbStrDesc;
927
928 pEvtDesc->enmType = enmType;
929 pEvtDesc->cbRawData = pEvtItemDesc->cbRawData;
930 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC_NAME, pEvtItemDesc->cbStrName);
931 }
932 else
933 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
934 }
935 else
936 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
937
938 return rc;
939}
940
941
942/**
943 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event item descriptor name.}
944 */
945static DECLCALLBACK(int) rtTraceLogRdrEvtItemDescNameRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
946 bool *pfContinuePoll)
947{
948 int rc = VINF_SUCCESS;
949 PRTTRACELOGEVTITEMDESC pEvtDesc = &pThis->pEvtDescCur->aEvtItemDesc[pThis->pEvtDescCur->idxEvtItemCur];
950 pEvtDesc->pszName = RTStrCacheEnterN(pThis->hStrCache, (const char *)pThis->pbScratch, pThis->pEvtDescCur->cbStrItemName);
951 if (RT_LIKELY(pEvtDesc->pszName))
952 {
953 if (pThis->pEvtDescCur->cbStrItemDesc)
954 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_ITEM_DESC_DESC, pThis->pEvtDescCur->cbStrItemDesc);
955 else
956 rc = rtTraceLogRdrEvtItemDescComplete(pThis, penmEvt, pfContinuePoll);
957 }
958 else
959 rc = VERR_NO_STR_MEMORY;
960
961 return rc;
962}
963
964
965/**
966 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event item description.}
967 */
968static DECLCALLBACK(int) rtTraceLogRdrEvtItemDescDescriptionRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
969 bool *pfContinuePoll)
970{
971 int rc = VINF_SUCCESS;
972 PRTTRACELOGEVTITEMDESC pEvtDesc = &pThis->pEvtDescCur->aEvtItemDesc[pThis->pEvtDescCur->idxEvtItemCur];
973 pEvtDesc->pszDesc = RTStrCacheEnterN(pThis->hStrCache, (const char *)pThis->pbScratch, pThis->pEvtDescCur->cbStrItemDesc);
974 if (RT_LIKELY(pEvtDesc->pszDesc))
975 rc = rtTraceLogRdrEvtItemDescComplete(pThis, penmEvt, pfContinuePoll);
976 else
977 rc = VERR_NO_STR_MEMORY;
978
979 return rc;
980}
981
982
983/**
984 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles a received event marker.}
985 */
986static DECLCALLBACK(int) rtTraceLogRdrEvtMarkerRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
987 bool *pfContinuePoll)
988{
989 int rc = VINF_SUCCESS;
990 PTRACELOGEVT pEvtStrm = (PTRACELOGEVT)pThis->pbScratch;
991 if (pThis->fConvEndianess)
992 rtTraceLogRdrEvtEndianessConv(pEvtStrm);
993
994 if ( (pEvtStrm->u64SeqNo == pThis->u64SeqNoLast + 1)
995 && !(pEvtStrm->fFlags & ~TRACELOG_EVT_F_VALID)
996 && pEvtStrm->u32EvtDescId < pThis->cEvtDescsCur)
997 {
998 PRTTRACELOGRDREVTDESC pEvtDesc = pThis->papEvtDescs[pEvtStrm->u32EvtDescId];
999 if ( ( !pEvtDesc->cRawDataNonStatic
1000 && pEvtStrm->cbEvtData == pEvtDesc->cbEvtData)
1001 || ( pEvtDesc->cRawDataNonStatic
1002 && pEvtStrm->cbEvtData >= pEvtDesc->cbEvtData
1003 && pEvtStrm->cRawEvtDataSz == pEvtDesc->cRawDataNonStatic))
1004 {
1005 size_t cbEvt = RT_UOFFSETOF_DYN(RTTRACELOGRDREVTINT, abEvtData[pEvtStrm->cbEvtData]);
1006 cbEvt += pEvtDesc->cRawDataNonStatic * sizeof(size_t);
1007 PRTTRACELOGRDREVTINT pEvt = (PRTTRACELOGRDREVTINT)RTMemAllocZ(cbEvt);
1008 if (RT_LIKELY(pEvt))
1009 {
1010 pEvt->pRdr = pThis;
1011 pEvt->u64SeqNo = pEvtStrm->u64SeqNo;
1012 pEvt->u64Ts = pEvtStrm->u64Ts;
1013 pEvt->pEvtDesc = pEvtDesc;
1014 pEvt->cbEvtData = pEvtStrm->cbEvtData;
1015 pEvt->pacbRawData = pEvtDesc->cRawDataNonStatic ? (size_t *)&pEvt->abEvtData[pEvtStrm->cbEvtData] : NULL;
1016 /** @todo Group handling and parenting. */
1017
1018 size_t cbEvtDataRecv = pEvtStrm->cRawEvtDataSz * pThis->cbTypeSize + pEvtStrm->cbEvtData;
1019 if (cbEvtDataRecv)
1020 {
1021 pThis->pEvtCur = pEvt;
1022 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_EVT_DATA, cbEvtDataRecv);
1023 }
1024 else
1025 {
1026 pThis->pEvtCur = NULL;
1027 RTSemMutexRequest(pThis->hMtx, RT_INDEFINITE_WAIT);
1028 pThis->u64SeqNoLast = pEvt->u64SeqNo;
1029 RTListAppend(&pThis->LstEvts, &pEvt->NdGlob);
1030 RTSemMutexRelease(pThis->hMtx);
1031 *penmEvt = RTTRACELOGRDRPOLLEVT_TRACE_EVENT_RECVD;
1032 *pfContinuePoll = false;
1033 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_MAGIC, TRACELOG_MAGIC_SZ);
1034 }
1035 }
1036 else
1037 rc = VERR_NO_MEMORY;
1038 }
1039 else
1040 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
1041 }
1042 else
1043 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
1044
1045 return rc;
1046}
1047
1048
1049/**
1050 * @callback_method_impl{FNRTTRACELOGRDRSTATEHANDLER, Handles received event data.}
1051 */
1052static DECLCALLBACK(int) rtTraceLogRdrEvtDataRecvd(PRTTRACELOGRDRINT pThis, RTTRACELOGRDRPOLLEVT *penmEvt,
1053 bool *pfContinuePoll)
1054{
1055 RT_NOREF(penmEvt, pfContinuePoll);
1056
1057 int rc = VINF_SUCCESS;
1058 PRTTRACELOGRDREVTINT pEvt = pThis->pEvtCur;
1059 PCRTTRACELOGRDREVTDESC pEvtDesc = pEvt->pEvtDesc;
1060 uint8_t *pbData = pThis->pbScratch;
1061 size_t cbRawDataNonStatic = 0;
1062
1063 /* Retrieve any raw data size indicators first. */
1064 for (unsigned i = 0; i < pEvtDesc->cRawDataNonStatic; i++)
1065 {
1066 size_t cb = 0;
1067 if (pThis->cbTypeSize == 4)
1068 {
1069 if (pThis->fConvEndianess)
1070 cb = RT_BSWAP_U32(*(uint32_t *)pbData);
1071 else
1072 cb = *(uint32_t *)pbData;
1073 pbData += 4;
1074 }
1075 else if (pThis->cbTypeSize == 8)
1076 {
1077 if (pThis->fConvEndianess)
1078 cb = RT_BSWAP_U64(*(uint64_t *)pbData);
1079 else
1080 cb = *(uint64_t *)pbData;
1081 pbData += 8;
1082 }
1083 else
1084 AssertMsgFailed(("Invalid size_t size %u\n", pThis->cbTypeSize));
1085
1086 pEvt->pacbRawData[i] = cb;
1087 cbRawDataNonStatic += cb;
1088 }
1089
1090 /* Verify that sizes add up. */
1091 if (pEvt->cbEvtData == pEvtDesc->cbEvtData + cbRawDataNonStatic)
1092 {
1093 /* Copy the data over. */
1094 memcpy(&pEvt->abEvtData[0], pbData, pEvt->cbEvtData);
1095
1096 /* Done add event to global list and generate event. */
1097 pThis->pEvtCur = NULL;
1098 RTSemMutexRequest(pThis->hMtx, RT_INDEFINITE_WAIT);
1099 pThis->u64SeqNoLast = pEvt->u64SeqNo;
1100 RTListAppend(&pThis->LstEvts, &pEvt->NdGlob);
1101 RTSemMutexRelease(pThis->hMtx);
1102 *penmEvt = RTTRACELOGRDRPOLLEVT_TRACE_EVENT_RECVD;
1103 *pfContinuePoll = false;
1104 rc = rtTraceLogRdrStateAdvance(pThis, RTTRACELOGRDRSTATE_RECV_MAGIC, TRACELOG_MAGIC_SZ);
1105 }
1106 else
1107 rc = VERR_TRACELOG_READER_MALFORMED_LOG;
1108
1109 return rc;
1110}
1111
1112
1113/**
1114 * @copydoc FNRTTRACELOGRDRSTREAM
1115 */
1116static DECLCALLBACK(int) rtTraceLogRdrFileStream(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbRead,
1117 RTMSINTERVAL cMsTimeout)
1118{
1119 RT_NOREF(cMsTimeout);
1120 RTFILE hFile = (RTFILE)pvUser;
1121 return RTFileRead(hFile, pvBuf, cbBuf, pcbRead);
1122}
1123
1124
1125/**
1126 * @copydoc FNRTTRACELOGSTREAMCLOSE
1127 */
1128static DECLCALLBACK(int) rtTraceLogRdrFileStreamClose(void *pvUser)
1129{
1130 RTFILE hFile = (RTFILE)pvUser;
1131 return RTFileClose(hFile);
1132}
1133
1134
1135/**
1136 * Returns the size of the data for the given event item descriptor.
1137 *
1138 * @returns Size in bytes for the given event item descriptor.
1139 * @param pThis The trace log rader instance.
1140 * @param pEvtItemDesc The event item descriptor.
1141 * @param pacbRawData The raw data size array for he associated event to get the size for non static raw data items.
1142 * @param pidxRawData The index into the raw data size array for the next item to use.
1143 */
1144static size_t rtTraceLogRdrEvtItemGetSz(PRTTRACELOGRDRINT pThis, PCRTTRACELOGEVTITEMDESC pEvtItemDesc,
1145 size_t *pacbRawData, unsigned *pidxRawData)
1146{
1147 size_t cbRet = 0;
1148
1149 switch (pEvtItemDesc->enmType)
1150 {
1151 case RTTRACELOGTYPE_BOOL:
1152 cbRet = sizeof(bool);
1153 break;
1154 case RTTRACELOGTYPE_UINT8:
1155 cbRet = sizeof(uint8_t);
1156 break;
1157 case RTTRACELOGTYPE_INT8:
1158 cbRet = sizeof(int8_t);
1159 break;
1160 case RTTRACELOGTYPE_UINT16:
1161 cbRet = sizeof(uint16_t);
1162 break;
1163 case RTTRACELOGTYPE_INT16:
1164 cbRet = sizeof(int16_t);
1165 break;
1166 case RTTRACELOGTYPE_UINT32:
1167 cbRet = sizeof(uint32_t);
1168 break;
1169 case RTTRACELOGTYPE_INT32:
1170 cbRet = sizeof(int32_t);
1171 break;
1172 case RTTRACELOGTYPE_UINT64:
1173 cbRet = sizeof(uint64_t);
1174 break;
1175 case RTTRACELOGTYPE_INT64:
1176 cbRet = sizeof(int64_t);
1177 break;
1178 case RTTRACELOGTYPE_FLOAT32:
1179 cbRet = sizeof(float);
1180 break;
1181 case RTTRACELOGTYPE_FLOAT64:
1182 cbRet = sizeof(double);
1183 break;
1184 case RTTRACELOGTYPE_RAWDATA:
1185 if (pEvtItemDesc->cbRawData == 0)
1186 {
1187 cbRet = pacbRawData[*pidxRawData];
1188 *pidxRawData++;
1189 }
1190 else
1191 cbRet = pEvtItemDesc->cbRawData;
1192 break;
1193 case RTTRACELOGTYPE_POINTER:
1194 cbRet = pThis->cbTypePtr;
1195 break;
1196 case RTTRACELOGTYPE_SIZE:
1197 cbRet = pThis->cbTypeSize;
1198 break;
1199 default:
1200 AssertMsgFailed(("Invalid type given %d\n", pEvtItemDesc->enmType));
1201 }
1202
1203 return cbRet;
1204}
1205
1206
1207/**
1208 * Resolves the offset of the field with the given name returning the offset and data type.
1209 *
1210 * @returns IPRT status code.
1211 * @param pEvt The event to fetch the data for.
1212 * @param pszName The field to fetch.
1213 * @param poffData Where to store the offset to the data on success.
1214 * @param pcbEvtData Where to store the size of the size of the event data.
1215 * @param ppEvtItemDesc Where to store the event item descriptor.
1216 */
1217static int rtTraceLogRdrEvtResolveData(PCRTTRACELOGRDREVTINT pEvt, const char *pszName, uint32_t *poffData,
1218 size_t *pcbEvtData, PPCRTTRACELOGEVTITEMDESC ppEvtItemDesc)
1219{
1220 PCRTTRACELOGRDREVTDESC pEvtDesc = pEvt->pEvtDesc;
1221 uint32_t offData = 0;
1222 unsigned idxRawData = 0;
1223
1224 for (unsigned i = 0; i < pEvtDesc->EvtDesc.cEvtItems; i++)
1225 {
1226 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = &pEvtDesc->aEvtItemDesc[i];
1227
1228 if (!RTStrCmp(pszName, pEvtItemDesc->pszName))
1229 {
1230 *poffData = offData;
1231 *pcbEvtData = rtTraceLogRdrEvtItemGetSz(pEvt->pRdr, pEvtItemDesc, pEvt->pacbRawData, &idxRawData);
1232 *ppEvtItemDesc = pEvtItemDesc;
1233 return VINF_SUCCESS;
1234 }
1235
1236 offData += (uint32_t)rtTraceLogRdrEvtItemGetSz(pEvt->pRdr, pEvtItemDesc, pEvt->pacbRawData, &idxRawData);
1237 }
1238
1239 return VERR_NOT_FOUND;
1240}
1241
1242
1243/**
1244 * Fills a value with the given event data.
1245 *
1246 * @returns IPRT status code.
1247 * @param pEvt The event to fetch the data for.
1248 * @param offData Offset the data is located in the event.
1249 * @param cbData Number of bytes for the data.
1250 * @param pEvtItemDesc The event item descriptor.
1251 * @param pVal The value to fill.
1252 */
1253static int rtTraceLogRdrEvtFillVal(PCRTTRACELOGRDREVTINT pEvt, uint32_t offData, size_t cbData, PCRTTRACELOGEVTITEMDESC pEvtItemDesc,
1254 PRTTRACELOGEVTVAL pVal)
1255{
1256 PRTTRACELOGRDRINT pThis = pEvt->pRdr;
1257 const uint8_t *pbData = &pEvt->abEvtData[offData];
1258
1259 pVal->pItemDesc = pEvtItemDesc;
1260 switch (pEvtItemDesc->enmType)
1261 {
1262 case RTTRACELOGTYPE_BOOL:
1263 pVal->u.f = *(bool *)pbData;
1264 break;
1265 case RTTRACELOGTYPE_UINT8:
1266 pVal->u.u8 = *pbData;
1267 break;
1268 case RTTRACELOGTYPE_INT8:
1269 pVal->u.i8 = *(int8_t *)pbData;
1270 break;
1271 case RTTRACELOGTYPE_UINT16:
1272 {
1273 uint16_t u16Tmp = *(uint16_t *)pbData;
1274 if (pThis->fConvEndianess)
1275 pVal->u.u16 = RT_BSWAP_U16(u16Tmp);
1276 else
1277 pVal->u.u16 = u16Tmp;
1278 break;
1279 }
1280 case RTTRACELOGTYPE_INT16:
1281 {
1282 uint8_t abData[2];
1283 if (pThis->fConvEndianess)
1284 {
1285 abData[0] = pbData[1];
1286 abData[1] = pbData[0];
1287 }
1288 else
1289 {
1290 abData[0] = pbData[0];
1291 abData[1] = pbData[1];
1292 }
1293
1294 pVal->u.i16 = *(int16_t *)&abData[0];
1295 break;
1296 }
1297 case RTTRACELOGTYPE_UINT32:
1298 {
1299 uint32_t u32Tmp = *(uint32_t *)pbData;
1300 if (pThis->fConvEndianess)
1301 pVal->u.u32 = RT_BSWAP_U32(u32Tmp);
1302 else
1303 pVal->u.u32 = u32Tmp;
1304 break;
1305 }
1306 case RTTRACELOGTYPE_INT32:
1307 {
1308 uint8_t abData[4];
1309 if (pThis->fConvEndianess)
1310 {
1311 abData[0] = pbData[3];
1312 abData[1] = pbData[2];
1313 abData[2] = pbData[1];
1314 abData[3] = pbData[0];
1315 }
1316 else
1317 {
1318 abData[0] = pbData[0];
1319 abData[1] = pbData[1];
1320 abData[2] = pbData[2];
1321 abData[3] = pbData[3];
1322 }
1323
1324 pVal->u.i32 = *(int32_t *)&abData[0];
1325 break;
1326 }
1327 case RTTRACELOGTYPE_UINT64:
1328 {
1329 uint64_t u64Tmp = *(uint64_t *)pbData;
1330 if (pThis->fConvEndianess)
1331 pVal->u.u64 = RT_BSWAP_U64(u64Tmp);
1332 else
1333 pVal->u.u64 = u64Tmp;
1334 break;
1335 }
1336 case RTTRACELOGTYPE_INT64:
1337 {
1338 uint8_t abData[8];
1339 if (pThis->fConvEndianess)
1340 {
1341 abData[0] = pbData[7];
1342 abData[1] = pbData[6];
1343 abData[2] = pbData[5];
1344 abData[3] = pbData[4];
1345 abData[4] = pbData[3];
1346 abData[5] = pbData[2];
1347 abData[6] = pbData[1];
1348 abData[7] = pbData[0];
1349 }
1350 else
1351 {
1352 abData[0] = pbData[0];
1353 abData[1] = pbData[1];
1354 abData[2] = pbData[2];
1355 abData[3] = pbData[3];
1356 abData[4] = pbData[4];
1357 abData[5] = pbData[5];
1358 abData[6] = pbData[6];
1359 abData[7] = pbData[7];
1360 }
1361
1362 pVal->u.i32 = *(int64_t *)&abData[0];
1363 break;
1364 }
1365 case RTTRACELOGTYPE_FLOAT32:
1366 {
1367 uint8_t abData[4];
1368 if (pThis->fConvEndianess)
1369 {
1370 abData[0] = pbData[3];
1371 abData[1] = pbData[2];
1372 abData[2] = pbData[1];
1373 abData[3] = pbData[0];
1374 }
1375 else
1376 {
1377 abData[0] = pbData[0];
1378 abData[1] = pbData[1];
1379 abData[2] = pbData[2];
1380 abData[3] = pbData[3];
1381 }
1382
1383 pVal->u.f32 = *(float *)&abData[0];
1384 break;
1385 }
1386 case RTTRACELOGTYPE_FLOAT64:
1387 {
1388 uint8_t abData[8];
1389 if (pThis->fConvEndianess)
1390 {
1391 abData[0] = pbData[7];
1392 abData[1] = pbData[6];
1393 abData[2] = pbData[5];
1394 abData[3] = pbData[4];
1395 abData[4] = pbData[3];
1396 abData[5] = pbData[2];
1397 abData[6] = pbData[1];
1398 abData[7] = pbData[0];
1399 }
1400 else
1401 {
1402 abData[0] = pbData[0];
1403 abData[1] = pbData[1];
1404 abData[2] = pbData[2];
1405 abData[3] = pbData[3];
1406 abData[4] = pbData[4];
1407 abData[5] = pbData[5];
1408 abData[6] = pbData[6];
1409 abData[7] = pbData[7];
1410 }
1411
1412 pVal->u.f64 = *(double *)&abData[0];
1413 break;
1414 }
1415 case RTTRACELOGTYPE_RAWDATA:
1416 pVal->u.RawData.pb = pbData;
1417 if (pEvtItemDesc->cbRawData == 0)
1418 pVal->u.RawData.cb = cbData;
1419 else
1420 pVal->u.RawData.cb = pEvtItemDesc->cbRawData;
1421 break;
1422 case RTTRACELOGTYPE_POINTER:
1423 {
1424 if (pThis->cbTypePtr == 4)
1425 {
1426 if (pThis->fConvEndianess)
1427 pVal->u.uPtr = RT_BSWAP_U32(*(uint32_t *)pbData);
1428 else
1429 pVal->u.uPtr = *(uint32_t *)pbData;
1430 }
1431 else if (pThis->cbTypePtr == 8)
1432 {
1433 if (pThis->fConvEndianess)
1434 pVal->u.uPtr = RT_BSWAP_U64(*(uint64_t *)pbData);
1435 else
1436 pVal->u.uPtr = *(uint64_t *)pbData;
1437 }
1438 else
1439 AssertMsgFailed(("Invalid pointer size %d, should not happen!\n", pThis->cbTypePtr));
1440 break;
1441 }
1442 case RTTRACELOGTYPE_SIZE:
1443 {
1444 if (pThis->cbTypeSize == 4)
1445 {
1446 if (pThis->fConvEndianess)
1447 pVal->u.sz = RT_BSWAP_U32(*(uint32_t *)pbData);
1448 else
1449 pVal->u.sz = *(uint32_t *)pbData;
1450 }
1451 else if (pThis->cbTypeSize == 8)
1452 {
1453 if (pThis->fConvEndianess)
1454 pVal->u.sz = RT_BSWAP_U64(*(uint64_t *)pbData);
1455 else
1456 pVal->u.sz = *(uint64_t *)pbData;
1457 }
1458 else
1459 AssertMsgFailed(("Invalid size_t size %d, should not happen!\n", pThis->cbTypeSize));
1460 break;
1461 }
1462 default:
1463 AssertMsgFailed(("Invalid type given %d\n", pEvtItemDesc->enmType));
1464 }
1465
1466 return VINF_SUCCESS;
1467}
1468
1469
1470/**
1471 * Finds the mapping descriptor for the given event.
1472 *
1473 * @returns Pointer to the mapping descriptor or NULL if not found.
1474 * @param paMapDesc Pointer to the array of mapping descriptors.
1475 * @param pEvt The event to look for the matching mapping descriptor.
1476 */
1477static PCRTTRACELOGRDRMAPDESC rtTraceLogRdrMapDescFindForEvt(PCRTTRACELOGRDRMAPDESC paMapDesc, PCRTTRACELOGRDREVTINT pEvt)
1478{
1479 AssertPtrReturn(paMapDesc, NULL);
1480 AssertPtrReturn(pEvt, NULL);
1481
1482 while (paMapDesc->pszEvtId)
1483 {
1484 if (!RTStrCmp(paMapDesc->pszEvtId, pEvt->pEvtDesc->EvtDesc.pszId))
1485 return paMapDesc;
1486
1487 paMapDesc++;
1488 }
1489
1490 return NULL;
1491}
1492
1493
1494/**
1495 * Fills the given event header with data from the given event using the matching mapping descriptor.
1496 *
1497 * @returns IPRT statsu code.
1498 * @param pEvtHdr The event header to fill.
1499 * @param pMapDesc The mapping descriptor to use.
1500 * @param pEvt The raw event to get the data from.
1501 */
1502static int rtTraceLogRdrMapFillEvt(PRTTRACELOGRDREVTHDR pEvtHdr, PCRTTRACELOGRDRMAPDESC pMapDesc, PCRTTRACELOGRDREVTINT pEvt)
1503{
1504 int rc = VINF_SUCCESS;
1505
1506 /* Fill in the status parts. */
1507 pEvtHdr->pEvtMapDesc = pMapDesc;
1508 pEvtHdr->pEvtDesc = &pEvt->pEvtDesc->EvtDesc;
1509 pEvtHdr->idSeqNo = pEvt->u64SeqNo;
1510 pEvtHdr->tsEvt = pEvt->u64Ts;
1511 pEvtHdr->paEvtItems = NULL;
1512
1513 /* Now the individual items if any. */
1514 if (pMapDesc->cEvtItems)
1515 {
1516 /* Allocate values for the items. */
1517 pEvtHdr->paEvtItems = (PCRTTRACELOGEVTVAL)RTMemAllocZ(pMapDesc->cEvtItems * sizeof(RTTRACELOGEVTVAL));
1518 if (RT_LIKELY(pEvtHdr->paEvtItems))
1519 {
1520 for (uint32_t i = 0; (i < pMapDesc->cEvtItems) && RT_SUCCESS(rc); i++)
1521 {
1522 uint32_t offData = 0;
1523 size_t cbData = 0;
1524 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = NULL;
1525 rc = rtTraceLogRdrEvtResolveData(pEvt, pMapDesc->paMapItems[i].pszName, &offData, &cbData, &pEvtItemDesc);
1526 if (RT_SUCCESS(rc))
1527 rc = rtTraceLogRdrEvtFillVal(pEvt, offData, cbData, pEvtItemDesc, (PRTTRACELOGEVTVAL)&pEvtHdr->paEvtItems[i]);
1528 }
1529
1530 if (RT_FAILURE(rc))
1531 {
1532 RTMemFree((void *)pEvtHdr->paEvtItems);
1533 pEvtHdr->paEvtItems = NULL;
1534 }
1535 }
1536 else
1537 rc = VERR_NO_MEMORY;
1538 }
1539
1540 return rc;
1541}
1542
1543
1544RTDECL(int) RTTraceLogRdrCreate(PRTTRACELOGRDR phTraceLogRdr, PFNRTTRACELOGRDRSTREAM pfnStreamIn,
1545 PFNRTTRACELOGSTREAMCLOSE pfnStreamClose, void *pvUser)
1546{
1547 AssertPtrReturn(phTraceLogRdr, VERR_INVALID_POINTER);
1548 AssertPtrReturn(pfnStreamIn, VERR_INVALID_POINTER);
1549 AssertPtrReturn(pfnStreamClose, VERR_INVALID_POINTER);
1550 int rc = VINF_SUCCESS;
1551 PRTTRACELOGRDRINT pThis = (PRTTRACELOGRDRINT)RTMemAllocZ(sizeof(*pThis));
1552 if (pThis)
1553 {
1554 rc = RTSemMutexCreate(&pThis->hMtx);
1555 if (RT_SUCCESS(rc))
1556 {
1557 rc = RTStrCacheCreate(&pThis->hStrCache, "TRACELOGRDR");
1558 if (RT_SUCCESS(rc))
1559 {
1560 RTListInit(&pThis->LstEvts);
1561 pThis->u32Magic = RTTRACELOGRDR_MAGIC;
1562 pThis->pfnStreamIn = pfnStreamIn;
1563 pThis->pfnStreamClose = pfnStreamClose;
1564 pThis->pvUser = pvUser;
1565 pThis->enmState = RTTRACELOGRDRSTATE_RECV_HDR;
1566 pThis->fConvEndianess = false;
1567 pThis->pszDesc = NULL;
1568 pThis->cEvtDescsCur = 0;
1569 pThis->cEvtDescsMax = 0;
1570 pThis->papEvtDescs = NULL;
1571 pThis->pEvtDescCur = NULL;
1572 pThis->u64SeqNoLast = 0;
1573 pThis->cbScratch = sizeof(TRACELOGHDR);
1574 pThis->offScratch = 0;
1575 pThis->cbRecvLeft = sizeof(TRACELOGHDR);
1576 pThis->pbScratch = (uint8_t *)RTMemAllocZ(pThis->cbScratch);
1577 if (RT_LIKELY(pThis->pbScratch))
1578 {
1579 *phTraceLogRdr = pThis;
1580 return VINF_SUCCESS;
1581 }
1582 else
1583 rc = VERR_NO_MEMORY;
1584
1585 RTStrCacheDestroy(pThis->hStrCache);
1586 }
1587
1588 RTSemMutexDestroy(pThis->hMtx);
1589 }
1590 RTMemFree(pThis);
1591 }
1592 else
1593 rc = VERR_NO_MEMORY;
1594
1595 return rc;
1596}
1597
1598
1599RTDECL(int) RTTraceLogRdrCreateFromFile(PRTTRACELOGRDR phTraceLogRdr, const char *pszFilename)
1600{
1601 AssertPtrReturn(phTraceLogRdr, VERR_INVALID_POINTER);
1602 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
1603
1604 RTFILE hFile = NIL_RTFILE;
1605 int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
1606 if (RT_SUCCESS(rc))
1607 {
1608 rc = RTTraceLogRdrCreate(phTraceLogRdr, rtTraceLogRdrFileStream, rtTraceLogRdrFileStreamClose, hFile);
1609 if (RT_FAILURE(rc))
1610 {
1611 RTFileClose(hFile);
1612 RTFileDelete(pszFilename);
1613 }
1614 }
1615
1616 return rc;
1617}
1618
1619
1620RTDECL(int) RTTraceLogRdrDestroy(RTTRACELOGRDR hTraceLogRdr)
1621{
1622 if (hTraceLogRdr == NIL_RTTRACELOGRDR)
1623 return VINF_SUCCESS;
1624 PRTTRACELOGRDRINT pThis = hTraceLogRdr;
1625 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1626 AssertReturn(pThis->u32Magic == RTTRACELOGRDR_MAGIC, VERR_INVALID_HANDLE);
1627
1628 pThis->u32Magic = RTTRACELOGRDR_MAGIC_DEAD;
1629 int rc = pThis->pfnStreamClose(pThis->pvUser);
1630 AssertRC(rc);
1631
1632 for (unsigned i = 0; i < pThis->cEvtDescsCur; i++)
1633 RTMemFree(pThis->papEvtDescs[i]);
1634 if (pThis->papEvtDescs)
1635 {
1636 RTMemFree(pThis->papEvtDescs);
1637 pThis->papEvtDescs = NULL;
1638 }
1639
1640 if (pThis->pEvtCur)
1641 {
1642 RTMemFree(pThis->pEvtCur);
1643 pThis->pEvtCur = NULL;
1644 }
1645
1646 PRTTRACELOGRDREVTINT pCur, pNext;
1647 RTListForEachSafe(&pThis->LstEvts, pCur, pNext, RTTRACELOGRDREVTINT, NdGlob)
1648 {
1649 RTMemFree(pCur);
1650 }
1651
1652 RTSemMutexDestroy(pThis->hMtx);
1653 pThis->hMtx = NIL_RTSEMMUTEX;
1654
1655 RTMemFree(pThis->pbScratch);
1656 pThis->pbScratch = NULL;
1657
1658 RTStrCacheDestroy(pThis->hStrCache);
1659 pThis->hStrCache = NIL_RTSTRCACHE;
1660
1661 RTMemFree(pThis);
1662 return VINF_SUCCESS;
1663}
1664
1665
1666RTDECL(int) RTTraceLogRdrEvtPoll(RTTRACELOGRDR hTraceLogRdr, RTTRACELOGRDRPOLLEVT *penmEvt, RTMSINTERVAL cMsTimeout)
1667{
1668 PRTTRACELOGRDRINT pThis = hTraceLogRdr;
1669 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1670 AssertReturn(pThis->u32Magic == RTTRACELOGRDR_MAGIC, VERR_INVALID_HANDLE);
1671 AssertPtrReturn(penmEvt, VERR_INVALID_POINTER);
1672
1673 int rc = VINF_SUCCESS;
1674 bool fContinue = true;
1675 while ( RT_SUCCESS(rc)
1676 && fContinue)
1677 {
1678 size_t cbRecvd = 0;
1679
1680 rc = rtTraceLogRdrStreamRead(pThis, &pThis->pbScratch[pThis->offScratch],
1681 pThis->cbRecvLeft, &cbRecvd, cMsTimeout);
1682 if (RT_SUCCESS(rc))
1683 {
1684 if (cbRecvd == pThis->cbRecvLeft)
1685 {
1686 /* Act according to the current state. */
1687 rc = g_aStateHandlers[pThis->enmState].pfn(pThis, penmEvt, &fContinue);
1688 }
1689 else
1690 pThis->cbRecvLeft -= cbRecvd;
1691 }
1692 }
1693
1694 return rc;
1695}
1696
1697
1698RTDECL(int) RTTraceLogRdrQueryLastEvt(RTTRACELOGRDR hTraceLogRdr, PRTTRACELOGRDREVT phRdrEvt)
1699{
1700 PRTTRACELOGRDRINT pThis = hTraceLogRdr;
1701 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1702 AssertReturn(pThis->u32Magic == RTTRACELOGRDR_MAGIC, VERR_INVALID_HANDLE);
1703 AssertPtrReturn(phRdrEvt, VERR_INVALID_POINTER);
1704
1705 int rc = VINF_SUCCESS;
1706 RTSemMutexRequest(pThis->hMtx, RT_INDEFINITE_WAIT);
1707 PRTTRACELOGRDREVTINT pEvt = RTListGetLast(&pThis->LstEvts, RTTRACELOGRDREVTINT, NdGlob);
1708 *phRdrEvt = pEvt;
1709 if (!pEvt)
1710 rc = VERR_NOT_FOUND;
1711 RTSemMutexRelease(pThis->hMtx);
1712
1713 return rc;
1714}
1715
1716
1717RTDECL(int) RTTraceLogRdrQueryIterator(RTTRACELOGRDR hTraceLogRdr, PRTTRACELOGRDRIT phIt)
1718{
1719 PRTTRACELOGRDRINT pThis = hTraceLogRdr;
1720 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1721 AssertReturn(pThis->u32Magic == RTTRACELOGRDR_MAGIC, VERR_INVALID_HANDLE);
1722 AssertPtrReturn(phIt, VERR_INVALID_POINTER);
1723
1724 int rc = VINF_SUCCESS;
1725 PRTTRACELOGRDRITINT pIt = (PRTTRACELOGRDRITINT)RTMemAllocZ(sizeof(*pIt));
1726 if (RT_LIKELY(pIt))
1727 {
1728 pIt->pRdr = pThis;
1729 pIt->pEvt = RTListGetFirst(&pThis->LstEvts, RTTRACELOGRDREVTINT, NdGlob);
1730 *phIt = pIt;
1731 }
1732 else
1733 rc = VERR_NO_MEMORY;
1734
1735 return rc;
1736}
1737
1738
1739RTDECL(int) RTTraceLogRdrEvtMapToStruct(RTTRACELOGRDR hTraceLogRdr, uint32_t fFlags, uint32_t cEvts,
1740 PCRTTRACELOGRDRMAPDESC paMapDesc, PCRTTRACELOGRDREVTHDR *ppaEvtHdr,
1741 uint32_t *pcEvts)
1742{
1743 RT_NOREF(fFlags);
1744
1745 PRTTRACELOGRDRINT pThis = hTraceLogRdr;
1746 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1747 AssertReturn(pThis->u32Magic == RTTRACELOGRDR_MAGIC, VERR_INVALID_HANDLE);
1748 AssertPtrReturn(paMapDesc, VERR_INVALID_PARAMETER);
1749 AssertPtrReturn(ppaEvtHdr, VERR_INVALID_POINTER);
1750 AssertPtrReturn(pcEvts, VERR_INVALID_POINTER);
1751
1752 int rc = VINF_SUCCESS;
1753 uint32_t cEvtsAlloc = cEvts != UINT32_MAX ? cEvts : _4K;
1754 PRTTRACELOGRDREVTHDR paEvtHdr = (PRTTRACELOGRDREVTHDR)RTMemAllocZ(cEvtsAlloc * sizeof(*paEvtHdr));
1755 if (RT_LIKELY(paEvtHdr))
1756 {
1757 uint32_t cEvtsRecv = 0;
1758
1759 while ( RT_SUCCESS(rc)
1760 && cEvtsRecv < cEvts)
1761 {
1762 RTTRACELOGRDRPOLLEVT enmEvt = RTTRACELOGRDRPOLLEVT_INVALID;
1763 rc = RTTraceLogRdrEvtPoll(pThis, &enmEvt, 0 /*cMsTimeout*/);
1764 if ( RT_SUCCESS(rc)
1765 && enmEvt == RTTRACELOGRDRPOLLEVT_TRACE_EVENT_RECVD)
1766 {
1767 /* Find the mapping descriptor. */
1768 PRTTRACELOGRDREVTINT pEvt = NULL;
1769 rc = RTTraceLogRdrQueryLastEvt(hTraceLogRdr, &pEvt);
1770 if (RT_SUCCESS(rc))
1771 {
1772 PCRTTRACELOGRDRMAPDESC pMapDesc = rtTraceLogRdrMapDescFindForEvt(paMapDesc, pEvt);
1773 if (pMapDesc)
1774 {
1775 if (cEvtsRecv == cEvtsAlloc)
1776 {
1777 Assert(cEvts == UINT32_MAX);
1778 PRTTRACELOGRDREVTHDR paEvtHdrNew = (PRTTRACELOGRDREVTHDR)RTMemRealloc(paEvtHdr, (cEvtsAlloc + _4K) * sizeof(*paEvtHdr));
1779 if (RT_LIKELY(paEvtHdrNew))
1780 {
1781 paEvtHdr = paEvtHdrNew;
1782 cEvtsAlloc += _4K;
1783 }
1784 else
1785 rc = VERR_NO_MEMORY;
1786 }
1787
1788 if (RT_SUCCESS(rc))
1789 rc = rtTraceLogRdrMapFillEvt(&paEvtHdr[cEvtsRecv++], pMapDesc, pEvt);
1790 cEvtsRecv++;
1791 }
1792 else
1793 rc = VERR_NOT_FOUND;
1794 }
1795 }
1796 }
1797
1798 if (RT_SUCCESS(rc))
1799 {
1800 *ppaEvtHdr = paEvtHdr;
1801 *pcEvts = cEvtsRecv;
1802 }
1803 else
1804 RTTraceLogRdrEvtMapFree(paEvtHdr, cEvtsRecv);
1805 }
1806 else
1807 rc = VERR_NO_MEMORY;
1808
1809 return rc;
1810}
1811
1812
1813RTDECL(void) RTTraceLogRdrEvtMapFree(PCRTTRACELOGRDREVTHDR paEvtHdr, uint32_t cEvts)
1814{
1815 for (uint32_t i = 0; i < cEvts; i++)
1816 {
1817 if (paEvtHdr[i].paEvtItems)
1818 RTMemFree((void *)paEvtHdr[i].paEvtItems);
1819 }
1820
1821 RTMemFree((void *)paEvtHdr);
1822}
1823
1824
1825RTDECL(void) RTTraceLogRdrIteratorFree(RTTRACELOGRDRIT hIt)
1826{
1827 PRTTRACELOGRDRITINT pIt = hIt;
1828 AssertPtrReturnVoid(pIt);
1829
1830 RTMemFree(pIt);
1831}
1832
1833
1834RTDECL(int) RTTraceLogRdrIteratorNext(RTTRACELOGRDRIT hIt)
1835{
1836 PRTTRACELOGRDRITINT pIt = hIt;
1837 AssertPtrReturn(pIt, VERR_INVALID_HANDLE);
1838
1839 if (!pIt->pEvt)
1840 return VERR_TRACELOG_READER_ITERATOR_END;
1841
1842 int rc = VINF_SUCCESS;
1843 PRTTRACELOGRDREVTINT pEvtNext = RTListGetNext(&pIt->pRdr->LstEvts, pIt->pEvt, RTTRACELOGRDREVTINT, NdGlob);
1844
1845 if (pEvtNext)
1846 pIt->pEvt = pEvtNext;
1847 else
1848 rc = VERR_TRACELOG_READER_ITERATOR_END;
1849
1850 return rc;
1851}
1852
1853
1854RTDECL(int) RTTraceLogRdrIteratorQueryEvent(RTTRACELOGRDRIT hIt, PRTTRACELOGRDREVT phRdrEvt)
1855{
1856 PRTTRACELOGRDRITINT pIt = hIt;
1857 AssertPtrReturn(pIt, VERR_INVALID_HANDLE);
1858 AssertPtrReturn(phRdrEvt, VERR_INVALID_POINTER);
1859
1860 *phRdrEvt = pIt->pEvt;
1861 return VINF_SUCCESS;
1862}
1863
1864
1865RTDECL(uint64_t) RTTraceLogRdrEvtGetSeqNo(RTTRACELOGRDREVT hRdrEvt)
1866{
1867 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1868 AssertPtrReturn(pEvt, 0);
1869
1870 return pEvt->u64SeqNo;
1871}
1872
1873
1874RTDECL(uint64_t) RTTraceLogRdrEvtGetTs(RTTRACELOGRDREVT hRdrEvt)
1875{
1876 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1877 AssertPtrReturn(pEvt, 0);
1878
1879 return pEvt->u64Ts;
1880}
1881
1882
1883RTDECL(bool) RTTraceLogRdrEvtIsGrouped(RTTRACELOGRDREVT hRdrEvt)
1884{
1885 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1886 AssertPtrReturn(pEvt, false);
1887
1888 return pEvt->idGrp != 0;
1889}
1890
1891
1892RTDECL(PCRTTRACELOGEVTDESC) RTTraceLogRdrEvtGetDesc(RTTRACELOGRDREVT hRdrEvt)
1893{
1894 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1895 AssertPtrReturn(pEvt, NULL);
1896
1897 return &pEvt->pEvtDesc->EvtDesc;
1898}
1899
1900
1901RTDECL(int) RTTraceLogRdrEvtQueryVal(RTTRACELOGRDREVT hRdrEvt, const char *pszName, PRTTRACELOGEVTVAL pVal)
1902{
1903 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1904 AssertPtrReturn(pEvt, VERR_INVALID_HANDLE);
1905
1906 uint32_t offData = 0;
1907 size_t cbData = 0;
1908 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = NULL;
1909 int rc = rtTraceLogRdrEvtResolveData(pEvt, pszName, &offData, &cbData, &pEvtItemDesc);
1910 if (RT_SUCCESS(rc))
1911 rc = rtTraceLogRdrEvtFillVal(pEvt, offData, cbData, pEvtItemDesc, pVal);
1912 return rc;
1913}
1914
1915
1916RTDECL(int) RTTraceLogRdrEvtFillVals(RTTRACELOGRDREVT hRdrEvt, unsigned idxItemStart, PRTTRACELOGEVTVAL paVals,
1917 unsigned cVals, unsigned *pcVals)
1918{
1919 PRTTRACELOGRDREVTINT pEvt = hRdrEvt;
1920 AssertPtrReturn(pEvt, VERR_INVALID_HANDLE);
1921
1922 PCRTTRACELOGRDREVTDESC pEvtDesc = pEvt->pEvtDesc;
1923 AssertReturn(idxItemStart < pEvtDesc->EvtDesc.cEvtItems, VERR_INVALID_PARAMETER);
1924
1925 /* Advance to the item the caller wants to fill in. */
1926 uint32_t offData = 0;
1927 unsigned idxRawData = 0;
1928
1929 for (unsigned i = 0; i < idxItemStart; i++)
1930 {
1931 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = &pEvtDesc->aEvtItemDesc[i];
1932 offData += (uint32_t)rtTraceLogRdrEvtItemGetSz(pEvt->pRdr, pEvtItemDesc, pEvt->pacbRawData, &idxRawData);
1933 }
1934
1935 int rc = VINF_SUCCESS;
1936 unsigned idxItemEnd = RT_MIN(idxItemStart + cVals, pEvtDesc->EvtDesc.cEvtItems);
1937 for (unsigned i = idxItemStart; i < idxItemEnd && RT_SUCCESS(rc); i++)
1938 {
1939 PCRTTRACELOGEVTITEMDESC pEvtItemDesc = &pEvtDesc->aEvtItemDesc[i];
1940 size_t cbData = rtTraceLogRdrEvtItemGetSz(pEvt->pRdr, pEvtItemDesc, pEvt->pacbRawData, &idxRawData);
1941
1942 rc = rtTraceLogRdrEvtFillVal(pEvt, offData, cbData, pEvtItemDesc, &paVals[i - idxItemStart]);
1943 offData += (uint32_t)cbData;
1944 }
1945
1946 *pcVals = idxItemEnd - idxItemStart;
1947
1948 return rc;
1949}
1950
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