VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/utils/cpu/exceptionsR3.cpp@ 78138

Last change on this file since 78138 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.5 KB
Line 
1/* $Id: exceptionsR3.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * exceptionsR3 - Tests various ring-3 CPU exceptions.
4 */
5
6/*
7 * Copyright (C) 2009-2019 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 <iprt/cdefs.h>
32#include <iprt/ctype.h>
33#include <iprt/getopt.h>
34#include <iprt/stream.h>
35#include <iprt/string.h>
36#include <iprt/test.h>
37#include <iprt/x86.h>
38
39#include <setjmp.h>
40
41#ifndef RT_OS_WINDOWS
42# define USE_SIGNALS
43# include <signal.h>
44# include <stdlib.h>
45#endif
46
47
48/*********************************************************************************************************************************
49* Defined Constants And Macros *
50*********************************************************************************************************************************/
51/** Executes a simple test. */
52#define TST_XCPT(Trapper, iTrap, uErr) \
53 do \
54 { \
55 RTTestISub(#Trapper); \
56 tstXcptReset(); \
57 if (!setjmp(g_JmpBuf)) \
58 { \
59 tstXcptAsm##Trapper(); \
60 RTTestIFailed("%s didn't trap (line no %u)", #Trapper, __LINE__); \
61 } \
62 else if ( (iTrap) != tstXcptCurTrap() \
63 || (uErr) != tstXcptCurErr() ) \
64 RTTestIFailed("%s trapped with %#x/%#x, expected %#x/%#x (line no %u)", \
65 #Trapper, tstXcptCurTrap(), tstXcptCurErr(), (iTrap), (uErr), __LINE__); \
66 else \
67 RTTestISubDone(); \
68 } while (0)
69
70
71/*********************************************************************************************************************************
72* Global Variables *
73*********************************************************************************************************************************/
74/** Where to longjmp to when getting a signal/exception. */
75jmp_buf g_JmpBuf;
76#ifdef USE_SIGNALS
77/** Pending signal.
78 * -1 if no signal is pending. */
79int32_t volatile g_iSignal;
80/** Pending signal info. */
81siginfo_t volatile g_SigInfo;
82#endif
83
84
85/*********************************************************************************************************************************
86* Internal Functions *
87*********************************************************************************************************************************/
88DECLASM(void) tstXcptAsmNullPtrRead(void);
89DECLASM(void) tstXcptAsmNullPtrWrite(void);
90DECLASM(void) tstXcptAsmSysEnter(void);
91DECLASM(void) tstXcptAsmSysCall(void);
92
93
94
95#ifdef USE_SIGNALS
96/**
97 * Generic signal handler.
98 */
99static void tstXcptSigHandler(int iSignal, siginfo_t *pSigInfo, void *pvCtx)
100{
101#if 1
102 RTStrmPrintf(g_pStdErr, "signal %d pSigInfo=%p pvCtx=%p", iSignal, pSigInfo, pvCtx);
103 if (pSigInfo)
104 RTStrmPrintf(g_pStdErr, " si_addr=%p si_code=%#x sival_ptr=%p sival_int=%d",
105 pSigInfo->si_addr, pSigInfo->si_code, pSigInfo->si_value.sival_ptr, pSigInfo->si_value.sival_int);
106 RTStrmPrintf(g_pStdErr, "\n");
107#endif
108 if (g_iSignal == -1)
109 {
110 g_iSignal = iSignal;
111 if (pSigInfo)
112 memcpy((void *)&g_SigInfo, pSigInfo, sizeof(g_SigInfo));
113 longjmp(g_JmpBuf, 1);
114 }
115 else
116 {
117 /* we're up the infamous creek... */
118 _Exit(2);
119 }
120}
121
122#elif defined(RT_OS_WINDOWS)
123/** @todo */
124//# error "PORTME"
125
126#else
127# error "PORTME"
128#endif
129
130
131/** Reset the current exception state and get ready for a new trap. */
132static void tstXcptReset(void)
133{
134#ifdef USE_SIGNALS
135 g_iSignal = -1;
136 memset((void *)&g_SigInfo, 0, sizeof(g_SigInfo));
137#endif
138}
139
140
141
142/** Get the current intel trap number. Returns -1 if none. */
143static int tstXcptCurTrap(void)
144{
145#ifdef USE_SIGNALS
146 /** @todo this is just a quick sketch. */
147 switch (g_iSignal)
148 {
149 case SIGBUS:
150# ifdef RT_OS_DARWIN
151 if (g_SigInfo.si_code == 2 /*KERN_PROTECTION_FAILURE*/)
152 return X86_XCPT_PF;
153# endif
154 return X86_XCPT_GP;
155
156 case SIGSEGV:
157 return X86_XCPT_GP;
158 }
159#endif
160 return -1;
161}
162
163
164/** Get the exception error code if applicable. */
165static uint32_t tstXcptCurErr(void)
166{
167#ifdef USE_SIGNALS
168 /** @todo this is just a quick sketch. */
169 switch (g_iSignal)
170 {
171 case SIGBUS:
172# ifdef RT_OS_DARWIN
173 if (g_SigInfo.si_code == 2 /*KERN_PROTECTION_FAILURE*/)
174 return 0;
175# endif
176 break;
177
178 case SIGSEGV:
179 break;
180 }
181#endif
182 return UINT32_MAX;
183}
184
185
186int main(int argc, char **argv)
187{
188 /*
189 * Prolog.
190 */
191 RTTEST hTest;
192 int rc = RTTestInitAndCreate("exceptionsR3", &hTest);
193 if (rc)
194 return rc;
195
196 /*
197 * Parse options.
198 */
199 bool volatile fRawMode = false;
200 static const RTGETOPTDEF s_aOptions[] =
201 {
202 { "--raw-mode", 'r', RTGETOPT_REQ_NOTHING },
203 };
204
205 RTGETOPTUNION ValUnion;
206 RTGETOPTSTATE GetState;
207 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
208 while ((rc = RTGetOpt(&GetState, &ValUnion)))
209 {
210 switch (rc)
211 {
212 case 'r':
213 fRawMode = true;
214 break;
215
216 default:
217 return RTGetOptPrintError(rc, &ValUnion);
218 }
219 }
220
221 /*
222 * Test setup.
223 */
224#ifdef USE_SIGNALS
225 struct sigaction Act;
226 RT_ZERO(Act);
227 Act.sa_sigaction = tstXcptSigHandler;
228 Act.sa_flags = SA_SIGINFO;
229 sigfillset(&Act.sa_mask);
230
231 sigaction(SIGILL, &Act, NULL);
232 sigaction(SIGTRAP, &Act, NULL);
233# ifdef SIGEMT
234 sigaction(SIGEMT, &Act, NULL);
235# endif
236 sigaction(SIGFPE, &Act, NULL);
237 sigaction(SIGBUS, &Act, NULL);
238 sigaction(SIGSEGV, &Act, NULL);
239
240#else
241 /** @todo Implement this using structured exception handling on Windows and
242 * OS/2. */
243#endif
244
245 /*
246 * The tests.
247 */
248 RTTestBanner(hTest);
249 TST_XCPT(NullPtrRead, X86_XCPT_PF, 0);
250 TST_XCPT(NullPtrWrite, X86_XCPT_PF, 0);
251 if (fRawMode)
252 {
253 TST_XCPT(SysEnter, X86_XCPT_GP, 0);
254 TST_XCPT(SysCall, X86_XCPT_UD, 0);
255 }
256
257 /*
258 * Epilog.
259 */
260 return RTTestSummaryAndDestroy(hTest);
261}
262
Note: See TracBrowser for help on using the repository browser.

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