VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/PDMLdr.cpp@ 94425

Last change on this file since 94425 was 93901, checked in by vboxsync, 3 years ago

VMM,Main,++: Removed VM_IS_RAW_MODE_ENABLED/VM_EXEC_ENGINE_RAW_MODE and added VM_IS_EXEC_ENGINE_IEM/VM_EXEC_ENGINE_IEM instead. In IMachineDebugger::getExecutionEngine VMExecutionEngine_RawMode was removed and VMExecutionEngine_Emulated added. Removed dead code and updated frontends accordingly. On darwin.arm64 HM now falls back on IEM execution since neither HM or NEM is availble there. bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 63.8 KB
Line 
1/* $Id: PDMLdr.cpp 93901 2022-02-23 15:35:26Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device Manager, module loader.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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
18//#define PDMLDR_FAKE_MODE
19
20
21/*********************************************************************************************************************************
22* Header Files *
23*********************************************************************************************************************************/
24#define LOG_GROUP LOG_GROUP_PDM_LDR
25#include "PDMInternal.h"
26#include <VBox/vmm/pdm.h>
27#include <VBox/vmm/mm.h>
28#include <VBox/vmm/trpm.h>
29#include <VBox/vmm/vmm.h>
30#include <VBox/vmm/vm.h>
31#include <VBox/vmm/uvm.h>
32#include <VBox/sup.h>
33#include <VBox/param.h>
34#include <VBox/err.h>
35#include <VBox/vmm/hm.h>
36#include <VBox/VBoxTpG.h>
37
38#include <VBox/log.h>
39#include <iprt/assert.h>
40#include <iprt/ctype.h>
41#include <iprt/file.h>
42#include <iprt/ldr.h>
43#include <iprt/mem.h>
44#include <iprt/path.h>
45#include <iprt/string.h>
46
47#include <limits.h>
48
49
50/*********************************************************************************************************************************
51* Structures and Typedefs *
52*********************************************************************************************************************************/
53/**
54 * Structure which the user argument of the RTLdrGetBits() callback points to.
55 * @internal
56 */
57typedef struct PDMGETIMPORTARGS
58{
59 PVM pVM;
60 PPDMMOD pModule;
61} PDMGETIMPORTARGS, *PPDMGETIMPORTARGS;
62
63
64/*********************************************************************************************************************************
65* Internal Functions *
66*********************************************************************************************************************************/
67#ifdef VBOX_WITH_RAW_MODE_KEEP
68static DECLCALLBACK(int) pdmR3GetImportRC(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
69static char *pdmR3FileRC(const char *pszFile, const char *pszSearchPath);
70#endif
71static int pdmR3LoadR0U(PUVM pUVM, const char *pszFilename, const char *pszName, const char *pszSearchPath);
72static char *pdmR3FileR0(const char *pszFile, const char *pszSearchPath);
73static char *pdmR3File(const char *pszFile, const char *pszDefaultExt, const char *pszSearchPath, bool fShared);
74
75
76
77/**
78 * Loads the VMMR0.r0 module early in the init process.
79 *
80 * @returns VBox status code.
81 * @param pUVM Pointer to the user mode VM structure.
82 */
83VMMR3_INT_DECL(int) PDMR3LdrLoadVMMR0U(PUVM pUVM)
84{
85 return pdmR3LoadR0U(pUVM, NULL, VMMR0_MAIN_MODULE_NAME, NULL);
86}
87
88
89/**
90 * Init the module loader part of PDM.
91 *
92 * This routine will load the Host Context Ring-0 and Guest
93 * Context VMM modules.
94 *
95 * @returns VBox status code.
96 * @param pUVM The user mode VM structure.
97 */
98int pdmR3LdrInitU(PUVM pUVM)
99{
100#if !defined(PDMLDR_FAKE_MODE) && defined(VBOX_WITH_RAW_MODE_KEEP)
101 /*
102 * Load the mandatory RC module, the VMMR0.r0 is loaded before VM creation.
103 */
104 PVM pVM = pUVM->pVM; AssertPtr(pVM);
105 if (VM_IS_RAW_MODE_ENABLED(pVM))
106 {
107 int rc = PDMR3LdrLoadRC(pVM, NULL, VMMRC_MAIN_MODULE_NAME);
108 if (RT_FAILURE(rc))
109 return rc;
110 }
111#else
112 RT_NOREF(pUVM);
113#endif
114 return VINF_SUCCESS;
115}
116
117
118/**
119 * Terminate the module loader part of PDM.
120 *
121 * This will unload and free all modules.
122 *
123 * @param pUVM The user mode VM structure.
124 * @param fFinal This is clear when in the PDMR3Term/vmR3Destroy call
125 * chain, and set when called from PDMR3TermUVM.
126 *
127 * @remarks This is normally called twice during termination.
128 */
129void pdmR3LdrTermU(PUVM pUVM, bool fFinal)
130{
131 /*
132 * Free the modules.
133 */
134 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
135 PPDMMOD pModule = pUVM->pdm.s.pModules;
136 pUVM->pdm.s.pModules = NULL;
137 PPDMMOD *ppNext = &pUVM->pdm.s.pModules;
138 while (pModule)
139 {
140 /* free loader item. */
141 if (pModule->hLdrMod != NIL_RTLDRMOD)
142 {
143 int rc2 = RTLdrClose(pModule->hLdrMod);
144 AssertRC(rc2);
145 pModule->hLdrMod = NIL_RTLDRMOD;
146 }
147
148 /* free bits. */
149 switch (pModule->eType)
150 {
151 case PDMMOD_TYPE_R0:
152 {
153 if (fFinal)
154 {
155 Assert(pModule->ImageBase);
156 int rc2 = SUPR3FreeModule((void *)(uintptr_t)pModule->ImageBase);
157 AssertRC(rc2);
158 pModule->ImageBase = 0;
159 break;
160 }
161
162 /* Postpone ring-0 module till the PDMR3TermUVM() phase as VMMR0.r0 is still
163 busy when we're called the first time very very early in vmR3Destroy(). */
164 PPDMMOD pNextModule = pModule->pNext;
165
166 pModule->pNext = NULL;
167 *ppNext = pModule;
168 ppNext = &pModule->pNext;
169
170 pModule = pNextModule;
171 continue;
172 }
173
174#ifdef VBOX_WITH_RAW_MODE_KEEP
175 case PDMMOD_TYPE_RC:
176#endif
177 case PDMMOD_TYPE_R3:
178 /* MM will free this memory for us - it's alloc only memory. :-) */
179 break;
180
181 default:
182 AssertMsgFailed(("eType=%d\n", pModule->eType));
183 break;
184 }
185 pModule->pvBits = NULL;
186
187 void *pvFree = pModule;
188 pModule = pModule->pNext;
189 RTMemFree(pvFree);
190 }
191 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
192}
193
194
195/**
196 * Applies relocations to RC modules.
197 *
198 * This must be done very early in the relocation
199 * process so that components can resolve RC symbols during relocation.
200 *
201 * @param pUVM Pointer to the user mode VM structure.
202 * @param offDelta Relocation delta relative to old location.
203 */
204VMMR3_INT_DECL(void) PDMR3LdrRelocateU(PUVM pUVM, RTGCINTPTR offDelta)
205{
206#ifdef VBOX_WITH_RAW_MODE_KEEP
207 LogFlow(("PDMR3LdrRelocate: offDelta=%RGv\n", offDelta));
208 RT_NOREF1(offDelta);
209
210 /*
211 * RC Modules.
212 */
213 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
214 if (pUVM->pdm.s.pModules)
215 {
216 /*
217 * The relocation have to be done in two passes so imports
218 * can be correctly resolved. The first pass will update
219 * the ImageBase saving the current value in OldImageBase.
220 * The second pass will do the actual relocation.
221 */
222 /* pass 1 */
223 PPDMMOD pCur;
224 for (pCur = pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
225 {
226 if (pCur->eType == PDMMOD_TYPE_RC)
227 {
228 pCur->OldImageBase = pCur->ImageBase;
229 pCur->ImageBase = MMHyperR3ToRC(pUVM->pVM, pCur->pvBits);
230 }
231 }
232
233 /* pass 2 */
234 for (pCur = pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
235 {
236 if (pCur->eType == PDMMOD_TYPE_RC)
237 {
238 PDMGETIMPORTARGS Args;
239 Args.pVM = pUVM->pVM;
240 Args.pModule = pCur;
241 int rc = RTLdrRelocate(pCur->hLdrMod, pCur->pvBits, pCur->ImageBase, pCur->OldImageBase,
242 pdmR3GetImportRC, &Args);
243 AssertFatalMsgRC(rc, ("RTLdrRelocate failed, rc=%d\n", rc));
244 }
245 }
246 }
247 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
248#else
249 RT_NOREF2(pUVM, offDelta);
250#endif
251}
252
253
254/**
255 * Loads a module into the host context ring-3.
256 *
257 * This is used by the driver and device init functions to load modules
258 * containing the drivers and devices. The function can be extended to
259 * load modules which are not native to the environment we're running in,
260 * but at the moment this is not required.
261 *
262 * No reference counting is kept, since we don't implement any facilities
263 * for unloading the module. But the module will naturally be released
264 * when the VM terminates.
265 *
266 * @returns VBox status code.
267 * @param pUVM Pointer to the user mode VM structure.
268 * @param pszFilename Filename of the module binary.
269 * @param pszName Module name. Case sensitive and the length is limited!
270 */
271int pdmR3LoadR3U(PUVM pUVM, const char *pszFilename, const char *pszName)
272{
273 /*
274 * Validate input.
275 */
276 AssertMsg(RTCritSectIsInitialized(&pUVM->pdm.s.ListCritSect), ("bad init order!\n"));
277 Assert(pszFilename);
278 size_t cchFilename = strlen(pszFilename);
279 Assert(pszName);
280 size_t cchName = strlen(pszName);
281 PPDMMOD pCur;
282 if (cchName >= sizeof(pCur->szName))
283 {
284 AssertMsgFailed(("Name is too long, cchName=%d pszName='%s'\n", cchName, pszName));
285 return VERR_INVALID_PARAMETER;
286 }
287
288 /*
289 * Try lookup the name and see if the module exists.
290 */
291 int rc;
292 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
293 for (pCur = pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
294 {
295 if (!strcmp(pCur->szName, pszName))
296 {
297 if (pCur->eType == PDMMOD_TYPE_R3)
298 rc = VINF_PDM_ALREADY_LOADED;
299 else
300 rc = VERR_PDM_MODULE_NAME_CLASH;
301 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
302
303 AssertMsgRC(rc, ("We've already got a module '%s' loaded!\n", pszName));
304 return rc;
305 }
306 }
307
308 /*
309 * Allocate the module list node and initialize it.
310 */
311 const char *pszSuff = RTLdrGetSuff();
312 size_t cchSuff = RTPathHasSuffix(pszFilename) ? 0 : strlen(pszSuff);
313 PPDMMOD pModule = (PPDMMOD)RTMemAllocZ(RT_UOFFSETOF_DYN(PDMMOD, szFilename[cchFilename + cchSuff + 1]));
314 if (pModule)
315 {
316 pModule->eType = PDMMOD_TYPE_R3;
317 memcpy(pModule->szName, pszName, cchName); /* memory is zero'd, no need to copy terminator :-) */
318 memcpy(pModule->szFilename, pszFilename, cchFilename);
319 memcpy(&pModule->szFilename[cchFilename], pszSuff, cchSuff);
320
321 /*
322 * Load the loader item.
323 */
324 RTERRINFOSTATIC ErrInfo;
325 RTErrInfoInitStatic(&ErrInfo);
326 rc = SUPR3HardenedLdrLoadPlugIn(pModule->szFilename, &pModule->hLdrMod, &ErrInfo.Core);
327 if (RT_SUCCESS(rc))
328 {
329 pModule->pNext = pUVM->pdm.s.pModules;
330 pUVM->pdm.s.pModules = pModule;
331 }
332 else
333 {
334 /* Something went wrong, most likely module not found. Don't consider other unlikely errors */
335 rc = VMSetError(pUVM->pVM, rc, RT_SRC_POS,
336 N_("Unable to load R3 module %s (%s): %s"), pModule->szFilename, pszName, ErrInfo.Core.pszMsg);
337 RTMemFree(pModule);
338 }
339 }
340 else
341 rc = VERR_NO_MEMORY;
342
343 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
344 return rc;
345}
346
347#ifdef VBOX_WITH_RAW_MODE_KEEP
348
349/**
350 * Resolve an external symbol during RTLdrGetBits() of a RC module.
351 *
352 * @returns VBox status code.
353 * @param hLdrMod The loader module handle.
354 * @param pszModule Module name.
355 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
356 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
357 * @param pValue Where to store the symbol value (address).
358 * @param pvUser User argument.
359 */
360static DECLCALLBACK(int) pdmR3GetImportRC(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol,
361 RTUINTPTR *pValue, void *pvUser)
362{
363 PVM pVM = ((PPDMGETIMPORTARGS)pvUser)->pVM;
364 PPDMMOD pModule = ((PPDMGETIMPORTARGS)pvUser)->pModule;
365 NOREF(hLdrMod); NOREF(uSymbol);
366
367 /*
368 * Adjust input.
369 */
370 if (pszModule && !*pszModule)
371 pszModule = NULL;
372
373 /*
374 * Builtin module.
375 */
376 if (!pszModule || !strcmp(pszModule, "VMMRCBuiltin.rc"))
377 {
378 int rc = VINF_SUCCESS;
379 if (!strcmp(pszSymbol, "g_VM"))
380 *pValue = pVM->pVMRC;
381 else if (!strcmp(pszSymbol, "g_VCpu0"))
382 *pValue = pVM->pVMRC + pVM->offVMCPU;
383 else if (!strcmp(pszSymbol, "g_CPUM"))
384 *pValue = VM_RC_ADDR(pVM, &pVM->cpum);
385 else if ( !strncmp(pszSymbol, "g_TRPM", 6)
386 || !strncmp(pszSymbol, "g_trpm", 6)
387 || !strncmp(pszSymbol, "TRPM", 4))
388 {
389 RTRCPTR RCPtr = 0;
390 rc = TRPMR3GetImportRC(pVM, pszSymbol, &RCPtr);
391 if (RT_SUCCESS(rc))
392 *pValue = RCPtr;
393 }
394 else if ( !strncmp(pszSymbol, "VMM", 3)
395 || !strcmp(pszSymbol, "g_Logger")
396 || !strcmp(pszSymbol, "g_RelLogger"))
397 {
398 RTRCPTR RCPtr = 0;
399 rc = VMMR3GetImportRC(pVM, pszSymbol, &RCPtr);
400 if (RT_SUCCESS(rc))
401 *pValue = RCPtr;
402 }
403 else
404 {
405 AssertMsg(!pszModule, ("Unknown builtin symbol '%s' for module '%s'!\n", pszSymbol, pModule->szName)); NOREF(pModule);
406 rc = VERR_SYMBOL_NOT_FOUND;
407 }
408 if (RT_SUCCESS(rc) || pszModule)
409 {
410 if (RT_FAILURE(rc))
411 LogRel(("PDMLdr: Couldn't find symbol '%s' in module '%s'!\n", pszSymbol, pszModule));
412 return rc;
413 }
414 }
415
416 /*
417 * Search for module.
418 */
419 PUVM pUVM = pVM->pUVM;
420 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
421 PPDMMOD pCur = pUVM->pdm.s.pModules;
422 while (pCur)
423 {
424 if ( pCur->eType == PDMMOD_TYPE_RC
425 && ( !pszModule
426 || !strcmp(pCur->szName, pszModule))
427 )
428 {
429 /* Search for the symbol. */
430 int rc = RTLdrGetSymbolEx(pCur->hLdrMod, pCur->pvBits, pCur->ImageBase, UINT32_MAX, pszSymbol, pValue);
431 if (RT_SUCCESS(rc))
432 {
433 AssertMsg(*pValue - pCur->ImageBase < RTLdrSize(pCur->hLdrMod),
434 ("%RRv-%RRv %s %RRv\n", (RTRCPTR)pCur->ImageBase,
435 (RTRCPTR)(pCur->ImageBase + RTLdrSize(pCur->hLdrMod) - 1),
436 pszSymbol, (RTRCPTR)*pValue));
437 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
438 return rc;
439 }
440 if (pszModule)
441 {
442 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
443 AssertLogRelMsgFailed(("PDMLdr: Couldn't find symbol '%s' in module '%s'!\n", pszSymbol, pszModule));
444 return VERR_SYMBOL_NOT_FOUND;
445 }
446 }
447
448 /* next */
449 pCur = pCur->pNext;
450 }
451
452 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
453 AssertLogRelMsgFailed(("Couldn't find module '%s' for resolving symbol '%s'!\n", pszModule, pszSymbol));
454 return VERR_SYMBOL_NOT_FOUND;
455}
456
457
458/**
459 * Loads a module into the raw-mode context (i.e. into the Hypervisor memory
460 * region).
461 *
462 * @returns VBox status code.
463 * @retval VINF_PDM_ALREADY_LOADED if the module is already loaded (name +
464 * filename match).
465 * @retval VERR_PDM_MODULE_NAME_CLASH if a different file has already been
466 * loaded with the name module name.
467 *
468 * @param pVM The cross context VM structure.
469 * @param pszFilename Filename of the module binary.
470 * @param pszName Module name. Case sensitive and the length is limited!
471 */
472VMMR3DECL(int) PDMR3LdrLoadRC(PVM pVM, const char *pszFilename, const char *pszName)
473{
474 /*
475 * Validate input.
476 */
477 AssertReturn(VM_IS_RAW_MODE_ENABLED(pVM), VERR_PDM_HM_IPE);
478
479 /*
480 * Find the file if not specified.
481 */
482 char *pszFile = NULL;
483 if (!pszFilename)
484 pszFilename = pszFile = pdmR3FileRC(pszName, NULL);
485
486 /*
487 * Check if a module by that name is already loaded.
488 */
489 int rc;
490 PUVM pUVM = pVM->pUVM;
491 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
492 PPDMMOD pCur = pUVM->pdm.s.pModules;
493 while (pCur)
494 {
495 if (!strcmp(pCur->szName, pszName))
496 {
497 /* Name clash. Hopefully due to it being the same file. */
498 if (!strcmp(pCur->szFilename, pszFilename))
499 rc = VINF_PDM_ALREADY_LOADED;
500 else
501 {
502 rc = VERR_PDM_MODULE_NAME_CLASH;
503 AssertMsgFailed(("We've already got a module '%s' loaded!\n", pszName));
504 }
505 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
506 RTMemTmpFree(pszFile);
507 return rc;
508 }
509 /* next */
510 pCur = pCur->pNext;
511 }
512
513 /*
514 * Allocate the module list node.
515 */
516 PPDMMOD pModule = (PPDMMOD)RTMemAllocZ(sizeof(*pModule) + strlen(pszFilename));
517 if (!pModule)
518 {
519 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
520 RTMemTmpFree(pszFile);
521 return VERR_NO_MEMORY;
522 }
523 AssertMsg(strlen(pszName) + 1 < sizeof(pModule->szName),
524 ("pazName is too long (%d chars) max is %d chars.\n", strlen(pszName), sizeof(pModule->szName) - 1));
525 strcpy(pModule->szName, pszName);
526 pModule->eType = PDMMOD_TYPE_RC;
527 strcpy(pModule->szFilename, pszFilename);
528
529
530 /*
531 * Open the loader item.
532 */
533 RTERRINFOSTATIC ErrInfo;
534 RTErrInfoInitStatic(&ErrInfo);
535 rc = SUPR3HardenedVerifyPlugIn(pszFilename, &ErrInfo.Core);
536 if (RT_SUCCESS(rc))
537 {
538 RTErrInfoClear(&ErrInfo.Core);
539 rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_X86_32, &pModule->hLdrMod);
540 }
541 if (RT_SUCCESS(rc))
542 {
543 /*
544 * Allocate space in the hypervisor.
545 */
546 size_t cb = RTLdrSize(pModule->hLdrMod);
547 cb = RT_ALIGN_Z(cb, RT_MAX(GUEST_PAGE_SIZE, HOST_PAGE_SIZE));
548 uint32_t cPages = (uint32_t)(cb >> HOST_PAGE_SHIFT);
549 if (((size_t)cPages << HOST_PAGE_SHIFT) == cb)
550 {
551 PSUPPAGE paPages = (PSUPPAGE)RTMemTmpAlloc(cPages * sizeof(paPages[0]));
552 if (paPages)
553 {
554 rc = SUPR3PageAllocEx(cPages, 0 /*fFlags*/, &pModule->pvBits, NULL /*pR0Ptr*/, paPages);
555 if (RT_SUCCESS(rc))
556 {
557 RTGCPTR GCPtr;
558 rc = VERR_NOT_IMPLEMENTED; //MMR3HyperMapPages(pVM, pModule->pvBits, NIL_RTR0PTR, cPages, paPages, pModule->szName, &GCPtr);
559 if (RT_SUCCESS(rc))
560 {
561 //MMR3HyperReserveFence(pVM);
562
563 /*
564 * Get relocated image bits.
565 */
566 Assert(MMHyperR3ToRC(pVM, pModule->pvBits) == GCPtr);
567 pModule->ImageBase = GCPtr;
568 PDMGETIMPORTARGS Args;
569 Args.pVM = pVM;
570 Args.pModule = pModule;
571 rc = RTLdrGetBits(pModule->hLdrMod, pModule->pvBits, pModule->ImageBase, pdmR3GetImportRC, &Args);
572 if (RT_SUCCESS(rc))
573 {
574#ifdef VBOX_WITH_DTRACE_RC
575 /*
576 * Register the tracer bits if present.
577 */
578 RTLDRADDR uValue;
579 rc = RTLdrGetSymbolEx(pModule->hLdrMod, pModule->pvBits, pModule->ImageBase, UINT32_MAX,
580 "g_VTGObjHeader", &uValue);
581 if (RT_SUCCESS(rc))
582 {
583 PVTGOBJHDR pVtgHdr = (PVTGOBJHDR)MMHyperRCToCC(pVM, (RTRCPTR)uValue);
584 if ( pVtgHdr
585 && !memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
586 rc = SUPR3TracerRegisterModule(~(uintptr_t)0, pModule->szName, pVtgHdr, uValue,
587 SUP_TRACER_UMOD_FLAGS_SHARED);
588 else
589 rc = pVtgHdr ? VERR_INVALID_MAGIC : VERR_INVALID_POINTER;
590 if (RT_FAILURE(rc))
591 LogRel(("PDMLdr: Failed to register tracepoints for '%s': %Rrc\n", pModule->szName, rc));
592 }
593#endif
594
595 /*
596 * Insert the module.
597 */
598 if (pUVM->pdm.s.pModules)
599 {
600 /* we don't expect this list to be very long, so rather save the tail pointer. */
601 pCur = pUVM->pdm.s.pModules;
602 while (pCur->pNext)
603 pCur = pCur->pNext;
604 pCur->pNext = pModule;
605 }
606 else
607 pUVM->pdm.s.pModules = pModule; /* (pNext is zeroed by alloc) */
608 Log(("PDM: RC Module at %RRv %s (%s)\n", (RTRCPTR)pModule->ImageBase, pszName, pszFilename));
609
610 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
611 RTMemTmpFree(pszFile);
612 RTMemTmpFree(paPages);
613
614 return VINF_SUCCESS;
615 }
616 }
617 else
618 {
619 AssertRC(rc);
620 SUPR3PageFreeEx(pModule->pvBits, cPages);
621 }
622 }
623 else
624 AssertMsgFailed(("SUPR3PageAlloc(%d,) -> %Rrc\n", cPages, rc));
625 RTMemTmpFree(paPages);
626 }
627 else
628 rc = VERR_NO_TMP_MEMORY;
629 }
630 else
631 rc = VERR_OUT_OF_RANGE;
632 int rc2 = RTLdrClose(pModule->hLdrMod);
633 AssertRC(rc2);
634 }
635 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
636
637 /* Don't consider VERR_PDM_MODULE_NAME_CLASH and VERR_NO_MEMORY above as these are very unlikely. */
638 if (RT_FAILURE(rc) && RTErrInfoIsSet(&ErrInfo.Core))
639 rc = VMSetError(pVM, rc, RT_SRC_POS, N_("Cannot load RC module %s: %s"), pszFilename, ErrInfo.Core.pszMsg);
640 else if (RT_FAILURE(rc))
641 rc = VMSetError(pVM, rc, RT_SRC_POS, N_("Cannot load RC module %s"), pszFilename);
642
643 RTMemFree(pModule);
644 RTMemTmpFree(pszFile);
645 return rc;
646}
647
648#endif /* VBOX_WITH_RAW_MODE_KEEP */
649
650/**
651 * Loads a module into the ring-0 context.
652 *
653 * @returns VBox status code.
654 * @param pUVM Pointer to the user mode VM structure.
655 * @param pszFilename Filename of the module binary.
656 * @param pszName Module name. Case sensitive and the length is limited!
657 * @param pszSearchPath List of directories to search if @a pszFilename is
658 * not specified. Can be NULL, in which case the arch
659 * dependent install dir is searched.
660 */
661static int pdmR3LoadR0U(PUVM pUVM, const char *pszFilename, const char *pszName, const char *pszSearchPath)
662{
663 /*
664 * Validate input.
665 */
666 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
667 PPDMMOD pCur = pUVM->pdm.s.pModules;
668 while (pCur)
669 {
670 if (!strcmp(pCur->szName, pszName))
671 {
672 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
673 AssertMsgFailed(("We've already got a module '%s' loaded!\n", pszName));
674 return VERR_PDM_MODULE_NAME_CLASH;
675 }
676 /* next */
677 pCur = pCur->pNext;
678 }
679
680 /*
681 * Find the file if not specified.
682 */
683 char *pszFile = NULL;
684 if (!pszFilename)
685 pszFilename = pszFile = pdmR3FileR0(pszName, pszSearchPath);
686
687 /*
688 * Allocate the module list node.
689 */
690 PPDMMOD pModule = (PPDMMOD)RTMemAllocZ(sizeof(*pModule) + strlen(pszFilename));
691 if (!pModule)
692 {
693 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
694 RTMemTmpFree(pszFile);
695 return VERR_NO_MEMORY;
696 }
697 AssertMsg(strlen(pszName) + 1 < sizeof(pModule->szName),
698 ("pazName is too long (%d chars) max is %d chars.\n", strlen(pszName), sizeof(pModule->szName) - 1));
699 strcpy(pModule->szName, pszName);
700 pModule->eType = PDMMOD_TYPE_R0;
701 strcpy(pModule->szFilename, pszFilename);
702
703 /*
704 * Ask the support library to load it.
705 */
706 void *pvImageBase;
707 RTERRINFOSTATIC ErrInfo;
708 RTErrInfoInitStatic(&ErrInfo);
709 int rc = SUPR3LoadModule(pszFilename, pszName, &pvImageBase, &ErrInfo.Core);
710 if (RT_SUCCESS(rc))
711 {
712 pModule->hLdrMod = NIL_RTLDRMOD;
713 pModule->ImageBase = (uintptr_t)pvImageBase;
714
715 /*
716 * Insert the module.
717 */
718 if (pUVM->pdm.s.pModules)
719 {
720 /* we don't expect this list to be very long, so rather save the tail pointer. */
721 pCur = pUVM->pdm.s.pModules;
722 while (pCur->pNext)
723 pCur = pCur->pNext;
724 pCur->pNext = pModule;
725 }
726 else
727 pUVM->pdm.s.pModules = pModule; /* (pNext is zeroed by alloc) */
728 Log(("PDM: R0 Module at %RHv %s (%s)\n", (RTR0PTR)pModule->ImageBase, pszName, pszFilename));
729 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
730 RTMemTmpFree(pszFile);
731 return VINF_SUCCESS;
732 }
733
734 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
735 RTMemFree(pModule);
736 LogRel(("PDMLdr: pdmR3LoadR0U: pszName=\"%s\" rc=%Rrc szErr=\"%s\"\n", pszName, rc, ErrInfo.Core.pszMsg));
737
738 /* Don't consider VERR_PDM_MODULE_NAME_CLASH and VERR_NO_MEMORY above as these are very unlikely. */
739 if (RT_FAILURE(rc))
740 rc = VMR3SetError(pUVM, rc, RT_SRC_POS, N_("Failed to load R0 module %s: %s"), pszFilename, ErrInfo.Core.pszMsg);
741
742 RTMemTmpFree(pszFile); /* might be reference thru pszFilename in the above VMSetError call. */
743 return rc;
744}
745
746
747/**
748 * Makes sure a ring-0 module is loaded.
749 *
750 * @returns VBox status code.
751 * @param pUVM Pointer to the user mode VM structure.
752 * @param pszModule Module name (no path).
753 * @param pszSearchPath List of directories to search for the module
754 * (assumes @a pszModule is also a filename).
755 */
756VMMR3_INT_DECL(int) PDMR3LdrLoadR0(PUVM pUVM, const char *pszModule, const char *pszSearchPath)
757{
758 /*
759 * Find the module.
760 */
761 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
762 for (PPDMMOD pModule = pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
763 {
764 if ( pModule->eType == PDMMOD_TYPE_R0
765 && !strcmp(pModule->szName, pszModule))
766 {
767 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
768 return VINF_SUCCESS;
769 }
770 }
771 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
772
773 /*
774 * Okay, load it.
775 */
776 return pdmR3LoadR0U(pUVM, NULL, pszModule, pszSearchPath);
777}
778
779
780/**
781 * Get the address of a symbol in a given HC ring 3 module.
782 *
783 * @returns VBox status code.
784 * @param pVM The cross context VM structure.
785 * @param pszModule Module name.
786 * @param pszSymbol Symbol name. If it's value is less than 64k it's treated like a
787 * ordinal value rather than a string pointer.
788 * @param ppvValue Where to store the symbol value.
789 */
790VMMR3_INT_DECL(int) PDMR3LdrGetSymbolR3(PVM pVM, const char *pszModule, const char *pszSymbol, void **ppvValue)
791{
792 /*
793 * Validate input.
794 */
795 AssertPtr(pVM);
796 AssertPtr(pszModule);
797 AssertPtr(ppvValue);
798 PUVM pUVM = pVM->pUVM;
799 AssertMsg(RTCritSectIsInitialized(&pUVM->pdm.s.ListCritSect), ("bad init order!\n"));
800
801 /*
802 * Find the module.
803 */
804 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
805 for (PPDMMOD pModule = pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
806 {
807 if ( pModule->eType == PDMMOD_TYPE_R3
808 && !strcmp(pModule->szName, pszModule))
809 {
810 RTUINTPTR Value = 0;
811 int rc = RTLdrGetSymbolEx(pModule->hLdrMod, pModule->pvBits, pModule->ImageBase, UINT32_MAX, pszSymbol, &Value);
812 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
813 if (RT_SUCCESS(rc))
814 {
815 *ppvValue = (void *)(uintptr_t)Value;
816 Assert((uintptr_t)*ppvValue == Value);
817 }
818 else
819 {
820 if ((uintptr_t)pszSymbol < 0x10000)
821 AssertMsg(rc, ("Couldn't symbol '%u' in module '%s'\n", (unsigned)(uintptr_t)pszSymbol, pszModule));
822 else
823 AssertMsg(rc, ("Couldn't symbol '%s' in module '%s'\n", pszSymbol, pszModule));
824 }
825 return rc;
826 }
827 }
828 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
829 AssertMsgFailed(("Couldn't locate module '%s'\n", pszModule));
830 return VERR_SYMBOL_NOT_FOUND;
831}
832
833
834/**
835 * Get the address of a symbol in a given HC ring 0 module.
836 *
837 * @returns VBox status code.
838 * @param pVM The cross context VM structure.
839 * @param pszModule Module name. If NULL the main R0 module (VMMR0.r0) is assumes.
840 * @param pszSymbol Symbol name. If it's value is less than 64k it's treated like a
841 * ordinal value rather than a string pointer.
842 * @param ppvValue Where to store the symbol value.
843 */
844VMMR3DECL(int) PDMR3LdrGetSymbolR0(PVM pVM, const char *pszModule, const char *pszSymbol, PRTR0PTR ppvValue)
845{
846#ifdef PDMLDR_FAKE_MODE
847 *ppvValue = 0xdeadbeef;
848 return VINF_SUCCESS;
849
850#else
851 /*
852 * Validate input.
853 */
854 AssertPtr(pVM);
855 AssertPtrNull(pszModule);
856 AssertPtr(ppvValue);
857 PUVM pUVM = pVM->pUVM;
858 AssertMsg(RTCritSectIsInitialized(&pUVM->pdm.s.ListCritSect), ("bad init order!\n"));
859
860 if (!pszModule)
861 pszModule = VMMR0_MAIN_MODULE_NAME;
862
863 /*
864 * Find the module.
865 */
866 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
867 for (PPDMMOD pModule = pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
868 {
869 if ( pModule->eType == PDMMOD_TYPE_R0
870 && !strcmp(pModule->szName, pszModule))
871 {
872 int rc = SUPR3GetSymbolR0((void *)(uintptr_t)pModule->ImageBase, pszSymbol, (void **)ppvValue);
873 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
874 if (RT_FAILURE(rc))
875 {
876 AssertMsgRC(rc, ("Couldn't find symbol '%s' in module '%s'\n", pszSymbol, pszModule));
877 LogRel(("PDMLdr: PDMGetSymbol: Couldn't find symbol '%s' in module '%s'\n", pszSymbol, pszModule));
878 }
879 return rc;
880 }
881 }
882 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
883 AssertMsgFailed(("Couldn't locate module '%s'\n", pszModule));
884 return VERR_SYMBOL_NOT_FOUND;
885#endif
886}
887
888
889/**
890 * Same as PDMR3LdrGetSymbolR0 except that the module will be attempted loaded if not found.
891 *
892 * @returns VBox status code.
893 * @param pVM The cross context VM structure.
894 * @param pszModule Module name. If NULL the main R0 module (VMMR0.r0) is assumed.
895 * @param pszSearchPath List of directories to search if @a pszFile is
896 * not qualified with a path. Can be NULL, in which
897 * case the arch dependent install dir is searched.
898 * @param pszSymbol Symbol name. If it's value is less than 64k it's treated like a
899 * ordinal value rather than a string pointer.
900 * @param ppvValue Where to store the symbol value.
901 */
902VMMR3DECL(int) PDMR3LdrGetSymbolR0Lazy(PVM pVM, const char *pszModule, const char *pszSearchPath, const char *pszSymbol,
903 PRTR0PTR ppvValue)
904{
905#ifdef PDMLDR_FAKE_MODE
906 *ppvValue = 0xdeadbeef;
907 return VINF_SUCCESS;
908
909#else
910 AssertPtr(pVM);
911 AssertPtrNull(pszModule);
912 AssertPtr(ppvValue);
913 PUVM pUVM = pVM->pUVM;
914 AssertMsg(RTCritSectIsInitialized(&pUVM->pdm.s.ListCritSect), ("bad init order!\n"));
915
916 if (pszModule) /* (We don't lazy load the main R0 module.) */
917 {
918 /*
919 * Since we're lazy, we'll only check if the module is present
920 * and hand it over to PDMR3LdrGetSymbolR0 when that's done.
921 */
922 AssertMsgReturn(!strpbrk(pszModule, "/\\:\n\r\t"), ("pszModule=%s\n", pszModule), VERR_INVALID_PARAMETER);
923 PPDMMOD pModule;
924 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
925 for (pModule = pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
926 if ( pModule->eType == PDMMOD_TYPE_R0
927 && !strcmp(pModule->szName, pszModule))
928 break;
929 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
930 if (!pModule)
931 {
932 int rc = pdmR3LoadR0U(pUVM, NULL, pszModule, pszSearchPath);
933 AssertMsgRCReturn(rc, ("pszModule=%s rc=%Rrc\n", pszModule, rc), VERR_MODULE_NOT_FOUND);
934 }
935 }
936
937 return PDMR3LdrGetSymbolR0(pVM, pszModule, pszSymbol, ppvValue);
938#endif
939}
940
941
942/**
943 * Get the address of a symbol in a given RC module.
944 *
945 * @returns VBox status code.
946 * @param pVM The cross context VM structure.
947 * @param pszModule Module name. If NULL the main R0 module (VMMRC.rc)
948 * is assumes.
949 * @param pszSymbol Symbol name. If it's value is less than 64k it's
950 * treated like a ordinal value rather than a string
951 * pointer.
952 * @param pRCPtrValue Where to store the symbol value.
953 */
954VMMR3DECL(int) PDMR3LdrGetSymbolRC(PVM pVM, const char *pszModule, const char *pszSymbol, PRTRCPTR pRCPtrValue)
955{
956#if defined(PDMLDR_FAKE_MODE) || !defined(VBOX_WITH_RAW_MODE_KEEP)
957 RT_NOREF(pVM, pszModule, pszSymbol);
958 *pRCPtrValue = NIL_RTRCPTR;
959 return VINF_SUCCESS;
960
961#else
962 /*
963 * Validate input.
964 */
965 AssertPtr(pVM);
966 AssertPtrNull(pszModule);
967 AssertPtr(pRCPtrValue);
968
969 if (!pszModule)
970 pszModule = VMMRC_MAIN_MODULE_NAME;
971
972 /*
973 * Find the module.
974 */
975 PUVM pUVM = pVM->pUVM;
976 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
977 for (PPDMMOD pModule = pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
978 {
979 if ( pModule->eType == PDMMOD_TYPE_RC
980 && !strcmp(pModule->szName, pszModule))
981 {
982 RTUINTPTR Value;
983 int rc = RTLdrGetSymbolEx(pModule->hLdrMod, pModule->pvBits, pModule->ImageBase, UINT32_MAX, pszSymbol, &Value);
984 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
985 if (RT_SUCCESS(rc))
986 {
987 *pRCPtrValue = (RTGCPTR)Value;
988 Assert(*pRCPtrValue == Value);
989 }
990 else
991 {
992 if ((uintptr_t)pszSymbol < 0x10000)
993 AssertMsg(rc, ("Couldn't symbol '%u' in module '%s'\n", (unsigned)(uintptr_t)pszSymbol, pszModule));
994 else
995 AssertMsg(rc, ("Couldn't symbol '%s' in module '%s'\n", pszSymbol, pszModule));
996 }
997 return rc;
998 }
999 }
1000 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
1001 AssertMsgFailed(("Couldn't locate module '%s'\n", pszModule));
1002 return VERR_SYMBOL_NOT_FOUND;
1003#endif
1004}
1005
1006
1007/**
1008 * Same as PDMR3LdrGetSymbolRC except that the module will be attempted loaded if not found.
1009 *
1010 * @returns VBox status code.
1011 * @param pVM The cross context VM structure.
1012 * @param pszModule Module name. If NULL the main RC module (VMMRC.rc)
1013 * is assumed.
1014 * @param pszSearchPath List of directories to search if @a pszFile is
1015 * not qualified with a path. Can be NULL, in which
1016 * case the arch dependent install dir is searched.
1017 * @param pszSymbol Symbol name. If it's value is less than 64k it's treated like a
1018 * ordinal value rather than a string pointer.
1019 * @param pRCPtrValue Where to store the symbol value.
1020 */
1021VMMR3DECL(int) PDMR3LdrGetSymbolRCLazy(PVM pVM, const char *pszModule, const char *pszSearchPath, const char *pszSymbol,
1022 PRTRCPTR pRCPtrValue)
1023{
1024#if defined(PDMLDR_FAKE_MODE) || !defined(VBOX_WITH_RAW_MODE_KEEP)
1025 RT_NOREF(pVM, pszModule, pszSearchPath, pszSymbol);
1026 *pRCPtrValue = NIL_RTRCPTR;
1027 return VINF_SUCCESS;
1028
1029#else
1030 AssertPtr(pVM);
1031 if (!pszModule)
1032 pszModule = VMMRC_MAIN_MODULE_NAME;
1033 AssertPtr(pszModule);
1034 AssertPtr(pRCPtrValue);
1035
1036 /*
1037 * Since we're lazy, we'll only check if the module is present
1038 * and hand it over to PDMR3LdrGetSymbolRC when that's done.
1039 */
1040 AssertMsgReturn(!strpbrk(pszModule, "/\\:\n\r\t"), ("pszModule=%s\n", pszModule), VERR_INVALID_PARAMETER);
1041 PUVM pUVM = pVM->pUVM;
1042 PPDMMOD pModule;
1043 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
1044 for (pModule = pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
1045 if ( pModule->eType == PDMMOD_TYPE_RC
1046 && !strcmp(pModule->szName, pszModule))
1047 break;
1048 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
1049 if (!pModule)
1050 {
1051 char *pszFilename = pdmR3FileRC(pszModule, pszSearchPath);
1052 AssertMsgReturn(pszFilename, ("pszModule=%s\n", pszModule), VERR_MODULE_NOT_FOUND);
1053 int rc = PDMR3LdrLoadRC(pVM, pszFilename, pszModule);
1054 RTMemTmpFree(pszFilename);
1055 AssertMsgRCReturn(rc, ("pszModule=%s rc=%Rrc\n", pszModule, rc), VERR_MODULE_NOT_FOUND);
1056 }
1057
1058 return PDMR3LdrGetSymbolRC(pVM, pszModule, pszSymbol, pRCPtrValue);
1059#endif
1060}
1061
1062
1063/**
1064 * Constructs the full filename for a R3 image file.
1065 *
1066 * @returns Pointer to temporary memory containing the filename.
1067 * Caller must free this using RTMemTmpFree().
1068 * @returns NULL on failure.
1069 *
1070 * @param pszFile File name (no path).
1071 * @param fShared If true, search in the shared directory (/usr/lib on Unix), else
1072 * search in the private directory (/usr/lib/virtualbox on Unix).
1073 * Ignored if VBOX_PATH_SHARED_LIBS is not defined.
1074 */
1075char *pdmR3FileR3(const char *pszFile, bool fShared)
1076{
1077 return pdmR3File(pszFile, NULL, NULL, fShared);
1078}
1079
1080
1081/**
1082 * Constructs the full filename for a R0 image file.
1083 *
1084 * @returns Pointer to temporary memory containing the filename.
1085 * Caller must free this using RTMemTmpFree().
1086 * @returns NULL on failure.
1087 *
1088 * @param pszFile File name (no path).
1089 * @param pszSearchPath List of directories to search if @a pszFile is
1090 * not qualified with a path. Can be NULL, in which
1091 * case the arch dependent install dir is searched.
1092 */
1093char *pdmR3FileR0(const char *pszFile, const char *pszSearchPath)
1094{
1095 return pdmR3File(pszFile, NULL, pszSearchPath, /*fShared=*/false);
1096}
1097
1098
1099/**
1100 * Constructs the full filename for a RC image file.
1101 *
1102 * @returns Pointer to temporary memory containing the filename.
1103 * Caller must free this using RTMemTmpFree().
1104 * @returns NULL on failure.
1105 *
1106 * @param pszFile File name (no path).
1107 * @param pszSearchPath List of directories to search if @a pszFile is
1108 * not qualified with a path. Can be NULL, in which
1109 * case the arch dependent install dir is searched.
1110 */
1111char *pdmR3FileRC(const char *pszFile, const char *pszSearchPath)
1112{
1113 return pdmR3File(pszFile, NULL, pszSearchPath, /*fShared=*/false);
1114}
1115
1116
1117/**
1118 * Worker for pdmR3File().
1119 *
1120 * @returns Pointer to temporary memory containing the filename.
1121 * Caller must free this using RTMemTmpFree().
1122 * @returns NULL on failure.
1123 *
1124 * @param pszDir Directory part
1125 * @param pszFile File name part
1126 * @param pszDefaultExt Extension part
1127 */
1128static char *pdmR3FileConstruct(const char *pszDir, const char *pszFile, const char *pszDefaultExt)
1129{
1130 /*
1131 * Allocate temp memory for return buffer.
1132 */
1133 size_t cchDir = strlen(pszDir);
1134 size_t cchFile = strlen(pszFile);
1135 size_t cchDefaultExt;
1136
1137 /*
1138 * Default extention?
1139 */
1140 if (!pszDefaultExt || strchr(pszFile, '.'))
1141 cchDefaultExt = 0;
1142 else
1143 cchDefaultExt = strlen(pszDefaultExt);
1144
1145 size_t cchPath = cchDir + 1 + cchFile + cchDefaultExt + 1;
1146 AssertMsgReturn(cchPath <= RTPATH_MAX, ("Path too long!\n"), NULL);
1147
1148 char *pszRet = (char *)RTMemTmpAlloc(cchDir + 1 + cchFile + cchDefaultExt + 1);
1149 AssertMsgReturn(pszRet, ("Out of temporary memory!\n"), NULL);
1150
1151 /*
1152 * Construct the filename.
1153 */
1154 memcpy(pszRet, pszDir, cchDir);
1155 pszRet[cchDir++] = '/'; /* this works everywhere */
1156 memcpy(pszRet + cchDir, pszFile, cchFile + 1);
1157 if (cchDefaultExt)
1158 memcpy(pszRet + cchDir + cchFile, pszDefaultExt, cchDefaultExt + 1);
1159
1160 return pszRet;
1161}
1162
1163
1164/**
1165 * Worker for pdmR3FileRC(), pdmR3FileR0() and pdmR3FileR3().
1166 *
1167 * @returns Pointer to temporary memory containing the filename.
1168 * Caller must free this using RTMemTmpFree().
1169 * @returns NULL on failure.
1170 * @param pszFile File name (no path).
1171 * @param pszDefaultExt The default extention, NULL if none.
1172 * @param pszSearchPath List of directories to search if @a pszFile is
1173 * not qualified with a path. Can be NULL, in which
1174 * case the arch dependent install dir is searched.
1175 * @param fShared If true, search in the shared directory (/usr/lib on Unix), else
1176 * search in the private directory (/usr/lib/virtualbox on Unix).
1177 * Ignored if VBOX_PATH_SHARED_LIBS is not defined.
1178 * @todo We'll have this elsewhere than in the root later!
1179 * @todo Remove the fShared hack again once we don't need to link against VBoxDD anymore!
1180 */
1181static char *pdmR3File(const char *pszFile, const char *pszDefaultExt, const char *pszSearchPath, bool fShared)
1182{
1183 char szPath[RTPATH_MAX];
1184 int rc;
1185
1186 AssertLogRelReturn(!fShared || !pszSearchPath, NULL);
1187 Assert(!RTPathHavePath(pszFile));
1188
1189 /*
1190 * If there is a path, search it.
1191 */
1192 if ( pszSearchPath
1193 && *pszSearchPath)
1194 {
1195 /* Check the filename length. */
1196 size_t const cchFile = strlen(pszFile);
1197 if (cchFile >= sizeof(szPath))
1198 return NULL;
1199
1200 /*
1201 * Walk the search path.
1202 */
1203 const char *psz = pszSearchPath;
1204 while (*psz)
1205 {
1206 /* Skip leading blanks - no directories with leading spaces, thank you. */
1207 while (RT_C_IS_BLANK(*psz))
1208 psz++;
1209
1210 /* Find the end of this element. */
1211 const char *pszNext;
1212 const char *pszEnd = strchr(psz, ';');
1213 if (!pszEnd)
1214 pszEnd = pszNext = strchr(psz, '\0');
1215 else
1216 pszNext = pszEnd + 1;
1217 if (pszEnd != psz)
1218 {
1219 rc = RTPathJoinEx(szPath, sizeof(szPath), psz, pszEnd - psz, pszFile, cchFile);
1220 if (RT_SUCCESS(rc))
1221 {
1222 if (RTFileExists(szPath))
1223 {
1224 size_t cchPath = strlen(szPath) + 1;
1225 char *pszRet = (char *)RTMemTmpAlloc(cchPath);
1226 if (pszRet)
1227 memcpy(pszRet, szPath, cchPath);
1228 return pszRet;
1229 }
1230 }
1231 }
1232
1233 /* advance */
1234 psz = pszNext;
1235 }
1236 }
1237
1238 /*
1239 * Use the default location.
1240 */
1241 rc = fShared
1242 ? RTPathSharedLibs( szPath, sizeof(szPath))
1243 : RTPathAppPrivateArch(szPath, sizeof(szPath));
1244 if (!RT_SUCCESS(rc))
1245 {
1246 AssertMsgFailed(("RTPath[SharedLibs|AppPrivateArch](,%d) failed rc=%d!\n", sizeof(szPath), rc));
1247 return NULL;
1248 }
1249
1250 return pdmR3FileConstruct(szPath, pszFile, pszDefaultExt);
1251}
1252
1253
1254/** @internal */
1255typedef struct QMFEIPARG
1256{
1257 RTINTPTR uPC;
1258
1259 char *pszNearSym1;
1260 size_t cchNearSym1;
1261 RTINTPTR offNearSym1;
1262
1263 char *pszNearSym2;
1264 size_t cchNearSym2;
1265 RTINTPTR offNearSym2;
1266} QMFEIPARG, *PQMFEIPARG;
1267
1268
1269/**
1270 * Enumeration callback function used by RTLdrEnumSymbols().
1271 *
1272 * @returns VBox status code. Failure will stop the enumeration.
1273 * @param hLdrMod The loader module handle.
1274 * @param pszSymbol Symbol name. NULL if ordinal only.
1275 * @param uSymbol Symbol ordinal, ~0 if not used.
1276 * @param Value Symbol value.
1277 * @param pvUser The user argument specified to RTLdrEnumSymbols().
1278 */
1279static DECLCALLBACK(int) pdmR3QueryModFromEIPEnumSymbols(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol,
1280 RTUINTPTR Value, void *pvUser)
1281{
1282 PQMFEIPARG pArgs = (PQMFEIPARG)pvUser;
1283 NOREF(hLdrMod);
1284
1285 RTINTPTR off = Value - pArgs->uPC;
1286 if (off <= 0) /* near1 is before or at same location. */
1287 {
1288 if (off > pArgs->offNearSym1)
1289 {
1290 pArgs->offNearSym1 = off;
1291 if (pArgs->pszNearSym1 && pArgs->cchNearSym1)
1292 {
1293 *pArgs->pszNearSym1 = '\0';
1294 if (pszSymbol)
1295 strncat(pArgs->pszNearSym1, pszSymbol, pArgs->cchNearSym1);
1296 else
1297 {
1298 char szOrd[32];
1299 RTStrPrintf(szOrd, sizeof(szOrd), "#%#x", uSymbol);
1300 strncat(pArgs->pszNearSym1, szOrd, pArgs->cchNearSym1);
1301 }
1302 }
1303 }
1304 }
1305 else /* near2 is after */
1306 {
1307 if (off < pArgs->offNearSym2)
1308 {
1309 pArgs->offNearSym2 = off;
1310 if (pArgs->pszNearSym2 && pArgs->cchNearSym2)
1311 {
1312 *pArgs->pszNearSym2 = '\0';
1313 if (pszSymbol)
1314 strncat(pArgs->pszNearSym2, pszSymbol, pArgs->cchNearSym2);
1315 else
1316 {
1317 char szOrd[32];
1318 RTStrPrintf(szOrd, sizeof(szOrd), "#%#x", uSymbol);
1319 strncat(pArgs->pszNearSym2, szOrd, pArgs->cchNearSym2);
1320 }
1321 }
1322 }
1323 }
1324
1325 return VINF_SUCCESS;
1326}
1327
1328
1329/**
1330 * Internal worker for PDMR3LdrQueryRCModFromPC and PDMR3LdrQueryR0ModFromPC.
1331 *
1332 * @returns VBox status code.
1333 *
1334 * @param pVM The cross context VM structure.
1335 * @param uPC The program counter (eip/rip) to locate the module for.
1336 * @param enmType The module type.
1337 * @param pszModName Where to store the module name.
1338 * @param cchModName Size of the module name buffer.
1339 * @param pMod Base address of the module.
1340 * @param pszNearSym1 Name of the closes symbol from below.
1341 * @param cchNearSym1 Size of the buffer pointed to by pszNearSym1.
1342 * @param pNearSym1 The address of pszNearSym1.
1343 * @param pszNearSym2 Name of the closes symbol from below.
1344 * @param cchNearSym2 Size of the buffer pointed to by pszNearSym2.
1345 * @param pNearSym2 The address of pszNearSym2.
1346 */
1347static int pdmR3LdrQueryModFromPC(PVM pVM, RTUINTPTR uPC, PDMMODTYPE enmType,
1348 char *pszModName, size_t cchModName, PRTUINTPTR pMod,
1349 char *pszNearSym1, size_t cchNearSym1, PRTUINTPTR pNearSym1,
1350 char *pszNearSym2, size_t cchNearSym2, PRTUINTPTR pNearSym2)
1351{
1352 PUVM pUVM = pVM->pUVM;
1353 int rc = VERR_MODULE_NOT_FOUND;
1354 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
1355 for (PPDMMOD pCur= pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
1356 {
1357 if (pCur->eType != enmType)
1358 continue;
1359
1360 /* The following RTLdrOpen call is a dirty hack to get ring-0 module information. */
1361 RTLDRMOD hLdrMod = pCur->hLdrMod;
1362 if (hLdrMod == NIL_RTLDRMOD && uPC >= pCur->ImageBase)
1363 {
1364 int rc2 = RTLdrOpen(pCur->szFilename, 0 /*fFlags*/, RTLDRARCH_HOST, &hLdrMod);
1365 if (RT_FAILURE(rc2))
1366 hLdrMod = NIL_RTLDRMOD;
1367 }
1368
1369 if ( hLdrMod != NIL_RTLDRMOD
1370 && uPC - pCur->ImageBase < RTLdrSize(hLdrMod))
1371 {
1372 if (pMod)
1373 *pMod = pCur->ImageBase;
1374 if (pszModName && cchModName)
1375 {
1376 *pszModName = '\0';
1377 strncat(pszModName, pCur->szName, cchModName);
1378 }
1379 if (pNearSym1) *pNearSym1 = 0;
1380 if (pNearSym2) *pNearSym2 = 0;
1381 if (pszNearSym1) *pszNearSym1 = '\0';
1382 if (pszNearSym2) *pszNearSym2 = '\0';
1383
1384 /*
1385 * Locate the nearest symbols.
1386 */
1387 QMFEIPARG Args;
1388 Args.uPC = uPC;
1389 Args.pszNearSym1 = pszNearSym1;
1390 Args.cchNearSym1 = cchNearSym1;
1391 Args.offNearSym1 = RTINTPTR_MIN;
1392 Args.pszNearSym2 = pszNearSym2;
1393 Args.cchNearSym2 = cchNearSym2;
1394 Args.offNearSym2 = RTINTPTR_MAX;
1395
1396 rc = RTLdrEnumSymbols(hLdrMod, RTLDR_ENUM_SYMBOL_FLAGS_ALL, pCur->pvBits, pCur->ImageBase,
1397 pdmR3QueryModFromEIPEnumSymbols, &Args);
1398 if (pNearSym1 && Args.offNearSym1 != RTINTPTR_MIN)
1399 *pNearSym1 = Args.offNearSym1 + uPC;
1400 if (pNearSym2 && Args.offNearSym2 != RTINTPTR_MAX)
1401 *pNearSym2 = Args.offNearSym2 + uPC;
1402
1403 rc = VINF_SUCCESS;
1404 }
1405
1406 if (hLdrMod != pCur->hLdrMod && hLdrMod != NIL_RTLDRMOD)
1407 RTLdrClose(hLdrMod);
1408
1409 if (RT_SUCCESS(rc))
1410 break;
1411 }
1412 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
1413 return rc;
1414}
1415
1416
1417/**
1418 * Queries raw-mode context module information from an PC (eip/rip).
1419 *
1420 * This is typically used to locate a crash address.
1421 *
1422 * @returns VBox status code.
1423 *
1424 * @param pVM The cross context VM structure.
1425 * @param uPC The program counter (eip/rip) to locate the module for.
1426 * @param pszModName Where to store the module name.
1427 * @param cchModName Size of the module name buffer.
1428 * @param pMod Base address of the module.
1429 * @param pszNearSym1 Name of the closes symbol from below.
1430 * @param cchNearSym1 Size of the buffer pointed to by pszNearSym1.
1431 * @param pNearSym1 The address of pszNearSym1.
1432 * @param pszNearSym2 Name of the closes symbol from below.
1433 * @param cchNearSym2 Size of the buffer pointed to by pszNearSym2.
1434 * @param pNearSym2 The address of pszNearSym2.
1435 */
1436VMMR3_INT_DECL(int) PDMR3LdrQueryRCModFromPC(PVM pVM, RTRCPTR uPC,
1437 char *pszModName, size_t cchModName, PRTRCPTR pMod,
1438 char *pszNearSym1, size_t cchNearSym1, PRTRCPTR pNearSym1,
1439 char *pszNearSym2, size_t cchNearSym2, PRTRCPTR pNearSym2)
1440{
1441 RTUINTPTR AddrMod = 0;
1442 RTUINTPTR AddrNear1 = 0;
1443 RTUINTPTR AddrNear2 = 0;
1444 int rc = pdmR3LdrQueryModFromPC(pVM, uPC, PDMMOD_TYPE_RC,
1445 pszModName, cchModName, &AddrMod,
1446 pszNearSym1, cchNearSym1, &AddrNear1,
1447 pszNearSym2, cchNearSym2, &AddrNear2);
1448 if (RT_SUCCESS(rc))
1449 {
1450 if (pMod)
1451 *pMod = (RTRCPTR)AddrMod;
1452 if (pNearSym1)
1453 *pNearSym1 = (RTRCPTR)AddrNear1;
1454 if (pNearSym2)
1455 *pNearSym2 = (RTRCPTR)AddrNear2;
1456 }
1457 return rc;
1458}
1459
1460
1461/**
1462 * Queries ring-0 context module information from an PC (eip/rip).
1463 *
1464 * This is typically used to locate a crash address.
1465 *
1466 * @returns VBox status code.
1467 *
1468 * @param pVM The cross context VM structure.
1469 * @param uPC The program counter (eip/rip) to locate the module for.
1470 * @param pszModName Where to store the module name.
1471 * @param cchModName Size of the module name buffer.
1472 * @param pMod Base address of the module.
1473 * @param pszNearSym1 Name of the closes symbol from below.
1474 * @param cchNearSym1 Size of the buffer pointed to by pszNearSym1.
1475 * @param pNearSym1 The address of pszNearSym1.
1476 * @param pszNearSym2 Name of the closes symbol from below.
1477 * @param cchNearSym2 Size of the buffer pointed to by pszNearSym2. Optional.
1478 * @param pNearSym2 The address of pszNearSym2. Optional.
1479 */
1480VMMR3_INT_DECL(int) PDMR3LdrQueryR0ModFromPC(PVM pVM, RTR0PTR uPC,
1481 char *pszModName, size_t cchModName, PRTR0PTR pMod,
1482 char *pszNearSym1, size_t cchNearSym1, PRTR0PTR pNearSym1,
1483 char *pszNearSym2, size_t cchNearSym2, PRTR0PTR pNearSym2)
1484{
1485 RTUINTPTR AddrMod = 0;
1486 RTUINTPTR AddrNear1 = 0;
1487 RTUINTPTR AddrNear2 = 0;
1488 int rc = pdmR3LdrQueryModFromPC(pVM, uPC, PDMMOD_TYPE_R0,
1489 pszModName, cchModName, &AddrMod,
1490 pszNearSym1, cchNearSym1, &AddrNear1,
1491 pszNearSym2, cchNearSym2, &AddrNear2);
1492 if (RT_SUCCESS(rc))
1493 {
1494 if (pMod)
1495 *pMod = (RTR0PTR)AddrMod;
1496 if (pNearSym1)
1497 *pNearSym1 = (RTR0PTR)AddrNear1;
1498 if (pNearSym2)
1499 *pNearSym2 = (RTR0PTR)AddrNear2;
1500 }
1501 return rc;
1502}
1503
1504
1505/**
1506 * Enumerate all PDM modules.
1507 *
1508 * @returns VBox status code.
1509 * @param pVM The cross context VM structure.
1510 * @param pfnCallback Function to call back for each of the modules.
1511 * @param pvArg User argument.
1512 */
1513VMMR3DECL(int) PDMR3LdrEnumModules(PVM pVM, PFNPDMR3ENUM pfnCallback, void *pvArg)
1514{
1515 PUVM pUVM = pVM->pUVM;
1516 int rc = VINF_SUCCESS;
1517 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
1518 for (PPDMMOD pCur = pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
1519 {
1520 rc = pfnCallback(pVM,
1521 pCur->szFilename,
1522 pCur->szName,
1523 pCur->ImageBase,
1524 pCur->eType == PDMMOD_TYPE_RC ? RTLdrSize(pCur->hLdrMod) : 0,
1525 pCur->eType == PDMMOD_TYPE_RC ? PDMLDRCTX_RAW_MODE
1526 : pCur->eType == PDMMOD_TYPE_R0 ? PDMLDRCTX_RING_0
1527 : pCur->eType == PDMMOD_TYPE_R3 ? PDMLDRCTX_RING_3
1528 : PDMLDRCTX_INVALID,
1529 pvArg);
1530 if (RT_FAILURE(rc))
1531 break;
1532 }
1533 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
1534 return rc;
1535}
1536
1537
1538/**
1539 * Locates a module.
1540 *
1541 * @returns Pointer to the module if found.
1542 * @param pUVM Pointer to the user mode VM structure.
1543 * @param pszModule The module name.
1544 * @param enmType The module type.
1545 * @param fLazy Lazy loading the module if set.
1546 * @param pszSearchPath Search path for use when lazy loading.
1547 */
1548static PPDMMOD pdmR3LdrFindModule(PUVM pUVM, const char *pszModule, PDMMODTYPE enmType,
1549 bool fLazy, const char *pszSearchPath)
1550{
1551 RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
1552 for (PPDMMOD pModule = pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
1553 if ( pModule->eType == enmType
1554 && !strcmp(pModule->szName, pszModule))
1555 {
1556 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
1557 return pModule;
1558 }
1559 RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
1560 if (fLazy)
1561 {
1562 switch (enmType)
1563 {
1564#ifdef VBOX_WITH_RAW_MODE_KEEP
1565 case PDMMOD_TYPE_RC:
1566 {
1567 char *pszFilename = pdmR3FileRC(pszModule, pszSearchPath);
1568 if (pszFilename)
1569 {
1570 int rc = PDMR3LdrLoadRC(pUVM->pVM, pszFilename, pszModule);
1571 RTMemTmpFree(pszFilename);
1572 if (RT_SUCCESS(rc))
1573 return pdmR3LdrFindModule(pUVM, pszModule, enmType, false, NULL);
1574 }
1575 break;
1576 }
1577#endif
1578
1579 case PDMMOD_TYPE_R0:
1580 {
1581 int rc = pdmR3LoadR0U(pUVM, NULL, pszModule, pszSearchPath);
1582 if (RT_SUCCESS(rc))
1583 return pdmR3LdrFindModule(pUVM, pszModule, enmType, false, NULL);
1584 break;
1585 }
1586
1587 default:
1588 AssertFailed();
1589 }
1590 }
1591 return NULL;
1592}
1593
1594
1595/**
1596 * Resolves a ring-0 or raw-mode context interface.
1597 *
1598 * @returns VBox status code.
1599 * @param pVM The cross context VM structure.
1600 * @param pvInterface Pointer to the interface structure. The symbol list
1601 * describes the layout.
1602 * @param cbInterface The size of the structure pvInterface is pointing
1603 * to. For bounds checking.
1604 * @param pszModule The module name. If NULL we assume it's the default
1605 * R0 or RC module (@a fRing0OrRC). We'll attempt to
1606 * load the module if it isn't found in the module
1607 * list.
1608 * @param pszSearchPath The module search path. If NULL, search the
1609 * architecture dependent install directory.
1610 * @param pszSymPrefix What to prefix the symbols in the list with. The
1611 * idea is that you define a list that goes with an
1612 * interface (INTERFACE_SYM_LIST) and reuse it with
1613 * each implementation.
1614 * @param pszSymList The symbol list for the interface. This is a
1615 * semi-colon separated list of symbol base names. As
1616 * mentioned above, each is prefixed with @a
1617 * pszSymPrefix before resolving. There are a couple
1618 * of special symbol names that will cause us to skip
1619 * ahead a little bit:
1620 * - U8:whatever,
1621 * - U16:whatever,
1622 * - U32:whatever,
1623 * - U64:whatever,
1624 * - RCPTR:whatever,
1625 * - R3PTR:whatever,
1626 * - R0PTR:whatever,
1627 * - GCPHYS:whatever,
1628 * - HCPHYS:whatever.
1629 * @param fRing0 Set if it's a ring-0 context interface, clear if
1630 * it's raw-mode context interface.
1631 */
1632VMMR3_INT_DECL(int) PDMR3LdrGetInterfaceSymbols(PVM pVM, void *pvInterface, size_t cbInterface,
1633 const char *pszModule, const char *pszSearchPath,
1634 const char *pszSymPrefix, const char *pszSymList,
1635 bool fRing0)
1636{
1637 bool const fNullRun = !fRing0;
1638
1639 /*
1640 * Find the module.
1641 */
1642 int rc = VINF_SUCCESS;
1643 PPDMMOD pModule = NULL;
1644 if (!fNullRun)
1645 pModule = pdmR3LdrFindModule(pVM->pUVM,
1646 pszModule ? pszModule : fRing0 ? "VMMR0.r0" : "VMMRC.rc",
1647 fRing0 ? PDMMOD_TYPE_R0 : PDMMOD_TYPE_RC,
1648 true /*fLazy*/, pszSearchPath);
1649 if (pModule || fNullRun)
1650 {
1651 /* Prep the symbol name. */
1652 char szSymbol[256];
1653 size_t const cchSymPrefix = strlen(pszSymPrefix);
1654 AssertReturn(cchSymPrefix + 5 < sizeof(szSymbol), VERR_SYMBOL_NOT_FOUND);
1655 memcpy(szSymbol, pszSymPrefix, cchSymPrefix);
1656
1657 /*
1658 * Iterate the symbol list.
1659 */
1660 uint32_t offInterface = 0;
1661 const char *pszCur = pszSymList;
1662 while (pszCur)
1663 {
1664 /*
1665 * Find the end of the current symbol name.
1666 */
1667 size_t cchSym;
1668 const char *pszNext = strchr(pszCur, ';');
1669 if (pszNext)
1670 {
1671 cchSym = pszNext - pszCur;
1672 pszNext++;
1673 }
1674 else
1675 cchSym = strlen(pszCur);
1676 AssertBreakStmt(cchSym > 0, rc = VERR_INVALID_PARAMETER);
1677
1678 /* Is it a skip instruction? */
1679 const char *pszColon = (const char *)memchr(pszCur, ':', cchSym);
1680 if (pszColon)
1681 {
1682 /*
1683 * String switch on the instruction and execute it, checking
1684 * that we didn't overshoot the interface structure.
1685 */
1686#define IS_SKIP_INSTR(szInstr) \
1687 ( cchSkip == sizeof(szInstr) - 1 \
1688 && !memcmp(pszCur, szInstr, sizeof(szInstr) - 1) )
1689
1690 size_t const cchSkip = pszColon - pszCur;
1691 if (IS_SKIP_INSTR("U8"))
1692 offInterface += sizeof(uint8_t);
1693 else if (IS_SKIP_INSTR("U16"))
1694 offInterface += sizeof(uint16_t);
1695 else if (IS_SKIP_INSTR("U32"))
1696 offInterface += sizeof(uint32_t);
1697 else if (IS_SKIP_INSTR("U64"))
1698 offInterface += sizeof(uint64_t);
1699 else if (IS_SKIP_INSTR("RCPTR"))
1700 offInterface += sizeof(RTRCPTR);
1701 else if (IS_SKIP_INSTR("R3PTR"))
1702 offInterface += sizeof(RTR3PTR);
1703 else if (IS_SKIP_INSTR("R0PTR"))
1704 offInterface += sizeof(RTR0PTR);
1705 else if (IS_SKIP_INSTR("HCPHYS"))
1706 offInterface += sizeof(RTHCPHYS);
1707 else if (IS_SKIP_INSTR("GCPHYS"))
1708 offInterface += sizeof(RTGCPHYS);
1709 else
1710 AssertMsgFailedBreakStmt(("Invalid skip instruction %.*s (prefix=%s)\n", cchSym, pszCur, pszSymPrefix),
1711 rc = VERR_INVALID_PARAMETER);
1712 AssertMsgBreakStmt(offInterface <= cbInterface,
1713 ("off=%#x cb=%#x (sym=%.*s prefix=%s)\n", offInterface, cbInterface, cchSym, pszCur, pszSymPrefix),
1714 rc = VERR_BUFFER_OVERFLOW);
1715#undef IS_SKIP_INSTR
1716 }
1717 else
1718 {
1719 /*
1720 * Construct the symbol name, get its value, store it and
1721 * advance the interface cursor.
1722 */
1723 AssertReturn(cchSymPrefix + cchSym < sizeof(szSymbol), VERR_SYMBOL_NOT_FOUND);
1724 memcpy(&szSymbol[cchSymPrefix], pszCur, cchSym);
1725 szSymbol[cchSymPrefix + cchSym] = '\0';
1726
1727 if (fRing0)
1728 {
1729 void *pvValue = NULL;
1730 if (!fNullRun)
1731 {
1732 rc = SUPR3GetSymbolR0((void *)(RTR0PTR)pModule->ImageBase, szSymbol, &pvValue);
1733 AssertMsgRCBreak(rc, ("Couldn't find symbol '%s' in module '%s'\n", szSymbol, pModule->szName));
1734 }
1735
1736 PRTR0PTR pValue = (PRTR0PTR)((uintptr_t)pvInterface + offInterface);
1737 AssertMsgBreakStmt(offInterface + sizeof(*pValue) <= cbInterface,
1738 ("off=%#x cb=%#x sym=%s\n", offInterface, cbInterface, szSymbol),
1739 rc = VERR_BUFFER_OVERFLOW);
1740 *pValue = (RTR0PTR)pvValue;
1741 Assert((void *)*pValue == pvValue);
1742 offInterface += sizeof(*pValue);
1743 }
1744 else
1745 {
1746 RTUINTPTR Value = 0;
1747 if (!fNullRun)
1748 {
1749 rc = RTLdrGetSymbolEx(pModule->hLdrMod, pModule->pvBits, pModule->ImageBase, UINT32_MAX, szSymbol, &Value);
1750 AssertMsgRCBreak(rc, ("Couldn't find symbol '%s' in module '%s'\n", szSymbol, pModule->szName));
1751 }
1752
1753 PRTRCPTR pValue = (PRTRCPTR)((uintptr_t)pvInterface + offInterface);
1754 AssertMsgBreakStmt(offInterface + sizeof(*pValue) <= cbInterface,
1755 ("off=%#x cb=%#x sym=%s\n", offInterface, cbInterface, szSymbol),
1756 rc = VERR_BUFFER_OVERFLOW);
1757 *pValue = (RTRCPTR)Value;
1758 Assert(*pValue == Value);
1759 offInterface += sizeof(*pValue);
1760 }
1761 }
1762
1763 /* advance */
1764 pszCur = pszNext;
1765 }
1766
1767 }
1768 else
1769 rc = VERR_MODULE_NOT_FOUND;
1770 return rc;
1771}
1772
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