summaryrefslogtreecommitdiffstats
path: root/src/VBox/Debugger/DBGPlugInLinuxModuleCodeTmpl.cpp.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Debugger/DBGPlugInLinuxModuleCodeTmpl.cpp.h')
-rw-r--r--src/VBox/Debugger/DBGPlugInLinuxModuleCodeTmpl.cpp.h560
1 files changed, 560 insertions, 0 deletions
diff --git a/src/VBox/Debugger/DBGPlugInLinuxModuleCodeTmpl.cpp.h b/src/VBox/Debugger/DBGPlugInLinuxModuleCodeTmpl.cpp.h
new file mode 100644
index 00000000..6b60058b
--- /dev/null
+++ b/src/VBox/Debugger/DBGPlugInLinuxModuleCodeTmpl.cpp.h
@@ -0,0 +1,560 @@
+/* $Id: DBGPlugInLinuxModuleCodeTmpl.cpp.h $ */
+/** @file
+ * DBGPlugInLinux - Code template for struct module processing.
+ */
+
+/*
+ * Copyright (C) 2019-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+#ifndef LNX_MK_VER
+# define LNX_MK_VER(major, minor, build) (((major) << 22) | ((minor) << 12) | (build))
+#endif
+#if LNX_64BIT
+# define LNX_ULONG_T uint64_t
+#else
+# define LNX_ULONG_T uint32_t
+#endif
+#if LNX_64BIT
+# define PAD32ON64(seq) uint32_t RT_CONCAT(u32Padding,seq);
+#else
+# define PAD32ON64(seq)
+#endif
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * Kernel module symbol (hasn't changed in ages).
+ */
+typedef struct RT_CONCAT(LNXMODKSYM,LNX_SUFFIX)
+{
+ LNX_ULONG_T uValue;
+ LNX_PTR_T uPtrSymName;
+} RT_CONCAT(LNXMODKSYM,LNX_SUFFIX);
+
+
+#if LNX_VER >= LNX_MK_VER(2,6,11)
+typedef struct RT_CONCAT(LNXMODKOBJECT,LNX_SUFFIX)
+{
+ LNX_PTR_T uPtrKName;
+# if LNX_VER < LNX_MK_VER(2,6,24)
+ char name[20];
+# endif
+# if LNX_VER < LNX_MK_VER(2,6,27)
+ int32_t cRefs;
+# if LNX_VER >= LNX_MK_VER(2,6,24)
+ PAD32ON64(0)
+# endif
+# endif
+ LNX_PTR_T uPtrNext;
+ LNX_PTR_T uPtrPrev;
+ LNX_PTR_T uPtrParent; /**< struct kobject pointer */
+ LNX_PTR_T uPtrKset; /**< struct kset pointer */
+ LNX_PTR_T uPtrKtype; /**< struct kobj_type pointer */
+ LNX_PTR_T uPtrDirEntry; /**< struct dentry pointer; 2.6.23+ sysfs_dirent. */
+# if LNX_VER >= LNX_MK_VER(2,6,17) && LNX_VER < LNX_MK_VER(2,6,24)
+ LNX_PTR_T aPtrWaitQueueHead[3];
+# endif
+# if LNX_VER >= LNX_MK_VER(2,6,27)
+ int32_t cRefs;
+ uint32_t uStateStuff;
+# elif LNX_VER >= LNX_MK_VER(2,6,25)
+ LNX_ULONG_T uStateStuff;
+# endif
+ /* non-kobject: */
+ LNX_PTR_T uPtrModule; /**< struct module pointer. */
+# if LNX_VER >= LNX_MK_VER(2,6,21)
+ LNX_PTR_T uPtrDriverDir; /**< Points to struct kobject. */
+# endif
+# if LNX_VER >= LNX_MK_VER(4,5,0)
+ LNX_PTR_T uPtrMp;
+ LNX_PTR_T uPtrCompletion; /**< Points to struct completion. */
+# endif
+} RT_CONCAT(LNXMODKOBJECT,LNX_SUFFIX);
+#endif
+#if LNX_VER == LNX_MK_VER(2,6,24) && LNX_64BIT
+AssertCompileMemberOffset(RT_CONCAT(LNXMODKOBJECT,LNX_SUFFIX), uPtrParent, 32);
+AssertCompileMemberOffset(RT_CONCAT(LNXMODKOBJECT,LNX_SUFFIX), uPtrParent, 32);
+AssertCompileSize(RT_CONCAT(LNXMODKOBJECT,LNX_SUFFIX), 80);
+#endif
+
+
+#if LNX_VER >= LNX_MK_VER(4,5,0)
+/**
+ * Red black tree node.
+ */
+typedef struct RT_CONCAT(LNXRBNODE,LNX_SUFFIX)
+{
+ LNX_ULONG_T uRbParentColor;
+ LNX_PTR_T uPtrRbRight;
+ LNX_PTR_T uPtrRbLeft;
+} RT_CONCAT(LNXRBNODE,LNX_SUFFIX);
+
+
+/**
+ * Latch tree node.
+ */
+typedef struct RT_CONCAT(LNXLATCHTREENODE,LNX_SUFFIX)
+{
+ RT_CONCAT(LNXRBNODE,LNX_SUFFIX) aNode[2];
+} RT_CONCAT(LNXLATCHTREENODE,LNX_SUFFIX);
+
+
+/**
+ * Module tree node.
+ */
+typedef struct RT_CONCAT(LNXMODTREENODE,LNX_SUFFIX)
+{
+ LNX_PTR_T uPtrKMod;
+ RT_CONCAT(LNXLATCHTREENODE,LNX_SUFFIX) Node;
+} RT_CONCAT(LNXMODTREENODE,LNX_SUFFIX);
+
+
+/**
+ * Module layout.
+ */
+typedef struct RT_CONCAT(LNXKMODLAYOUT,LNX_SUFFIX)
+{
+ LNX_PTR_T uPtrBase; /**< Base pointer to text and data. */
+ uint32_t cb; /**< Size of the module. */
+ uint32_t cbText; /**< Size of the text section. */
+ uint32_t cbRo; /**< Size of the readonly portion (text + ro data). */
+ RT_CONCAT(LNXMODTREENODE,LNX_SUFFIX) ModTreeNd; /**< Only available when CONFIG_MODULES_TREE_LOOKUP is set (default). */
+} RT_CONCAT(LNXKMODLAYOUT,LNX_SUFFIX);
+
+
+/**
+ * Mutex.
+ */
+typedef struct RT_CONCAT(LNXMUTEX,LNX_SUFFIX)
+{
+ LNX_ULONG_T uOwner;
+ uint32_t wait_lock; /**< Actually spinlock_t */
+ PAD32ON64(0)
+ LNX_PTR_T uWaitLstPtrNext;
+ LNX_PTR_T uWaitLstPtrPrev;
+} RT_CONCAT(LNXMUTEX,LNX_SUFFIX);
+#endif
+
+
+/**
+ * Maps to the start of struct module in include/linux/module.h.
+ */
+typedef struct RT_CONCAT(LNXKMODULE,LNX_SUFFIX)
+{
+#if LNX_VER >= LNX_MK_VER(4,5,0)
+ /* Completely new layout to not feed the spaghetti dragons further. */
+ int32_t state;
+ PAD32ON64(0)
+ LNX_PTR_T uPtrNext;
+ LNX_PTR_T uPtrPrev;
+ char name[64 - sizeof(LNX_PTR_T)];
+
+ RT_CONCAT(LNXMODKOBJECT,LNX_SUFFIX) mkobj;
+ LNX_PTR_T uPtrModInfoAttrs; /**< Points to struct module_attribute. */
+ LNX_PTR_T uPtrVersion; /**< String pointers. */
+ LNX_PTR_T uPtrSrcVersion; /**< String pointers. */
+ LNX_PTR_T uPtrHolderDir; /**< Points to struct kobject. */
+
+ /** @name Exported Symbols
+ * @{ */
+ LNX_PTR_T uPtrSyms; /**< Array of struct kernel_symbol. */
+ LNX_PTR_T uPtrCrcs; /**< unsigned long array */
+ uint32_t num_syms;
+ /** @} */
+
+ /** @name Kernel parameters
+ * @{ */
+ RT_CONCAT(LNXMUTEX,LNX_SUFFIX) Mtx; /**< Mutex. */
+ LNX_PTR_T uPtrKp; /**< Points to struct kernel_param */
+ uint32_t num_kp;
+ /** @} */
+
+ /** @name GPL Symbols
+ * @{ */
+ uint32_t num_gpl_syms;
+ LNX_PTR_T uPtrGplSyms; /**< Array of struct kernel_symbol. */
+ LNX_PTR_T uPtrGplCrcs; /**< unsigned long array */
+ /** @} */
+
+ /** @name Unused symbols
+ * @{ */
+ LNX_PTR_T uPtrUnusedSyms; /**< Array of struct kernel_symbol. */
+ LNX_PTR_T uPtrUnusedCrcs; /**< unsigned long array */
+ uint32_t num_unused_syms;
+ uint32_t num_unused_gpl_syms;
+ LNX_PTR_T uPtrUnusedGplSyms; /**< Array of struct kernel_symbol. */
+ LNX_PTR_T uPtrUnusedGplCrcs; /**< unsigned long array */
+ /** @} */
+
+ uint8_t sig_ok;
+ uint8_t async_probe_requested;
+
+ /** @name Future GPL Symbols
+ * @{ */
+ LNX_PTR_T uPtrGplFutureSyms; /**< Array of struct kernel_symbol. */
+ LNX_PTR_T uPtrGplFutureCrcs; /**< unsigned long array */
+ uint32_t num_gpl_future_syms;
+ /** @} */
+
+ /** @name Exception table.
+ * @{ */
+ uint32_t num_exentries;
+ LNX_PTR_T uPtrEntries; /**< struct exception_table_entry array. */
+ /** @} */
+
+ LNX_PTR_T pfnInit;
+ RT_CONCAT(LNXKMODLAYOUT,LNX_SUFFIX) CoreLayout; /**< Should be aligned on a cache line. */
+ RT_CONCAT(LNXKMODLAYOUT,LNX_SUFFIX) InitLayout;
+
+#elif LNX_VER >= LNX_MK_VER(2,5,48)
+ /*
+ * This first part is mostly always the same.
+ */
+ int32_t state;
+ PAD32ON64(0)
+ LNX_PTR_T uPtrNext;
+ LNX_PTR_T uPtrPrev;
+ char name[64 - sizeof(LNX_PTR_T)];
+
+ /*
+ * Here be spaghetti dragons.
+ */
+# if LNX_VER >= LNX_MK_VER(2,6,11)
+ RT_CONCAT(LNXMODKOBJECT,LNX_SUFFIX) mkobj; /**< Was just kobj for a while. */
+ LNX_PTR_T uPtrParamAttrs; /**< Points to struct module_param_attrs. */
+# if LNX_VER >= LNX_MK_VER(2,6,17)
+ LNX_PTR_T uPtrModInfoAttrs; /**< Points to struct module_attribute. */
+# endif
+# if LNX_VER == LNX_MK_VER(2,6,20)
+ LNX_PTR_T uPtrDriverDir; /**< Points to struct kobject. */
+# elif LNX_VER >= LNX_MK_VER(2,6,21)
+ LNX_PTR_T uPtrHolderDir; /**< Points to struct kobject. */
+# endif
+# if LNX_VER >= LNX_MK_VER(2,6,13)
+ LNX_PTR_T uPtrVersion; /**< String pointers. */
+ LNX_PTR_T uPtrSrcVersion; /**< String pointers. */
+# endif
+# else
+# if LNX_VER >= LNX_MK_VER(2,6,7)
+ LNX_PTR_T uPtrMkObj;
+# endif
+# if LNX_VER >= LNX_MK_VER(2,6,10)
+ LNX_PTR_T uPtrParamsKobject;
+# endif
+# endif
+
+ /** @name Exported Symbols
+ * @{ */
+# if LNX_VER < LNX_MK_VER(2,5,67)
+ LNX_PTR_T uPtrSymsNext, uPtrSymsPrev, uPtrSymsOwner;
+# if LNX_VER >= LNX_MK_VER(2,5,55)
+ int32_t syms_gplonly;
+ uint32_t num_syms;
+# else
+ uint32_t num_syms;
+ PAD32ON64(1)
+# endif
+# endif
+ LNX_PTR_T uPtrSyms; /**< Array of struct kernel_symbol. */
+# if LNX_VER >= LNX_MK_VER(2,5,67)
+ uint32_t num_syms;
+ PAD32ON64(1)
+# endif
+# if LNX_VER >= LNX_MK_VER(2,5,60)
+ LNX_PTR_T uPtrCrcs; /**< unsigned long array */
+# endif
+ /** @} */
+
+ /** @name GPL Symbols
+ * @since 2.5.55
+ * @{ */
+# if LNX_VER >= LNX_MK_VER(2,5,55)
+# if LNX_VER < LNX_MK_VER(2,5,67)
+ LNX_PTR_T uPtrGplSymsNext, uPtrGplSymsPrev, uPtrGplSymsOwner;
+# if LNX_VER >= LNX_MK_VER(2,5,55)
+ int32_t gpl_syms_gplonly;
+ uint32_t num_gpl_syms;
+# else
+ uint32_t num_gpl_syms;
+ PAD32ON64(2)
+# endif
+# endif
+ LNX_PTR_T uPtrGplSyms; /**< Array of struct kernel_symbol. */
+# if LNX_VER >= LNX_MK_VER(2,5,67)
+ uint32_t num_gpl_syms;
+ PAD32ON64(2)
+# endif
+# if LNX_VER >= LNX_MK_VER(2,5,60)
+ LNX_PTR_T uPtrGplCrcs; /**< unsigned long array */
+# endif
+# endif /* > 2.5.55 */
+ /** @} */
+
+ /** @name Unused Exported Symbols
+ * @since 2.6.18
+ * @{ */
+# if LNX_VER >= LNX_MK_VER(2,6,18)
+ LNX_PTR_T uPtrUnusedSyms; /**< Array of struct kernel_symbol. */
+ uint32_t num_unused_syms;
+ PAD32ON64(4)
+ LNX_PTR_T uPtrUnusedCrcs; /**< unsigned long array */
+# endif
+ /** @} */
+
+ /** @name Unused GPL Symbols
+ * @since 2.6.18
+ * @{ */
+# if LNX_VER >= LNX_MK_VER(2,6,18)
+ LNX_PTR_T uPtrUnusedGplSyms; /**< Array of struct kernel_symbol. */
+ uint32_t num_unused_gpl_syms;
+ PAD32ON64(5)
+ LNX_PTR_T uPtrUnusedGplCrcs; /**< unsigned long array */
+# endif
+ /** @} */
+
+ /** @name Future GPL Symbols
+ * @since 2.6.17
+ * @{ */
+# if LNX_VER >= LNX_MK_VER(2,6,17)
+ LNX_PTR_T uPtrGplFutureSyms; /**< Array of struct kernel_symbol. */
+ uint32_t num_gpl_future_syms;
+ PAD32ON64(3)
+ LNX_PTR_T uPtrGplFutureCrcs; /**< unsigned long array */
+# endif
+ /** @} */
+
+ /** @name Exception table.
+ * @{ */
+# if LNX_VER < LNX_MK_VER(2,5,67)
+ LNX_PTR_T uPtrXcptTabNext, uPtrXcptTabPrev;
+# endif
+ uint32_t num_exentries;
+ PAD32ON64(6)
+ LNX_PTR_T uPtrEntries; /**< struct exception_table_entry array. */
+ /** @} */
+
+ /*
+ * Hopefully less spaghetti from here on...
+ */
+ LNX_PTR_T pfnInit;
+ LNX_PTR_T uPtrModuleInit;
+ LNX_PTR_T uPtrModuleCore;
+ LNX_ULONG_T cbInit;
+ LNX_ULONG_T cbCore;
+# if LNX_VER >= LNX_MK_VER(2,5,74)
+ LNX_ULONG_T cbInitText;
+ LNX_ULONG_T cbCoreText;
+# endif
+
+# if LNX_VER >= LNX_MK_VER(2,6,18)
+ LNX_PTR_T uPtrUnwindInfo;
+# endif
+#else
+ uint32_t structure_size;
+
+#endif
+} RT_CONCAT(LNXKMODULE,LNX_SUFFIX);
+
+# if LNX_VER == LNX_MK_VER(2,6,24) && LNX_64BIT
+AssertCompileMemberOffset(RT_CONCAT(LNXKMODULE,LNX_SUFFIX), uPtrParamAttrs, 160);
+AssertCompileMemberOffset(RT_CONCAT(LNXKMODULE,LNX_SUFFIX), num_syms, 208);
+AssertCompileMemberOffset(RT_CONCAT(LNXKMODULE,LNX_SUFFIX), num_gpl_syms, 232);
+AssertCompileMemberOffset(RT_CONCAT(LNXKMODULE,LNX_SUFFIX), num_unused_syms, 256);
+AssertCompileMemberOffset(RT_CONCAT(LNXKMODULE,LNX_SUFFIX), num_unused_gpl_syms, 280);
+AssertCompileMemberOffset(RT_CONCAT(LNXKMODULE,LNX_SUFFIX), num_gpl_future_syms, 304);
+AssertCompileMemberOffset(RT_CONCAT(LNXKMODULE,LNX_SUFFIX), num_exentries, 320);
+AssertCompileMemberOffset(RT_CONCAT(LNXKMODULE,LNX_SUFFIX), uPtrModuleCore, 352);
+AssertCompileMemberOffset(RT_CONCAT(LNXKMODULE,LNX_SUFFIX), uPtrUnwindInfo, 392);
+#endif
+
+
+
+/**
+ * Loads the kernel symbols at the given start address.
+ *
+ * @returns VBox status code.
+ * @param pUVM Pointer to the user-mode VM instance.
+ * @param hDbgMod The module handle to add the loaded symbols to.
+ * @param uPtrModuleStart The virtual address where the kernel module starts we want to extract symbols from.
+ * @param uPtrSymStart The start address of the array of symbols.
+ * @param cSyms Number of symbols in the array.
+ */
+static int RT_CONCAT(dbgDiggerLinuxLoadModuleSymbols,LNX_SUFFIX)(PUVM pUVM, PCVMMR3VTABLE pVMM, RTDBGMOD hDbgMod,
+ LNX_PTR_T uPtrModuleStart, LNX_PTR_T uPtrSymStart, uint32_t cSyms)
+{
+ int rc = VINF_SUCCESS;
+ DBGFADDRESS AddrSym;
+ pVMM->pfnDBGFR3AddrFromFlat(pUVM, &AddrSym, uPtrSymStart);
+
+ while ( cSyms
+ && RT_SUCCESS(rc))
+ {
+ RT_CONCAT(LNXMODKSYM,LNX_SUFFIX) aSyms[64];
+ uint32_t cThisLoad = RT_MIN(cSyms, RT_ELEMENTS(aSyms));
+
+ rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, &AddrSym, &aSyms[0], cThisLoad * sizeof(aSyms[0]));
+ if (RT_SUCCESS(rc))
+ {
+ cSyms -= cThisLoad;
+ pVMM->pfnDBGFR3AddrAdd(&AddrSym, cThisLoad * sizeof(aSyms[0]));
+
+ for (uint32_t i = 0; i < cThisLoad; i++)
+ {
+ char szSymName[128];
+ DBGFADDRESS AddrSymName;
+ rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &AddrSymName, aSyms[i].uPtrSymName),
+ &szSymName[0], sizeof(szSymName));
+ if (RT_FAILURE(rc))
+ break;
+
+ /* Verify string encoding - ignore the symbol if it fails. */
+ rc = RTStrValidateEncodingEx(&szSymName[0], sizeof(szSymName), RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
+ if (RT_FAILURE(rc))
+ continue;
+
+ Assert(aSyms[i].uValue >= uPtrModuleStart);
+ rc = RTDbgModSymbolAdd(hDbgMod, szSymName, RTDBGSEGIDX_RVA, aSyms[i].uValue - uPtrModuleStart,
+ 0 /*cb*/, 0 /*fFlags*/, NULL);
+ if (RT_SUCCESS(rc))
+ LogFlowFunc(("Added symbol '%s' successfully\n", szSymName));
+ else
+ {
+ LogFlowFunc(("Adding symbol '%s' failed with: %Rrc\n", szSymName, rc));
+ rc = VINF_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+
+/**
+ * Version specific module processing code.
+ */
+static uint64_t RT_CONCAT(dbgDiggerLinuxLoadModule,LNX_SUFFIX)(PDBGDIGGERLINUX pThis, PUVM pUVM,
+ PCVMMR3VTABLE pVMM, PDBGFADDRESS pAddrModule)
+{
+ RT_CONCAT(LNXKMODULE,LNX_SUFFIX) Module;
+
+ int rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrSub(pAddrModule, RT_UOFFSETOF(RT_CONCAT(LNXKMODULE,LNX_SUFFIX),
+ uPtrNext)),
+ &Module, sizeof(Module));
+ if (RT_FAILURE(rc))
+ {
+ LogRelFunc(("Failed to read module structure at %#RX64: %Rrc\n", pAddrModule->FlatPtr, rc));
+ return 0;
+ }
+
+ /*
+ * Check the module name.
+ */
+#if LNX_VER >= LNX_MK_VER(2,5,48)
+ const char *pszName = Module.name;
+ size_t const cbName = sizeof(Module.name);
+#else
+
+#endif
+ if ( RTStrNLen(pszName, cbName) >= cbName
+ || RT_FAILURE(RTStrValidateEncoding(pszName))
+ || *pszName == '\0')
+ {
+ LogRelFunc(("%#RX64: Bad name: %.*Rhxs\n", pAddrModule->FlatPtr, (int)cbName, pszName));
+ return 0;
+ }
+
+ /*
+ * Create a simple module for it.
+ */
+#if LNX_VER >= LNX_MK_VER(4,5,0)
+ LNX_PTR_T uPtrModuleCore = Module.CoreLayout.uPtrBase;
+ uint32_t cbCore = Module.CoreLayout.cb;
+#else
+ LNX_PTR_T uPtrModuleCore = Module.uPtrModuleCore;
+ uint32_t cbCore = (uint32_t)Module.cbCore;
+#endif
+ LogRelFunc((" %#RX64: %#RX64 LB %#RX32 %s\n", pAddrModule->FlatPtr, uPtrModuleCore, cbCore, pszName));
+
+ RTDBGMOD hDbgMod;
+ rc = RTDbgModCreate(&hDbgMod, pszName, cbCore, 0 /*fFlags*/);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTDbgModSetTag(hDbgMod, DIG_LNX_MOD_TAG);
+ if (RT_SUCCESS(rc))
+ {
+ RTDBGAS hAs = pVMM->pfnDBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
+ rc = RTDbgAsModuleLink(hAs, hDbgMod, uPtrModuleCore, RTDBGASLINK_FLAGS_REPLACE /*fFlags*/);
+ RTDbgAsRelease(hAs);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RT_CONCAT(dbgDiggerLinuxLoadModuleSymbols,LNX_SUFFIX)(pUVM, pVMM, hDbgMod, uPtrModuleCore,
+ Module.uPtrSyms, Module.num_syms);
+ if (RT_FAILURE(rc))
+ LogRelFunc((" Faild to load symbols: %Rrc\n", rc));
+
+#if LNX_VER >= LNX_MK_VER(2,5,55)
+ rc = RT_CONCAT(dbgDiggerLinuxLoadModuleSymbols,LNX_SUFFIX)(pUVM, pVMM, hDbgMod, uPtrModuleCore,
+ Module.uPtrGplSyms, Module.num_gpl_syms);
+ if (RT_FAILURE(rc))
+ LogRelFunc((" Faild to load GPL symbols: %Rrc\n", rc));
+#endif
+
+#if LNX_VER >= LNX_MK_VER(2,6,17)
+ rc = RT_CONCAT(dbgDiggerLinuxLoadModuleSymbols,LNX_SUFFIX)(pUVM, pVMM, hDbgMod, uPtrModuleCore,
+ Module.uPtrGplFutureSyms, Module.num_gpl_future_syms);
+ if (RT_FAILURE(rc))
+ LogRelFunc((" Faild to load future GPL symbols: %Rrc\n", rc));
+#endif
+
+#if LNX_VER >= LNX_MK_VER(2,6,18)
+ rc = RT_CONCAT(dbgDiggerLinuxLoadModuleSymbols,LNX_SUFFIX)(pUVM, pVMM, hDbgMod, uPtrModuleCore,
+ Module.uPtrUnusedSyms, Module.num_unused_syms);
+ if (RT_FAILURE(rc))
+ LogRelFunc((" Faild to load unused symbols: %Rrc\n", rc));
+
+ rc = RT_CONCAT(dbgDiggerLinuxLoadModuleSymbols,LNX_SUFFIX)(pUVM, pVMM, hDbgMod, uPtrModuleCore,
+ Module.uPtrUnusedGplSyms, Module.num_unused_gpl_syms);
+ if (RT_FAILURE(rc))
+ LogRelFunc((" Faild to load unused GPL symbols: %Rrc\n", rc));
+#endif
+ }
+ }
+ else
+ LogRel(("DbgDiggerOs2: RTDbgModSetTag failed: %Rrc\n", rc));
+ RTDbgModRelease(hDbgMod);
+ }
+
+ RT_NOREF(pThis);
+ return Module.uPtrNext;
+}
+
+#undef LNX_VER
+#undef LNX_SUFFIX
+#undef LNX_ULONG_T
+#undef PAD32ON64