Skip to content

Instantly share code, notes, and snippets.

@Kalinovcic
Created September 7, 2018 17:22
Show Gist options
  • Save Kalinovcic/ca2c346ec7622216da45b252bad1581f to your computer and use it in GitHub Desktop.
Save Kalinovcic/ca2c346ec7622216da45b252bad1581f to your computer and use it in GitHub Desktop.
Some code using undocumented NT profiling functions to count LLC misses. I don't know how accurate it is, haven't used it for anything yet.
typedef enum _KPROFILE_SOURCE
{
ProfileTime = 0x00,
ProfileTotalIssues = 0x02,
ProfileBranchInstructions = 0x06,
ProfileCacheMisses = 0x0A,
ProfileBranchMispredictions = 0x0B,
ProfileTotalCycles = 0x13,
ProfileUnhaltedCoreCycles = 0x19,
ProfileInstructionRetired = 0x1A,
ProfileUnhaltedReferenceCycles = 0x1B,
ProfileLLCReference = 0x1C,
ProfileLLCMisses = 0x1D,
ProfileBranchInstructionRetired = 0x1E,
ProfileBranchMispredictsRetired = 0x1F,
} KPROFILE_SOURCE, *PKPROFILE_SOURCE;
typedef NTSYSAPI NTSTATUS NTAPI F_NtCreateProfile(
OUT PHANDLE ProfileHandle,
IN HANDLE Process OPTIONAL,
IN PVOID ImageBase,
IN ULONG ImageSize,
IN ULONG BucketSize,
IN PVOID Buffer,
IN ULONG BufferSize,
IN KPROFILE_SOURCE ProfileSource,
IN KAFFINITY Affinity
);
typedef NTSYSAPI NTSTATUS NTAPI F_NtStartProfile(
IN HANDLE ProfileHandle
);
typedef NTSYSAPI NTSTATUS NTAPI F_NtStopProfile(
IN HANDLE ProfileHandle
);
HMODULE GetCurrentModule()
{
HMODULE module = NULL;
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR) GetCurrentModule, &module);
return module;
}
void test()
{
HMODULE nt = LoadLibraryA("ntdll.dll");
F_NtCreateProfile* NtCreateProfile = (F_NtCreateProfile*) GetProcAddress(nt, "NtCreateProfile");
F_NtStartProfile* NtStartProfile = (F_NtStartProfile*) GetProcAddress(nt, "NtStartProfile");
F_NtStopProfile* NtStopProfile = (F_NtStopProfile*) GetProcAddress(nt, "NtStopProfile");
HANDLE process = GetCurrentProcess();
HMODULE module = GetCurrentModule();
printf("%p %p\n", process, module);
MODULEINFO module_info;
BOOL module_info_success = GetModuleInformation(process, module, &module_info, sizeof(module_info));
if (!module_info_success)
{
printf("GetModuleInformation() failed!\n");
return;
}
void* image_base = module_info.lpBaseOfDll;
umm image_size = module_info.SizeOfImage;
printf("%p\n", image_base);
printf("%d\n", (int) image_size);
HANDLE profile;
ULONG buffer[1] = {};
NTSTATUS create_status = NtCreateProfile(&profile, process, image_base, image_size, 30, buffer, 4, ProfileLLCMisses, -1);
printf("NtCreateProfile: %x\n", create_status);
NtStartProfile(profile);
{
int* matrix = (int*) malloc(sizeof(int) * 16 * 1024 * 16 * 1024);
for (int i = 0; i < 10000; i++)
for (int j = 0; j < 10000; j++)
matrix[i * 16 * 1024 + j] *= i * j;
free(matrix);
}
NtStopProfile(profile);
printf("Cache misses 1: %d\n", buffer[0]);
buffer[0] = 0;
NtStartProfile(profile);
{
int* matrix = (int*) malloc(sizeof(int) * 16 * 1024 * 16 * 1024);
for (int i = 0; i < 10000; i++)
for (int j = 0; j < 10000; j++)
matrix[j * 16 * 1024 + i] *= i * j;
free(matrix);
}
NtStopProfile(profile);
printf("Cache misses 2: %d\n", buffer[0]);
buffer[0] = 0;
exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment