text: /*
   * Copyright (c) 2020 Bitdefender
   * SPDX-License-Identifier: Apache-2.0
   */
  #ifndef _STATS_H_
  #define _STATS_H_
  
  #include "introdefs.h"
  
  ///
  /// @brief  Stat IDs.
  ///
  /// Each ID is used to identify a specific code section to time (this can be as large as an entire VMEXIT event handler,
  /// or a more specific event). Stats may be nested in other stats.
  ///
  typedef enum _STAT_ID
  {
      statsEptViolation = 0,      ///< Measures all EPT violations.
      statsEptRead,               ///< Measures read EPT violations.
      statsEptWrite,              ///< Measures write EPT violations.
      statsEptExecute,            ///< Measures execute EPT violations.
      statsEptKernel,             ///< Measures EPT violations generated while the guest was in kernel mode.
      statsEptUser,               ///< Measures EPT violations generated while the guest was in user mode.
      statsEptDecode,             ///< Measures the decoding of instructions that generate EPT violations.
      statsEptLookup,             ///< Measures the look-up of EPT violation handlers.
      statsEptHandle,             ///< Measures the execution of EPT violation handlers.
      statsEptRMW,                ///< Measures the EPT violations for which the instruction does a read and a write.
  
      statsVmcall,                ///< Measures the handling of VMCALL exits.
      statsCrViolation,           ///< Measures CR violation exits.
      statsMsrViolation,          ///< Measures MSR violation exits.
      statsXcrViolation,          ///< Measures XCR violation exits.
      statsTimer,                 ///< Measures the timer events.
      statsInt3,                  ///< Measures the INT3 events.
      statsDtrViolation,          ///< Measures the DTR violation exits.
      statsEventInjection,        ///< Measures event injections.
      statsModuleLoadViolation,   ///< Measures module load violation handling.
  
      statsDeleteRegion,          ///< Measures the deletion of #HOOK_REGION_DESCRIPTOR objects.
      statsDeleteGva,             ///< Measures the deletion of #HOOK_GVA objects.
  
      statsHookCommit,            ///< Measures the hook commits.
  
      statsPtWriteProc,           ///< Measures page table writes.
      statsPtWriteEmu,            ///< Measures page table writes emulation.
      statsPtWriteTotal,          ///< Measures all the page table writes.
      statsPtWriteHits,           ///< Measures page table entries writes.
      statsPtWriteRelevant,       ///< Measures page table writes that are actually relevant for Introcore.
  
      statsExceptionsUser,        ///< Measures user mode exceptions checks.
      statsExceptionsKern,        ///< Measures kernel mode exceptions checks.
      statsExceptionsGlobMatch,   ///< Measures glob-match exceptions.
  
      statsUmCrash,               ///< Measures user mode crash handlers.
  
      statsVasmon,                ///< Measures page table writes done by the VAS monitor.
      statsVadCommitExisting,     ///< Measures the #IntWinVadHandleCommit detour handler.
  
      statsPtsIntegrity,          ///< Measures page tables integrity checks.
      statsPtsFilterInt3,         ///< Measures the INT3 exits generated by the page table filtering mechanism.
      statsPtsFilterVmcall,       ///< Measures the VMCALL exists generated by the page table filtering agent.
      statsPtsFilterInsSearch,    ///< Measures the instruction search done for the page table filtering agent.
      statsSwapgsInsSearch,       ///< Measures the instruction search done for the SWAPGS protection.
  
      statsSelfMapEntryProtection,///< Measures the self map entry validation.
  
      statsCopyMemoryTotal,       ///< Measures the #IntWinProcHandleCopyMemory detour handler.
  
      statsCopyMemoryRead,        ///< Measures #IntWinProcHandleCopyMemory invocations done for memory reads.
      statsCopyMemoryWrite,       ///< Measures #IntWinProcHandleCopyMemory invocations done for memory writes.
      /// @brief  Measures the handling of memory reads in which a read protection policy exists.
      statsCopyMemoryProtectedRead,
      /// @brief  Measures the handling of memory reads in which a write protection policy exists.
      statsCopyMemoryProtectedWrite,
  
      statsDepViolation,          ///< Measures #IntWinHandleException invocations done for DEP violations.
  
      statsStackTrace32,          ///< Measures the stack trace mechanism for 32-bit execution contexts.
      statsStackTrace64,          ///< Measures the stack trace mechanism for 64-bit execution contexts.
      /// @brief Measures the cases in which the stack trace mechanism encounters a JMP after a CALL.
      statsStackTraceSpecialCase,
  
      statsDpiGatherInfo,         ///< Measures the information gathering for the DPI mechanism.
      statsProcessCreationCheck,  ///< Measures the process creation checks.
  
      statsDpiDebugFlag,          ///< Measures the debug flag DPI protection information gathering.
      statsDpiStackPivot,         ///< Measures the pivoted stack DPI protection information gathering.
      statsDpiStealToken,         ///< Measures the stolen token flag DPI protection information gathering.
      statsDpiHeapSpray,          ///< Measures the heap spray DPI protection information gathering.
      statsDpiTokenPrivs,         ///< Measures the token privileges DPI protection information gathering.
      statsDpiThreadStart,        ///< Measures the thread start DPI protection information gathering.
  
      statsNtEatRead,             ///< Measures reads done from the kernel EAT.
      statsTokenWrites,           ///< Token writes.
  
      statsTokenChangeCheck,      ///< Measures the checks to see if the token has been changed when a write occurs over the token.
      statsTokenSwapCheck,        ///< Measures the checks to see if the token has been changed when a token swap occurs.
  
      statsKmUmWrites,            ///< Writes done from kernel mode over user mode.
      statsSetProcInfo,           ///< Measures exits on NtSetInformationProcess.
  
      statsDpiSdAcl,              ///< Measures the security descriptor DPI protection information gathering.
  
      statsSudIntegrity,          ///< Measures the checks done on SharedUserData.
  
      statsSudExec,               ///< Measures the execution handling on SharedUserData page.
  
      statsSecDesc,               ///< Measures the integrity checks on the process security descriptor.
  
      /// @brief  The number of valid stats IDs. Not a valid ID. Must always be the last entry in the enum.
      statsMaxCounter
  } STAT_ID;
  
  
  #ifndef DEBUG
  #define STATS_DISABLE_TIMER 1
  #endif
  
  #if defined(USER_MODE) && !defined(CFG_DISABLE_HIRES_COUNTERS) && !defined(STATS_DISABLE_TIMER)
  # include <time.h>
  # define STATS_HAS_HIGHRES_TIMER 1
  #endif
  
  #ifdef STATS_HAS_HIGHRES_TIMER
  typedef struct timespec TIMESPEC;
  #else
  typedef QWORD TIMESPEC;
  #endif
  
  ///
  /// @brief  A stats counter.
  ///
  typedef struct _STAT_COUNTER
  {
      QWORD       TotalCount; ///< The total number of times an event was measured.
  
  #ifndef STATS_DISABLE_TIMER
      TIMESPEC    Start;      ///< The last time a measurement for this counter was started.
  
      /// The value of #gEventId when the last measurement was started.
      QWORD       StartEventId;
      QWORD       Max;        ///< The maximum time interval measured for this event.
      /// @brief  The number of the other stats which were gathered while this one was measured.
      ///
      /// This is used in order to exclude the time taken by a #GetTime call.
      QWORD       StatCalls;
  
      TIMESPEC    Total;      ///< The total time consumed by this event.
  #endif
  } STAT_COUNTER, *PSTAT_COUNTER;
  
  #ifdef STATS_DISABLE_TIMER
  #define STATS_ENTER(id)
  #define STATS_DISCARD(id)
  #else
  #define STATS_ENTER(id)                 IntStatStart(id)
  #define STATS_DISCARD(id)               IntStatDiscard(id)
  #endif
  
  #define STATS_EXIT(id)                  IntStatStop(id)
  
  void
  IntStatsDumpAll(
      void
      );
  
  #ifdef STATS_DISABLE_TIMER
  
  extern STAT_COUNTER gCounters[statsMaxCounter];
  
  __forceinline void
  IntStatStart(
      _In_ STAT_ID StatId
      )
  {
      UNREFERENCED_PARAMETER(StatId);
  }
  
  __forceinline void
  IntStatStop(
      _In_ STAT_ID StatId
      )
  {
      gCounters[StatId].TotalCount++;
  }
  
  #else
  
  void
  IntStatStart(
      _In_ STAT_ID StatId
      );
  
  void
  IntStatStop(
      _In_ STAT_ID StatId
      );
  
  #endif // STATS_DISABLE_TIMER
  
  void
  IntStatDiscard(
      _In_ STAT_ID StatId
      );
  
  void
  IntStatsResetAll(
      void
      );
  
  void
  IntStatsReset(
      _In_ STAT_ID StatId
      );
  
  void
  IntStatsInit(
      void
      );
  
  #endif // _STATS_H_
  