105b261ecSmrg/*
205b261ecSmrg * Copyright 1995-1998 by Metro Link, Inc.
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that
705b261ecSmrg * copyright notice and this permission notice appear in supporting
805b261ecSmrg * documentation, and that the name of Metro Link, Inc. not be used in
905b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1005b261ecSmrg * specific, written prior permission.  Metro Link, Inc. makes no
1105b261ecSmrg * representations about the suitability of this software for any purpose.
1205b261ecSmrg *  It is provided "as is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL METRO LINK, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2105b261ecSmrg */
2205b261ecSmrg/*
2305b261ecSmrg * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
2405b261ecSmrg *
2505b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
2605b261ecSmrg * copy of this software and associated documentation files (the "Software"),
2705b261ecSmrg * to deal in the Software without restriction, including without limitation
2805b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
2905b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
3005b261ecSmrg * Software is furnished to do so, subject to the following conditions:
3105b261ecSmrg *
3205b261ecSmrg * The above copyright notice and this permission notice shall be included in
3305b261ecSmrg * all copies or substantial portions of the Software.
3405b261ecSmrg *
3505b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3605b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3705b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
3805b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
3905b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4005b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4105b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE.
4205b261ecSmrg *
4305b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s)
4405b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote
4505b261ecSmrg * the sale, use or other dealings in this Software without prior written
4605b261ecSmrg * authorization from the copyright holder(s) and author(s).
4705b261ecSmrg */
4805b261ecSmrg
4905b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
5005b261ecSmrg#include <xorg-config.h>
5105b261ecSmrg#endif
5205b261ecSmrg
5305b261ecSmrg#include <string.h>
5405b261ecSmrg#include "os.h"
5505b261ecSmrg#include "loader.h"
5605b261ecSmrg#include "loaderProcs.h"
5705b261ecSmrg
589ace9065Smrg#ifdef HAVE_DLFCN_H
5905b261ecSmrg
609ace9065Smrg#include <dlfcn.h>
619ace9065Smrg#include <X11/Xos.h>
626747b715Smrg
639ace9065Smrg#else
649ace9065Smrg#error i have no dynamic linker and i must scream
659ace9065Smrg#endif
6605b261ecSmrg
677e31ba66Smrg#ifndef XORG_NO_SDKSYMS
689ace9065Smrgextern void *xorg_symbols[];
697e31ba66Smrg#endif
706747b715Smrg
716747b715Smrgvoid
726747b715SmrgLoaderInit(void)
736747b715Smrg{
747e31ba66Smrg#ifndef XORG_NO_SDKSYMS
757e31ba66Smrg    LogMessageVerb(X_INFO, 2, "Loader magic: %p\n", (void *) xorg_symbols);
767e31ba66Smrg#endif
777e31ba66Smrg    LogMessageVerb(X_INFO, 2, "Module ABI versions:\n");
787e31ba66Smrg    LogWrite(2, "\t%s: %d.%d\n", ABI_CLASS_ANSIC,
797e31ba66Smrg             GET_ABI_MAJOR(LoaderVersionInfo.ansicVersion),
807e31ba66Smrg             GET_ABI_MINOR(LoaderVersionInfo.ansicVersion));
817e31ba66Smrg    LogWrite(2, "\t%s: %d.%d\n", ABI_CLASS_VIDEODRV,
827e31ba66Smrg             GET_ABI_MAJOR(LoaderVersionInfo.videodrvVersion),
837e31ba66Smrg             GET_ABI_MINOR(LoaderVersionInfo.videodrvVersion));
847e31ba66Smrg    LogWrite(2, "\t%s : %d.%d\n", ABI_CLASS_XINPUT,
857e31ba66Smrg             GET_ABI_MAJOR(LoaderVersionInfo.xinputVersion),
867e31ba66Smrg             GET_ABI_MINOR(LoaderVersionInfo.xinputVersion));
877e31ba66Smrg    LogWrite(2, "\t%s : %d.%d\n", ABI_CLASS_EXTENSION,
887e31ba66Smrg             GET_ABI_MAJOR(LoaderVersionInfo.extensionVersion),
897e31ba66Smrg             GET_ABI_MINOR(LoaderVersionInfo.extensionVersion));
9005b261ecSmrg
9105b261ecSmrg}
9205b261ecSmrg
9305b261ecSmrg/* Public Interface to the loader. */
9405b261ecSmrg
959ace9065Smrgvoid *
967e31ba66SmrgLoaderOpen(const char *module, int *errmaj)
9705b261ecSmrg{
989ace9065Smrg    void *ret;
9905b261ecSmrg
10005b261ecSmrg#if defined(DEBUG)
10105b261ecSmrg    ErrorF("LoaderOpen(%s)\n", module);
10205b261ecSmrg#endif
10305b261ecSmrg
1047e31ba66Smrg    LogMessage(X_INFO, "Loading %s\n", module);
10505b261ecSmrg
106f7df2e56Smrg    if (!(ret = dlopen(module, RTLD_LAZY | RTLD_GLOBAL))) {
1077e31ba66Smrg        LogMessage(X_ERROR, "Failed to load %s: %s\n", module, dlerror());
108f7df2e56Smrg        if (errmaj)
109f7df2e56Smrg            *errmaj = LDR_NOLOAD;
110f7df2e56Smrg        return NULL;
11105b261ecSmrg    }
11205b261ecSmrg
1139ace9065Smrg    return ret;
11405b261ecSmrg}
11505b261ecSmrg
1166747b715Smrgvoid *
1179ace9065SmrgLoaderSymbol(const char *name)
11805b261ecSmrg{
1199ace9065Smrg    static void *global_scope = NULL;
1209ace9065Smrg    void *p;
12105b261ecSmrg
1229ace9065Smrg    p = dlsym(RTLD_DEFAULT, name);
1239ace9065Smrg    if (p != NULL)
124f7df2e56Smrg        return p;
12505b261ecSmrg
1269ace9065Smrg    if (!global_scope)
127f7df2e56Smrg        global_scope = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
12805b261ecSmrg
1299ace9065Smrg    if (global_scope)
130f7df2e56Smrg        return dlsym(global_scope, name);
13105b261ecSmrg
1329ace9065Smrg    return NULL;
1339ace9065Smrg}
13405b261ecSmrg
135f7df2e56Smrgvoid *
136f7df2e56SmrgLoaderSymbolFromModule(void *handle, const char *name)
137f7df2e56Smrg{
1385a112b11Smrg    ModuleDescPtr mod = handle;
1395a112b11Smrg    return dlsym(mod->handle, name);
140f7df2e56Smrg}
141f7df2e56Smrg
1429ace9065Smrgvoid
1439ace9065SmrgLoaderUnload(const char *name, void *handle)
1449ace9065Smrg{
145f7df2e56Smrg    LogMessageVerbSigSafe(X_INFO, 1, "Unloading %s\n", name);
1469ace9065Smrg    if (handle)
147f7df2e56Smrg        dlclose(handle);
14805b261ecSmrg}
14905b261ecSmrg
15005b261ecSmrgunsigned long LoaderOptions = 0;
15105b261ecSmrg
15205b261ecSmrgvoid
15305b261ecSmrgLoaderSetOptions(unsigned long opts)
15405b261ecSmrg{
15505b261ecSmrg    LoaderOptions |= opts;
15605b261ecSmrg}
15705b261ecSmrg
1586747b715SmrgBool
1594642e01fSmrgLoaderShouldIgnoreABI(void)
1604642e01fSmrg{
1614642e01fSmrg    return (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) != 0;
1624642e01fSmrg}
1634642e01fSmrg
1646747b715Smrgint
16505b261ecSmrgLoaderGetABIVersion(const char *abiclass)
16605b261ecSmrg{
16705b261ecSmrg    struct {
16805b261ecSmrg        const char *name;
16905b261ecSmrg        int version;
17005b261ecSmrg    } classes[] = {
171f7df2e56Smrg        {ABI_CLASS_ANSIC, LoaderVersionInfo.ansicVersion},
172f7df2e56Smrg        {ABI_CLASS_VIDEODRV, LoaderVersionInfo.videodrvVersion},
173f7df2e56Smrg        {ABI_CLASS_XINPUT, LoaderVersionInfo.xinputVersion},
174f7df2e56Smrg        {ABI_CLASS_EXTENSION, LoaderVersionInfo.extensionVersion},
175f7df2e56Smrg        {NULL, 0}
17605b261ecSmrg    };
17705b261ecSmrg    int i;
17805b261ecSmrg
179f7df2e56Smrg    for (i = 0; classes[i].name; i++) {
180f7df2e56Smrg        if (!strcmp(classes[i].name, abiclass)) {
18105b261ecSmrg            return classes[i].version;
18205b261ecSmrg        }
18305b261ecSmrg    }
18405b261ecSmrg
18505b261ecSmrg    return 0;
18605b261ecSmrg}
187