tstLdr-4.cpp revision 588f763595b21d28ce311148a618cc4ead630558
38856343f90103280eb83b5e697f9f618b407d83vboxsync/* $Id$ */
38856343f90103280eb83b5e697f9f618b407d83vboxsync/** @file
38856343f90103280eb83b5e697f9f618b407d83vboxsync * InnoTek Portable Runtime - Testcase for RTLdrOpen using ldrLdrObjR0.r0.
38856343f90103280eb83b5e697f9f618b407d83vboxsync */
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync/*
38856343f90103280eb83b5e697f9f618b407d83vboxsync * Copyright (C) 2006 InnoTek Systemberatung GmbH
38856343f90103280eb83b5e697f9f618b407d83vboxsync *
38856343f90103280eb83b5e697f9f618b407d83vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
38856343f90103280eb83b5e697f9f618b407d83vboxsync * available from http://www.virtualbox.org. This file is free software;
38856343f90103280eb83b5e697f9f618b407d83vboxsync * you can redistribute it and/or modify it under the terms of the GNU
38856343f90103280eb83b5e697f9f618b407d83vboxsync * General Public License as published by the Free Software Foundation,
38856343f90103280eb83b5e697f9f618b407d83vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
38856343f90103280eb83b5e697f9f618b407d83vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
38856343f90103280eb83b5e697f9f618b407d83vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
38856343f90103280eb83b5e697f9f618b407d83vboxsync *
38856343f90103280eb83b5e697f9f618b407d83vboxsync * If you received this file as part of a commercial VirtualBox
38856343f90103280eb83b5e697f9f618b407d83vboxsync * distribution, then only the terms of your commercial VirtualBox
38856343f90103280eb83b5e697f9f618b407d83vboxsync * license agreement apply instead of the previous paragraph.
38856343f90103280eb83b5e697f9f618b407d83vboxsync */
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync/*******************************************************************************
38856343f90103280eb83b5e697f9f618b407d83vboxsync* Header Files *
38856343f90103280eb83b5e697f9f618b407d83vboxsync*******************************************************************************/
38856343f90103280eb83b5e697f9f618b407d83vboxsync#include <iprt/ldr.h>
38856343f90103280eb83b5e697f9f618b407d83vboxsync#include <iprt/alloc.h>
38856343f90103280eb83b5e697f9f618b407d83vboxsync#include <iprt/stream.h>
38856343f90103280eb83b5e697f9f618b407d83vboxsync#include <iprt/assert.h>
38856343f90103280eb83b5e697f9f618b407d83vboxsync#include <iprt/runtime.h>
38856343f90103280eb83b5e697f9f618b407d83vboxsync#include <iprt/err.h>
38856343f90103280eb83b5e697f9f618b407d83vboxsync#include <iprt/string.h>
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsyncextern "C" DECLEXPORT(int) DisasmTest1(void);
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync/**
38856343f90103280eb83b5e697f9f618b407d83vboxsync * Resolve an external symbol during RTLdrGetBits().
38856343f90103280eb83b5e697f9f618b407d83vboxsync *
38856343f90103280eb83b5e697f9f618b407d83vboxsync * @returns iprt status code.
38856343f90103280eb83b5e697f9f618b407d83vboxsync * @param hLdrMod The loader module handle.
38856343f90103280eb83b5e697f9f618b407d83vboxsync * @param pszModule Module name.
38856343f90103280eb83b5e697f9f618b407d83vboxsync * @param pszSymbol Symbol name, NULL if uSymbol should be used.
38856343f90103280eb83b5e697f9f618b407d83vboxsync * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
38856343f90103280eb83b5e697f9f618b407d83vboxsync * @param pValue Where to store the symbol value (address).
38856343f90103280eb83b5e697f9f618b407d83vboxsync * @param pvUser User argument.
38856343f90103280eb83b5e697f9f618b407d83vboxsync */
38856343f90103280eb83b5e697f9f618b407d83vboxsyncstatic DECLCALLBACK(int) testGetImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
38856343f90103280eb83b5e697f9f618b407d83vboxsync{
4f5c03319462e58ce23cdd7d37d17a72e57f7105vboxsync if ( !strcmp(pszSymbol, "AssertMsg1") || !strcmp(pszSymbol, "_AssertMsg1"))
38856343f90103280eb83b5e697f9f618b407d83vboxsync *pValue = (uintptr_t)AssertMsg1;
4f5c03319462e58ce23cdd7d37d17a72e57f7105vboxsync else if (!strcmp(pszSymbol, "AssertMsg2") || !strcmp(pszSymbol, "_AssertMsg2"))
38856343f90103280eb83b5e697f9f618b407d83vboxsync *pValue = (uintptr_t)AssertMsg2;
4f5c03319462e58ce23cdd7d37d17a72e57f7105vboxsync else if (!strcmp(pszSymbol, "RTLogDefaultInstance") || !strcmp(pszSymbol, "_RTLogDefaultInstance"))
38856343f90103280eb83b5e697f9f618b407d83vboxsync *pValue = (uintptr_t)RTLogDefaultInstance;
4f5c03319462e58ce23cdd7d37d17a72e57f7105vboxsync else if (!strcmp(pszSymbol, "MyPrintf") || !strcmp(pszSymbol, "_MyPrintf"))
38856343f90103280eb83b5e697f9f618b407d83vboxsync *pValue = (uintptr_t)RTPrintf;
38856343f90103280eb83b5e697f9f618b407d83vboxsync else
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: Unexpected import '%s'!\n", pszSymbol);
38856343f90103280eb83b5e697f9f618b407d83vboxsync return VERR_SYMBOL_NOT_FOUND;
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync return VINF_SUCCESS;
38856343f90103280eb83b5e697f9f618b407d83vboxsync}
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync/**
38856343f90103280eb83b5e697f9f618b407d83vboxsync * One test iteration with one file.
38856343f90103280eb83b5e697f9f618b407d83vboxsync *
38856343f90103280eb83b5e697f9f618b407d83vboxsync * The test is very simple, we load the the file three times
38856343f90103280eb83b5e697f9f618b407d83vboxsync * into two different regions. The first two into each of the
38856343f90103280eb83b5e697f9f618b407d83vboxsync * regions the for compare usage. The third is loaded into one
38856343f90103280eb83b5e697f9f618b407d83vboxsync * and then relocated between the two and other locations a few times.
38856343f90103280eb83b5e697f9f618b407d83vboxsync *
38856343f90103280eb83b5e697f9f618b407d83vboxsync * @returns number of errors.
38856343f90103280eb83b5e697f9f618b407d83vboxsync * @param pszFilename The file to load the mess with.
38856343f90103280eb83b5e697f9f618b407d83vboxsync */
38856343f90103280eb83b5e697f9f618b407d83vboxsyncstatic int testLdrOne(const char *pszFilename)
38856343f90103280eb83b5e697f9f618b407d83vboxsync{
38856343f90103280eb83b5e697f9f618b407d83vboxsync int cErrors = 0;
38856343f90103280eb83b5e697f9f618b407d83vboxsync size_t cbImage = 0;
38856343f90103280eb83b5e697f9f618b407d83vboxsync struct Load
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTLDRMOD hLdrMod;
38856343f90103280eb83b5e697f9f618b407d83vboxsync void *pvBits;
38856343f90103280eb83b5e697f9f618b407d83vboxsync char *pszName;
38856343f90103280eb83b5e697f9f618b407d83vboxsync } aLoads[6] =
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync { NULL, NULL, "foo" },
38856343f90103280eb83b5e697f9f618b407d83vboxsync { NULL, NULL, "bar" },
38856343f90103280eb83b5e697f9f618b407d83vboxsync { NULL, NULL, "foobar" },
38856343f90103280eb83b5e697f9f618b407d83vboxsync { NULL, NULL, "kLdr-foo" },
38856343f90103280eb83b5e697f9f618b407d83vboxsync { NULL, NULL, "kLdr-bar" },
38856343f90103280eb83b5e697f9f618b407d83vboxsync { NULL, NULL, "kLdr-foobar" }
38856343f90103280eb83b5e697f9f618b407d83vboxsync };
38856343f90103280eb83b5e697f9f618b407d83vboxsync unsigned i;
38856343f90103280eb83b5e697f9f618b407d83vboxsync int rc;
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync /*
38856343f90103280eb83b5e697f9f618b407d83vboxsync * Load them.
38856343f90103280eb83b5e697f9f618b407d83vboxsync */
38856343f90103280eb83b5e697f9f618b407d83vboxsync for (i = 0; i < ELEMENTS(aLoads); i++)
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (!strncmp(aLoads[i].pszName, "kLdr-", sizeof("kLdr-") - 1))
38856343f90103280eb83b5e697f9f618b407d83vboxsync rc = RTLdrOpenkLdr(pszFilename, &aLoads[i].hLdrMod);
38856343f90103280eb83b5e697f9f618b407d83vboxsync else
38856343f90103280eb83b5e697f9f618b407d83vboxsync rc = RTLdrOpen(pszFilename, &aLoads[i].hLdrMod);
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (RT_FAILURE(rc))
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: Failed to open '%s'/%d, rc=%Rrc. aborting test.\n", pszFilename, i, rc);
38856343f90103280eb83b5e697f9f618b407d83vboxsync Assert(aLoads[i].hLdrMod == NIL_RTLDRMOD);
38856343f90103280eb83b5e697f9f618b407d83vboxsync cErrors++;
38856343f90103280eb83b5e697f9f618b407d83vboxsync break;
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync /* size it */
38856343f90103280eb83b5e697f9f618b407d83vboxsync size_t cb = RTLdrSize(aLoads[i].hLdrMod);
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (cbImage && cb != cbImage)
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: Size mismatch '%s'/%d. aborting test.\n", pszFilename, i);
38856343f90103280eb83b5e697f9f618b407d83vboxsync cErrors++;
38856343f90103280eb83b5e697f9f618b407d83vboxsync break;
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync cbImage = cb;
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync /* Allocate bits. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync aLoads[i].pvBits = RTMemAlloc(cb);
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (!aLoads[i].pvBits)
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: Out of memory '%s'/%d cbImage=%d. aborting test.\n", pszFilename, i, cbImage);
38856343f90103280eb83b5e697f9f618b407d83vboxsync cErrors++;
38856343f90103280eb83b5e697f9f618b407d83vboxsync break;
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync /* Get the bits. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync rc = RTLdrGetBits(aLoads[i].hLdrMod, aLoads[i].pvBits, (uintptr_t)aLoads[i].pvBits, testGetImport, NULL);
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (RT_FAILURE(rc))
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: Failed to get bits for '%s'/%d, rc=%Rrc. aborting test\n", pszFilename, i, rc);
38856343f90103280eb83b5e697f9f618b407d83vboxsync cErrors++;
38856343f90103280eb83b5e697f9f618b407d83vboxsync break;
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync /*
38856343f90103280eb83b5e697f9f618b407d83vboxsync * Execute the code.
38856343f90103280eb83b5e697f9f618b407d83vboxsync */
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (!cErrors)
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync for (i = 0; i < ELEMENTS(aLoads); i += 1)
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync /* get the pointer. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTUINTPTR Value;
38856343f90103280eb83b5e697f9f618b407d83vboxsync rc = RTLdrGetSymbolEx(aLoads[i].hLdrMod, aLoads[i].pvBits, (uintptr_t)aLoads[i].pvBits, "DisasmTest1", &Value);
4f5c03319462e58ce23cdd7d37d17a72e57f7105vboxsync if (rc == VERR_SYMBOL_NOT_FOUND)
4f5c03319462e58ce23cdd7d37d17a72e57f7105vboxsync rc = RTLdrGetSymbolEx(aLoads[i].hLdrMod, aLoads[i].pvBits, (uintptr_t)aLoads[i].pvBits, "_DisasmTest1", &Value);
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (RT_FAILURE(rc))
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
588f763595b21d28ce311148a618cc4ead630558vboxsync RTPrintf("tstLdr-4: Failed to get symbol \"DisasmTest1\" from load #%d: %Rrc\n", i, rc);
38856343f90103280eb83b5e697f9f618b407d83vboxsync cErrors++;
38856343f90103280eb83b5e697f9f618b407d83vboxsync break;
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync DECLCALLBACKPTR(int, pfnDisasmTest1)(void) = (DECLCALLBACKPTR(int, )(void))(uintptr_t)Value; /* eeeh. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: pfnDisasmTest1=%p / add-symbol-file %s %#x\n", pfnDisasmTest1, pszFilename, aLoads[i].pvBits);
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync /* call the test function. */
38856343f90103280eb83b5e697f9f618b407d83vboxsync rc = pfnDisasmTest1();
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (rc)
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: load #%d Test1 -> %#x\n", i, rc);
38856343f90103280eb83b5e697f9f618b407d83vboxsync cErrors++;
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync /*
38856343f90103280eb83b5e697f9f618b407d83vboxsync * Clean up.
38856343f90103280eb83b5e697f9f618b407d83vboxsync */
38856343f90103280eb83b5e697f9f618b407d83vboxsync for (i = 0; i < ELEMENTS(aLoads); i++)
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (aLoads[i].pvBits)
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTMemFree(aLoads[i].pvBits);
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (aLoads[i].hLdrMod)
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync int rc = RTLdrClose(aLoads[i].hLdrMod);
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (RT_FAILURE(rc))
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: Failed to close '%s' i=%d, rc=%Rrc.\n", pszFilename, i, rc);
38856343f90103280eb83b5e697f9f618b407d83vboxsync cErrors++;
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync return cErrors;
38856343f90103280eb83b5e697f9f618b407d83vboxsync}
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsyncint main(int argc, char **argv)
38856343f90103280eb83b5e697f9f618b407d83vboxsync{
38856343f90103280eb83b5e697f9f618b407d83vboxsync int cErrors = 0;
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTR3Init();
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync /*
38856343f90103280eb83b5e697f9f618b407d83vboxsync * Sanity check.
38856343f90103280eb83b5e697f9f618b407d83vboxsync */
38856343f90103280eb83b5e697f9f618b407d83vboxsync int rc = DisasmTest1();
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (rc)
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: FATAL ERROR - DisasmTest1 is buggy: rc=%#x\n", rc);
38856343f90103280eb83b5e697f9f618b407d83vboxsync return 1;
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync /*
38856343f90103280eb83b5e697f9f618b407d83vboxsync * Execute the test.
38856343f90103280eb83b5e697f9f618b407d83vboxsync */
38856343f90103280eb83b5e697f9f618b407d83vboxsync char szPath[RTPATH_MAX];
38856343f90103280eb83b5e697f9f618b407d83vboxsync rc = RTPathProgram(szPath, sizeof(szPath) - sizeof("/tstLdrObjR0.r0"));
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (RT_SUCCESS(rc))
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync strcat(szPath, "/tstLdrObjR0.r0");
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: TESTING '%s'...\n", szPath);
38856343f90103280eb83b5e697f9f618b407d83vboxsync cErrors += testLdrOne(szPath);
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync else
38856343f90103280eb83b5e697f9f618b407d83vboxsync {
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: RTPathProgram -> %Rrc\n", rc);
38856343f90103280eb83b5e697f9f618b407d83vboxsync cErrors++;
38856343f90103280eb83b5e697f9f618b407d83vboxsync }
38856343f90103280eb83b5e697f9f618b407d83vboxsync
38856343f90103280eb83b5e697f9f618b407d83vboxsync /*
38856343f90103280eb83b5e697f9f618b407d83vboxsync * Test result summary.
38856343f90103280eb83b5e697f9f618b407d83vboxsync */
38856343f90103280eb83b5e697f9f618b407d83vboxsync if (!cErrors)
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: SUCCESS\n");
38856343f90103280eb83b5e697f9f618b407d83vboxsync else
38856343f90103280eb83b5e697f9f618b407d83vboxsync RTPrintf("tstLdr-4: FAILURE - %d errors\n", cErrors);
38856343f90103280eb83b5e697f9f618b407d83vboxsync return !!cErrors;
38856343f90103280eb83b5e697f9f618b407d83vboxsync}