From 29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:21:29 +0200 Subject: Adding upstream version 1:0.1.9998svn3589+dfsg. Signed-off-by: Daniel Baumann --- src/lib/kStuff/kLdr/testcase/tst-0-driver.c | 502 ++++++++++++++++++++++++++++ 1 file changed, 502 insertions(+) create mode 100644 src/lib/kStuff/kLdr/testcase/tst-0-driver.c (limited to 'src/lib/kStuff/kLdr/testcase/tst-0-driver.c') diff --git a/src/lib/kStuff/kLdr/testcase/tst-0-driver.c b/src/lib/kStuff/kLdr/testcase/tst-0-driver.c new file mode 100644 index 0000000..be304d5 --- /dev/null +++ b/src/lib/kStuff/kLdr/testcase/tst-0-driver.c @@ -0,0 +1,502 @@ +/* $Id: tst-0-driver.c 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kLdr - Dynamic Loader testcase no. 0, Driver. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include "tst.h" +#include +#include +#include +#include + + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +/** Select the appropriate KLDRSYMKIND bit define. */ +#define MY_KLDRSYMKIND_BITS ( sizeof(void *) == 4 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT ) + + +/******************************************************************************* +* Global Variables * +*******************************************************************************/ +/** The numbers of errors. */ +static int g_cErrors = 0; + + + +/** + * Report failure. + */ +static int Failure(const char *pszFormat, ...) +{ + va_list va; + + g_cErrors++; + + printf("tst-0-driver: "); + va_start(va, pszFormat); + vprintf(pszFormat, va); + va_end(va); + printf("\n"); + return 1; +} + + +int main(int argc, char **argv) +{ + const char *pszErrInit = "Error, szErr wasn't zapped"; + char szErr[512]; + char szBuf[512]; + char *psz; + KSIZE cch; + HKLDRMOD hMod; + int rc; + + /* + * The first thing to do is a simple load / unload test + * using the tst-0-a library (it'll drag in tst-0-d). + */ + printf("tst-0-driver: Basic API test using 'tst-0-a'...\n"); + hMod = (HKLDRMOD)0xffffeeee; + strcpy(szErr, pszErrInit); + rc = kLdrDyldLoad("tst-0-a", NULL, NULL, KLDRDYLD_SEARCH_HOST, + KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT, &hMod, szErr, sizeof(szErr)); + if (rc) + Failure("kLdrDyldLoad(\"tst-0\",...) failed, rc=%d (%#x). szErr='%s'.\n", rc, rc, szErr); + if (!strcmp(szErr, pszErrInit)) + Failure("szErr wasn't set.\n"); + if (hMod == (HKLDRMOD)0xffffeeee) + Failure("hMod wasn't set.\n"); + if (hMod == NIL_HKLDRMOD && !rc) + Failure("rc=0 but hMod=NIL_HKLDRMOD\n"); + if (!rc) + { + HKLDRMOD hMod2; + HKLDRMOD hMod3; + printf("tst-0-driver: hMod=%p ('tst-0-a')\n", (void *)hMod); + + /* + * Simple test of kLdrDyldFindByName. + */ + hMod2 = (HKLDRMOD)0xffffeeee; + rc = kLdrDyldFindByName("tst-0", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod2); + if (!rc) + Failure("kLdrDyldFindByName(\"tst-0\",,,) didn't fail!\n"); + if (rc && hMod2 != NIL_HKLDRMOD) + Failure("hMod2 wasn't set correctly on kLdrDyldFindByName failure!\n"); + + hMod2 = (HKLDRMOD)0xffffeeee; + rc = kLdrDyldFindByName("tst-0-a", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod2); + if (rc) + Failure("kLdrDyldFindByName(\"tst-0-a\",,,) failed, rc=%d (%#x)\n", rc, rc); + if (!rc && hMod2 != hMod) + Failure("kLdrDyldFindByName(\"tst-0-a\",,,) returned the wrong module handle: %p instead of %p\n", + (void *)hMod2, (void *)hMod); + + hMod2 = (HKLDRMOD)0xffffeeee; + rc = kLdrDyldFindByName("tst-0-d", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod2); + if (!rc) + printf("tst-0-driver: hMod2=%p ('tst-0-d')\n", (void *)hMod2); + else + Failure("kLdrDyldFindByName(\"tst-0-d\",,,) failed, rc=%d (%#x)\n", rc, rc); + + /* + * Get the name and filename for each of the two modules. + */ + rc = kLdrDyldGetName(hMod2, szBuf, sizeof(szBuf)); + if (!rc) + { + printf("tst-0-driver: name: '%s' ('tst-0-d')\n", szBuf); + psz = strstr(szBuf, "-0-"); + if ( !psz + || strnicmp(psz, "-0-d", sizeof("-0-d") - 1)) + Failure("kLdrDyldGetName(\"tst-0-d\",,,) -> '%s': pattern '-0-d' not found\n", szBuf); + + /* overflow test. */ + cch = strlen(szBuf); + szBuf[cch + 1] = szBuf[cch] = szBuf[cch - 1] = 'x'; + szBuf[cch + 2] = '\0'; + rc = kLdrDyldGetName(hMod2, szBuf, cch); + if (rc == KERR_BUFFER_OVERFLOW) + { + if (!szBuf[0]) + Failure("kLdrDyldGetName didn't return partial result on overflow\n"); + else if (szBuf[cch - 1]) + Failure("kLdrDyldGetName didn't terminate partial result correctly overflow: '%s'\n", szBuf); + else if (szBuf[cch] != 'x') + Failure("kLdrDyldGetName exceeded the buffer limit on partial overflow: '%s'\n", szBuf); + } + else + Failure("kLdrDyldGetName(\"tst-0-d\",,,) -> rc=%d (%#x) instead of KERR_BUFFER_OVERFLOW\n", rc, rc); + + /* check that we can query the module by the returned name. */ + rc = kLdrDyldGetName(hMod2, szBuf, sizeof(szBuf)); + if (!rc) + { + hMod3 = (HKLDRMOD)0xffffeeee; + rc = kLdrDyldFindByName(szBuf, NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod3); + if (rc || hMod3 != hMod2) + Failure("kLdrDyldFindByName(\"%s\",,,) failed, rc=%d (%#x) hMod3=%p hMod2=%p\n", + szBuf, rc, rc, (void *)hMod3, (void *)hMod2); + } + else + Failure("kLdrDyldGetName(\"tst-0-d\",,,) failed (b), rc=%d (%#x)\n", rc, rc); + } + else + Failure("kLdrDyldGetName(\"tst-0-d\",,,) failed, rc=%d (%#x)\n", rc, rc); + + rc = kLdrDyldGetFilename(hMod2, szBuf, sizeof(szBuf)); + if (!rc) + { + printf("tst-0-driver: filename: '%s' ('tst-0-d')\n", szBuf); + + /* overflow test. */ + cch = strlen(szBuf); + szBuf[cch + 1] = szBuf[cch] = szBuf[cch - 1] = 'x'; + szBuf[cch + 2] = '\0'; + rc = kLdrDyldGetFilename(hMod2, szBuf, cch); + if (rc == KERR_BUFFER_OVERFLOW) + { + if (!szBuf[0]) + Failure("kLdrDyldGetFilename didn't return partial result on overflow\n"); + else if (szBuf[cch - 1]) + Failure("kLdrDyldGetFilename didn't terminate partial result correctly overflow: '%s'\n", szBuf); + else if (szBuf[cch] != 'x') + Failure("kLdrDyldGetFilename exceeded the buffer limit on partial overflow: '%s'\n", szBuf); + } + else + Failure("kLdrDyldGetFilename(\"tst-0-d\",,,) -> rc=%d (%#x) instead of KERR_BUFFER_OVERFLOW\n", rc, rc); + + /* check that we can query the module by the returned filename. */ + rc = kLdrDyldGetFilename(hMod2, szBuf, sizeof(szBuf)); + if (!rc) + { + hMod3 = (HKLDRMOD)0xffffeeee; + rc = kLdrDyldFindByName(szBuf, NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod3); + if (rc || hMod3 != hMod2) + Failure("kLdrDyldFindByName(\"%s\",,,) failed, rc=%d (%#x) hMod3=%p hMod2=%p\n", + szBuf, rc, rc, (void *)hMod3, (void *)hMod2); + } + else + Failure("kLdrDyldGetName(\"tst-0-d\",,,) failed (b), rc=%d (%#x)\n", rc, rc); + } + else + Failure("kLdrDyldGetFilename(\"tst-0-d\",,,) failed, rc=%d (%#x)\n", rc, rc); + + /* the other module */ + rc = kLdrDyldGetName(hMod, szBuf, sizeof(szBuf)); + if (!rc) + { + printf("tst-0-driver: name: '%s' ('tst-0-a')\n", szBuf); + psz = strstr(szBuf, "-0-"); + if ( !psz + || strnicmp(psz, "-0-a", sizeof("-0-a") - 1)) + Failure("kLdrDyldGetName(\"tst-0-a\",,,) -> '%s': pattern '-0-a' not found\n", szBuf); + + /* check that we can query the module by the returned name. */ + hMod3 = (HKLDRMOD)0xffffeeee; + rc = kLdrDyldFindByName(szBuf, NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod3); + if (rc || hMod3 != hMod) + Failure("kLdrDyldFindByName(\"%s\",,,) failed, rc=%d (%#x) hMod3=%p hMod=%p\n", + szBuf, rc, rc, (void *)hMod3, (void *)hMod); + } + else + Failure("kLdrDyldGetName(\"tst-0-a\",,,) failed, rc=%d (%#x)\n", rc, rc); + + rc = kLdrDyldGetFilename(hMod, szBuf, sizeof(szBuf)); + if (!rc) + { + printf("tst-0-driver: filename: '%s' ('tst-0-a')\n", szBuf); + + /* check that we can query the module by the returned filename. */ + hMod3 = (HKLDRMOD)0xffffeeee; + rc = kLdrDyldFindByName(szBuf, NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod3); + if (rc || hMod3 != hMod) + Failure("kLdrDyldFindByName(\"%s\",,,) failed, rc=%d (%#x) hMod3=%p hMod=%p\n", + szBuf, rc, rc, (void *)hMod3, (void *)hMod); + } + else + Failure("kLdrDyldGetFilename(\"tst-0-a\",,,) failed, rc=%d (%#x)\n", rc, rc); + + + /* + * Resolve the symbol exported by each of the two modules and call them. + */ + if (!g_cErrors) + { + KUPTR uValue; + KU32 fKind; + + fKind = 0xffeeffee; + uValue = ~(KUPTR)42; + rc = kLdrDyldQuerySymbol(hMod, NIL_KLDRMOD_SYM_ORDINAL, MY_NAME("FuncA"), NULL, &uValue, &fKind); + if (!rc) + { + if (uValue == ~(KUPTR)42) + Failure("kLdrDyldQuerySymbol(\"tst-0-a\",,\"FuncA\",): uValue wasn't set.\n"); + if (fKind == 0xffeeffee) + Failure("kLdrDyldQuerySymbol(\"tst-0-a\",,\"FuncA\",): fKind wasn't set.\n"); + if ( (fKind & KLDRSYMKIND_BIT_MASK) != KLDRSYMKIND_NO_BIT + && (fKind & KLDRSYMKIND_BIT_MASK) != MY_KLDRSYMKIND_BITS) + Failure("fKind=%#x indicates a different code 'bit' mode than we running at.\n", fKind); + if ( (fKind & KLDRSYMKIND_TYPE_MASK) != KLDRSYMKIND_NO_TYPE + && (fKind & KLDRSYMKIND_TYPE_MASK) != KLDRSYMKIND_CODE) + Failure("fKind=%#x indicates that \"FuncA\" isn't code.\n", fKind); + if (fKind & KLDRSYMKIND_FORWARDER) + Failure("fKind=%#x indicates that \"FuncA\" is a forwarder. it isn't.\n", fKind); + + /* call it. */ + if (!g_cErrors) + { + int (*pfnFuncA)(void) = (int (*)(void))uValue; + rc = pfnFuncA(); + if (rc != 0x42000042) + Failure("FuncA returned %#x expected 0x42000042\n", rc); + } + + /* + * Test kLdrDyldFindByAddress now that we've got an address. + */ + hMod3 = (HKLDRMOD)0xeeeeffff; + rc = kLdrDyldFindByAddress(uValue, &hMod3, NULL, NULL); + if (!rc) + { + KUPTR offSegment; + KU32 iSegment; + + if (hMod3 != hMod) + Failure("kLdrDyldFindByAddress(%#p/*FuncA*/, \"tst-0-a\",,,) return incorrect hMod3=%p instead of %p.\n", + uValue, hMod3, hMod); + + hMod3 = (HKLDRMOD)0xeeeeffff; + iSegment = 0x42424242; + rc = kLdrDyldFindByAddress(uValue, &hMod3, &iSegment, &offSegment); + if (!rc) + { + if (hMod3 != hMod) + Failure("Bad hMod3 on 2nd kLdrDyldFindByAddress call.\n"); + if (iSegment > 0x1000) /* safe guess */ + Failure("Bad iSegment=%#x\n", iSegment); + if (offSegment > 0x100000) /* guesswork */ + Failure("Bad offSegment=%p\n", (void *)offSegment); + } + else + Failure("kLdrDyldFindByAddress(%#p/*FuncA*/, \"tst-0-a\",,,) failed (b), rc=%d (%#x)\n", + uValue, rc, rc); + + /* negative test */ + hMod3 = (HKLDRMOD)0xeeeeffff; + iSegment = 0x42424242; + offSegment = 0x87654321; + rc = kLdrDyldFindByAddress(~(KUPTR)16, &hMod3, &iSegment, &offSegment); + if (!rc) + Failure("negative kLdrDyldFindByAddress test returned successfully!\n"); + if (iSegment != ~(KU32)0) + Failure("negative kLdrDyldFindByAddress: bad iSegment=%#x\n", iSegment); + if (offSegment != ~(KUPTR)0) + Failure("negative kLdrDyldFindByAddress: bad offSegment=%p\n", (void *)offSegment); + if (hMod3 != NIL_HKLDRMOD) + Failure("negative kLdrDyldFindByAddress: bad hMod3=%p\n", (void *)hMod3); + } + else + Failure("kLdrDyldFindByAddress(%#p/*FuncA*/, \"tst-0-a\",,,) failed, rc=%d (%#x)\n", + uValue, rc, rc); + } + else + Failure("kLdrDyldQuerySymbol(\"tst-0-a\",,\"FuncA\",) failed, rc=%d (%#x)\n", rc, rc); + + fKind = 0xffeeffee; + uValue = ~(KUPTR)42; + rc = kLdrDyldQuerySymbol(hMod2, NIL_KLDRMOD_SYM_ORDINAL, MY_NAME("FuncD"), NULL, &uValue, &fKind); + if (!rc) + { + if (uValue == ~(KUPTR)42) + Failure("kLdrDyldQuerySymbol(\"tst-0-d\",,\"FuncD\",): uValue wasn't set.\n"); + if (fKind == 0xffeeffee) + Failure("kLdrDyldQuerySymbol(\"tst-0-d\",,\"FuncD\",): fKind wasn't set.\n"); + if ( (fKind & KLDRSYMKIND_BIT_MASK) != KLDRSYMKIND_NO_BIT + && (fKind & KLDRSYMKIND_BIT_MASK) != MY_KLDRSYMKIND_BITS) + Failure("fKind=%#x indicates a different code 'bit' mode than we running at.\n", fKind); + if ( (fKind & KLDRSYMKIND_TYPE_MASK) != KLDRSYMKIND_NO_TYPE + && (fKind & KLDRSYMKIND_TYPE_MASK) != KLDRSYMKIND_CODE) + Failure("fKind=%#x indicates that \"FuncD\" isn't code.\n", fKind); + if (fKind & KLDRSYMKIND_FORWARDER) + Failure("fKind=%#x indicates that \"FuncD\" is a forwarder. it isn't.\n", fKind); + + /* call it. */ + if (!g_cErrors) + { + int (*pfnFuncD)(void) = (int (*)(void))uValue; + rc = pfnFuncD(); + if (rc != 0x42000000) + Failure("FuncD returned %#x expected 0x42000000\n", rc); + } + + /* use the address to get the module handle. */ + hMod3 = (HKLDRMOD)0xeeeeffff; + rc = kLdrDyldFindByAddress(uValue, &hMod3, NULL, NULL); + if (!rc) + { + if (hMod3 != hMod2) + Failure("kLdrDyldFindByAddress(%#p/*FuncD*/,,,) return incorrect hMod3=%p instead of %p.\n", + uValue, hMod3, hMod2); + } + else + Failure("kLdrDyldFindByAddress(%#p/*FuncD*/,,,) failed, rc=%d (%#x)\n", + uValue, rc, rc); + } + else + Failure("kLdrDyldQuerySymbol(\"tst-0-a\",,\"FuncA\",) failed, rc=%d (%#x)\n", rc, rc); + + } + + /* + * Finally unload it. + */ + rc = kLdrDyldUnload(hMod); + if (rc) + Failure("kLdrDyldUnload() failed. rc=%d (%#x)\n", rc, rc); + if (!rc) + { + rc = kLdrDyldFindByName("tst-0-d", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod2); + if (rc != KLDR_ERR_MODULE_NOT_FOUND) + Failure("kLdrDyldFindByName(\"tst-0-d\",,,) return rc=%d (%#x), expected KLDR_ERR_MODULE_NOT_FOUND\n", rc, rc); + + rc = kLdrDyldFindByName("tst-0-a", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod2); + if (rc != KLDR_ERR_MODULE_NOT_FOUND) + Failure("kLdrDyldFindByName(\"tst-0-a\",,,) return rc=%d (%#x), expected KLDR_ERR_MODULE_NOT_FOUND\n", rc, rc); + } + } + + /* + * Now do what tst-0 would do; load the three dlls, resolve and call their functions. + */ + if (!g_cErrors) + { + HKLDRMOD hModA; + int (*pfnFuncA)(void); + HKLDRMOD hModB; + int (*pfnFuncB)(void); + HKLDRMOD hModC; + int (*pfnFuncC)(void); + KUPTR uValue; + + rc = kLdrDyldLoad("tst-0-a", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hModA, NULL, 0); + if (rc) + Failure("kLdrDyldLoad(\"tst-0-a\",,,,) -> %d (%#x)\n", rc, rc); + if (!rc) + { + rc = kLdrDyldLoad("tst-0-b", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hModB, szErr, sizeof(szErr)); + if (rc) + Failure("kLdrDyldLoad(\"tst-0-b\",,,,) -> %d (%#x) szErr='%s'\n", rc, rc, szErr); + } + if (!rc) + { + rc = kLdrDyldLoad("tst-0-c", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hModC, szErr, sizeof(szErr)); + if (rc) + Failure("kLdrDyldLoad(\"tst-0-c\",,,,) -> %d (%#x) szErr='%s'\n", rc, rc, szErr); + } + if (!rc) + { + rc = kLdrDyldQuerySymbol(hModA, NIL_KLDRMOD_SYM_ORDINAL, MY_NAME("FuncA"), NULL, &uValue, NULL); + if (!rc) + pfnFuncA = (int (*)(void))uValue; + else + Failure("kLdrDyldQuerySymbol(,,\"FuncA\",,) -> %d (%#x)\n", rc, rc); + } + if (!rc) + { + rc = kLdrDyldQuerySymbol(hModB, NIL_KLDRMOD_SYM_ORDINAL, MY_NAME("FuncB"), NULL, &uValue, NULL); + if (!rc) + pfnFuncB = (int (*)(void))uValue; + else + Failure("kLdrDyldQuerySymbol(,,\"FuncB\",,) -> %d (%#x)\n", rc, rc); + } + if (!rc) + { + rc = kLdrDyldQuerySymbol(hModC, NIL_KLDRMOD_SYM_ORDINAL, MY_NAME("FuncC"), NULL, &uValue, NULL); + if (!rc) + pfnFuncC = (int (*)(void))uValue; + else + Failure("kLdrDyldQuerySymbol(,,\"FuncA\",,) -> %d (%#x)\n", rc, rc); + } + if (!rc) + { + int u = pfnFuncA() | pfnFuncB() | pfnFuncC(); + if (u == 0x42424242) + printf("tst-0-driver: FuncA/B/C => %#x (correct)\n", u); + else + Failure("FuncA/B/C => %#x\n", u); + + rc = kLdrDyldUnload(hModA); + if (rc) + Failure("Unload A failed, rc=%d (%#x)\n", rc, rc); + u = pfnFuncB() | pfnFuncC(); + if (u != 0x42424200) + Failure("FuncB/C returns %#x instead of 0x42424200 after unloading A\n", u); + + rc = kLdrDyldUnload(hModB); + if (rc) + Failure("Unload B failed, rc=%d (%#x)\n", rc, rc); + u = pfnFuncC(); + if (u != 0x42420000) + Failure("FuncC returns %#x instead of 0x42420000 after unloading A\n", u); + + rc = kLdrDyldUnload(hModC); + if (rc) + Failure("Unload C failed, rc=%d (%#x)\n", rc, rc); + + rc = kLdrDyldFindByName("tst-0-d", NULL, NULL, KLDRDYLD_SEARCH_HOST, 0, &hMod); + if (rc != KLDR_ERR_MODULE_NOT_FOUND) + Failure("Query for \"tst-0-d\" after unloading A,B and C returns rc=%d (%#x) instead of KLDR_ERR_MODULE_NOT_FOUND\n", + rc, rc); + } + } + + /* + * Now invoke the executable stub which launches the tst-0 program. + */ + if (!g_cErrors) + { + /// @todo + } + + /* + * Summary + */ + if (!g_cErrors) + printf("tst-0-driver: SUCCESS\n"); + else + printf("tst-0-driver: FAILURE - %d errors\n", g_cErrors); + return !!g_cErrors; +} + -- cgit v1.2.3