Bitdefender Hypervisor Memory Introspection
bitmask.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "bitmask.h"
6 #include "glue.h"
7 #include "introcrt.h"
8 
9 
10 static inline
11 UINT64 *
13  _In_ BITMASK *BitMask,
14  _Inout_ DWORD *BitPos
15  )
26 {
27  UINT64 *b = (UINT64 *)BitMask->Bits + (*BitPos / 64);
28 
29  *BitPos %= 64;
30 
31  return b;
32 }
33 
34 
35 static inline
36 UINT64 *
38  _In_ BITMASK *BitMask,
39  _In_ DWORD BitPos
40  )
50 {
51  return (UINT64 *)BitMask->Bits + (BitPos / 64);
52 }
53 
54 
55 BITMASK *
57  _In_ size_t Size
58  )
69 {
70  BITMASK *bitmask = HpAllocWithTag(sizeof(*bitmask) + (Size / 8) + (Size % 8 != 0), IC_TAG_ALLOC);
71  if (NULL == bitmask)
72  {
73  return NULL;
74  }
75 
76  bitmask->Length = Size;
77 
78  return bitmask;
79 }
80 
81 
82 void
84  _Inout_ BITMASK **BitMask
85  )
91 {
93 }
94 
95 
96 void
98  _Inout_ BITMASK *BitMask,
99  _In_ DWORD BitPos
100  )
109 {
110  if (BitPos > BitMask->Length)
111  {
112  ERROR("[ERROR] Trying to set bit %u which is outside of the bitmask (%zu length)\n",
113  BitPos, BitMask->Length);
114  return;
115  }
116 
117  UINT64 *bitBase = BitMaskGetBaseAndBit(BitMask, &BitPos);
118 
119  *bitBase |= (1ull << BitPos);
120 }
121 
122 
123 void
125  _Inout_ BITMASK *BitMask,
126  _In_ DWORD BitPos
127  )
136 {
137  if (BitPos > BitMask->Length)
138  {
139  ERROR("[ERROR] Trying to set bit %u which is outside of the bitmask (%zu length)\n",
140  BitPos, BitMask->Length);
141  return;
142  }
143 
144  UINT64 *bitBase = BitMaskGetBaseAndBit(BitMask, &BitPos);
145 
146  *bitBase &= ~(1ull << BitPos);
147 }
148 
149 
150 BYTE
152  _In_ BITMASK *BitMask,
153  _In_ DWORD BitPos
154  )
165 {
166  if (BitPos > BitMask->Length)
167  {
168  ERROR("[ERROR] Trying to set bit %u which is outside of the bitmask (%zu length)\n",
169  BitPos, BitMask->Length);
170  return 0;
171  }
172 
173  UINT64 *bitBase = BitMaskGetBaseAndBit(BitMask, &BitPos);
174 
175  return (*bitBase >> BitPos) & 1;
176 }
177 
178 
179 BYTE
181  _Inout_ BITMASK *BitMask,
182  _In_ DWORD BitPos
183  )
195 {
196  if (BitPos > BitMask->Length)
197  {
198  ERROR("[ERROR] Trying to set bit %u which is outside of the bitmask (%zu length)\n",
199  BitPos, BitMask->Length);
200  return 0;
201  }
202 
203  UINT64 *bitBase = BitMaskGetBaseAndBit(BitMask, &BitPos);
204 
205  BYTE old = (*bitBase >> BitPos) & 1;
206 
207  *bitBase |= (1ull << BitPos);
208 
209  return old;
210 }
211 
212 
213 BYTE
215  _Inout_ BITMASK *BitMask,
216  _In_ DWORD BitPos
217  )
229 {
230  if (BitPos > BitMask->Length)
231  {
232  ERROR("[ERROR] Trying to set bit %u which is outside of the bitmask (%zu length)\n",
233  BitPos, BitMask->Length);
234 
235  return 0;
236  }
237 
238  UINT64 *bitBase = BitMaskGetBaseAndBit(BitMask, &BitPos);
239 
240  BYTE old = (*bitBase >> BitPos) & 1;
241 
242  *bitBase &= ~(1ull << BitPos);
243 
244  return old;
245 }
246 
247 
248 DWORD
250  _In_ BITMASK *BitMask
251  )
258 {
259  DWORD index = 0;
260 
261  for (DWORD i = 0; i < BitMask->Length; i += 64)
262  {
263  UINT64 base = *BitMaskGetBase(BitMask, i);
264 
265  if (!_BitScanForward64(&index, ~base))
266  {
267  continue;
268  }
269 
270  return i + index;
271  }
272 
273  return (DWORD) -1;
274 }
Represents a bit mask.
Definition: bitmask.h:15
void BitMaskClear(BITMASK *BitMask, DWORD BitPos)
Clears a bit in a BITMASK.
Definition: bitmask.c:124
DWORD BitMaskScanForward(BITMASK *BitMask)
Search for a set bit starting from the least significant bit.
Definition: bitmask.c:249
BITMASK * BitMaskAlloc(size_t Size)
Creates a new BITMASK.
Definition: bitmask.c:56
uint8_t BYTE
Definition: intro_types.h:47
#define _In_
Definition: intro_sal.h:21
static uint8_t _BitScanForward64(uint32_t *Index, uint64_t Mask)
Definition: intrinsics.h:104
BYTE BitMaskTestAndReset(BITMASK *BitMask, DWORD BitPos)
Tests and clears a bit in a BITMASK.
Definition: bitmask.c:214
#define ERROR(fmt,...)
Definition: glue.h:62
#define HpAllocWithTag(Len, Tag)
Definition: glue.h:516
void BitMaskFree(BITMASK **BitMask)
Frees a BITMASK allocated by BitMaskAlloc.
Definition: bitmask.c:83
static UINT64 * BitMaskGetBase(BITMASK *BitMask, DWORD BitPos)
Returns the bit base for a given bit position.
Definition: bitmask.c:37
#define _Inout_
Definition: intro_sal.h:20
size_t Length
The number of bits included.
Definition: bitmask.h:17
static UINT64 * BitMaskGetBaseAndBit(BITMASK *BitMask, DWORD *BitPos)
Return the base and the position of a bit relative to that base.
Definition: bitmask.c:12
#define HpFreeAndNullWithTag(Add, Tag)
Definition: glue.h:517
unsigned long long UINT64
Definition: intro_types.h:40
uint32_t DWORD
Definition: intro_types.h:49
#define IC_TAG_ALLOC
Memory allocation.
Definition: memtags.h:28
BYTE BitMaskTest(BITMASK *BitMask, DWORD BitPos)
Tests a bit in a BITMASK.
Definition: bitmask.c:151
BYTE BitMaskTestAndSet(BITMASK *BitMask, DWORD BitPos)
Tests and sets a bit in a BITMASK.
Definition: bitmask.c:180
void BitMaskSet(BITMASK *BitMask, DWORD BitPos)
Sets a bit in a BITMASK.
Definition: bitmask.c:97