Changeset 45928 in vbox for trunk/include
- Timestamp:
- May 7, 2013 8:33:19 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 85566
- Location:
- trunk/include/iprt
- Files:
-
- 2 added
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/ldrlazy.h
r45910 r45928 1 1 /** @file 2 * IPRT - Runtime Loader Generation.2 * IPRT - Lazy share library linking (2nd try). 3 3 */ 4 4 5 5 /* 6 * Copyright (C) 20 08-2012Oracle Corporation6 * Copyright (C) 2013 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 24 24 */ 25 25 26 #include <iprt/types.h> 27 #ifdef RT_RUNTIME_LOADER_GENERATE_BODY_STUBS 28 # include <iprt/ldr.h> 29 # include <iprt/log.h> 30 # include <iprt/once.h> 31 #endif 26 #ifndef ___iprt_ldrlazy_h 27 #define ___iprt_ldrlazy_h 32 28 33 /** @defgroup grp_rt_runtime_loader Runtime Loader Generation 29 #include <iprt/ldr.h> 30 31 /** @defgroup grp_rt_ldrlazy Lazy shared library linking. 34 32 * @ingroup grp_rt 35 33 * 36 * How to use this loader generator37 *38 * This loader generator can be used to generate stub code for loading a shared39 * library and its functions at runtime, or for generating a header file with40 * the declaration of the loader function and optionally declarations for the41 * functions loaded. It should be included in a header file or a C source42 * file, after defining certain macros which it makes use of.43 *44 * To generate the C source code for function proxy stubs and the library45 * loader function, you should define the following macros in your source file46 * before including this header:47 *48 * RT_RUNTIME_LOADER_LIB_NAME - the file name of the library to load49 * RT_RUNTIME_LOADER_FUNCTION - the name of the loader function50 * RT_RUNTIME_LOADER_INSERT_SYMBOLS - a macro containing the names of the51 * functions to be loaded, defined in the52 * following pattern:53 * @code54 * #define RT_RUNTIME_LOADER_INSERT_SYMBOLS \55 * RT_PROXY_STUB(func_name, ret_type, (long_param_list), (short_param_list)) \56 * RT_PROXY_STUB(func_name2, ret_type2, (long_param_list2), (short_param_list2)) \57 * ...58 * @endcode59 *60 * where long_param_list is a parameter list for declaring the function of the61 * form (type1 arg1, type2 arg2, ...) and short_param_list for calling it, of62 * the form (arg1, arg2, ...).63 *64 * To generate the header file, you should define RT_RUNTIME_LOADER_FUNCTION65 * and if you wish to generate declarations for the functions you should66 * additionally define RT_RUNTIME_LOADER_INSERT_SYMBOLS as above and67 * RT_RUNTIME_LOADER_GENERATE_DECLS (without a value) before including this68 * file.69 34 * 70 35 * @{ 71 36 */ 72 /** @todo this is far too complicated. A script for generating the files would73 * probably be preferable.74 *75 * bird> An alternative is to generate assembly jump wrappers, this only76 * requires the symbol names and prefix. I've done this ages ago when we forked77 * the EMX/GCC toolchain on OS/2... It's a wee bit more annoying in x86 PIC/PIE78 * mode, but nothing that cannot be dealt with.79 */80 /** @todo r=bird: The use of RTR3DECL here is an unresolved issue. */81 /** @todo r=bird: The lack of RT_C_DECLS_BEGIN/END is an unresolved issue. Here82 * we'll get into trouble if we use the same symbol names as the83 * original! */84 /** @todo r=bird: The prefix usage here is very confused: RT_RUNTIME_LOADER_XXX,85 * RT_PROXY_STUB, etc. */86 37 87 #ifdef RT_RUNTIME_LOADER_GENERATE_BODY_STUBS88 89 /* The following are the symbols which we need from the library. */90 # define RT_PROXY_STUB(function, rettype, signature, shortsig) \91 void (*function ## _fn)(void); \92 RTR3DECL(rettype) function signature \93 { return ( (rettype (*) signature) function ## _fn ) shortsig; }94 95 RT_RUNTIME_LOADER_INSERT_SYMBOLS96 97 # undef RT_PROXY_STUB98 99 /* Now comes a table of functions to be loaded from the library. */100 typedef struct101 {102 const char *pszName;103 void (**ppfn)(void);104 } RTLDRSHAREDFUNC;105 106 # define RT_PROXY_STUB(s, dummy1, dummy2, dummy3 ) { #s , & s ## _fn } ,107 static RTLDRSHAREDFUNC g_aSharedFuncs[] =108 {109 RT_RUNTIME_LOADER_INSERT_SYMBOLS110 { NULL, NULL }111 };112 # undef RT_PROXY_STUB113 38 114 39 /** 115 * The function which does the actual work for RT_RUNTIME_LOADER_FUNCTION, 116 * serialised for thread safety. 40 * Defines a module for use in lazy resolving. 41 * 42 * @param a_Mod The module name (C name). 43 * @param a_pszFile The file to tell RTLdrLoad to load. 117 44 */ 118 static DECLCALLBACK(int) rtldrLoadOnce(void *) 119 { 120 RTLDRMOD hLib; 121 int rc; 122 123 LogFlowFunc(("\n")); 124 rc = RTLdrLoad(RT_RUNTIME_LOADER_LIB_NAME, &hLib); 125 for (unsigned i = 0; RT_SUCCESS(rc) && g_aSharedFuncs[i].pszName != NULL; ++i) 126 rc = RTLdrGetSymbol(hLib, g_aSharedFuncs[i].pszName, (void **)g_aSharedFuncs[i].ppfn); 127 LogFlowFunc(("rc = %Rrc\n", rc)); 128 129 return rc; 130 } 45 #define RTLDRLAZY_MODULE(a_Mod, a_pszFile) \ 46 RTLDRLAZY_MODULE_EX(a_Mod, a_pszFile, RTLdrLoad) 131 47 132 48 /** 133 * Load the shared library RT_RUNTIME_LOADER_LIB_NAME and resolve the symbols 134 * pointed to by RT_RUNTIME_LOADER_INSERT_SYMBOLS. 49 * Defines a module for use in lazy resolving. 135 50 * 136 * May safely be called from multiple threads and will not return until the137 * library is loaded or has failed to load.138 * 139 * @returns IPRT status code.51 * @param a_Mod The module name (C name). 52 * @param a_pszFile The file to tell RTLdrLoad to load. 53 * @param a_pfnLoadIt Function to call for loading the DLL, replacing 54 * RTLdrLoad. 140 55 */ 141 RTR3DECL(int) RT_RUNTIME_LOADER_FUNCTION(void) 142 { 143 static RTONCE s_Once = RTONCE_INITIALIZER; 144 int rc; 56 #define RTLDRLAZY_MODULE_EX(a_Mod, a_pszFile, a_pfnLoadIt) \ 57 static bool rtLdrLazy_##a_Mod##_Resolve(const char *pszName, void **ppvSymbol) \ 58 { \ 59 static RTLDRMOD volatile s_hMod = NIL_RTLDRMOD; \ 60 static bool volatile s_fLoaded = false; \ 61 RTLDRMOD hMod; \ 62 int rc; \ 63 if (!s_fLoaded) \ 64 { \ 65 rc = a_pfnLoadIt(a_pszFile, &hMod); \ 66 s_hMod = RT_SUCCESS(rc) ? hMod : NIL_RTLDRMOD; \ 67 s_fLoaded = true; \ 68 if (RT_FAILURE(rc)) \ 69 return false; \ 70 } \ 71 hMod = s_hMod; \ 72 if (hMod == NIL_RTLDRMOD) \ 73 return false; \ 74 rc = RTLdrGetSymbol(hMod, pszName, ppvSymbol); \ 75 return RT_SUCCESS(rc); \ 76 } 145 77 146 LogFlowFunc(("\n"));147 rc = RTOnce(&s_Once, rtldrLoadOnce, NULL);148 LogFlowFunc(("rc = %Rrc\n", rc));149 78 150 return rc;151 }152 79 153 #elif defined(RT_RUNTIME_LOADER_GENERATE_HEADER) 154 # ifdef RT_RUNTIME_LOADER_GENERATE_DECLS 155 /* Declarations of the functions that we need from 156 * RT_RUNTIME_LOADER_LIB_NAME */ 157 # define RT_PROXY_STUB(function, rettype, signature, shortsig) \ 158 RTR3DECL(rettype) ( function ) signature ; 159 160 RT_RUNTIME_LOADER_INSERT_SYMBOLS 161 162 # undef RT_PROXY_STUB 163 # endif /* RT_RUNTIME_LOADER_GENERATE_DECLS */ 80 /** Function name mangler for preventing collision with system prototypes. */ 81 #define RTLDRLAZY_FUNC_NAME(a_Mod, a_Name) a_Mod##__##a_Name 164 82 165 83 /** 166 * Try to dynamically load the library. This function should be called before 167 * attempting to use any of the library functions. It is safe to call this 168 * function multiple times. 169 * 170 * @returns iprt status code 84 * Defines a function that should be lazily resolved. 171 85 */ 172 RTR3DECL(int) RT_RUNTIME_LOADER_FUNCTION(void); 86 #define RTLDRLAZY_FUNC(a_Mod, a_RetType, a_CallConv, a_Name, a_ParamDecl, a_ParamNames, a_ErrRet) \ 87 DECLINLINE(a_RetType) RTLDRLAZY_FUNC_NAME(a_Mod, a_Name) a_ParamDecl \ 88 { \ 89 static a_RetType (a_CallConv * s_pfn) a_ParamDecl; \ 90 if (!s_pfn) \ 91 { \ 92 if (!rtLdrLazy_##a_Mod##_Resolve(#a_Name, (void **)&s_pfn)) \ 93 return a_ErrRet; \ 94 } \ 95 return s_pfn a_ParamNames; \ 96 } 173 97 174 #else175 # error "One of RT_RUNTIME_LOADER_GENERATE_HEADER or RT_RUNTIME_LOADER_GENERATE_BODY_STUBS must be defined when including this file"176 #endif177 98 178 99 /** @} */ 179 100 101 #endif 102
Note:
See TracChangeset
for help on using the changeset viewer.