VirtualBox

Changeset 45928 in vbox for trunk/include


Ignore:
Timestamp:
May 7, 2013 8:33:19 AM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
85566
Message:

ldrlazy.h + win/lazy-dbghelp.h: New lazy loader that works on windows.

Location:
trunk/include/iprt
Files:
2 added
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/ldrlazy.h

    r45910 r45928  
    11/** @file
    2  * IPRT - Runtime Loader Generation.
     2 * IPRT - Lazy share library linking (2nd try).
    33 */
    44
    55/*
    6  * Copyright (C) 2008-2012 Oracle Corporation
     6 * Copyright (C) 2013 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2424 */
    2525
    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
    3228
    33 /** @defgroup grp_rt_runtime_loader     Runtime Loader Generation
     29#include <iprt/ldr.h>
     30
     31/** @defgroup grp_rt_ldrlazy        Lazy shared library linking.
    3432 * @ingroup grp_rt
    3533 *
    36  * How to use this loader generator
    37  *
    38  * This loader generator can be used to generate stub code for loading a shared
    39  * library and its functions at runtime, or for generating a header file with
    40  * the declaration of the loader function and optionally declarations for the
    41  * functions loaded.  It should be included in a header file or a C source
    42  * file, after defining certain macros which it makes use of.
    43  *
    44  * To generate the C source code for function proxy stubs and the library
    45  * loader function, you should define the following macros in your source file
    46  * before including this header:
    47  *
    48  *  RT_RUNTIME_LOADER_LIB_NAME       - the file name of the library to load
    49  *  RT_RUNTIME_LOADER_FUNCTION       - the name of the loader function
    50  *  RT_RUNTIME_LOADER_INSERT_SYMBOLS - a macro containing the names of the
    51  *                                     functions to be loaded, defined in the
    52  *                                     following pattern:
    53  * @code
    54  * #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  * @endcode
    59  *
    60  * where long_param_list is a parameter list for declaring the function of the
    61  * form (type1 arg1, type2 arg2, ...) and short_param_list for calling it, of
    62  * the form (arg1, arg2, ...).
    63  *
    64  * To generate the header file, you should define RT_RUNTIME_LOADER_FUNCTION
    65  * and if you wish to generate declarations for the functions you should
    66  * additionally define RT_RUNTIME_LOADER_INSERT_SYMBOLS as above and
    67  * RT_RUNTIME_LOADER_GENERATE_DECLS (without a value) before including this
    68  * file.
    6934 *
    7035 * @{
    7136 */
    72 /** @todo this is far too complicated.  A script for generating the files would
    73  * probably be preferable.
    74  *
    75  * bird> An alternative is to generate assembly jump wrappers, this only
    76  * requires the symbol names and prefix.  I've done this ages ago when we forked
    77  * the EMX/GCC toolchain on OS/2...  It's a wee bit more annoying in x86 PIC/PIE
    78  * 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.  Here
    82  *        we'll get into trouble if we use the same symbol names as the
    83  *        original! */
    84 /** @todo r=bird: The prefix usage here is very confused: RT_RUNTIME_LOADER_XXX,
    85  *        RT_PROXY_STUB, etc. */
    8637
    87 #ifdef RT_RUNTIME_LOADER_GENERATE_BODY_STUBS
    88 
    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_SYMBOLS
    96 
    97 # undef RT_PROXY_STUB
    98 
    99 /* Now comes a table of functions to be loaded from the library. */
    100 typedef struct
    101 {
    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_SYMBOLS
    110     { NULL, NULL }
    111 };
    112 # undef RT_PROXY_STUB
    11338
    11439/**
    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.
    11744 */
    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)
    13147
    13248/**
    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.
    13550 *
    136  * May safely be called from multiple threads and will not return until the
    137  * 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.
    14055 */
    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    }
    14577
    146     LogFlowFunc(("\n"));
    147     rc = RTOnce(&s_Once, rtldrLoadOnce, NULL);
    148     LogFlowFunc(("rc = %Rrc\n", rc));
    14978
    150     return rc;
    151 }
    15279
    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
    16482
    16583/**
    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.
    17185 */
    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    }
    17397
    174 #else
    175 # error "One of RT_RUNTIME_LOADER_GENERATE_HEADER or RT_RUNTIME_LOADER_GENERATE_BODY_STUBS must be defined when including this file"
    176 #endif
    17798
    17899/** @} */
    179100
     101#endif
     102
Note: See TracChangeset for help on using the changeset viewer.

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