-
-
Save kika123/39d598f05b78f51486e8 to your computer and use it in GitHub Desktop.
ARM code support on Windows RT/IoT detection and example.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ARM code support on Windows RT/IoT detection and example. | |
// By Myria, 2016/03/03. | |
#ifndef _M_ARM_NT | |
#error "This code is for ARMv7-Thumb2 only." | |
#endif | |
#define _WIN32_WINNT 0x0602 | |
#include <errno.h> | |
#include <stdbool.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <Windows.h> | |
#include <process.h> | |
#pragma warning(suppress:4325) | |
#pragma section(".text", read, execute) | |
static DWORD WINAPI DummyThreadProc(void *context) | |
{ | |
(void) context; | |
return 0; | |
} | |
bool DetectKernelARMSupport(void) | |
{ | |
HANDLE thread = (HANDLE) CreateThread(NULL, 4096, DummyThreadProc, NULL, CREATE_SUSPENDED, NULL); | |
if (!thread) | |
{ | |
fprintf(stderr, "DetectKernelARMSupport: Unable to create helper thread: %d\n", errno); | |
return false; | |
} | |
CONTEXT context; | |
memset(&context, 0xCC, sizeof(context)); | |
context.ContextFlags = CONTEXT_CONTROL; | |
if (!GetThreadContext(thread, &context)) | |
{ | |
fprintf(stderr, "DetectKernelARMSupport: GetThreadContext[1] on helper thread failed: %lu\n", GetLastError()); | |
TerminateThread(thread, 0); | |
CloseHandle(thread); | |
return false; | |
} | |
printf("Before: PC = %08lX, CPSR = %08lX, T = %lu\n", context.Pc, context.Cpsr, (context.Cpsr >> 5) & 1); | |
// Attempt to put the thread into ARM mode. | |
context.Pc &= ~(DWORD) 3; | |
context.Cpsr &= ~(DWORD) (1 << 5); | |
if (!SetThreadContext(thread, &context)) | |
{ | |
fprintf(stderr, "DetectKernelARMSupport: SetThreadContext on helper thread failed: %lu\n", GetLastError()); | |
TerminateThread(thread, 0); | |
CloseHandle(thread); | |
return false; | |
} | |
// Check whether we succeeded. | |
memset(&context, 0xFF, sizeof(context)); | |
context.ContextFlags = CONTEXT_CONTROL; | |
if (!GetThreadContext(thread, &context)) | |
{ | |
fprintf(stderr, "DetectKernelARMSupport: GetThreadContext[1] on helper thread failed: %lu\n", GetLastError()); | |
TerminateThread(thread, 0); | |
CloseHandle(thread); | |
return false; | |
} | |
printf("After: PC = %08lX, CPSR = %08lX, T = %lu\n", context.Pc, context.Cpsr, (context.Cpsr >> 5) & 1); | |
TerminateThread(thread, 0); | |
CloseHandle(thread); | |
// If the kernel doesn't support ARM, it will not allow us to clear the T bit via SetThreadContext. | |
return !(context.Pc & 3) && !(context.Cpsr & (1 << 5)); | |
} | |
// Test ARM execution for a short time. | |
__declspec(allocate(".text")) const uint32_t s_countTo5[] = | |
{ | |
0xE3A00000, // _00: mov r0, #0 | |
0xE2800001, // _04: add r0, r0, #r1 | |
0xE3500005, // _08: cmp r0, #5 | |
0x1AFFFFFC, // _0C: bne _04 | |
0xE12FFF1E, // _10: bx lr | |
}; | |
// Test ARM code for a long time. | |
__declspec(allocate(".text")) const uint32_t s_countToFourBillion[] = | |
{ | |
0xE3A00001, // _00: mov r0, #1 | |
0xE2800001, // _04: add r0, r0, #r1 | |
0xE3500000, // _08: cmp r0, #0 | |
0x1AFFFFFC, // _0C: bne _04 | |
0xE12FFF1E, // _10: bx lr | |
}; | |
union FunctionPointer | |
{ | |
unsigned (*m_function)(void); | |
uintptr_t m_pointer; | |
}; | |
C_ASSERT(RTL_FIELD_SIZE(union FunctionPointer, m_function) == RTL_FIELD_SIZE(union FunctionPointer, m_pointer)); | |
int main(void) | |
{ | |
printf("Kernel supports user-mode programs in ARM mode: %s\n", DetectKernelARMSupport() ? "YES" : "NO"); | |
// Call the sample functions. | |
union FunctionPointer countTo5; | |
union FunctionPointer countToFourBillion; | |
// Mask off the low bit because the compiler likes to add 1 if the object is in a code section. | |
countTo5.m_pointer = ((uintptr_t) s_countTo5) & ~(uintptr_t) 1; | |
countToFourBillion.m_pointer = ((uintptr_t) s_countToFourBillion) & ~(uintptr_t) 1; | |
printf("countTo5: %08IX, %08X\n", countTo5.m_pointer, (*countTo5.m_function)()); | |
fflush(stdout); | |
printf("countToFourBillion: %08IX %08X\n", countToFourBillion.m_pointer, (*countToFourBillion.m_function)()); | |
fflush(stdout); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment