From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-x242.google.com (mail-wm0-x242.google.com [IPv6:2a00:1450:400c:c09::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id C654B81E06 for ; Mon, 14 Nov 2016 03:06:54 -0800 (PST) Received: by mail-wm0-x242.google.com with SMTP id m203so14231105wma.3 for ; Mon, 14 Nov 2016 03:06:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=akeo-ie.20150623.gappssmtp.com; s=20150623; h=to:from:subject:message-id:date:user-agent:mime-version :content-transfer-encoding; bh=oigT4lVJU108wSKjHO/Ss4GC2eRYJpIJfo3XuSHC0cI=; b=u2j/G8OYx9XHf9zZNVQXxoZOrTJtc04okxP8FUMOFKKUx9Vzt5UNbZAxbiLUePIejk odz5ng4XrkSpX08CzlLAhZD7DIzak/73J+CB+0u4mJMmfOJD69CSQmUnzgmJWJYXyvpT nBttIFdxqchJfQAoKjNwBxPhVAOOp7z/xLkQedoT5PLPwkJD8GST6/e+QZSh+ZdNYNeV btSVrBAiA2HgtKHiOX12OlcRmDRqjx3+vR9qIZrpuYw2ZRIvIZDDoepUpLypAAHTp7X7 dqBnZS+3v0yIWCyHKJlCz9MknpsNWZdjExftjg7DweZVMAnH82ymZTldZbOwPPNhcWdI PLbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-transfer-encoding; bh=oigT4lVJU108wSKjHO/Ss4GC2eRYJpIJfo3XuSHC0cI=; b=fniCgxzlJEvTtE9giIbZ10vzFL1s5zC/JANDennLqNSjAQIAXeCgNKkgdtnAG3Xo/7 MbYDgVyoY6hFumYR/d5UDPJZcwj1jesZoTLRT18xaWZabphjSTp787a1vKqUART8NIdW s+m2SHzy3ZKS3rDGXj0uAJM9yQ/FjWRTasNEcFtHacFC/NW5Tp9RAr20vArYwJ7S2Yos cmkpq+87icKKxvhikTzJDsymapWc/c61bFEs2mrrpskgB0bEm2YV4CL4CEmmcwPe6mly nzi9n9Fx3MOk36kYe04iKsZ3aEDDKGTU2LufQFAciJPwo9CJRaEKSf16WxWFZVwjPH11 8wmA== X-Gm-Message-State: ABUngvdKerdm/o/kspLhgLO9MIyb9BvVRicC/AMYNNtSt81EqdvSORdv2Vn8LeLKLmLE1g== X-Received: by 10.28.7.198 with SMTP id 189mr9640692wmh.65.1479121617590; Mon, 14 Nov 2016 03:06:57 -0800 (PST) Received: from [10.0.0.101] ([84.203.71.247]) by smtp.googlemail.com with ESMTPSA id w66sm35540912wme.4.2016.11.14.03.06.56 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Nov 2016 03:06:57 -0800 (PST) To: "edk2-devel@lists.01.org" From: Pete Batard Message-ID: Date: Mon, 14 Nov 2016 11:06:56 +0000 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 Subject: [PATCH v2 1/3] MdeModulePkg/EbcDxe: add EBC Debugger X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 14 Nov 2016 11:06:55 -0000 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit This patch introduces EbcDebuggerHook.c/h and inserts the required EBCDebugger references into the existing EBC source files. With all the hooks defined to their empty version in EbcDebuggerHook.c the existing EBC VM behaviour is left unaffected. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Pete Batard --- MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c | 3 + MdeModulePkg/Universal/EbcDxe/EbcDebuggerHook.c | 158 +++++++++++++++++++++ MdeModulePkg/Universal/EbcDxe/EbcDebuggerHook.h | 113 +++++++++++++++ MdeModulePkg/Universal/EbcDxe/EbcDxe.inf | 4 +- MdeModulePkg/Universal/EbcDxe/EbcExecute.c | 39 +++++ MdeModulePkg/Universal/EbcDxe/EbcInt.c | 6 + MdeModulePkg/Universal/EbcDxe/Ia32/EbcSupport.c | 7 +- MdeModulePkg/Universal/EbcDxe/Ipf/EbcSupport.c | 9 +- MdeModulePkg/Universal/EbcDxe/X64/EbcSupport.c | 7 +- 9 files changed, 339 insertions(+), 7 deletions(-) create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebuggerHook.c create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebuggerHook.h diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c index c5cc76d..ade47c4 100644 --- a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c +++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c @@ -18,6 +18,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "EbcInt.h" #include "EbcExecute.h" +#include "EbcDebuggerHook.h" // // Amount of space that is not used in the stack @@ -225,6 +226,7 @@ EbcInterpret ( // // Begin executing the EBC code // + EbcDebuggerHookEbcInterpret (&VmContext); EbcExecute (&VmContext); // @@ -336,6 +338,7 @@ ExecuteEbcImageEntryPoint ( // // Begin executing the EBC code // + EbcDebuggerHookExecuteEbcImageEntryPoint (&VmContext); EbcExecute (&VmContext); // diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebuggerHook.c b/MdeModulePkg/Universal/EbcDxe/EbcDebuggerHook.c new file mode 100644 index 0000000..68fc472 --- /dev/null +++ b/MdeModulePkg/Universal/EbcDxe/EbcDebuggerHook.c @@ -0,0 +1,158 @@ +/** @file + Contains the empty version of the EBC Debugger hooks, to be used when + compiling the regular EBC VM module. + As debugging is not needed for the standard EBC VM, all calls are left empty. + + The EBC Debugger defines its own version for these calls in EbdHooks.c. + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +VOID +EbcDebuggerHookInit ( + IN EFI_HANDLE Handle, + IN EFI_DEBUG_SUPPORT_PROTOCOL *EbcDebugProtocol + ) +{ + return; +} + +VOID +EbcDebuggerHookUnload ( + VOID + ) +{ + return; +} + +VOID +EbcDebuggerHookEbcUnloadImage ( + IN EFI_HANDLE Handle + ) +{ + return; +} + +VOID +EbcDebuggerHookExecuteEbcImageEntryPoint ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookEbcInterpret ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookExecuteStart ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookExecuteEnd ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookCALLStart ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookCALLEnd ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookCALLEXStart ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookCALLEXEnd ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookRETStart ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookRETEnd ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookJMPStart ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookJMPEnd ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookJMP8Start ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} + +VOID +EbcDebuggerHookJMP8End ( + IN VM_CONTEXT *VmPtr + ) +{ + return; +} diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebuggerHook.h b/MdeModulePkg/Universal/EbcDxe/EbcDebuggerHook.h new file mode 100644 index 0000000..383052b --- /dev/null +++ b/MdeModulePkg/Universal/EbcDxe/EbcDebuggerHook.h @@ -0,0 +1,113 @@ +/** @file + Prototypes for the EBC Debugger hooks. + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _EFI_EBC_DEBUGGER_HOOK_H_ +#define _EFI_EBC_DEBUGGER_HOOK_H_ + +// +// Hooks in EbcInt.c +// +VOID +EbcDebuggerHookInit ( + IN EFI_HANDLE Handle, + IN EFI_DEBUG_SUPPORT_PROTOCOL *EbcDebugProtocol + ); + +VOID +EbcDebuggerHookUnload ( + VOID + ); + +VOID +EbcDebuggerHookEbcUnloadImage ( + IN EFI_HANDLE Handle + ); + +// +// Hooks in EbcSupport.c +// +VOID +EbcDebuggerHookExecuteEbcImageEntryPoint ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookEbcInterpret ( + IN VM_CONTEXT *VmPtr + ); + +// +// Hooks in EbcExecute.c +// +VOID +EbcDebuggerHookExecuteStart ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookExecuteEnd ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookCALLStart ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookCALLEnd ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookCALLEXStart ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookCALLEXEnd ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookRETStart ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookRETEnd ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookJMPStart ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookJMPEnd ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookJMP8Start ( + IN VM_CONTEXT *VmPtr + ); + +VOID +EbcDebuggerHookJMP8End ( + IN VM_CONTEXT *VmPtr + ); + +#endif diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf index e9a0b28..d11888e 100644 --- a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf +++ b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf @@ -33,6 +33,8 @@ # [Sources] + EbcDebuggerHook.h + EbcDebuggerHook.c EbcExecute.h EbcExecute.c EbcInt.h @@ -88,4 +90,4 @@ # EVENT_TYPE_PERIODIC_TIMER ## CONSUMES [UserExtensions.TianoCore."ExtraFiles"] - EbcDxeExtra.uni \ No newline at end of file + EbcDxeExtra.uni diff --git a/MdeModulePkg/Universal/EbcDxe/EbcExecute.c b/MdeModulePkg/Universal/EbcDxe/EbcExecute.c index d9c17f4..a4c51e9 100644 --- a/MdeModulePkg/Universal/EbcDxe/EbcExecute.c +++ b/MdeModulePkg/Universal/EbcDxe/EbcExecute.c @@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "EbcInt.h" #include "EbcExecute.h" +#include "EbcDebuggerHook.h" // @@ -1488,6 +1489,9 @@ EbcExecute ( Status = EFI_UNSUPPORTED; goto Done; } + + EbcDebuggerHookExecuteStart (VmPtr); + // // The EBC VM is a strongly ordered processor, so perform a fence operation before // and after each instruction is executed. @@ -1498,6 +1502,8 @@ EbcExecute ( MemoryFence (); + EbcDebuggerHookExecuteEnd (VmPtr); + // // If the step flag is set, signal an exception and continue. We don't // clear it here. Assuming the debugger is responsible for clearing it. @@ -1976,7 +1982,9 @@ ExecuteJMP ( ConditionFlag = (UINT8) VMFLAG_ISSET (VmPtr, VMFLAGS_CC); if ((Operand & CONDITION_M_CONDITIONAL) != 0) { if (CompareSet != ConditionFlag) { + EbcDebuggerHookJMPStart (VmPtr); VmPtr->Ip += Size; + EbcDebuggerHookJMPEnd (VmPtr); return EFI_SUCCESS; } } @@ -2015,11 +2023,13 @@ ExecuteJMP ( // // Take jump -- relative or absolute // + EbcDebuggerHookJMPStart (VmPtr); if ((Operand & JMP_M_RELATIVE) != 0) { VmPtr->Ip += (UINTN) Data64 + Size; } else { VmPtr->Ip = (VMIP) (UINTN) Data64; } + EbcDebuggerHookJMPEnd (VmPtr); return EFI_SUCCESS; } @@ -2065,11 +2075,14 @@ ExecuteJMP ( return EFI_UNSUPPORTED; } + EbcDebuggerHookJMPStart (VmPtr); if ((Operand & JMP_M_RELATIVE) != 0) { VmPtr->Ip += (UINTN) Addr + Size; } else { VmPtr->Ip = (VMIP) Addr; } + EbcDebuggerHookJMPEnd (VmPtr); + } else { // // Form: JMP32 Rx {Immed32} @@ -2085,11 +2098,14 @@ ExecuteJMP ( return EFI_UNSUPPORTED; } + EbcDebuggerHookJMPStart (VmPtr); if ((Operand & JMP_M_RELATIVE) != 0) { VmPtr->Ip += (UINTN) Addr + Size; } else { VmPtr->Ip = (VMIP) Addr; } + EbcDebuggerHookJMPEnd (VmPtr); + } return EFI_SUCCESS; @@ -2129,7 +2145,9 @@ ExecuteJMP8 ( // if ((Opcode & CONDITION_M_CONDITIONAL) != 0) { if (CompareSet != ConditionFlag) { + EbcDebuggerHookJMP8Start (VmPtr); VmPtr->Ip += 2; + EbcDebuggerHookJMP8End (VmPtr); return EFI_SUCCESS; } } @@ -2141,7 +2159,9 @@ ExecuteJMP8 ( // // Want to check for offset == -2 and then raise an exception? // + EbcDebuggerHookJMP8Start (VmPtr); VmPtr->Ip += (Offset * 2) + 2; + EbcDebuggerHookJMP8End (VmPtr); return EFI_SUCCESS; } @@ -2966,6 +2986,13 @@ ExecuteCALL ( // Opcode = GETOPCODE (VmPtr); Operands = GETOPERANDS (VmPtr); + + if (Operands & OPERAND_M_NATIVE_CALL) { + EbcDebuggerHookCALLEXStart (VmPtr); + } else { + EbcDebuggerHookCALLStart (VmPtr); + } + // // Assign these as well to avoid compiler warnings // @@ -3067,6 +3094,12 @@ ExecuteCALL ( } } + if (Operands & OPERAND_M_NATIVE_CALL) { + EbcDebuggerHookCALLEXEnd (VmPtr); + } else { + EbcDebuggerHookCALLEnd (VmPtr); + } + return EFI_SUCCESS; } @@ -3087,6 +3120,9 @@ ExecuteRET ( IN VM_CONTEXT *VmPtr ) { + + EbcDebuggerHookRETStart (VmPtr); + // // If we're at the top of the stack, then simply set the done // flag and return @@ -3114,6 +3150,9 @@ ExecuteRET ( VmPtr->Gpr[0] += 8; } + + EbcDebuggerHookRETEnd (VmPtr); + return EFI_SUCCESS; } diff --git a/MdeModulePkg/Universal/EbcDxe/EbcInt.c b/MdeModulePkg/Universal/EbcDxe/EbcInt.c index 549e0dd..6fd2aaf 100644 --- a/MdeModulePkg/Universal/EbcDxe/EbcInt.c +++ b/MdeModulePkg/Universal/EbcDxe/EbcInt.c @@ -16,6 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "EbcInt.h" #include "EbcExecute.h" +#include "EbcDebuggerHook.h" // // We'll keep track of all thunks we create in a linked list. Each @@ -497,6 +498,8 @@ InitializeEbcDriver ( InitEbcVmTestProtocol (&ImageHandle); DEBUG_CODE_END (); + EbcDebuggerHookInit (ImageHandle, EbcDebugProtocol); + return EFI_SUCCESS; ErrorExit: @@ -1094,6 +1097,9 @@ EbcUnloadImage ( // Now free up the image list element // FreePool (ImageList); + + EbcDebuggerHookEbcUnloadImage (ImageHandle); + return EFI_SUCCESS; } diff --git a/MdeModulePkg/Universal/EbcDxe/Ia32/EbcSupport.c b/MdeModulePkg/Universal/EbcDxe/Ia32/EbcSupport.c index bddfbf6..8e660b9 100644 --- a/MdeModulePkg/Universal/EbcDxe/Ia32/EbcSupport.c +++ b/MdeModulePkg/Universal/EbcDxe/Ia32/EbcSupport.c @@ -15,6 +15,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "EbcInt.h" #include "EbcExecute.h" +#include "EbcDebuggerHook.h" // // NOTE: This is the stack size allocated for the interpreter @@ -332,10 +333,11 @@ EbcInterpret ( // // Begin executing the EBC code // + EbcDebuggerHookEbcInterpret (&VmContext); EbcExecute (&VmContext); // - // Return the value in R[7] unless there was an error + // Return the value in Gpr[7] unless there was an error // ReturnEBCStack(StackIndex); return (UINT64) VmContext.Gpr[7]; @@ -432,10 +434,11 @@ ExecuteEbcImageEntryPoint ( // // Begin executing the EBC code // + EbcDebuggerHookExecuteEbcImageEntryPoint (&VmContext); EbcExecute (&VmContext); // - // Return the value in R[7] unless there was an error + // Return the value in Gpr[7] unless there was an error // ReturnEBCStack(StackIndex); return (UINT64) VmContext.Gpr[7]; diff --git a/MdeModulePkg/Universal/EbcDxe/Ipf/EbcSupport.c b/MdeModulePkg/Universal/EbcDxe/Ipf/EbcSupport.c index 23b6c1b..95837cb 100644 --- a/MdeModulePkg/Universal/EbcDxe/Ipf/EbcSupport.c +++ b/MdeModulePkg/Universal/EbcDxe/Ipf/EbcSupport.c @@ -16,6 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "EbcInt.h" #include "EbcExecute.h" #include "EbcSupport.h" +#include "EbcDebuggerHook.h" /** Given raw bytes of Itanium based code, format them into a bundle and @@ -214,12 +215,15 @@ EbcInterpret ( PushU64 (&VmContext, 0); PushU64 (&VmContext, 0xDEADBEEFDEADBEEF); VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0]; + // // Begin executing the EBC code // + EbcDebuggerHookEbcInterpret (&VmContext); EbcExecute (&VmContext); + // - // Return the value in R[7] unless there was an error + // Return the value in Gpr[7] unless there was an error // ReturnEBCStack(StackIndex); return (UINT64) VmContext.Gpr[7]; @@ -334,10 +338,11 @@ ExecuteEbcImageEntryPoint ( // // Begin executing the EBC code // + EbcDebuggerHookExecuteEbcImageEntryPoint (&VmContext); EbcExecute (&VmContext); // - // Return the value in R[7] unless there was an error + // Return the value in Gpr[7] unless there was an error // ReturnEBCStack(StackIndex); return (UINT64) VmContext.Gpr[7]; diff --git a/MdeModulePkg/Universal/EbcDxe/X64/EbcSupport.c b/MdeModulePkg/Universal/EbcDxe/X64/EbcSupport.c index bdde5e4..4325e2e 100644 --- a/MdeModulePkg/Universal/EbcDxe/X64/EbcSupport.c +++ b/MdeModulePkg/Universal/EbcDxe/X64/EbcSupport.c @@ -15,6 +15,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "EbcInt.h" #include "EbcExecute.h" +#include "EbcDebuggerHook.h" // // NOTE: This is the stack size allocated for the interpreter @@ -278,10 +279,11 @@ EbcInterpret ( // // Begin executing the EBC code // + EbcDebuggerHookEbcInterpret (&VmContext); EbcExecute (&VmContext); // - // Return the value in R[7] unless there was an error + // Return the value in Gpr[7] unless there was an error // ReturnEBCStack(StackIndex); return (UINT64) VmContext.Gpr[7]; @@ -389,10 +391,11 @@ ExecuteEbcImageEntryPoint ( // // Begin executing the EBC code // + EbcDebuggerHookExecuteEbcImageEntryPoint (&VmContext); EbcExecute (&VmContext); // - // Return the value in R[7] unless there was an error + // Return the value in Gpr[7] unless there was an error // ReturnEBCStack(StackIndex); return (UINT64) VmContext.Gpr[7]; -- 2.9.3.windows.2