示例#1
0
void *
dlopen (const char *path, int mode)
{
    void *(*_dlopen) (const char *path, int mode);
    char *new_path = NULL;
    void *result;

    _dlopen = (void *(*)(const char *path, int mode)) dlsym (RTLD_NEXT, "dlopen");

    if (path && path[0] == '/') {
        new_path = redirect_path (path);
        result = _dlopen (new_path, mode);
        free (new_path);
    } else {
        // non-absolute library paths aren't simply relative paths, they need
        // a whole lookup algorithm
        result = _dlopen (path, mode);
    }

    return result;
}
示例#2
0
文件: dlsym.cpp 项目: groleo/apitrace
/*
 * Several applications, such as Quake3, use dlopen("libGL.so.1"), but
 * LD_PRELOAD does not intercept symbols obtained via dlopen/dlsym, therefore
 * we need to intercept the dlopen() call here, and redirect to our wrapper
 * shared object.
 */
extern "C" PUBLIC
void * dlopen(const char *filename, int flag)
{
    void *handle;

    if (!filename) {
        return _dlopen(filename, flag);
    }

    LibClass libClass = classifyLibrary(filename);
    bool intercept = libClass != LIB_UNKNOWN;

    if (intercept) {
        void *caller = __builtin_return_address(0);
        Dl_info info;
        const char *caller_module = "<unknown>";
        if (dladdr(caller, &info)) {
            caller_module = info.dli_fname;
            intercept = classifyLibrary(caller_module) == LIB_UNKNOWN;
        }

        const char * libgl_filename = getenv("TRACE_LIBGL");
        if (libgl_filename) {
            // Don't intercept when using LD_LIBRARY_PATH instead of LD_PRELOAD
            intercept = false;
        }

        os::log("apitrace: %s dlopen(\"%s\", 0x%x) from %s\n",
                intercept ? "redirecting" : "ignoring",
                filename, flag, caller_module);
    }

#ifdef EGLTRACE

    if (intercept) {
        /* The current dispatch implementation relies on core entry-points to be globally available, so force this.
         *
         * TODO: A better approach would be note down the entry points here and
         * use them latter. Another alternative would be to reopen the library
         * with RTLD_NOLOAD | RTLD_GLOBAL.
         */
        flag &= ~RTLD_LOCAL;
        flag |= RTLD_GLOBAL;
    }

#endif

    handle = _dlopen(filename, flag);
    if (!handle) {
        return handle;
    }

    if (intercept) {
        if (libClass == LIB_GL) {
            // Use the true libGL.so handle instead of RTLD_NEXT from now on
            _libGlHandle = handle;
        }

        // Get the file path for our shared object, and use it instead
        static int dummy = 0xdeedbeef;
        Dl_info info;
        if (dladdr(&dummy, &info)) {
            handle = _dlopen(info.dli_fname, flag);
        } else {
            os::log("apitrace: warning: dladdr() failed\n");
        }

#ifdef EGLTRACE
        // SDL will skip dlopen'ing libEGL.so after it spots EGL symbols on our
        // wrapper, so force loading it here.
        // (https://github.com/apitrace/apitrace/issues/291#issuecomment-59734022)
        if (strcmp(filename, "libEGL.so") != 0 &&
            strcmp(filename, "libEGL.so.1") != 0) {
            _dlopen("libEGL.so.1", RTLD_GLOBAL | RTLD_LAZY);
        }
#endif
    }

    return handle;
}