VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/utils/cpu/cidet-app.cpp@ 53563

Last change on this file since 53563 was 53563, checked in by vboxsync, 10 years ago

cidet: More hacking.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.4 KB
Line 
1/* $Id: cidet-app.cpp 53563 2014-12-18 02:31:37Z vboxsync $ */
2/** @file
3 * CPU Instruction Decoding & Execution Tests - Ring-3 Driver Application.
4 */
5
6/*
7 * Copyright (C) 2014 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include "cidet.h"
32
33#include <iprt/asm-amd64-x86.h>
34#include <iprt/buildconfig.h>
35#include <iprt/getopt.h>
36#include <iprt/initterm.h>
37#include <iprt/mem.h>
38#include <iprt/param.h>
39#include <iprt/rand.h>
40#include <iprt/stream.h>
41#include <iprt/string.h>
42#include <iprt/test.h>
43
44#ifdef RT_OS_WINDOWS
45# include <Windows.h>
46#else
47# define USE_SIGNALS
48# include <signal.h>
49# include <unistd.h>
50#endif
51
52
53
54/*******************************************************************************
55* Structures and Typedefs *
56*******************************************************************************/
57/**
58 * CIDET driver app buffer.
59 */
60typedef struct CIDETAPPBUF
61{
62 /** The buffer size. */
63 size_t cb;
64 /** The normal allocation.
65 * There is a fence page before this as well as at pbNormal+cb. */
66 uint8_t *pbNormal;
67 /** The low memory allocation (32-bit addressable if 64-bit host, 16-bit
68 * addressable if 32-bit host). */
69 uint8_t *pbLow;
70 /** Set if we're using the normal buffer, clear if it's the low one. */
71 bool fUsingNormal : 1;
72 /** Set if the buffer is armed, clear if mostly accessible. */
73 bool fArmed : 1;
74 /** Set if this is a code buffer. */
75 bool fIsCode : 1;
76 /** The memory protection for the pages (RTMEM_PROT_XXX). */
77 uint8_t fDefaultProt : 3;
78 /** The memory protection for the last page (RTMEM_PROT_XXX). */
79 uint8_t fLastPageProt : 3;
80 /** The buffer index. */
81 uint16_t idxCfg;
82} CIDETAPPBUF;
83/** Pointer to a CIDET driver app buffer. */
84typedef CIDETAPPBUF *PCIDETAPPBUF;
85
86/** Number of code buffers. */
87#define CIDETAPP_CODE_BUF_COUNT 1
88/** Number of data buffers. */
89#define CIDETAPP_DATA_BUF_COUNT 1
90
91
92/**
93 * CIDET driver app instance.
94 */
95typedef struct CIDETAPP
96{
97 /** The core structure. */
98 CIDETCORE Core;
99 /** The execute return context. */
100 CIDETCPUCTX ExecuteCtx;
101 /** Code buffers (runs parallel to g_aCodeBufCfgs). */
102 CIDETAPPBUF aCodeBuffers[CIDETAPP_CODE_BUF_COUNT];
103 /** Data buffers (runs parallel to g_aDataBufCfgs). */
104 CIDETAPPBUF aDataBuffers[CIDETAPP_DATA_BUF_COUNT];
105
106 /** The lowest stack address. */
107 uint8_t *pbStackLow;
108 /** The end of the stack allocation (highest address). */
109 uint8_t *pbStackEnd;
110 /** Stack size (= pbStackEnd - pbStackLow). */
111 uint32_t cbStack;
112} CIDETAPP;
113/** Pointer to a CIDET driver app instance. */
114typedef CIDETAPP *PCIDETAPP;
115/** Pointer to a pointer to a CIDET driver app instance. */
116typedef PCIDETAPP *PPCIDETAPP;
117
118
119/*******************************************************************************
120* Global Variables *
121*******************************************************************************/
122/** The test instance handle. */
123static RTTEST g_hTest;
124/** Points to the instance data while executing, NULL if not executing or if
125 * we've already handled the first exception while executing. */
126static PCIDETAPP volatile g_pExecutingThis;
127
128
129/** Code buffer configurations (parallel to CIDETAPP::aCodeBuffers). */
130static CIDETBUFCFG g_aCodeBufCfgs[CIDETAPP_CODE_BUF_COUNT] =
131{
132 {
133 "Normal",
134 CIDETBUF_PROT_RWX | CIDETBUF_DPL_3 | CIDETBUF_DPL_SAME | CIDETBUF_SEG_ER | CIDETBUF_KIND_CODE,
135 },
136};
137
138/** Data buffer configurations (parallel to CIDETAPP::aDataBuffers). */
139static CIDETBUFCFG g_aDataBufCfgs[CIDETAPP_DATA_BUF_COUNT] =
140{
141 {
142 "Normal",
143 CIDETBUF_PROT_RWX | CIDETBUF_DPL_3 | CIDETBUF_DPL_SAME | CIDETBUF_SEG_RW | CIDETBUF_KIND_DATA,
144 },
145};
146
147
148/*******************************************************************************
149* Internal Functions *
150*******************************************************************************/
151DECLASM(void) CidetAppSaveAndRestoreCtx(void);
152DECLASM(void) CidetAppRestoreCtx(PCCIDETCPUCTX pRestoreCtx);
153DECLASM(void) CidetAppExecute(PCIDETCPUCTX pSaveCtx, PCCIDETCPUCTX pRestoreCtx);
154
155
156/*
157 *
158 *
159 * Exception and signal handling.
160 * Exception and signal handling.
161 * Exception and signal handling.
162 *
163 *
164 */
165
166#ifdef RT_OS_WINDOWS
167static int CidetAppXcptFilter(EXCEPTION_POINTERS *pXcptPtrs)
168{
169 /*
170 * Grab the this point. We expect at most one signal.
171 */
172 PCIDETAPP pThis = g_pExecutingThis;
173 g_pExecutingThis = NULL;
174 if (pThis == NULL)
175 {
176 /* we're up the infamous creek... */
177 for (;;) ExitProcess(2);
178 }
179
180 /*
181 * Gather CPU state information from the context structure.
182 */
183 CONTEXT *pSrcCtx = pXcptPtrs->ContextRecord;
184# ifdef RT_ARCH_AMD64
185 if ( (pSrcCtx->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS))
186 != (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS))
187 __debugbreak();
188 pThis->Core.ActualCtx.rip = pSrcCtx->Rip;
189 pThis->Core.ActualCtx.rfl = pSrcCtx->EFlags;
190 pThis->Core.ActualCtx.aGRegs[X86_GREG_xAX] = pSrcCtx->Rax;
191 pThis->Core.ActualCtx.aGRegs[X86_GREG_xCX] = pSrcCtx->Rcx;
192 pThis->Core.ActualCtx.aGRegs[X86_GREG_xDX] = pSrcCtx->Rdx;
193 pThis->Core.ActualCtx.aGRegs[X86_GREG_xBX] = pSrcCtx->Rbx;
194 pThis->Core.ActualCtx.aGRegs[X86_GREG_xSP] = pSrcCtx->Rsp;
195 pThis->Core.ActualCtx.aGRegs[X86_GREG_xBP] = pSrcCtx->Rbp;
196 pThis->Core.ActualCtx.aGRegs[X86_GREG_xSI] = pSrcCtx->Rsi;
197 pThis->Core.ActualCtx.aGRegs[X86_GREG_xDI] = pSrcCtx->Rdi;
198 pThis->Core.ActualCtx.aGRegs[X86_GREG_x8] = pSrcCtx->R8;
199 pThis->Core.ActualCtx.aGRegs[X86_GREG_x9] = pSrcCtx->R9;
200 pThis->Core.ActualCtx.aGRegs[X86_GREG_x10] = pSrcCtx->R10;
201 pThis->Core.ActualCtx.aGRegs[X86_GREG_x11] = pSrcCtx->R11;
202 pThis->Core.ActualCtx.aGRegs[X86_GREG_x12] = pSrcCtx->R12;
203 pThis->Core.ActualCtx.aGRegs[X86_GREG_x13] = pSrcCtx->R13;
204 pThis->Core.ActualCtx.aGRegs[X86_GREG_x14] = pSrcCtx->R14;
205 pThis->Core.ActualCtx.aGRegs[X86_GREG_x15] = pSrcCtx->R15;
206 pThis->Core.ActualCtx.aSRegs[X86_SREG_ES] = pSrcCtx->SegEs;
207 pThis->Core.ActualCtx.aSRegs[X86_SREG_CS] = pSrcCtx->SegCs;
208 pThis->Core.ActualCtx.aSRegs[X86_SREG_SS] = pSrcCtx->SegSs;
209 pThis->Core.ActualCtx.aSRegs[X86_SREG_DS] = pSrcCtx->SegDs;
210 pThis->Core.ActualCtx.aSRegs[X86_SREG_FS] = pSrcCtx->SegFs;
211 pThis->Core.ActualCtx.aSRegs[X86_SREG_GS] = pSrcCtx->SegGs;
212 if (pSrcCtx->ContextFlags & CONTEXT_FLOATING_POINT)
213 {
214 /* ... */
215 }
216 if (pSrcCtx->ContextFlags & CONTEXT_DEBUG_REGISTERS)
217 {
218 /* ... */
219 }
220
221# elif defined(RT_ARCH_X86)
222 if ( (pSrcCtx->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS))
223 != (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS))
224 __debugbreak();
225 pThis->Core.ActualCtx.rip = pSrcCtx->Eip;
226 pThis->Core.ActualCtx.rfl = pSrcCtx->EFlags;
227 pThis->Core.ActualCtx.aGRegs[X86_GREG_xAX] = pSrcCtx->Eax;
228 pThis->Core.ActualCtx.aGRegs[X86_GREG_xCX] = pSrcCtx->Ecx;
229 pThis->Core.ActualCtx.aGRegs[X86_GREG_xDX] = pSrcCtx->Edx;
230 pThis->Core.ActualCtx.aGRegs[X86_GREG_xBX] = pSrcCtx->Ebx;
231 pThis->Core.ActualCtx.aGRegs[X86_GREG_xSP] = pSrcCtx->Esp;
232 pThis->Core.ActualCtx.aGRegs[X86_GREG_xBP] = pSrcCtx->Ebp;
233 pThis->Core.ActualCtx.aGRegs[X86_GREG_xSI] = pSrcCtx->Esi;
234 pThis->Core.ActualCtx.aGRegs[X86_GREG_xDI] = pSrcCtx->Edi;
235 pThis->Core.ActualCtx.aGRegs[X86_GREG_x8] = 0;
236 pThis->Core.ActualCtx.aGRegs[X86_GREG_x9] = 0;
237 pThis->Core.ActualCtx.aGRegs[X86_GREG_x10] = 0;
238 pThis->Core.ActualCtx.aGRegs[X86_GREG_x11] = 0;
239 pThis->Core.ActualCtx.aGRegs[X86_GREG_x12] = 0;
240 pThis->Core.ActualCtx.aGRegs[X86_GREG_x13] = 0;
241 pThis->Core.ActualCtx.aGRegs[X86_GREG_x14] = 0;
242 pThis->Core.ActualCtx.aGRegs[X86_GREG_x15] = 0;
243 pThis->Core.ActualCtx.aSRegs[X86_SREG_ES] = pSrcCtx->SegEs;
244 pThis->Core.ActualCtx.aSRegs[X86_SREG_CS] = pSrcCtx->SegCs;
245 pThis->Core.ActualCtx.aSRegs[X86_SREG_SS] = pSrcCtx->SegSs;
246 pThis->Core.ActualCtx.aSRegs[X86_SREG_DS] = pSrcCtx->SegDs;
247 pThis->Core.ActualCtx.aSRegs[X86_SREG_FS] = pSrcCtx->SegFs;
248 pThis->Core.ActualCtx.aSRegs[X86_SREG_GS] = pSrcCtx->SegGs;
249 if (pSrcCtx->ContextFlags & CONTEXT_FLOATING_POINT)
250 {
251 /* ... */
252 }
253 if (pSrcCtx->ContextFlags & CONTEXT_EXTENDED_REGISTERS)
254 {
255 /* ... */
256 }
257 if (pSrcCtx->ContextFlags & CONTEXT_DEBUG_REGISTERS)
258 {
259 /* ... */
260 }
261# else
262# error "Not supported"
263# endif
264
265 /*
266 * Add/Adjust CPU state information according to the exception code.
267 */
268 pThis->Core.ActualCtx.uErr = UINT64_MAX;
269 switch (pXcptPtrs->ExceptionRecord->ExceptionCode)
270 {
271 case EXCEPTION_INT_DIVIDE_BY_ZERO:
272 pThis->Core.ActualCtx.uXcpt = X86_XCPT_DE;
273 break;
274 case EXCEPTION_SINGLE_STEP:
275 pThis->Core.ActualCtx.uXcpt = X86_XCPT_DB;
276 break;
277 case EXCEPTION_BREAKPOINT:
278 pThis->Core.ActualCtx.uXcpt = X86_XCPT_BP;
279 break;
280 case EXCEPTION_INT_OVERFLOW:
281 pThis->Core.ActualCtx.uXcpt = X86_XCPT_OF;
282 break;
283 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
284 pThis->Core.ActualCtx.uXcpt = X86_XCPT_BR;
285 break;
286 case EXCEPTION_ILLEGAL_INSTRUCTION:
287 pThis->Core.ActualCtx.uXcpt = X86_XCPT_UD;
288 break;
289
290 case EXCEPTION_PRIV_INSTRUCTION:
291 pThis->Core.ActualCtx.uXcpt = X86_XCPT_GP;
292 pThis->Core.ActualCtx.uErr = 0;
293 break;
294
295 case EXCEPTION_ACCESS_VIOLATION:
296 {
297 pThis->Core.ActualCtx.uXcpt = X86_XCPT_PF;
298 pThis->Core.ActualCtx.cr2 = pXcptPtrs->ExceptionRecord->ExceptionInformation[1];
299 pThis->Core.ActualCtx.uErr = 0;
300 if (pXcptPtrs->ExceptionRecord->ExceptionInformation[0] == EXCEPTION_WRITE_FAULT)
301 pThis->Core.ActualCtx.uErr = X86_TRAP_PF_RW;
302 else if (pXcptPtrs->ExceptionRecord->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
303 pThis->Core.ActualCtx.uErr = X86_TRAP_PF_ID;
304 else if (pXcptPtrs->ExceptionRecord->ExceptionInformation[0] != EXCEPTION_READ_FAULT)
305 AssertFatalFailed();
306
307 MEMORY_BASIC_INFORMATION MemInfo = {0};
308 if (VirtualQuery((PVOID)pXcptPtrs->ExceptionRecord->ExceptionInformation[1], &MemInfo, sizeof(MemInfo)) > 0)
309 switch (MemInfo.Protect & 0xff)
310 {
311 case PAGE_NOACCESS:
312 break;
313 case PAGE_READONLY:
314 case PAGE_READWRITE:
315 case PAGE_WRITECOPY:
316 case PAGE_EXECUTE:
317 case PAGE_EXECUTE_READ:
318 case PAGE_EXECUTE_READWRITE:
319 case PAGE_EXECUTE_WRITECOPY:
320 pThis->Core.ActualCtx.uErr |= X86_TRAP_PF_P;
321 break;
322 default:
323 AssertFatalFailed();
324 }
325 break;
326 }
327
328 case EXCEPTION_FLT_DENORMAL_OPERAND:
329 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
330 case EXCEPTION_FLT_INEXACT_RESULT:
331 case EXCEPTION_FLT_INVALID_OPERATION:
332 case EXCEPTION_FLT_OVERFLOW:
333 case EXCEPTION_FLT_STACK_CHECK:
334 case EXCEPTION_FLT_UNDERFLOW:
335 pThis->Core.ActualCtx.uXcpt = X86_XCPT_MF;
336 break;
337
338 case EXCEPTION_DATATYPE_MISALIGNMENT:
339 pThis->Core.ActualCtx.uXcpt = X86_XCPT_AC;
340 break;
341
342 default:
343 pThis->Core.ActualCtx.uXcpt = pXcptPtrs->ExceptionRecord->ExceptionCode;
344 break;
345 }
346
347 /*
348 * Our own personal long jump implementation.
349 */
350 CidetAppRestoreCtx(&pThis->ExecuteCtx);
351
352 /* Won't return...*/
353 return EXCEPTION_EXECUTE_HANDLER;
354}
355
356
357/**
358 * Vectored exception handler.
359 *
360 * @returns Long jumps or terminates the process.
361 * @param pXcptPtrs The exception record.
362 */
363static LONG CALLBACK CidetAppVectoredXcptHandler(EXCEPTION_POINTERS *pXcptPtrs)
364{
365 RTStrmPrintf(g_pStdErr, "CidetAppVectoredXcptHandler!\n");
366 CidetAppXcptFilter(pXcptPtrs);
367
368 /* won't get here. */
369 return EXCEPTION_CONTINUE_SEARCH;
370}
371
372
373/**
374 * Unhandled exception filter.
375 *
376 * @returns Long jumps or terminates the process.
377 * @param pXcptPtrs The exception record.
378 */
379static LONG CALLBACK CidetAppUnhandledXcptFilter(EXCEPTION_POINTERS *pXcptPtrs)
380{
381 RTStrmPrintf(g_pStdErr, "CidetAppUnhandledXcptFilter!\n");
382 CidetAppXcptFilter(pXcptPtrs);
383
384 /* won't get here. */
385 return EXCEPTION_CONTINUE_SEARCH;
386}
387
388
389#elif defined(USE_SIGNALS)
390/**
391 * Signal handler.
392 */
393static void CidetAppSigHandler(int iSignal, siginfo_t *pSigInfo, void *pvCtx)
394{
395# if 1
396 RTStrmPrintf(g_pStdErr, "signal %d pSigInfo=%p pvCtx=%p", iSignal, pSigInfo, pvCtx);
397 if (pSigInfo)
398 RTStrmPrintf(g_pStdErr, " si_addr=%p si_code=%#x sival_ptr=%p sival_int=%d",
399 pSigInfo->si_addr, pSigInfo->si_code, pSigInfo->si_value.sival_ptr, pSigInfo->si_value.sival_int);
400 RTStrmPrintf(g_pStdErr, "\n");
401# endif
402
403 /*
404 * Grab the this point. We expect at most one signal.
405 */
406 PCIDETAPP pThis = g_pExecutingThis;
407 g_pExecutingThis = NULL;
408 if (pThis == NULL)
409 {
410 /* we're up the infamous creek... */
411 RTStrmPrintf(g_pStdErr, "Creek time!\n");
412 for (;;) _exit(2);
413 }
414
415 /*
416 * Gather all the CPU state information available.
417 */
418
419
420 /*
421 * Jump back to CidetAppCbExecute.
422 */
423 CidetAppRestoreCtx(&pThis->ExecuteCtx);
424}
425#endif
426
427
428
429/*
430 *
431 * Buffer handling
432 * Buffer handling
433 * Buffer handling
434 *
435 *
436 */
437
438static int cidetAppAllocateAndConfigureOneBuffer(PCIDETAPP pThis, PCIDETAPPBUF pBuf, uint16_t idxBuf, bool fIsCode,
439 uint32_t fFlags)
440{
441 static uint8_t const s_afBufProtToDefaultMemProt[] =
442 {
443 /* [0] = */ RTMEM_PROT_NONE,
444 /* [1] = */ RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC,
445 /* [2] = */ RTMEM_PROT_READ | RTMEM_PROT_WRITE,
446 /* [3] = */ RTMEM_PROT_READ | RTMEM_PROT_EXEC,
447 /* [4] = */ RTMEM_PROT_READ,
448 /* [5] = */ RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC,
449 /* [6] = */ RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC,
450 /* [7] = */ RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC,
451 /* [8] = */ RTMEM_PROT_NONE,
452 /* [9] = */ RTMEM_PROT_NONE,
453 /* [10] = */ RTMEM_PROT_NONE,
454 /* [11] = */ RTMEM_PROT_NONE,
455 /* [12] = */ RTMEM_PROT_NONE,
456 /* [13] = */ RTMEM_PROT_NONE,
457 /* [14] = */ RTMEM_PROT_NONE,
458 /* [15] = */ RTMEM_PROT_NONE,
459 };
460 static uint8_t const s_afBufProtToLastPageMemProt[] =
461 {
462 /* [0] = */ RTMEM_PROT_NONE,
463 /* [1] = */ RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC,
464 /* [2] = */ RTMEM_PROT_READ | RTMEM_PROT_WRITE,
465 /* [3] = */ RTMEM_PROT_READ | RTMEM_PROT_EXEC,
466 /* [4] = */ RTMEM_PROT_READ,
467 /* [5] = */ RTMEM_PROT_NONE,
468 /* [6] = */ RTMEM_PROT_READ | RTMEM_PROT_WRITE,
469 /* [7] = */ RTMEM_PROT_READ,
470 /* [8] = */ RTMEM_PROT_NONE,
471 /* [9] = */ RTMEM_PROT_NONE,
472 /* [10] = */ RTMEM_PROT_NONE,
473 /* [11] = */ RTMEM_PROT_NONE,
474 /* [12] = */ RTMEM_PROT_NONE,
475 /* [13] = */ RTMEM_PROT_NONE,
476 /* [14] = */ RTMEM_PROT_NONE,
477 /* [15] = */ RTMEM_PROT_NONE,
478 };
479
480 int rc;
481 Assert(CIDETBUF_IS_CODE(fFlags) == fIsCode);
482 pBuf->fIsCode = fIsCode;
483 pBuf->idxCfg = idxBuf;
484 pBuf->fUsingNormal = true;
485 pBuf->fDefaultProt = s_afBufProtToDefaultMemProt[fFlags & CIDETBUF_PROT_MASK];
486 pBuf->fLastPageProt = s_afBufProtToLastPageMemProt[fFlags & CIDETBUF_PROT_MASK];
487 if (pBuf->fDefaultProt != RTMEM_PROT_NONE)
488 {
489 /*
490 * Allocate a 3 page buffer plus two fence pages.
491 */
492 pBuf->cb = fIsCode ? CIDET_CODE_BUF_SIZE : CIDET_DATA_BUF_SIZE;
493 pBuf->pbNormal = (uint8_t *)RTMemPageAlloc(PAGE_SIZE + pBuf->cb + PAGE_SIZE);
494 if (pBuf->pbNormal)
495 {
496 memset(pBuf->pbNormal, 0x55, PAGE_SIZE);
497 memset(pBuf->pbNormal + PAGE_SIZE, 0xcc, pBuf->cb);
498 memset(pBuf->pbNormal + PAGE_SIZE + pBuf->cb, 0x77, PAGE_SIZE);
499
500 /* Set up fence pages. */
501 rc = RTMemProtect(pBuf->pbNormal, PAGE_SIZE, RTMEM_PROT_NONE); /* fence */
502 if (RT_SUCCESS(rc))
503 rc = RTMemProtect(pBuf->pbNormal + PAGE_SIZE + pBuf->cb, PAGE_SIZE, RTMEM_PROT_NONE); /* fence */
504 pBuf->pbNormal += PAGE_SIZE;
505
506 /* Default protection + read + write. */
507 if (RT_SUCCESS(rc))
508 rc = RTMemProtect(pBuf->pbNormal, pBuf->cb, pBuf->fDefaultProt | RTMEM_PROT_READ | RTMEM_PROT_WRITE);
509
510 /*
511 * Allocate a low memory buffer or LDT if necessary.
512 */
513 if ( RT_SUCCESS(rc)
514 && (uintptr_t)pBuf->pbNormal + pBuf->cb > RT_BIT_64(sizeof(uintptr_t) / 2 * 8))
515 {
516 /** @todo Buffers for the other addressing mode. */
517 pBuf->pbLow = NULL;
518 }
519 else
520 pBuf->pbLow = pBuf->pbNormal;
521 if (RT_SUCCESS(rc))
522 return VINF_SUCCESS;
523
524 }
525 else
526 rc = RTTestIFailedRc(VERR_NO_PAGE_MEMORY, "Error allocating three pages.");
527 }
528 else
529 rc = RTTestIFailedRc(VERR_NO_PAGE_MEMORY, "Unsupported buffer config: fFlags=%#x, idxBuf=%u", fFlags, idxBuf);
530 return rc;
531}
532
533
534static void CidetAppDeleteBuffer(PCIDETAPPBUF pBuf)
535{
536 RTMemProtect(pBuf->pbNormal - PAGE_SIZE, PAGE_SIZE + pBuf->cb + PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
537 RTMemPageFree(pBuf->pbNormal - PAGE_SIZE, PAGE_SIZE + pBuf->cb + PAGE_SIZE);
538 if (pBuf->pbLow != pBuf->pbNormal && pBuf->pbLow)
539 {
540 RTMemProtect(pBuf->pbLow, pBuf->cb, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
541 RTMemFreeEx(pBuf->pbLow, pBuf->cb);
542 }
543}
544
545
546static bool CidetAppArmBuf(PCIDETAPP pThis, PCIDETAPPBUF pAppBuf)
547{
548 uint8_t *pbUsingBuf = (pAppBuf->fUsingNormal ? pAppBuf->pbNormal : pAppBuf->pbLow);
549 if (pAppBuf->fLastPageProt == pAppBuf->fDefaultProt)
550 {
551 if ((pAppBuf->fDefaultProt & (RTMEM_PROT_READ | RTMEM_PROT_WRITE)) != (RTMEM_PROT_READ | RTMEM_PROT_WRITE))
552 RTTESTI_CHECK_RC_RET(RTMemProtect(pbUsingBuf, pAppBuf->cb, pAppBuf->fDefaultProt), VINF_SUCCESS, false);
553 }
554 else
555 {
556 if ((pAppBuf->fDefaultProt & (RTMEM_PROT_READ | RTMEM_PROT_WRITE)) != (RTMEM_PROT_READ | RTMEM_PROT_WRITE))
557 RTTESTI_CHECK_RC_RET(RTMemProtect(pbUsingBuf, pAppBuf->cb - PAGE_SIZE, pAppBuf->fDefaultProt), VINF_SUCCESS, false);
558 RTTESTI_CHECK_RC_RET(RTMemProtect(pbUsingBuf + pAppBuf->cb - PAGE_SIZE, PAGE_SIZE, pAppBuf->fLastPageProt),
559 VINF_SUCCESS, false);
560 }
561 pAppBuf->fArmed = true;
562 return true;
563}
564
565
566static bool CidetAppDearmBuf(PCIDETAPP pThis, PCIDETAPPBUF pAppBuf)
567{
568 uint8_t *pbUsingBuf = (pAppBuf->fUsingNormal ? pAppBuf->pbNormal : pAppBuf->pbLow);
569 int rc = RTMemProtect(pbUsingBuf, pAppBuf->cb, pAppBuf->fDefaultProt | RTMEM_PROT_READ | RTMEM_PROT_WRITE);
570 if (RT_FAILURE(rc))
571 {
572 RTTestIFailed("RTMemProtect failed on %s buf #%u: %Rrc", pAppBuf->fIsCode ? "code" : "data", pAppBuf->idxCfg, rc);
573 return false;
574 }
575 pAppBuf->fArmed = false;
576 return true;
577}
578
579
580/**
581 * @interface_method_impl{CIDETCORE::pfnReInitDataBuf}
582 */
583static DECLCALLBACK(bool) CidetAppCbReInitDataBuf(PCIDETCORE pThis, PCIDETBUF pBuf)
584{
585 PCIDETAPP pThisApp = (PCIDETAPP)pThis;
586 PCIDETAPPBUF pAppBuf = &pThisApp->aDataBuffers[pBuf->idxCfg];
587 Assert(CIDETBUF_IS_DATA(pBuf->pCfg->fFlags));
588
589 /*
590 * De-arm the buffer.
591 */
592 if (pAppBuf->fArmed)
593 if (RT_UNLIKELY(!CidetAppDearmBuf(pThisApp, pAppBuf)))
594 return false;
595
596 /*
597 * Check the allocation requirements.
598 */
599 if (RT_UNLIKELY((size_t)pBuf->off + pBuf->cb > pAppBuf->cb))
600 {
601 RTTestIFailed("Buffer too small; off=%#x cb=%#x pAppBuf->cb=%#x (%s)",
602 pBuf->off, pBuf->cb, pAppBuf->cb, pBuf->pCfg->pszName);
603 return false;
604 }
605
606 /*
607 * Do we need to use the low buffer? Check that we have one, if we need it.
608 */
609 bool fUseNormal = pThis->cbAddrMode == ARCH_BITS;
610 if (!fUseNormal && !pAppBuf->pbLow)
611 return false;
612
613 /*
614 * Update the state.
615 */
616 pAppBuf->fUsingNormal = fUseNormal;
617
618 pBuf->offActive = pBuf->off;
619 pBuf->cbActive = pBuf->cb;
620 pBuf->cbPrologue = 0;
621 pBuf->cbEpilogue = 0;
622 pBuf->uSeg = UINT32_MAX;
623 pBuf->cbActiveSegLimit = UINT64_MAX;
624 pBuf->uSegBase = 0;
625 if (fUseNormal)
626 pBuf->uEffBufAddr = (uintptr_t)pAppBuf->pbNormal;
627 else
628 pBuf->uEffBufAddr = (uintptr_t)pAppBuf->pbLow;
629
630 return true;
631}
632
633
634/**
635 * @interface_method_impl{CIDETCORE::pfnSetupDataBuf}
636 */
637static DECLCALLBACK(bool) CidetAppCbSetupDataBuf(PCIDETCORE pThis, PCIDETBUF pBuf, void const *pvSrc)
638{
639 PCIDETAPP pThisApp = (PCIDETAPP)pThis;
640 PCIDETAPPBUF pAppBuf = &pThisApp->aDataBuffers[pBuf->idxCfg];
641 Assert(CIDETBUF_IS_DATA(pBuf->pCfg->fFlags));
642 Assert(!pAppBuf->fArmed);
643
644
645 /*
646 * Copy over the data.
647 */
648 uint8_t *pbUsingBuf = (pAppBuf->fUsingNormal ? pAppBuf->pbNormal : pAppBuf->pbLow);
649 memcpy(pbUsingBuf + pBuf->offActive, pvSrc, pBuf->cbActive);
650
651 /*
652 * Arm the buffer.
653 */
654 return CidetAppArmBuf(pThisApp, pAppBuf);
655}
656
657
658/**
659 * @interface_method_impl{CIDETCORE::pfnIsBufEqual}
660 */
661static DECLCALLBACK(bool) CidetAppCbIsBufEqual(PCIDETCORE pThis, struct CIDETBUF *pBuf, void const *pvExpected)
662{
663 PCIDETAPP pThisApp = (PCIDETAPP)pThis;
664 PCIDETAPPBUF pAppBuf = CIDETBUF_IS_CODE(pBuf->pCfg->fFlags)
665 ? &pThisApp->aCodeBuffers[pBuf->idxCfg]
666 : &pThisApp->aDataBuffers[pBuf->idxCfg];
667
668 /*
669 * Disarm the buffer if we can't read it all.
670 */
671 if ( pAppBuf->fArmed
672 && ( !(pAppBuf->fLastPageProt & RTMEM_PROT_READ)
673 || !(pAppBuf->fDefaultProt & RTMEM_PROT_READ)) )
674 if (RT_UNLIKELY(!CidetAppDearmBuf(pThisApp, pAppBuf)))
675 return false;
676
677 /*
678 * Do the comparing.
679 */
680 uint8_t *pbUsingBuf = (pAppBuf->fUsingNormal ? pAppBuf->pbNormal : pAppBuf->pbLow);
681 if (memcmp(pbUsingBuf + pBuf->offActive, pvExpected, pBuf->cbActive) != 0)
682 {
683 /** @todo RTMEM_PROT_NONE may kill content on some hosts... */
684 return false;
685 }
686
687 /** @todo check padding. */
688 return true;
689}
690
691
692/*
693 *
694 * Code buffer, prologue, epilogue, and execution.
695 * Code buffer, prologue, epilogue, and execution.
696 * Code buffer, prologue, epilogue, and execution.
697 *
698 *
699 */
700
701
702/**
703 * @interface_method_impl{CIDETCORE::pfnReInitCodeBuf}
704 */
705static DECLCALLBACK(bool) CidetAppCbReInitCodeBuf(PCIDETCORE pThis, PCIDETBUF pBuf)
706{
707 PCIDETAPP pThisApp = (PCIDETAPP)pThis;
708 PCIDETAPPBUF pAppBuf = &pThisApp->aCodeBuffers[pBuf->idxCfg];
709 Assert(CIDETBUF_IS_CODE(pBuf->pCfg->fFlags));
710 Assert(pAppBuf->fUsingNormal);
711
712 /*
713 * De-arm the buffer.
714 */
715 if (pAppBuf->fArmed)
716 if (RT_UNLIKELY(!CidetAppDearmBuf(pThisApp, pAppBuf)))
717 return false;
718
719 /*
720 * Determin the prologue and epilogue sizes.
721 */
722 uint16_t cbPrologue = 0;
723 uint16_t cbEpilogue = ARCH_BITS == 64 ? 0x56 : 0x4e;
724 if (pThis->InCtx.fTrickyStack)
725 cbEpilogue = 16;
726
727 /*
728 * Check the allocation requirements.
729 */
730 if (RT_UNLIKELY( cbPrologue > pBuf->off
731 || (size_t)pBuf->off + pBuf->cb + cbEpilogue > pAppBuf->cb))
732 {
733 RTTestIFailed("Buffer too small; off=%#x cb=%#x cbPro=%#x cbEpi=%#x pAppBuf->cb=%#x (%s)",
734 pBuf->off, pBuf->cb, cbPrologue, cbEpilogue, pAppBuf->cb, pBuf->pCfg->pszName);
735 return false;
736 }
737
738 /*
739 * Update the state.
740 */
741 pAppBuf->fUsingNormal = true;
742
743 pBuf->cbActive = pBuf->cb;
744 pBuf->offActive = pBuf->off;
745 pBuf->cbPrologue = cbPrologue;
746 pBuf->cbEpilogue = cbEpilogue;
747 pBuf->uSeg = UINT32_MAX;
748 pBuf->cbActiveSegLimit = UINT64_MAX;
749 pBuf->uSegBase = 0;
750 pBuf->uEffBufAddr = (uintptr_t)pAppBuf->pbNormal;
751
752 return true;
753}
754
755
756/**
757 * @interface_method_impl{CIDETCORE::pfnSetupCodeBuf}
758 */
759static DECLCALLBACK(bool) CidetAppCbSetupCodeBuf(PCIDETCORE pThis, PCIDETBUF pBuf, void const *pvInstr)
760{
761 PCIDETAPP pThisApp = (PCIDETAPP)pThis;
762 PCIDETAPPBUF pAppBuf =&pThisApp->aCodeBuffers[pBuf->idxCfg];
763 Assert(CIDETBUF_IS_CODE(pBuf->pCfg->fFlags));
764 Assert(pAppBuf->fUsingNormal);
765 Assert(!pAppBuf->fArmed);
766
767 /*
768 * Emit prologue code.
769 */
770 uint8_t *pbDst = pAppBuf->pbNormal + pBuf->offActive - pBuf->cbPrologue;
771
772 /*
773 * Copy over the code.
774 */
775 Assert(pbDst == &pAppBuf->pbNormal[pBuf->offActive]);
776 memcpy(pbDst, pvInstr, pBuf->cbActive);
777 pbDst += pBuf->cbActive;
778
779 /*
780 * Emit epilogue code.
781 */
782 if (!pThis->InCtx.fTrickyStack)
783 {
784 /*
785 * The stack is reasonably good, do minimal work.
786 *
787 * Note! Ideally, we would just fill in 16 int3s here and check that
788 * we hit the first right one. However, if we wish to run this
789 * code with IEM, we better skip unnecessary trips to ring-0.
790 */
791
792 /* jmp $+6 */
793 *pbDst++ = 0xeb;
794 *pbDst++ = 0x06; /* This is a push es, so if the decoder is one off, we'll hit the int 3 below. */
795
796 /* Six int3s for trapping incorrectly decoded instructions. */
797 *pbDst++ = 0xcc;
798 *pbDst++ = 0xcc;
799 *pbDst++ = 0xcc;
800 *pbDst++ = 0xcc;
801 *pbDst++ = 0xcc;
802 *pbDst++ = 0xcc;
803
804 /* push rip / call $+0 */
805 *pbDst++ = 0xe8;
806 *pbDst++ = 0x00;
807 *pbDst++ = 0x00;
808 *pbDst++ = 0x00;
809 *pbDst++ = 0x00;
810
811 /* push xCX */
812 *pbDst++ = 0x51;
813
814 /* mov xCX, [xSP + xCB] */
815 *pbDst++ = 0x48;
816 *pbDst++ = 0x8b;
817 *pbDst++ = 0x4c;
818 *pbDst++ = 0x24;
819 *pbDst++ = 0x08;
820
821 /* lea xCX, [xCX - 14] */
822 *pbDst++ = 0x48;
823 *pbDst++ = 0x8d;
824 *pbDst++ = 0x49;
825 *pbDst++ = 0xf2;
826
827 /* mov xCX, [xSP + xCB] */
828 *pbDst++ = 0x48;
829 *pbDst++ = 0x89;
830 *pbDst++ = 0x4c;
831 *pbDst++ = 0x24;
832 *pbDst++ = 0x08;
833
834 /* mov xCX, &pThis->ActualCtx */
835#ifdef RT_ARCH_AMD64
836 *pbDst++ = 0x48;
837#endif
838 *pbDst++ = 0xb9;
839 *(uintptr_t *)pbDst = (uintptr_t)&pThisApp->Core.ActualCtx;
840 pbDst += sizeof(uintptr_t);
841
842 /* pop [ss:rcx + ActualCtx.aGRegs[X86_GREG_xCX]] */
843 *pbDst++ = 0x36;
844 *pbDst++ = 0x8f;
845 *pbDst++ = 0x41;
846 *pbDst++ = RT_OFFSETOF(CIDETCPUCTX, aGRegs[X86_GREG_xCX]);
847 Assert(RT_OFFSETOF(CIDETCPUCTX, aGRegs[X86_GREG_xCX]) < 0x7f);
848
849 /* mov [ss:rcx + ActualCtx.aGRegs[X86_GREG_xDX]], rdx */
850 *pbDst++ = 0x36;
851#ifdef RT_ARCH_AMD64
852 *pbDst++ = 0x48;
853#endif
854 *pbDst++ = 0x89;
855 *pbDst++ = 0x51;
856 *pbDst++ = RT_OFFSETOF(CIDETCPUCTX, aGRegs[X86_GREG_xDX]);
857 Assert(RT_OFFSETOF(CIDETCPUCTX, aGRegs[X86_GREG_xDX]) < 0x7f);
858
859 /* mov [ss:rcx + ActualCtx.aSRegs[X86_GREG_DS]], ds */
860 *pbDst++ = 0x36;
861 *pbDst++ = 0x8c;
862 *pbDst++ = 0x99;
863 *(uint32_t *)pbDst = RT_OFFSETOF(CIDETCPUCTX, aSRegs[X86_SREG_DS]);
864 pbDst += sizeof(uint32_t);
865
866 /* mov edx, 0XXYYh */
867 *pbDst++ = 0xba;
868 *(uint32_t *)pbDst = pThisApp->Core.InTemplateCtx.aSRegs[X86_SREG_DS];
869 pbDst += sizeof(uint32_t);
870
871 /* mov ds, dx */
872 *pbDst++ = 0x8e;
873 *pbDst++ = 0xda;
874
875 /* mov xDX, &pThisApp->ExecuteCtx */
876#ifdef RT_ARCH_AMD64
877 *pbDst++ = 0x48;
878#endif
879 *pbDst++ = 0xba;
880 *(uintptr_t *)pbDst = (uintptr_t)&pThisApp->ExecuteCtx;
881 pbDst += sizeof(uintptr_t);
882
883#ifdef RT_ARCH_AMD64
884 /* jmp [cs:$ wrt rip] */
885 *pbDst++ = 0xff;
886 *pbDst++ = 0x25;
887 *(uint32_t *)pbDst = 0;
888 pbDst += sizeof(uint32_t);
889#else
890 /* jmp NAME(CidetAppSaveAndRestoreCtx) */
891 *pbDst++ = 0xb9;
892#endif
893 *(uintptr_t *)pbDst = (uintptr_t)CidetAppSaveAndRestoreCtx;
894 pbDst += sizeof(uintptr_t);
895
896 /* int3 */
897 *pbDst++ = 0xcc;
898 }
899 else
900 {
901 /*
902 * Tricky stack, so just make it raise #UD after a successful run.
903 */
904 *pbDst++ = 0xf0; /* lock prefix */
905 //*pbDst++ = 0xcc; /* lock prefix */
906 memset(pbDst, 0xcc, 15); /* int3 */
907 pbDst += 15;
908 }
909
910 AssertMsg(pbDst == &pAppBuf->pbNormal[pBuf->offActive + pBuf->cb + pBuf->cbEpilogue],
911 ("cbEpilogue=%#x, actual %#x\n", pBuf->cbEpilogue, pbDst - &pAppBuf->pbNormal[pBuf->offActive + pBuf->cb]));
912
913 /*
914 * Arm the buffer.
915 */
916 return CidetAppArmBuf(pThisApp, pAppBuf);
917}
918
919
920/**
921 * @interface_method_impl{CIDETCORE::pfnExecute}
922 */
923static DECLCALLBACK(bool) CidetAppCbExecute(PCIDETCORE pThis)
924{
925#if defined(RT_OS_WINDOWS)
926 /* Skip tricky stack because windows cannot dispatch exception if RSP/ESP is bad. */
927 if (pThis->InCtx.fTrickyStack)
928 return false;
929#endif
930
931 g_pExecutingThis = (PCIDETAPP)pThis;
932#ifdef RT_OS_WINDOWS
933 __try
934 {
935 CidetAppExecute(&((PCIDETAPP)pThis)->ExecuteCtx, &pThis->InCtx);
936 }
937 __except (CidetAppXcptFilter(GetExceptionInformation()))
938 {
939 /* Won't end up here... */
940 }
941#else
942 CidetAppExecute(&((PCIDETAPP)pThis)->ExecuteCtx, &pThis->InCtx);
943#endif
944 g_pExecutingThis = NULL;
945
946 return true;
947}
948
949
950
951
952/*
953 *
954 *
955 * CIDET Application.
956 * CIDET Application.
957 * CIDET Application.
958 *
959 *
960 */
961
962
963/**
964 * @interface_method_impl{CIDETCORE::pfnSetupBuf}
965 */
966static DECLCALLBACK(void) CidetAppCbFailureV(PCIDETCORE pThis, const char *pszMsg, va_list va)
967{
968 RTTestIFailedV(pszMsg, va);
969}
970
971
972static int cidetAppAllocateAndConfigureBuffers(PCIDETAPP pThis)
973{
974 /*
975 * Code buffers.
976 */
977 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCodeBuffers); i++)
978 {
979 int rc = cidetAppAllocateAndConfigureOneBuffer(pThis, &pThis->aCodeBuffers[i], i, true /*fCode*/,
980 g_aCodeBufCfgs[i].fFlags);
981 if (RT_FAILURE(rc))
982 return rc;
983 }
984
985 /*
986 * Data buffers.
987 */
988 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aDataBuffers); i++)
989 {
990 int rc = cidetAppAllocateAndConfigureOneBuffer(pThis, &pThis->aDataBuffers[i], i, false /*fCode*/,
991 g_aDataBufCfgs[i].fFlags);
992 if (RT_FAILURE(rc))
993 return rc;
994 }
995
996 /*
997 * Stack.
998 */
999 pThis->cbStack = _32K;
1000 pThis->pbStackLow = (uint8_t *)RTMemPageAlloc(pThis->cbStack);
1001 if (!pThis->pbStackLow)
1002 {
1003 RTTestIFailed("Failed to allocate %u bytes for stack\n", pThis->cbStack);
1004 return false;
1005 }
1006 pThis->pbStackEnd = pThis->pbStackLow + pThis->cbStack;
1007
1008 return true;
1009}
1010
1011
1012static int CidetAppCreate(PPCIDETAPP ppThis)
1013{
1014 PCIDETAPP pThis = (PCIDETAPP)RTMemAlloc(sizeof(*pThis));
1015 if (!pThis)
1016 return RTTestIFailedRc(VERR_NO_MEMORY, "Error allocating %zu bytes.", sizeof(*pThis));
1017
1018 /* Create a random source. */
1019 RTRAND hRand;
1020 int rc = RTRandAdvCreateParkMiller(&hRand);
1021 if (RT_SUCCESS(rc))
1022 {
1023 uint64_t uSeed = ASMReadTSC();
1024 rc = RTRandAdvSeed(hRand, uSeed);
1025 if (RT_SUCCESS(rc))
1026 RTTestIPrintf(RTTESTLVL_ALWAYS, "Random seed %#llx\n", uSeed);
1027
1028 /* Initialize the CIDET structure. */
1029 rc = CidetCoreInit(&pThis->Core, hRand);
1030 if (RT_SUCCESS(rc))
1031 {
1032 pThis->Core.pfnReInitDataBuf = CidetAppCbReInitDataBuf;
1033 pThis->Core.pfnSetupDataBuf = CidetAppCbSetupDataBuf;
1034 pThis->Core.pfnIsBufEqual = CidetAppCbIsBufEqual;
1035 pThis->Core.pfnReInitCodeBuf = CidetAppCbReInitCodeBuf;
1036 pThis->Core.pfnSetupCodeBuf = CidetAppCbSetupCodeBuf;
1037 pThis->Core.pfnExecute = CidetAppCbExecute;
1038 pThis->Core.pfnFailure = CidetAppCbFailureV;
1039
1040 pThis->Core.paCodeBufConfigs = g_aCodeBufCfgs;
1041 pThis->Core.cCodeBufConfigs = CIDETAPP_CODE_BUF_COUNT;
1042 pThis->Core.paDataBufConfigs = g_aDataBufCfgs;
1043 pThis->Core.cDataBufConfigs = CIDETAPP_DATA_BUF_COUNT;
1044
1045 rc = cidetAppAllocateAndConfigureBuffers(pThis);
1046 if (RT_SUCCESS(rc))
1047 {
1048 rc = CidetCoreSetTargetMode(&pThis->Core, ARCH_BITS == 32 ? CIDETMODE_PP_32 : CIDETMODE_LM_64);
1049 if (RT_SUCCESS(rc))
1050 {
1051 pThis->Core.InTemplateCtx.aSRegs[X86_SREG_CS] = ASMGetCS();
1052 pThis->Core.InTemplateCtx.aSRegs[X86_SREG_DS] = ASMGetDS();
1053 pThis->Core.InTemplateCtx.aSRegs[X86_SREG_ES] = ASMGetES();
1054 pThis->Core.InTemplateCtx.aSRegs[X86_SREG_FS] = ASMGetFS();
1055 pThis->Core.InTemplateCtx.aSRegs[X86_SREG_GS] = ASMGetGS();
1056 pThis->Core.InTemplateCtx.aSRegs[X86_SREG_SS] = ASMGetSS();
1057 pThis->Core.InTemplateCtx.aGRegs[X86_GREG_xSP] = (uintptr_t)pThis->pbStackEnd - 64;
1058
1059 *ppThis = pThis;
1060 return VINF_SUCCESS;
1061 }
1062 rc = RTTestIFailedRc(rc, "Error setting target mode: %Rrc", rc);
1063 }
1064 CidetCoreDelete(&pThis->Core);
1065 }
1066 else
1067 {
1068 rc = RTTestIFailedRc(rc, "CidetCoreInit failed: %Rrc", rc);
1069 RTRandAdvDestroy(hRand);
1070 }
1071 }
1072 else
1073 rc = RTTestIFailedRc(rc, "RTRandAdvCreate failed: %Rrc", rc);
1074 RTMemFree(pThis);
1075 *ppThis = NULL;
1076 return rc;
1077}
1078
1079
1080static void CidetAppDestroy(PCIDETAPP pThis)
1081{
1082 CidetCoreDelete(&pThis->Core);
1083
1084 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCodeBuffers); i++)
1085 CidetAppDeleteBuffer(&pThis->aCodeBuffers[i]);
1086 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aDataBuffers); i++)
1087 CidetAppDeleteBuffer(&pThis->aDataBuffers[i]);
1088 RTMemPageFree(pThis->pbStackLow, pThis->cbStack);
1089
1090 RTMemFree(pThis);
1091}
1092
1093
1094static void CidetAppTestBunch(PCIDETAPP pThis, PCCIDETINSTR paInstructions, uint32_t cInstructions, const char *pszBunchName)
1095{
1096 for (uint32_t iInstr = 0; iInstr < cInstructions; iInstr++)
1097 {
1098 RTTestSubF(g_hTest, "%s - %s", pszBunchName, paInstructions[iInstr].pszMnemonic);
1099 CidetCoreTestInstruction(&pThis->Core, &paInstructions[iInstr]);
1100 }
1101}
1102
1103
1104int main(int argc, char **argv)
1105{
1106 /*
1107 * Initialize the runtime.
1108 */
1109 RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, 0, "cidet-app", &g_hTest);
1110 if (rcExit != RTEXITCODE_SUCCESS)
1111 return rcExit;
1112
1113 /*
1114 * Parse arguments.
1115 */
1116 static const RTGETOPTDEF s_aOptions[] =
1117 {
1118 { "--noop", 'n', RTGETOPT_REQ_NOTHING },
1119 };
1120
1121 int chOpt;
1122 RTGETOPTUNION ValueUnion;
1123 RTGETOPTSTATE GetState;
1124 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
1125 while ((chOpt = RTGetOpt(&GetState, &ValueUnion)))
1126 {
1127 switch (chOpt)
1128 {
1129 case 'n':
1130 break;
1131
1132 case 'h':
1133 RTPrintf("usage: %s\n", argv[0]);
1134 return RTEXITCODE_SUCCESS;
1135
1136 case 'V':
1137 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
1138 return RTEXITCODE_SUCCESS;
1139
1140 default:
1141 return RTGetOptPrintError(chOpt, &ValueUnion);
1142 }
1143 }
1144
1145#ifdef USE_SIGNALS
1146 /*
1147 * Set up signal handlers with alternate stack.
1148 */
1149 /* Alternative stack so we can play with esp/rsp. */
1150 struct sigaltstack AltStack;
1151 RT_ZERO(AltStack);
1152 AltStack.ss_flags = SS_ONSTACK;
1153# ifdef SIGSTKSZ
1154 AltStack.ss_size = RT_MAX(SIGSTKSZ, _128K);
1155# else
1156 AltStack.ss_size = _128K;
1157# endif
1158 AltStack.ss_sp = RTMemPageAlloc(AltStack.ss_size);
1159 RTTESTI_CHECK_RET(AltStack.ss_sp != NULL, RTEXITCODE_FAILURE);
1160 RTTESTI_CHECK_RC_RET(sigaltstack(&AltStack, NULL), 0, RTEXITCODE_FAILURE);
1161
1162 /* Default signal action config. */
1163 struct sigaction Act;
1164 RT_ZERO(Act);
1165 Act.sa_sigaction = CidetAppSigHandler;
1166 Act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1167 sigfillset(&Act.sa_mask);
1168
1169 /* Hook the signals we might need. */
1170 sigaction(SIGILL, &Act, NULL);
1171 sigaction(SIGTRAP, &Act, NULL);
1172# ifdef SIGEMT
1173 sigaction(SIGEMT, &Act, NULL);
1174# endif
1175 sigaction(SIGFPE, &Act, NULL);
1176 sigaction(SIGBUS, &Act, NULL);
1177 sigaction(SIGSEGV, &Act, NULL);
1178
1179#elif defined(RT_OS_WINDOWS)
1180 /*
1181 * Register vectored exception handler and override the default unhandled
1182 * exception filter, just to be on the safe side...
1183 */
1184 RTTESTI_CHECK(AddVectoredExceptionHandler(1 /* first */, CidetAppVectoredXcptHandler) != NULL);
1185 SetUnhandledExceptionFilter(CidetAppUnhandledXcptFilter);
1186#endif
1187
1188 /*
1189 * Do the work.
1190 */
1191 RTTestBanner(g_hTest);
1192
1193 PCIDETAPP pThis;
1194 int rc = CidetAppCreate(&pThis);
1195 if (RT_SUCCESS(rc))
1196 {
1197 CidetAppTestBunch(pThis, g_aCidetInstructions1, g_cCidetInstructions1, "First Bunch");
1198
1199 CidetAppDestroy(pThis);
1200 }
1201
1202 return RTTestSummaryAndDestroy(g_hTest);
1203}
1204
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette