loader.c revision 6747b715
1/* 2 * Copyright 1995-1998 by Metro Link, Inc. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Metro Link, Inc. not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Metro Link, Inc. makes no 11 * representations about the suitability of this software for any purpose. 12 * It is provided "as is" without express or implied warranty. 13 * 14 * METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL METRO LINK, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22/* 23 * Copyright (c) 1997-2003 by The XFree86 Project, Inc. 24 * 25 * Permission is hereby granted, free of charge, to any person obtaining a 26 * copy of this software and associated documentation files (the "Software"), 27 * to deal in the Software without restriction, including without limitation 28 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 29 * and/or sell copies of the Software, and to permit persons to whom the 30 * Software is furnished to do so, subject to the following conditions: 31 * 32 * The above copyright notice and this permission notice shall be included in 33 * all copies or substantial portions of the Software. 34 * 35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 36 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 37 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 38 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 39 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 40 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 41 * OTHER DEALINGS IN THE SOFTWARE. 42 * 43 * Except as contained in this notice, the name of the copyright holder(s) 44 * and author(s) shall not be used in advertising or otherwise to promote 45 * the sale, use or other dealings in this Software without prior written 46 * authorization from the copyright holder(s) and author(s). 47 */ 48 49#ifdef HAVE_XORG_CONFIG_H 50#include <xorg-config.h> 51#endif 52 53#include <errno.h> 54#include <stdio.h> 55#include <stdlib.h> 56#include <sys/types.h> 57#if defined(UseMMAP) || (defined(linux) && defined(__ia64__)) 58#include <sys/mman.h> 59#endif 60#include <unistd.h> 61#include <sys/stat.h> 62#include <fcntl.h> 63#include <string.h> 64#if defined(linux) && \ 65 (defined(__alpha__) || defined(__powerpc__) || defined(__ia64__) \ 66 || defined(__amd64__)) 67#include <malloc.h> 68#endif 69#include <stdarg.h> 70 71#include "os.h" 72#include "loader.h" 73#include "loaderProcs.h" 74#include "xf86.h" 75#include "xf86Priv.h" 76#include "compiler.h" 77 78extern void *xorg_symbols[]; 79 80#define MAX_HANDLE 256 81static int refCount[MAX_HANDLE]; 82 83static int moduleseq = 0; 84 85/* Prototypes for static functions. */ 86static loaderPtr listHead = NULL; 87 88static loaderPtr 89_LoaderListPush(void) 90{ 91 loaderPtr item = calloc(1, sizeof(struct _loader)); 92 93 item->next = listHead; 94 listHead = item; 95 96 return item; 97} 98 99static loaderPtr 100_LoaderListPop(int handle) 101{ 102 loaderPtr item = listHead; 103 loaderPtr *bptr = &listHead; /* pointer to previous node */ 104 105 while (item) { 106 if (item->handle == handle) { 107 *bptr = item->next; /* remove this from the list */ 108 return item; 109 } 110 bptr = &(item->next); 111 item = item->next; 112 } 113 114 return 0; 115} 116 117void 118LoaderInit(void) 119{ 120 xf86MsgVerb(X_INFO, 2, "Loader magic: %p\n", (void *)xorg_symbols); 121 xf86MsgVerb(X_INFO, 2, "Module ABI versions:\n"); 122 xf86ErrorFVerb(2, "\t%s: %d.%d\n", ABI_CLASS_ANSIC, 123 GET_ABI_MAJOR(LoaderVersionInfo.ansicVersion), 124 GET_ABI_MINOR(LoaderVersionInfo.ansicVersion)); 125 xf86ErrorFVerb(2, "\t%s: %d.%d\n", ABI_CLASS_VIDEODRV, 126 GET_ABI_MAJOR(LoaderVersionInfo.videodrvVersion), 127 GET_ABI_MINOR(LoaderVersionInfo.videodrvVersion)); 128 xf86ErrorFVerb(2, "\t%s : %d.%d\n", ABI_CLASS_XINPUT, 129 GET_ABI_MAJOR(LoaderVersionInfo.xinputVersion), 130 GET_ABI_MINOR(LoaderVersionInfo.xinputVersion)); 131 xf86ErrorFVerb(2, "\t%s : %d.%d\n", ABI_CLASS_EXTENSION, 132 GET_ABI_MAJOR(LoaderVersionInfo.extensionVersion), 133 GET_ABI_MINOR(LoaderVersionInfo.extensionVersion)); 134 135#if defined(__UNIXWARE__) && !defined(__GNUC__) 136 /* For UnixWare we need to load the C Runtime libraries which are 137 * normally auto-linked by the compiler. Otherwise we are bound to 138 * see unresolved symbols when trying to use the type "long long". 139 * Obviously, this does not apply if the GNU C compiler is used. 140 */ 141 { 142 int errmaj, errmin, wasLoaded; /* place holders */ 143 char *xcrtpath = DEFAULT_MODULE_PATH "/libcrt.a"; 144 char *uwcrtpath = "/usr/ccs/lib/libcrt.a"; 145 char *path; 146 struct stat st; 147 148 if(stat(xcrtpath, &st) < 0) 149 path = uwcrtpath; /* fallback: try to get libcrt.a from the uccs */ 150 else 151 path = xcrtpath; /* get the libcrt.a we compiled with */ 152 LoaderOpen (path, "libcrt", 0, &errmaj, &errmin, &wasLoaded); 153 } 154#endif 155} 156 157/* Public Interface to the loader. */ 158 159int 160LoaderOpen(const char *module, const char *cname, int handle, 161 int *errmaj, int *errmin, int *wasLoaded, int flags) 162{ 163 loaderPtr tmp; 164 int new_handle; 165 166#if defined(DEBUG) 167 ErrorF("LoaderOpen(%s)\n", module); 168#endif 169 170 /* Is the module already loaded? */ 171 if (handle >= 0) { 172 tmp = listHead; 173 while (tmp) { 174#ifdef DEBUGLIST 175 ErrorF("strcmp(%x(%s),{%x} %x(%s))\n", module, module, 176 &(tmp->name), tmp->name, tmp->name); 177#endif 178 if (!strcmp(module, tmp->name)) { 179 refCount[tmp->handle]++; 180 if (wasLoaded) 181 *wasLoaded = 1; 182 xf86MsgVerb(X_INFO, 2, "Reloading %s\n", module); 183 return tmp->handle; 184 } 185 tmp = tmp->next; 186 } 187 } 188 189 /* 190 * OK, it's a new one. Add it. 191 */ 192 xf86Msg(X_INFO, "Loading %s\n", module); 193 if (wasLoaded) 194 *wasLoaded = 0; 195 196 /* 197 * Find a free handle. 198 */ 199 new_handle = 1; 200 while (new_handle < MAX_HANDLE && refCount[new_handle]) 201 new_handle++; 202 203 if (new_handle == MAX_HANDLE) { 204 xf86Msg(X_ERROR, "Out of loader space\n"); /* XXX */ 205 if (errmaj) 206 *errmaj = LDR_NOSPACE; 207 if (errmin) 208 *errmin = LDR_NOSPACE; 209 return -1; 210 } 211 212 refCount[new_handle] = 1; 213 214 tmp = _LoaderListPush(); 215 tmp->name = malloc(strlen(module) + 1); 216 strcpy(tmp->name, module); 217 tmp->cname = malloc(strlen(cname) + 1); 218 strcpy(tmp->cname, cname); 219 tmp->handle = new_handle; 220 tmp->module = moduleseq++; 221 222 if ((tmp->private = DLLoadModule(tmp, flags)) == NULL) { 223 xf86Msg(X_ERROR, "Failed to load %s\n", module); 224 _LoaderListPop(new_handle); 225 refCount[new_handle] = 0; 226 if (errmaj) 227 *errmaj = LDR_NOLOAD; 228 if (errmin) 229 *errmin = LDR_NOLOAD; 230 return -1; 231 } 232 233 return new_handle; 234} 235 236int 237LoaderHandleOpen(int handle) 238{ 239 if (handle < 0 || handle >= MAX_HANDLE) 240 return -1; 241 242 if (!refCount[handle]) 243 return -1; 244 245 refCount[handle]++; 246 return handle; 247} 248 249void * 250LoaderSymbol(const char *sym) 251{ 252 return (DLFindSymbol(sym)); 253} 254 255int 256LoaderUnload(int handle) 257{ 258 loaderRec fakeHead; 259 loaderPtr tmp = &fakeHead; 260 261 if (handle < 0 || handle >= MAX_HANDLE) 262 return -1; 263 264 /* 265 * check the reference count, only free it if it goes to zero 266 */ 267 if (--refCount[handle]) 268 return 0; 269 /* 270 * find the loaderRecs associated with this handle. 271 */ 272 273 while ((tmp = _LoaderListPop(handle)) != NULL) { 274 xf86Msg(X_INFO, "Unloading %s\n", tmp->name); 275 DLUnloadModule(tmp->private); 276 free(tmp->name); 277 free(tmp->cname); 278 free(tmp); 279 } 280 281 return 0; 282} 283 284unsigned long LoaderOptions = 0; 285 286void 287LoaderSetOptions(unsigned long opts) 288{ 289 LoaderOptions |= opts; 290} 291 292Bool 293LoaderShouldIgnoreABI(void) 294{ 295 return (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) != 0; 296} 297 298int 299LoaderGetABIVersion(const char *abiclass) 300{ 301 struct { 302 const char *name; 303 int version; 304 } classes[] = { 305 { ABI_CLASS_ANSIC, LoaderVersionInfo.ansicVersion }, 306 { ABI_CLASS_VIDEODRV, LoaderVersionInfo.videodrvVersion }, 307 { ABI_CLASS_XINPUT, LoaderVersionInfo.xinputVersion }, 308 { ABI_CLASS_EXTENSION, LoaderVersionInfo.extensionVersion }, 309 { ABI_CLASS_FONT, LoaderVersionInfo.fontVersion }, 310 { NULL, 0 } 311 }; 312 int i; 313 314 for(i = 0; classes[i].name; i++) { 315 if(!strcmp(classes[i].name, abiclass)) { 316 return classes[i].version; 317 } 318 } 319 320 return 0; 321} 322