98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/* $Id$ */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/** @file
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * VirtualBox Support Library - Loader related bits.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Copyright (C) 2006-2013 Oracle Corporation
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * available from http://www.virtualbox.org. This file is free software;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * General Public License (GPL) as published by the Free Software
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * The contents of this file may alternatively be used under the terms
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * of the Common Development and Distribution License Version 1.0
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * VirtualBox OSE distribution, in which case the provisions of the
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * CDDL are applicable instead of those of the GPL.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * You may elect to license modified versions of this file under the
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * terms and conditions of either the GPL or the CDDL or both.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/** @page pg_sup SUP - The Support Library
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * The support library is responsible for providing facilities to load
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * VMM Host Ring-0 code, to call Host VMM Ring-0 code from Ring-3 Host
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * code, to pin down physical memory, and more.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * The VMM Host Ring-0 code can be combined in the support driver if
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * permitted by kernel module license policies. If it is not combined
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * it will be externalized in a .r0 module that will be loaded using
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * the IPRT loader.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * The Ring-0 calling is done thru a generic SUP interface which will
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * transfer an argument set and call a predefined entry point in the Host
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * VMM Ring-0 code.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * See @ref grp_sup "SUP - Support APIs" for API details.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/*******************************************************************************
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync* Header Files *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync*******************************************************************************/
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#define LOG_GROUP LOG_GROUP_SUP
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <VBox/sup.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <VBox/err.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <VBox/param.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <VBox/log.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <VBox/VBoxTpG.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/assert.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/alloc.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/alloca.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/ldr.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/asm.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/mp.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/cpuset.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/thread.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/process.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/path.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/string.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/env.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/rand.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include <iprt/x86.h>
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include "SUPDrvIOC.h"
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#include "SUPLibInternal.h"
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/*******************************************************************************
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync* Defined Constants And Macros *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync*******************************************************************************/
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/** R0 VMM module name. */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#define VMMR0_NAME "VMMR0"
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/*******************************************************************************
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync* Structures and Typedefs *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync*******************************************************************************/
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsynctypedef DECLCALLBACK(int) FNCALLVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsynctypedef FNCALLVMMR0 *PFNCALLVMMR0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/*******************************************************************************
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync* Global Variables *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync*******************************************************************************/
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/** VMMR0 Load Address. */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncstatic RTR0PTR g_pvVMMR0 = NIL_RTR0PTR;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/*******************************************************************************
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync* Internal Functions *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync*******************************************************************************/
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncstatic int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncstatic DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncSUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Check that the module can be trusted.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync int rc = SUPR3HardenedVerifyPlugIn(pszFilename, pErrInfo);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = supLoadModule(pszFilename, pszModule, NULL, ppvImageBase);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_FAILURE(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTErrInfoSetF(pErrInfo, rc, "SUPR3LoadModule: supLoadModule returned %Rrc", rc);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncSUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync const char *pszSrvReqHandler, void **ppvImageBase)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtrReturn(pszSrvReqHandler, VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Check that the module can be trusted.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync int rc = SUPR3HardenedVerifyPlugIn(pszFilename, NULL /*pErrInfo*/);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = supLoadModule(pszFilename, pszModule, pszSrvReqHandler, ppvImageBase);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUPR3LoadServiceModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/**
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Resolve an external symbol during RTLdrGetBits().
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @returns VBox status code.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param hLdrMod The loader module handle.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param pszModule Module name.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param pszSymbol Symbol name, NULL if uSymbol should be used.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param pValue Where to store the symbol value (address).
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param pvUser User argument.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncstatic DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule,
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync NOREF(hLdrMod); NOREF(pvUser); NOREF(uSymbol);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtr(pValue);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtr(pvUser);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Only SUPR0 and VMMR0.r0
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if ( pszModule
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && *pszModule
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && strcmp(pszModule, "VBoxDrv.sys")
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && strcmp(pszModule, "VMMR0.r0"))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitive)\n", pvUser, pszModule));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VERR_SYMBOL_NOT_FOUND;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * No ordinals.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (pszSymbol < (const char*)0x10000)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertMsgFailed(("%s is importing by ordinal (ord=%d)\n", pvUser, (int)(uintptr_t)pszSymbol));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VERR_SYMBOL_NOT_FOUND;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Lookup symbol.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /** @todo is this actually used??? */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /* skip the 64-bit ELF import prefix first. */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (!strncmp(pszSymbol, RT_STR_TUPLE("SUPR0$")))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pszSymbol += sizeof("SUPR0$") - 1;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Check the VMMR0.r0 module if loaded.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /** @todo call the SUPR3LoadModule caller.... */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /** @todo proper reference counting and such. */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (g_pvVMMR0 != NIL_RTR0PTR)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync void *pvValue;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (!SUPR3GetSymbolR0((void *)g_pvVMMR0, pszSymbol, &pvValue))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *pValue = (uintptr_t)pvValue;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /* iterate the function table. */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync int c = g_pSupFunctions->u.Out.cFunctions;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync PSUPFUNC pFunc = &g_pSupFunctions->u.Out.aFunctions[0];
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync while (c-- > 0)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (!strcmp(pFunc->szName, pszSymbol))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *pValue = (uintptr_t)pFunc->pfn;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pFunc++;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * The GIP.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if ( pszSymbol
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && g_pSUPGlobalInfoPage
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && g_pSUPGlobalInfoPageR0
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && !strcmp(pszSymbol, "g_SUPGlobalInfoPage")
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync )
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *pValue = (uintptr_t)g_pSUPGlobalInfoPageR0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Symbols that are undefined by convention.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#ifdef RT_OS_SOLARIS
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync static const char * const s_apszConvSyms[] =
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync "", "mod_getctl",
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync "", "mod_install",
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync "", "mod_remove",
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync "", "mod_info",
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync "", "mod_miscops",
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync };
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync for (unsigned i = 0; i < RT_ELEMENTS(s_apszConvSyms); i += 2)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if ( !RTStrCmp(s_apszConvSyms[i], pszModule)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && !RTStrCmp(s_apszConvSyms[i + 1], pszSymbol))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *pValue = ~(uintptr_t)0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#endif
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Despair.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync c = g_pSupFunctions->u.Out.cFunctions;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pFunc = &g_pSupFunctions->u.Out.aFunctions[0];
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync while (c-- > 0)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTAssertMsg2Weak("%d: %s\n", g_pSupFunctions->u.Out.cFunctions - c, pFunc->szName);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pFunc++;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertLogRelMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (g_uSupFakeMode)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *pValue = 0xdeadbeef;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VERR_SYMBOL_NOT_FOUND;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/** Argument package for supLoadModuleCalcSizeCB. */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsynctypedef struct SUPLDRCALCSIZEARGS
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync size_t cbStrings;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync uint32_t cSymbols;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync size_t cbImage;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync} SUPLDRCALCSIZEARGS, *PSUPLDRCALCSIZEARGS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/**
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Callback used to calculate the image size.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @return VINF_SUCCESS
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncstatic DECLCALLBACK(int) supLoadModuleCalcSizeCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync PSUPLDRCALCSIZEARGS pArgs = (PSUPLDRCALCSIZEARGS)pvUser;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if ( pszSymbol != NULL
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && *pszSymbol
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && Value <= pArgs->cbImage)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pArgs->cSymbols++;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pArgs->cbStrings += strlen(pszSymbol) + 1;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync NOREF(hLdrMod); NOREF(uSymbol);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/** Argument package for supLoadModuleCreateTabsCB. */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsynctypedef struct SUPLDRCREATETABSARGS
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync size_t cbImage;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync PSUPLDRSYM pSym;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync char *pszBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync char *psz;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync} SUPLDRCREATETABSARGS, *PSUPLDRCREATETABSARGS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/**
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Callback used to calculate the image size.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @return VINF_SUCCESS
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncstatic DECLCALLBACK(int) supLoadModuleCreateTabsCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync PSUPLDRCREATETABSARGS pArgs = (PSUPLDRCREATETABSARGS)pvUser;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if ( pszSymbol != NULL
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && *pszSymbol
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && Value <= pArgs->cbImage)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pArgs->pSym->offSymbol = (uint32_t)Value;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pArgs->pSym->offName = pArgs->psz - pArgs->pszBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pArgs->pSym++;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync size_t cbCopy = strlen(pszSymbol) + 1;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync memcpy(pArgs->psz, pszSymbol, cbCopy);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pArgs->psz += cbCopy;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync NOREF(hLdrMod); NOREF(uSymbol);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/**
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Worker for SUPR3LoadModule().
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @returns VBox status code.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param pszFilename Name of the VMMR0 image file
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncstatic int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync int rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Validate input.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtrReturn(pszModule, VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtrReturn(ppvImageBase, VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertReturn(strlen(pszModule) < RT_SIZEOFMEMB(SUPLDROPEN, u.In.szName), VERR_FILENAME_TOO_LONG);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync char szAbsFilename[RT_SIZEOFMEMB(SUPLDROPEN, u.In.szFilename)];
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_FAILURE(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pszFilename = szAbsFilename;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync const bool fIsVMMR0 = !strcmp(pszModule, "VMMR0.r0");
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertReturn(!pszSrvReqHandler || !fIsVMMR0, VERR_INTERNAL_ERROR);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *ppvImageBase = NULL;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Open image file and figure its size.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTLDRMOD hLdrMod;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_HOST, &hLdrMod);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (!RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: RTLdrOpen failed for %s (%s)\n", pszModule, pszFilename, rc));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync SUPLDRCALCSIZEARGS CalcArgs;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync CalcArgs.cbStrings = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync CalcArgs.cSymbols = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync CalcArgs.cbImage = RTLdrSize(hLdrMod);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCalcSizeCB, &CalcArgs);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync const uint32_t offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync const uint32_t offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync const uint32_t cbImageWithTabs = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Open the R0 image.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync SUPLDROPEN OpenReq;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.Hdr.u32Cookie = g_u32Cookie;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.Hdr.u32SessionCookie = g_u32SessionCookie;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.Hdr.cbIn = SUP_IOCTL_LDR_OPEN_SIZE_IN;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.Hdr.cbOut = SUP_IOCTL_LDR_OPEN_SIZE_OUT;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.Hdr.rc = VERR_INTERNAL_ERROR;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.u.In.cbImageWithTabs = cbImageWithTabs;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync strcpy(OpenReq.u.In.szName, pszModule);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync strcpy(OpenReq.u.In.szFilename, pszFilename);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (!g_uSupFakeMode)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = OpenReq.Hdr.rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.u.Out.fNeedsLoading = true;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.u.Out.pvImageBase = 0xef423420;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *ppvImageBase = (void *)OpenReq.u.Out.pvImageBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if ( RT_SUCCESS(rc)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && OpenReq.u.Out.fNeedsLoading)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * We need to load it.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Allocate memory for the image bits.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync PSUPLDRLOAD pLoadReq = (PSUPLDRLOAD)RTMemTmpAlloc(SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (pLoadReq)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Get the image bits.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync supLoadModuleResolveImport, (void *)pszModule);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Get the entry points.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTUINTPTR VMMR0EntryInt = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTUINTPTR VMMR0EntryFast = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTUINTPTR VMMR0EntryEx = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTUINTPTR SrvReqHandler = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTUINTPTR ModuleInit = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTUINTPTR ModuleTerm = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (fIsVMMR0)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
0c8e85263a357c44964520942cb5816ab1c2e69dvboxsync rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "VMMR0EntryInt", &VMMR0EntryInt);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
0c8e85263a357c44964520942cb5816ab1c2e69dvboxsync rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "VMMR0EntryFast", &VMMR0EntryFast);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
0c8e85263a357c44964520942cb5816ab1c2e69dvboxsync rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "VMMR0EntryEx", &VMMR0EntryEx);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else if (pszSrvReqHandler)
0c8e85263a357c44964520942cb5816ab1c2e69dvboxsync rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, pszSrvReqHandler, &SrvReqHandler);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
0c8e85263a357c44964520942cb5816ab1c2e69dvboxsync int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "ModuleInit", &ModuleInit);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_FAILURE(rc2))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync ModuleInit = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
0c8e85263a357c44964520942cb5816ab1c2e69dvboxsync rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "ModuleTerm", &ModuleTerm);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_FAILURE(rc2))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync ModuleTerm = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Create the symbol and string tables.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync SUPLDRCREATETABSARGS CreateArgs;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync CreateArgs.cbImage = CalcArgs.cbImage;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync CreateArgs.pSym = (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab];
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync CreateArgs.pszBase = (char *)&pLoadReq->u.In.abImage[offStrTab];
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync CreateArgs.psz = CreateArgs.pszBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= CalcArgs.cbStrings);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab]) <= CalcArgs.cSymbols);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Upload the image.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->Hdr.u32Cookie = g_u32Cookie;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->Hdr.u32SessionCookie = g_u32SessionCookie;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->Hdr.cbIn = SUP_IOCTL_LDR_LOAD_SIZE_IN(cbImageWithTabs);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->Hdr.cbOut = SUP_IOCTL_LDR_LOAD_SIZE_OUT;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_IN;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->Hdr.rc = VERR_INTERNAL_ERROR;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.pfnModuleInit = (RTR0PTR)ModuleInit;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.pfnModuleTerm = (RTR0PTR)ModuleTerm;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (fIsVMMR0)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.eEPType = SUPLDRLOADEP_VMMR0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.EP.VMMR0.pvVMMR0 = OpenReq.u.Out.pvImageBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryInt = (RTR0PTR)VMMR0EntryInt;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryFast= (RTR0PTR)VMMR0EntryFast;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryEx = (RTR0PTR)VMMR0EntryEx;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else if (pszSrvReqHandler)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.eEPType = SUPLDRLOADEP_SERVICE;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.EP.Service.pfnServiceReq = (RTR0PTR)SrvReqHandler;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.EP.Service.apvReserved[0] = NIL_RTR0PTR;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.EP.Service.apvReserved[1] = NIL_RTR0PTR;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.EP.Service.apvReserved[2] = NIL_RTR0PTR;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.eEPType = SUPLDRLOADEP_NOTHING;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.offStrTab = offStrTab;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.cbStrTab = (uint32_t)CalcArgs.cbStrings;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertRelease(pLoadReq->u.In.cbStrTab == CalcArgs.cbStrings);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.offSymbols = offSymTab;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.cSymbols = CalcArgs.cSymbols;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.cbImageWithTabs = cbImageWithTabs;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pLoadReq->u.In.pvImageBase = OpenReq.u.Out.pvImageBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (!g_uSupFakeMode)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = pLoadReq->Hdr.rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: SUP_IOCTL_LDR_LOAD ioctl for %s (%s) failed rc=%Rrc\n", pszModule, pszFilename, rc));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if ( RT_SUCCESS(rc)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync || rc == VERR_ALREADY_LOADED /* A competing process. */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync )
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: Loaded %s (%s) at %#p - ModuleInit at %RTptr and ModuleTerm at %RTptr%s\n",
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pszModule, pszFilename, OpenReq.u.Out.pvImageBase, ModuleInit, ModuleTerm,
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.u.Out.fNativeLoader ? " using the native ring-0 loader" : ""));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (fIsVMMR0)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: VMMR0EntryEx located at %RTptr, VMMR0EntryFast at %RTptr and VMMR0EntryInt at %RTptr\n",
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync VMMR0EntryEx, VMMR0EntryFast, VMMR0EntryInt));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#ifdef RT_OS_WINDOWS
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#endif
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTMemTmpFree(pLoadReq);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTLdrClose(hLdrMod);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: Loading failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: RTLdrEnumSymbols failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: Failed to get entry points for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: RTLdrGetBits failed for %s (%s). rc=%Rrc\n", pszModule, pszFilename, rc));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTMemTmpFree(pLoadReq);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertMsgFailed(("failed to allocated %u bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs)));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = VERR_NO_TMP_MEMORY;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync else if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (fIsVMMR0)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: Opened %s (%s) at %#p.\n", pszModule, pszFilename, OpenReq.u.Out.pvImageBase,
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync OpenReq.u.Out.fNativeLoader ? " loaded by the native ring-0 loader" : ""));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#ifdef RT_OS_WINDOWS
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#endif
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTLdrClose(hLdrMod);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncSUPR3DECL(int) SUPR3FreeModule(void *pvImageBase)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /* fake */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_UNLIKELY(g_uSupFakeMode))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync g_pvVMMR0 = NIL_RTR0PTR;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Free the requested module.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync SUPLDRFREE Req;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.u32Cookie = g_u32Cookie;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.u32SessionCookie = g_u32SessionCookie;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.cbIn = SUP_IOCTL_LDR_FREE_SIZE_IN;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.cbOut = SUP_IOCTL_LDR_FREE_SIZE_OUT;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.rc = VERR_INTERNAL_ERROR;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_FREE, &Req, SUP_IOCTL_LDR_FREE_SIZE);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = Req.Hdr.rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if ( RT_SUCCESS(rc)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync && (RTR0PTR)pvImageBase == g_pvVMMR0)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync g_pvVMMR0 = NIL_RTR0PTR;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncSUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *ppvValue = NULL;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /* fake */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_UNLIKELY(g_uSupFakeMode))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *ppvValue = (void *)(uintptr_t)0xdeadf00d;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VINF_SUCCESS;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Do ioctl.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync SUPLDRGETSYMBOL Req;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.u32Cookie = g_u32Cookie;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.u32SessionCookie = g_u32SessionCookie;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.cbIn = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_IN;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.cbOut = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_OUT;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.Hdr.rc = VERR_INTERNAL_ERROR;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync size_t cchSymbol = strlen(pszSymbol);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (cchSymbol >= sizeof(Req.u.In.szSymbol))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VERR_SYMBOL_NOT_FOUND;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync memcpy(Req.u.In.szSymbol, pszSymbol, cchSymbol + 1);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_GET_SYMBOL, &Req, SUP_IOCTL_LDR_GET_SYMBOL_SIZE);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = Req.Hdr.rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_SUCCESS(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *ppvValue = (void *)Req.u.Out.pvSymbol;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncSUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync void *pvImageBase;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase, NULL /*pErrInfo*/);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncSUPR3DECL(int) SUPR3UnloadVMM(void)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return SUPR3FreeModule((void*)g_pvVMMR0);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync/**
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Worker for SUPR3HardenedLdrLoad and SUPR3HardenedLdrLoadAppPriv.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @returns iprt status code.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param pszFilename The full file name.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param phLdrMod Where to store the handle to the loaded module.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param fFlags See RTLDFLAGS_.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * @param pErrInfo Where to return extended error information.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Optional.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncstatic int supR3HardenedLdrLoadIt(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#ifdef VBOX_WITH_HARDENING
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Verify the image file.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
f4e030a05d813de75c81e7fb0072fe7eb704a5a4vboxsync int rc = SUPR3HardenedVerifyInit();
f4e030a05d813de75c81e7fb0072fe7eb704a5a4vboxsync if (RT_FAILURE(rc))
f4e030a05d813de75c81e7fb0072fe7eb704a5a4vboxsync rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_FAILURE(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("supR3HardenedLdrLoadIt: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return RTErrInfoSet(pErrInfo, rc, "supR3HardenedVerifyFixedFile failed");
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#endif
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Try load it.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return RTLdrLoadEx(pszFilename, phLdrMod, fFlags, pErrInfo);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncSUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Validate input.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTErrInfoClear(pErrInfo);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtrReturn(phLdrMod, VERR_INVALID_POINTER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *phLdrMod = NIL_RTLDRMOD;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertReturn(RTPathHavePath(pszFilename), VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Add the default extension if it's missing.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (!RTPathHasSuffix(pszFilename))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync const char *pszSuff = RTLdrGetSuff();
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync size_t cchSuff = strlen(pszSuff);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync size_t cchFilename = strlen(pszFilename);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync char *psz = (char *)alloca(cchFilename + cchSuff + 1);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertReturn(psz, VERR_NO_TMP_MEMORY);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync memcpy(psz, pszFilename, cchFilename);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync memcpy(psz + cchFilename, pszSuff, cchSuff + 1);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pszFilename = psz;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Pass it on to the common library loader.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return supR3HardenedLdrLoadIt(pszFilename, phLdrMod, fFlags, pErrInfo);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncSUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogFlow(("SUPR3HardenedLdrLoadAppPriv: pszFilename=%p:{%s} phLdrMod=%p fFlags=%08x pErrInfo=%p\n", pszFilename, pszFilename, phLdrMod, fFlags, pErrInfo));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Validate input.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTErrInfoClear(pErrInfo);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *phLdrMod = NIL_RTLDRMOD;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertMsgReturn(!RTPathHavePath(pszFilename), ("%s\n", pszFilename), VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Check the filename.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync size_t cchFilename = strlen(pszFilename);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertMsgReturn(cchFilename < (RTPATH_MAX / 4) * 3, ("%zu\n", cchFilename), VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync const char *pszExt = "";
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync size_t cchExt = 0;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (!RTPathHasSuffix(pszFilename))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync pszExt = RTLdrGetSuff();
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync cchExt = strlen(pszExt);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Construct the private arch path and check if the file exists.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync char szPath[RTPATH_MAX];
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync int rc = RTPathAppPrivateArch(szPath, sizeof(szPath) - 1 - cchExt - cchFilename);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertRCReturn(rc, rc);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync char *psz = strchr(szPath, '\0');
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *psz++ = RTPATH_SLASH;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync memcpy(psz, pszFilename, cchFilename);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync psz += cchFilename;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync memcpy(psz, pszExt, cchExt + 1);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (!RTPathExists(szPath))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("SUPR3HardenedLdrLoadAppPriv: \"%s\" not found\n", szPath));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return VERR_FILE_NOT_FOUND;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Pass it on to SUPR3HardenedLdrLoad.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync rc = SUPR3HardenedLdrLoad(szPath, phLdrMod, fFlags, pErrInfo);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogFlow(("SUPR3HardenedLdrLoadAppPriv: returns %Rrc\n", rc));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsyncSUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync{
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Validate input.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync RTErrInfoClear(pErrInfo);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync *phLdrMod = NIL_RTLDRMOD;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync AssertReturn(RTPathStartsWithRoot(pszFilename), VERR_INVALID_PARAMETER);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#ifdef VBOX_WITH_HARDENING
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Verify the image file.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, true /*fMaybe3rdParty*/, pErrInfo);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (RT_FAILURE(rc))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync {
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync if (!RTErrInfoIsSet(pErrInfo))
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return rc;
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync }
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync#endif
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync /*
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync * Try load it.
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync */
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync return RTLdrLoadEx(pszFilename, phLdrMod, RTLDRLOAD_FLAGS_LOCAL, pErrInfo);
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync}
98b3fe217f35498ace90d9b63a8298c0b6353c2cvboxsync