VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstLdr-4.cpp@ 85155

Last change on this file since 85155 was 85121, checked in by vboxsync, 5 years ago

iprt/cdefs.h: Refactored the typedef use of DECLCALLBACK as well as DECLCALLBACKMEMBER to wrap the whole expression, similar to the DECLR?CALLBACKMEMBER macros. This allows adding a throw() at the end when compiling with the VC++ compiler to indicate that the callbacks won't throw anything, so we can stop supressing the C5039 warning about passing functions that can potential throw C++ exceptions to extern C code that can't necessarily cope with such (unwind,++). Introduced a few _EX variations that allows specifying different/no calling convention too, as that's handy when dynamically resolving host APIs. Fixed numerous places missing DECLCALLBACK and such. Left two angry @todos regarding use of CreateThread. bugref:9794

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 11.4 KB
Line 
1/* $Id: tstLdr-4.cpp 85121 2020-07-08 19:33:26Z vboxsync $ */
2/** @file
3 * IPRT - Testcase for RTLdrOpen using ldrLdrObjR0.r0.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/ldr.h>
32#include <iprt/alloc.h>
33#include <iprt/log.h>
34#include <iprt/stream.h>
35#include <iprt/assert.h>
36#include <iprt/param.h>
37#include <iprt/path.h>
38#include <iprt/initterm.h>
39#include <iprt/err.h>
40#include <iprt/string.h>
41
42#include <VBox/sup.h>
43
44
45/*********************************************************************************************************************************
46* Global Variables *
47*********************************************************************************************************************************/
48static SUPGLOBALINFOPAGE g_MyGip = { SUPGLOBALINFOPAGE_MAGIC, SUPGLOBALINFOPAGE_VERSION, SUPGIPMODE_INVARIANT_TSC, 42 };
49static PSUPGLOBALINFOPAGE g_pMyGip = &g_MyGip;
50
51extern "C" DECLEXPORT(int) DisasmTest1(void);
52
53
54static DECLCALLBACK(int) testEnumSegment(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser)
55{
56 uint32_t *piSeg = (uint32_t *)pvUser;
57 RTPrintf(" Seg#%02u: %RTptr LB %RTptr %s\n"
58 " link=%RTptr LB %RTptr align=%RTptr fProt=%#x offFile=%RTfoff\n"
59 , *piSeg, pSeg->RVA, pSeg->cbMapped, pSeg->pszName,
60 pSeg->LinkAddress, pSeg->cb, pSeg->Alignment, pSeg->fProt, pSeg->offFile);
61 *piSeg += 1;
62 RT_NOREF(hLdrMod);
63 return VINF_SUCCESS;
64}
65
66
67/**
68 * Resolve an external symbol during RTLdrGetBits().
69 *
70 * @returns iprt status code.
71 * @param hLdrMod The loader module handle.
72 * @param pszModule Module name.
73 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
74 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
75 * @param pValue Where to store the symbol value (address).
76 * @param pvUser User argument.
77 */
78static DECLCALLBACK(int) testGetImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
79{
80 RT_NOREF4(hLdrMod, pszModule, uSymbol, pvUser);
81 if ( !strcmp(pszSymbol, "RTAssertMsg1Weak") || !strcmp(pszSymbol, "_RTAssertMsg1Weak"))
82 *pValue = (uintptr_t)RTAssertMsg1Weak;
83 else if (!strcmp(pszSymbol, "RTAssertMsg2Weak") || !strcmp(pszSymbol, "_RTAssertMsg2Weak"))
84 *pValue = (uintptr_t)RTAssertMsg1Weak;
85 else if (!strcmp(pszSymbol, "RTAssertMsg1") || !strcmp(pszSymbol, "_RTAssertMsg1"))
86 *pValue = (uintptr_t)RTAssertMsg1;
87 else if (!strcmp(pszSymbol, "RTAssertMsg2") || !strcmp(pszSymbol, "_RTAssertMsg2"))
88 *pValue = (uintptr_t)RTAssertMsg2;
89 else if (!strcmp(pszSymbol, "RTAssertMsg2V") || !strcmp(pszSymbol, "_RTAssertMsg2V"))
90 *pValue = (uintptr_t)RTAssertMsg2V;
91 else if (!strcmp(pszSymbol, "RTAssertMayPanic") || !strcmp(pszSymbol, "_RTAssertMayPanic"))
92 *pValue = (uintptr_t)RTAssertMayPanic;
93 else if (!strcmp(pszSymbol, "RTLogDefaultInstanceEx") || !strcmp(pszSymbol, "RTLogDefaultInstanceEx"))
94 *pValue = (uintptr_t)RTLogDefaultInstanceEx;
95 else if (!strcmp(pszSymbol, "RTLogLoggerExV") || !strcmp(pszSymbol, "_RTLogLoggerExV"))
96 *pValue = (uintptr_t)RTLogLoggerExV;
97 else if (!strcmp(pszSymbol, "RTLogPrintfV") || !strcmp(pszSymbol, "_RTLogPrintfV"))
98 *pValue = (uintptr_t)RTLogPrintfV;
99 else if (!strcmp(pszSymbol, "RTR0AssertPanicSystem")|| !strcmp(pszSymbol, "_RTR0AssertPanicSystem"))
100 *pValue = (uintptr_t)0;
101 else if (!strcmp(pszSymbol, "MyPrintf") || !strcmp(pszSymbol, "_MyPrintf"))
102 *pValue = (uintptr_t)RTPrintf;
103 else if (!strcmp(pszSymbol, "SUPR0Printf") || !strcmp(pszSymbol, "_SUPR0Printf"))
104 *pValue = (uintptr_t)RTPrintf;
105 else if (!strcmp(pszSymbol, "SomeImportFunction") || !strcmp(pszSymbol, "_SomeImportFunction"))
106 *pValue = (uintptr_t)0;
107 else if (!strcmp(pszSymbol, "g_pSUPGlobalInfoPage") || !strcmp(pszSymbol, "_g_pSUPGlobalInfoPage"))
108 *pValue = (uintptr_t)&g_pMyGip;
109 else if (!strcmp(pszSymbol, "g_SUPGlobalInfoPage") || !strcmp(pszSymbol, "_g_SUPGlobalInfoPage"))
110 *pValue = (uintptr_t)&g_MyGip;
111 else
112 {
113 RTPrintf("tstLdr-4: Unexpected import '%s'!\n", pszSymbol);
114 return VERR_SYMBOL_NOT_FOUND;
115 }
116 return VINF_SUCCESS;
117}
118
119
120/**
121 * One test iteration with one file.
122 *
123 * The test is very simple, we load the file three times
124 * into two different regions. The first two into each of the
125 * regions the for compare usage. The third is loaded into one
126 * and then relocated between the two and other locations a few times.
127 *
128 * @returns number of errors.
129 * @param pszFilename The file to load the mess with.
130 */
131static int testLdrOne(const char *pszFilename)
132{
133 int cErrors = 0;
134 size_t cbImage = 0;
135 struct Load
136 {
137 RTLDRMOD hLdrMod;
138 void *pvBits;
139 size_t cbBits;
140 const char *pszName;
141 } aLoads[6] =
142 {
143 { NULL, NULL, 0, "foo" },
144 { NULL, NULL, 0, "bar" },
145 { NULL, NULL, 0, "foobar" },
146 };
147 unsigned i;
148 int rc;
149
150 /*
151 * Load them.
152 */
153 for (i = 0; i < RT_ELEMENTS(aLoads); i++)
154 {
155 rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_WHATEVER, &aLoads[i].hLdrMod);
156 if (RT_FAILURE(rc))
157 {
158 RTPrintf("tstLdr-4: Failed to open '%s'/%d, rc=%Rrc. aborting test.\n", pszFilename, i, rc);
159 Assert(aLoads[i].hLdrMod == NIL_RTLDRMOD);
160 cErrors++;
161 break;
162 }
163
164 /* size it */
165 size_t cb = RTLdrSize(aLoads[i].hLdrMod);
166 if (cbImage && cb != cbImage)
167 {
168 RTPrintf("tstLdr-4: Size mismatch '%s'/%d. aborting test.\n", pszFilename, i);
169 cErrors++;
170 break;
171 }
172 aLoads[i].cbBits = cbImage = cb;
173
174 /* Allocate bits. */
175 aLoads[i].pvBits = RTMemExecAlloc(cb);
176 if (!aLoads[i].pvBits)
177 {
178 RTPrintf("tstLdr-4: Out of memory '%s'/%d cbImage=%d. aborting test.\n", pszFilename, i, cbImage);
179 cErrors++;
180 break;
181 }
182
183 /* Get the bits. */
184 rc = RTLdrGetBits(aLoads[i].hLdrMod, aLoads[i].pvBits, (uintptr_t)aLoads[i].pvBits, testGetImport, NULL);
185 if (RT_FAILURE(rc))
186 {
187 RTPrintf("tstLdr-4: Failed to get bits for '%s'/%d, rc=%Rrc. aborting test\n", pszFilename, i, rc);
188 cErrors++;
189 break;
190 }
191 }
192
193 /*
194 * Execute the code.
195 */
196 if (!cErrors)
197 {
198 for (i = 0; i < RT_ELEMENTS(aLoads); i += 1)
199 {
200 /* VERR_ELF_EXE_NOT_SUPPORTED in the previous loop? */
201 if (!aLoads[i].hLdrMod)
202 continue;
203 /* get the pointer. */
204 RTUINTPTR Value;
205 rc = RTLdrGetSymbolEx(aLoads[i].hLdrMod, aLoads[i].pvBits, (uintptr_t)aLoads[i].pvBits,
206 UINT32_MAX, "DisasmTest1", &Value);
207 if (rc == VERR_SYMBOL_NOT_FOUND)
208 rc = RTLdrGetSymbolEx(aLoads[i].hLdrMod, aLoads[i].pvBits, (uintptr_t)aLoads[i].pvBits,
209 UINT32_MAX, "_DisasmTest1", &Value);
210 if (RT_FAILURE(rc))
211 {
212 RTPrintf("tstLdr-4: Failed to get symbol \"DisasmTest1\" from load #%d: %Rrc\n", i, rc);
213 cErrors++;
214 break;
215 }
216 typedef DECLCALLBACKPTR(int, PFNDISASMTEST1,(void));
217 PFNDISASMTEST1 pfnDisasmTest1 = (PFNDISASMTEST1)(uintptr_t)Value;
218 RTPrintf("tstLdr-4: pfnDisasmTest1=%p / add-symbol-file %s %#x\n", pfnDisasmTest1, pszFilename, aLoads[i].pvBits);
219 uint32_t iSeg = 0;
220 RTLdrEnumSegments(aLoads[i].hLdrMod, testEnumSegment, &iSeg);
221
222 /* call the test function. */
223 rc = pfnDisasmTest1();
224 if (rc)
225 {
226 RTPrintf("tstLdr-4: load #%d Test1 -> %#x\n", i, rc);
227 cErrors++;
228 }
229
230 /* While we're here, check a couple of RTLdrQueryProp calls too */
231 void *pvBits = aLoads[i].pvBits;
232 for (unsigned iBits = 0; iBits < 2; iBits++, pvBits = NULL)
233 {
234 union
235 {
236 char szName[127];
237 } uBuf;
238 rc = RTLdrQueryPropEx(aLoads[i].hLdrMod, RTLDRPROP_INTERNAL_NAME, aLoads[i].pvBits,
239 uBuf.szName, sizeof(uBuf.szName), NULL);
240 if (RT_SUCCESS(rc))
241 RTPrintf("tstLdr-4: internal name #%d: '%s'\n", i, uBuf.szName);
242 else if (rc != VERR_NOT_FOUND && rc != VERR_NOT_SUPPORTED)
243 RTPrintf("tstLdr-4: internal name #%d failed: %Rrc\n", i, rc);
244 }
245 }
246 }
247
248 /*
249 * Clean up.
250 */
251 for (i = 0; i < RT_ELEMENTS(aLoads); i++)
252 {
253 if (aLoads[i].pvBits)
254 RTMemExecFree(aLoads[i].pvBits, aLoads[i].cbBits);
255 if (aLoads[i].hLdrMod)
256 {
257 rc = RTLdrClose(aLoads[i].hLdrMod);
258 if (RT_FAILURE(rc))
259 {
260 RTPrintf("tstLdr-4: Failed to close '%s' i=%d, rc=%Rrc.\n", pszFilename, i, rc);
261 cErrors++;
262 }
263 }
264 }
265
266 return cErrors;
267}
268
269
270
271int main(int argc, char **argv)
272{
273 int cErrors = 0;
274 RTR3InitExe(argc, &argv, 0);
275
276 /*
277 * Sanity check.
278 */
279 int rc = DisasmTest1();
280 if (rc)
281 {
282 RTPrintf("tstLdr-4: FATAL ERROR - DisasmTest1 is buggy: rc=%#x\n", rc);
283 return 1;
284 }
285
286 /*
287 * Execute the test.
288 */
289 char szPath[RTPATH_MAX];
290 rc = RTPathExecDir(szPath, sizeof(szPath) - sizeof("/tstLdrObjR0.r0"));
291 if (RT_SUCCESS(rc))
292 {
293 strcat(szPath, "/tstLdrObjR0.r0");
294 RTPrintf("tstLdr-4: TESTING '%s'...\n", szPath);
295 cErrors += testLdrOne(szPath);
296 }
297 else
298 {
299 RTPrintf("tstLdr-4: RTPathExecDir -> %Rrc\n", rc);
300 cErrors++;
301 }
302
303 /*
304 * Test result summary.
305 */
306 if (!cErrors)
307 RTPrintf("tstLdr-4: SUCCESS\n");
308 else
309 RTPrintf("tstLdr-4: FAILURE - %d errors\n", cErrors);
310 return !!cErrors;
311}
Note: See TracBrowser for help on using the repository browser.

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