loader.c revision 4642e01f
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#include "sym.h" 78 79/* 80 * handles are used to identify files that are loaded. Even archives 81 * are counted as a single file. 82 */ 83#define MAX_HANDLE 256 84#define HANDLE_FREE 0 85#define HANDLE_USED 1 86static char freeHandles[MAX_HANDLE]; 87static int refCount[MAX_HANDLE]; 88 89/* 90 * modules are used to identify compilation units (ie object modules). 91 * Archives contain multiple modules, each of which is treated seperately. 92 */ 93static int moduleseq = 0; 94 95/* Prototypes for static functions. */ 96static loaderPtr _LoaderListPush(void); 97static loaderPtr _LoaderListPop(int); 98 99void 100LoaderInit(void) 101{ 102 const char *osname = NULL; 103 104 char *ld_bind_now = getenv("LD_BIND_NOW"); 105 if (ld_bind_now && *ld_bind_now) { 106 xf86Msg(X_ERROR, "LD_BIND_NOW is set, dlloader will NOT work!\n"); 107 } 108 109 xf86MsgVerb(X_INFO, 2, "Loader magic: %p\n", (void *) 110 ((long)dixLookupTab ^ (long)extLookupTab 111 ^ (long)miLookupTab ^ (long)xfree86LookupTab)); 112 xf86MsgVerb(X_INFO, 2, "Module ABI versions:\n"); 113 xf86ErrorFVerb(2, "\t%s: %d.%d\n", ABI_CLASS_ANSIC, 114 GET_ABI_MAJOR(LoaderVersionInfo.ansicVersion), 115 GET_ABI_MINOR(LoaderVersionInfo.ansicVersion)); 116 xf86ErrorFVerb(2, "\t%s: %d.%d\n", ABI_CLASS_VIDEODRV, 117 GET_ABI_MAJOR(LoaderVersionInfo.videodrvVersion), 118 GET_ABI_MINOR(LoaderVersionInfo.videodrvVersion)); 119 xf86ErrorFVerb(2, "\t%s : %d.%d\n", ABI_CLASS_XINPUT, 120 GET_ABI_MAJOR(LoaderVersionInfo.xinputVersion), 121 GET_ABI_MINOR(LoaderVersionInfo.xinputVersion)); 122 xf86ErrorFVerb(2, "\t%s : %d.%d\n", ABI_CLASS_EXTENSION, 123 GET_ABI_MAJOR(LoaderVersionInfo.extensionVersion), 124 GET_ABI_MINOR(LoaderVersionInfo.extensionVersion)); 125 126 LoaderGetOS(&osname, NULL, NULL, NULL); 127 if (osname) 128 xf86MsgVerb(X_INFO, 2, "Loader running on %s\n", osname); 129 130#if defined(__UNIXWARE__) && !defined(__GNUC__) 131 /* For UnixWare we need to load the C Runtime libraries which are 132 * normally auto-linked by the compiler. Otherwise we are bound to 133 * see unresolved symbols when trying to use the type "long long". 134 * Obviously, this does not apply if the GNU C compiler is used. 135 */ 136 { 137 int errmaj, errmin, wasLoaded; /* place holders */ 138 char *xcrtpath = DEFAULT_MODULE_PATH "/libcrt.a"; 139 char *uwcrtpath = "/usr/ccs/lib/libcrt.a"; 140 char *path; 141 struct stat st; 142 143 if(stat(xcrtpath, &st) < 0) 144 path = uwcrtpath; /* fallback: try to get libcrt.a from the uccs */ 145 else 146 path = xcrtpath; /* get the libcrt.a we compiled with */ 147 LoaderOpen (path, "libcrt", 0, &errmaj, &errmin, &wasLoaded); 148 } 149#endif 150} 151 152static loaderPtr listHead = (loaderPtr) 0; 153 154static loaderPtr 155_LoaderListPush() 156{ 157 loaderPtr item = calloc(1, sizeof(struct _loader)); 158 159 item->next = listHead; 160 listHead = item; 161 162 return item; 163} 164 165static loaderPtr 166_LoaderListPop(int handle) 167{ 168 loaderPtr item = listHead; 169 loaderPtr *bptr = &listHead; /* pointer to previous node */ 170 171 while (item) { 172 if (item->handle == handle) { 173 *bptr = item->next; /* remove this from the list */ 174 return item; 175 } 176 bptr = &(item->next); 177 item = item->next; 178 } 179 180 return 0; 181} 182 183/* These four are just ABI stubs */ 184_X_EXPORT void 185LoaderRefSymbols(const char *sym0, ...) 186{ 187} 188 189_X_EXPORT void 190LoaderRefSymLists(const char **list0, ...) 191{ 192} 193 194_X_EXPORT void 195LoaderReqSymLists(const char **list0, ...) 196{ 197} 198 199_X_EXPORT void 200LoaderReqSymbols(const char *sym0, ...) 201{ 202} 203 204/* Public Interface to the loader. */ 205 206int 207LoaderOpen(const char *module, const char *cname, int handle, 208 int *errmaj, int *errmin, int *wasLoaded, int flags) 209{ 210 loaderPtr tmp; 211 int new_handle; 212 213#if defined(DEBUG) 214 ErrorF("LoaderOpen(%s)\n", module); 215#endif 216 217 /* 218 * Check to see if the module is already loaded. 219 * Only if we are loading it into an existing namespace. 220 * If it is to be loaded into a new namespace, don't check. 221 * Note: We only have one namespace. 222 */ 223 if (handle >= 0) { 224 tmp = listHead; 225 while (tmp) { 226#ifdef DEBUGLIST 227 ErrorF("strcmp(%x(%s),{%x} %x(%s))\n", module, module, 228 &(tmp->name), tmp->name, tmp->name); 229#endif 230 if (!strcmp(module, tmp->name)) { 231 refCount[tmp->handle]++; 232 if (wasLoaded) 233 *wasLoaded = 1; 234 xf86MsgVerb(X_INFO, 2, "Reloading %s\n", module); 235 return tmp->handle; 236 } 237 tmp = tmp->next; 238 } 239 } 240 241 /* 242 * OK, it's a new one. Add it. 243 */ 244 xf86Msg(X_INFO, "Loading %s\n", module); 245 if (wasLoaded) 246 *wasLoaded = 0; 247 248 /* 249 * Find a free handle. 250 */ 251 new_handle = 1; 252 while (freeHandles[new_handle] && new_handle < MAX_HANDLE) 253 new_handle++; 254 255 if (new_handle == MAX_HANDLE) { 256 xf86Msg(X_ERROR, "Out of loader space\n"); /* XXX */ 257 if (errmaj) 258 *errmaj = LDR_NOSPACE; 259 if (errmin) 260 *errmin = LDR_NOSPACE; 261 return -1; 262 } 263 264 freeHandles[new_handle] = HANDLE_USED; 265 refCount[new_handle] = 1; 266 267 tmp = _LoaderListPush(); 268 tmp->name = malloc(strlen(module) + 1); 269 strcpy(tmp->name, module); 270 tmp->cname = malloc(strlen(cname) + 1); 271 strcpy(tmp->cname, cname); 272 tmp->handle = new_handle; 273 tmp->module = moduleseq++; 274 275 if ((tmp->private = DLLoadModule(tmp, flags)) == NULL) { 276 xf86Msg(X_ERROR, "Failed to load %s\n", module); 277 _LoaderListPop(new_handle); 278 freeHandles[new_handle] = HANDLE_FREE; 279 if (errmaj) 280 *errmaj = LDR_NOLOAD; 281 if (errmin) 282 *errmin = LDR_NOLOAD; 283 return -1; 284 } 285 286 return new_handle; 287} 288 289int 290LoaderHandleOpen(int handle) 291{ 292 if (handle < 0 || handle >= MAX_HANDLE) 293 return -1; 294 295 if (freeHandles[handle] != HANDLE_USED) 296 return -1; 297 298 refCount[handle]++; 299 return handle; 300} 301 302_X_EXPORT void * 303LoaderSymbol(const char *sym) 304{ 305 return (DLFindSymbol(sym)); 306} 307 308/* more stub */ 309_X_EXPORT int 310LoaderCheckUnresolved(int delay_flag) 311{ 312 return 0; 313} 314 315int 316LoaderUnload(int handle) 317{ 318 loaderRec fakeHead; 319 loaderPtr tmp = &fakeHead; 320 321 if (handle < 0 || handle >= MAX_HANDLE) 322 return -1; 323 324 /* 325 * check the reference count, only free it if it goes to zero 326 */ 327 if (--refCount[handle]) 328 return 0; 329 /* 330 * find the loaderRecs associated with this handle. 331 */ 332 333 while ((tmp = _LoaderListPop(handle)) != NULL) { 334 if (strchr(tmp->name, ':') == NULL) { 335 /* It is not a member of an archive */ 336 xf86Msg(X_INFO, "Unloading %s\n", tmp->name); 337 } 338 DLUnloadModule(tmp->private); 339 free(tmp->name); 340 free(tmp->cname); 341 free(tmp); 342 } 343 344 freeHandles[handle] = HANDLE_FREE; 345 346 return 0; 347} 348 349unsigned long LoaderOptions = 0; 350 351void 352LoaderSetOptions(unsigned long opts) 353{ 354 LoaderOptions |= opts; 355} 356 357_X_EXPORT Bool 358LoaderShouldIgnoreABI(void) 359{ 360 return (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) != 0; 361} 362 363_X_EXPORT int 364LoaderGetABIVersion(const char *abiclass) 365{ 366 struct { 367 const char *name; 368 int version; 369 } classes[] = { 370 { ABI_CLASS_ANSIC, LoaderVersionInfo.ansicVersion }, 371 { ABI_CLASS_VIDEODRV, LoaderVersionInfo.videodrvVersion }, 372 { ABI_CLASS_XINPUT, LoaderVersionInfo.xinputVersion }, 373 { ABI_CLASS_EXTENSION, LoaderVersionInfo.extensionVersion }, 374 { ABI_CLASS_FONT, LoaderVersionInfo.fontVersion }, 375 { NULL, 0 } 376 }; 377 int i; 378 379 for(i = 0; classes[i].name; i++) { 380 if(!strcmp(classes[i].name, abiclass)) { 381 return classes[i].version; 382 } 383 } 384 385 return 0; 386} 387