~ubuntu-branches/ubuntu/precise/xorg-server/precise-updates

« back to all changes in this revision

Viewing changes to hw/xfree86/loader/dlloader.c

Tags: 2:1.10.1-2
* Build xserver-xorg-core-udeb on hurd-i386.  Thanks, Samuel Thibault!
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 1997 The XFree86 Project, Inc.
3
 
 *
4
 
 * Permission to use, copy, modify, distribute, and sell this software
5
 
 * and its documentation for any purpose is hereby granted without
6
 
 * fee, provided that the above copyright notice appear in all copies
7
 
 * and that both that copyright notice and this permission notice
8
 
 * appear in supporting documentation, and that the name of the
9
 
 * XFree86 Project, Inc. not be used in advertising or publicity
10
 
 * pertaining to distribution of the software without specific,
11
 
 * written prior permission.  The Xfree86 Project, Inc. makes no
12
 
 * representations about the suitability of this software for any
13
 
 * purpose.  It is provided "as is" without express or implied
14
 
 * warranty.
15
 
 *
16
 
 * THE XFREE86 PROJECT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO
17
 
 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18
 
 * AND FITNESS, IN NO EVENT SHALL THE XFREE86 PROJECT, INC. BE LIABLE
19
 
 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20
 
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21
 
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22
 
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23
 
 * SOFTWARE.
24
 
 */
25
 
 
26
 
/*
27
 
 * Once upon a time, X had multiple loader backends, three of which were
28
 
 * essentially libdl reimplementations.  This was nonsense so we chucked
29
 
 * it, but we still retain the factorization between loader API and
30
 
 * platform implementation.  This file is the libdl implementation, and
31
 
 * currently the only backend.  If you find yourself porting to a platform
32
 
 * without working libdl - hpux, win32, some forsaken a.out host, etc. -
33
 
 * make a new backend rather than hacking up this file.
34
 
 */
35
 
 
36
 
#ifdef HAVE_XORG_CONFIG_H
37
 
#include <xorg-config.h>
38
 
#endif
39
 
 
40
 
#include <stdio.h>
41
 
#include <stdlib.h>
42
 
#include <dlfcn.h>
43
 
 
44
 
#include <X11/Xos.h>
45
 
#include "os.h"
46
 
 
47
 
#include "loader.h"
48
 
#include "dlloader.h"
49
 
 
50
 
#if defined(DL_LAZY)
51
 
#define DLOPEN_LAZY DL_LAZY
52
 
#elif defined(RTLD_LAZY)
53
 
#define DLOPEN_LAZY RTLD_LAZY
54
 
#elif defined(__FreeBSD__)
55
 
#define DLOPEN_LAZY 1
56
 
#else
57
 
#define DLOPEN_LAZY 0
58
 
#endif
59
 
 
60
 
#if defined(LD_GLOBAL)
61
 
#define DLOPEN_GLOBAL LD_GLOBAL
62
 
#elif defined(RTLD_GLOBAL)
63
 
#define DLOPEN_GLOBAL RTLD_GLOBAL
64
 
#else
65
 
#define DLOPEN_GLOBAL 0
66
 
#endif
67
 
 
68
 
#if defined(CSRG_BASED) && !defined(__ELF__)
69
 
#define DLSYM_PREFIX "_"
70
 
#else
71
 
#define DLSYM_PREFIX ""
72
 
#endif
73
 
 
74
 
/* Hooray, yet another open coded linked list! FIXME */
75
 
typedef struct DLModuleList {
76
 
    void *module;
77
 
    struct DLModuleList *next;
78
 
} DLModuleList;
79
 
 
80
 
static DLModuleList *dlModuleList = NULL;
81
 
 
82
 
static void *
83
 
DLFindSymbolLocal(pointer module, const char *name)
84
 
{
85
 
    void *p;
86
 
    char *n;
87
 
 
88
 
    static const char symPrefix[] = DLSYM_PREFIX;
89
 
 
90
 
    if (sizeof(symPrefix) > 1) {
91
 
        n = malloc(strlen(symPrefix) + strlen(name) + 1);
92
 
        sprintf(n, "%s%s", symPrefix, name);
93
 
        name = n;
94
 
    }
95
 
 
96
 
    p = dlsym(module, name);
97
 
 
98
 
    if (sizeof(symPrefix) > 1)
99
 
        free(n);
100
 
 
101
 
    return p;
102
 
}
103
 
 
104
 
static void *global_scope = NULL;
105
 
 
106
 
void *
107
 
DLFindSymbol(const char *name)
108
 
{
109
 
    DLModuleList *l;
110
 
    void *p;
111
 
 
112
 
    p = dlsym(RTLD_DEFAULT, name);
113
 
    if (p != NULL)
114
 
        return p;
115
 
 
116
 
    for (l = dlModuleList; l != NULL; l = l->next) {
117
 
        p = DLFindSymbolLocal(l->module, name);
118
 
        if (p)
119
 
            return p;
120
 
    }
121
 
 
122
 
    if (!global_scope)
123
 
        global_scope = dlopen(NULL, DLOPEN_LAZY | DLOPEN_GLOBAL);
124
 
 
125
 
    if (global_scope)
126
 
        return DLFindSymbolLocal(global_scope, name);
127
 
 
128
 
    return NULL;
129
 
}
130
 
 
131
 
void *
132
 
DLLoadModule(loaderPtr modrec, int flags)
133
 
{
134
 
    void * dlfile;
135
 
    DLModuleList *l;
136
 
    int dlopen_flags;
137
 
 
138
 
    if (flags & LD_FLAG_GLOBAL)
139
 
        dlopen_flags = DLOPEN_LAZY | DLOPEN_GLOBAL;
140
 
    else
141
 
        dlopen_flags = DLOPEN_LAZY;
142
 
    dlfile = dlopen(modrec->name, dlopen_flags);
143
 
    if (dlfile == NULL) {
144
 
        ErrorF("dlopen: %s\n", dlerror());
145
 
        return NULL;
146
 
    }
147
 
 
148
 
    l = malloc(sizeof(DLModuleList));
149
 
    l->module = dlfile;
150
 
    l->next = dlModuleList;
151
 
    dlModuleList = l;
152
 
 
153
 
    return (void *)dlfile;
154
 
}
155
 
 
156
 
void
157
 
DLUnloadModule(void *modptr)
158
 
{
159
 
    DLModuleList *l, *p;
160
 
 
161
 
    /* remove it from dlModuleList. */
162
 
    if (dlModuleList->module == modptr) {
163
 
        l = dlModuleList;
164
 
        dlModuleList = l->next;
165
 
        free(l);
166
 
    } else {
167
 
        p = dlModuleList;
168
 
        for (l = dlModuleList->next; l != NULL; l = l->next) {
169
 
            if (l->module == modptr) {
170
 
                p->next = l->next;
171
 
                free(l);
172
 
                break;
173
 
            }
174
 
            p = l;
175
 
        }
176
 
    }
177
 
    dlclose(modptr);
178
 
}