1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1997-2011 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * * 19 ***********************************************************************/ 20 #pragma prototyped 21 /* 22 * provide dlopen/dlsym/dlerror interface 23 * 24 * David Korn 25 * Glenn Fowler 26 * AT&T Research 27 */ 28 29 #include <ast.h> 30 #include <dlldefs.h> 31 #include <error.h> 32 33 #define T(x) ERROR_dictionary(x) 34 35 #if _BLD_dll && defined(__EXPORT__) 36 #define extern __EXPORT__ 37 #endif 38 39 #if _hdr_dlfcn && _lib_dlopen 40 41 /* 42 * standard 43 */ 44 45 # include <dlfcn.h> 46 47 #else 48 #if _hdr_dl 49 50 /* 51 * HP-UX 52 */ 53 54 # include <dl.h> 55 # ifndef BIND_FIRST 56 # define BIND_FIRST 0x4 57 # endif 58 # ifndef BIND_NOSTART 59 # define BIND_NOSTART 0x10 60 # endif 61 62 static shl_t all; 63 static int err; 64 dlopen(const char * path,int mode)65 extern void* dlopen(const char* path, int mode) 66 { 67 void* dll; 68 69 if (!path) 70 return (void*)&all; 71 if (mode) 72 mode = (BIND_IMMEDIATE|BIND_FIRST|BIND_NOSTART); 73 if (!(dll = (void*)shl_load(path, mode, 0L))) 74 err = errno; 75 return dll; 76 } 77 dlclose(void * dll)78 extern int dlclose(void* dll) 79 { 80 return 0; 81 } 82 dlsym(void * dll,const char * name)83 extern void* dlsym(void* dll, const char* name) 84 { 85 shl_t handle; 86 long addr; 87 88 handle = dll == (void*)&all ? (shl_t)0 : (shl_t)dll; 89 if (shl_findsym(&handle, name, TYPE_UNDEFINED, &addr)) 90 { 91 err = errno; 92 return 0; 93 } 94 return (void*)addr; 95 } 96 dlerror(void)97 extern char* dlerror(void) 98 { 99 char* msg; 100 101 if (!err) 102 return 0; 103 msg = fmterror(err); 104 err = 0; 105 return msg; 106 } 107 108 #else 109 #if _sys_ldr && _lib_loadbind 110 111 /* 112 * rs6000 113 */ 114 115 # include <sys/ldr.h> 116 # include <xcoff.h> 117 118 /* xcoff module header */ 119 struct hdr 120 { 121 struct filehdr f; 122 struct aouthdr a; 123 struct scnhdr s[1]; 124 }; 125 126 static struct ld_info* ld_info; 127 static unsigned int ld_info_size = 1024; 128 static void* last_module; 129 static int err; 130 dlopen(const char * path,int mode)131 extern void* dlopen(const char* path, int mode) 132 { 133 void* dll; 134 135 if (!(dll = (void*)load((char*)path, mode, getenv("LIBPATH")))) 136 err = errno; 137 return dll; 138 } 139 dlclose(void * dll)140 extern int dlclose(void* dll) 141 { 142 return 0; 143 } 144 getquery(void)145 static int getquery(void) 146 { 147 if (!ld_info) 148 ld_info = malloc(ld_info_size); 149 for (;;) 150 { 151 if (!ld_info) 152 return 1; 153 if (!loadquery(L_GETINFO, ld_info, ld_info_size)) 154 return 0; 155 if (errno != ENOMEM) 156 return 1; 157 ld_info = realloc(ld_info, ld_info_size *= 2); 158 } 159 } 160 161 /* find the loaded module whose data area contains the 162 * address passed in. Remember that procedure pointers 163 * are implemented as pointers to descriptors in the 164 * data area of the module defining the procedure 165 */ getinfo(void * module)166 static struct ld_info* getinfo(void* module) 167 { 168 struct ld_info* info = ld_info; 169 register int n = 1; 170 171 if (!ld_info || module != last_module) 172 { 173 last_module = module; 174 if (getquery()) 175 return 0; 176 info = ld_info; 177 } 178 while (n) 179 { 180 if ((char*)(info->ldinfo_dataorg) <= (char*)module && 181 (char*)module <= ((char*)(info->ldinfo_dataorg) 182 + (unsigned)(info->ldinfo_datasize))) 183 return info; 184 if (n=info->ldinfo_next) 185 info = (void*)((char*)info + n); 186 } 187 return 0; 188 } 189 getloc(struct hdr * hdr,char * data,char * name)190 static char* getloc(struct hdr* hdr, char* data, char* name) 191 { 192 struct ldhdr* ldhdr; 193 struct ldsym* ldsym; 194 ulong datareloc; 195 ulong textreloc; 196 int i; 197 198 /* data is relocated by the difference between 199 * its virtual origin and where it was 200 * actually placed 201 */ 202 /*N.B. o_sndata etc. are one based */ 203 datareloc = (ulong)data - hdr->s[hdr->a.o_sndata-1].s_vaddr; 204 /*hdr is address of header, not text, so add text s_scnptr */ 205 textreloc = (ulong)hdr + hdr->s[hdr->a.o_sntext-1].s_scnptr 206 - hdr->s[hdr->a.o_sntext-1].s_vaddr; 207 ldhdr = (void*)((char*)hdr+ hdr->s[hdr->a.o_snloader-1].s_scnptr); 208 ldsym = (void*) (ldhdr+1); 209 /* search the exports symbols */ 210 for(i=0; i < ldhdr->l_nsyms;ldsym++,i++) 211 { 212 char *symname,symbuf[9]; 213 char *loc; 214 /* the symbol name representation is a nuisance since 215 * 8 character names appear in l_name but may 216 * not be null terminated. This code works around 217 * that by brute force 218 */ 219 if (ldsym->l_zeroes) 220 { 221 symname = symbuf; 222 memcpy(symbuf,ldsym->l_name,8); 223 symbuf[8] = 0; 224 } 225 else 226 symname = (void*)(ldsym->l_offset + (ulong)ldhdr + ldhdr->l_stoff); 227 if (strcmp(symname,name)) 228 continue; 229 loc = (char*)ldsym->l_value; 230 if ((ldsym->l_scnum==hdr->a.o_sndata) || 231 (ldsym->l_scnum==hdr->a.o_snbss)) 232 loc += datareloc; 233 else if (ldsym->l_scnum==hdr->a.o_sntext) 234 loc += textreloc; 235 return loc; 236 } 237 return 0; 238 } 239 dlsym(void * handle,const char * name)240 extern void* dlsym(void* handle, const char* name) 241 { 242 void* addr; 243 struct ld_info* info; 244 245 if (!(info = getinfo(handle)) || !(addr = getloc(info->ldinfo_textorg,info->ldinfo_dataorg,(char*)name))) 246 { 247 err = errno; 248 return 0; 249 } 250 return addr; 251 } 252 dlerror(void)253 extern char* dlerror(void) 254 { 255 char* msg; 256 257 if (!err) 258 return 0; 259 msg = fmterror(err); 260 err = 0; 261 return msg; 262 } 263 264 #else 265 #if _hdr_dll && _lib_dllload 266 267 /* 268 * MVS 269 */ 270 271 # include <dll.h> 272 273 static int err; 274 dlopen(const char * path,int mode)275 extern void* dlopen(const char* path, int mode) 276 { 277 void* dll; 278 279 NoP(mode); 280 if (!(dll = (void*)dllload(path))) 281 err = errno; 282 return dll; 283 } 284 dlclose(void * dll)285 extern int dlclose(void* dll) 286 { 287 return 0; 288 } 289 dlsym(void * handle,const char * name)290 extern void* dlsym(void* handle, const char* name) 291 { 292 void* addr; 293 294 if (!(addr = (void*)dllqueryfn(handle, (char*)name))) 295 err = errno; 296 return addr; 297 } 298 dlerror(void)299 extern char* dlerror(void) 300 { 301 char* msg; 302 303 if (!err) 304 return 0; 305 msg = fmterror(err); 306 err = 0; 307 return msg; 308 } 309 310 #else 311 #if _hdr_mach_o_dyld 312 313 /* 314 * mac[h] 315 */ 316 317 # include <mach-o/dyld.h> 318 319 typedef const struct mach_header* NSImage; 320 321 typedef struct Dll_s 322 { 323 unsigned long magic; 324 NSImage image; 325 NSModule module; 326 char path[1]; 327 } Dll_t; 328 329 #define DL_MAGIC 0x04190c04 330 #define DL_NEXT ((Dll_t*)RTLD_NEXT) 331 332 static const char* dlmessage = "no error"; 333 334 static const char e_cover[] = T("cannot access covered library"); 335 static const char e_handle[] = T("invalid handle"); 336 static const char e_space[] = T("out of space"); 337 static const char e_static[] = T("image statically linked"); 338 static const char e_undefined[] = T("undefined symbol"); 339 340 static Dll_t global = { DL_MAGIC }; 341 undefined(const char * name)342 static void undefined(const char* name) 343 { 344 } 345 multiple(NSSymbol sym,NSModule om,NSModule nm)346 static NSModule multiple(NSSymbol sym, NSModule om, NSModule nm) 347 { 348 return om; 349 } 350 linkedit(NSLinkEditErrors c,int n,const char * f,const char * m)351 static void linkedit(NSLinkEditErrors c, int n, const char* f, const char* m) 352 { 353 dlmessage = m; 354 } 355 356 static NSLinkEditErrorHandlers handlers = 357 { 358 undefined, multiple, linkedit 359 }; 360 dlopen(const char * path,int mode)361 extern void* dlopen(const char* path, int mode) 362 { 363 Dll_t* dll; 364 int i; 365 NSObjectFileImage image; 366 367 static int init = 0; 368 369 if (!_dyld_present()) 370 { 371 dlmessage = e_static; 372 return 0; 373 } 374 if (!init) 375 { 376 init = 1; 377 NSInstallLinkEditErrorHandlers(&handlers); 378 } 379 if (!path) 380 dll = &global; 381 else if (!(dll = newof(0, Dll_t, 1, strlen(path)))) 382 { 383 dlmessage = e_space; 384 return 0; 385 } 386 else 387 { 388 switch (NSCreateObjectFileImageFromFile(path, &image)) 389 { 390 case NSObjectFileImageSuccess: 391 dll->module = NSLinkModule(image, path, (mode & RTLD_LAZY) ? 0 : NSLINKMODULE_OPTION_BINDNOW); 392 NSDestroyObjectFileImage(image); 393 if (!dll->module) 394 { 395 free(dll); 396 return 0; 397 } 398 break; 399 case NSObjectFileImageInappropriateFile: 400 dll->image = NSAddImage(path, 0); 401 if (!dll->image) 402 { 403 free(dll); 404 return 0; 405 } 406 break; 407 default: 408 free(dll); 409 return 0; 410 } 411 strcpy(dll->path, path); 412 dll->magic = DL_MAGIC; 413 } 414 return (void*)dll; 415 } 416 dlclose(void * handle)417 extern int dlclose(void* handle) 418 { 419 Dll_t* dll = (Dll_t*)handle; 420 421 if (!dll || dll == DL_NEXT || dll->magic != DL_MAGIC) 422 { 423 dlmessage = e_handle; 424 return -1; 425 } 426 if (dll->module) 427 NSUnLinkModule(dll->module, 0); 428 free(dll); 429 return 0; 430 } 431 432 static NSSymbol lookup(Dll_t * dll,const char * name)433 lookup(Dll_t* dll, const char* name) 434 { 435 unsigned long pun; 436 void* address; 437 438 if (dll == DL_NEXT) 439 { 440 if (!_dyld_func_lookup(name, &pun)) 441 return 0; 442 address = (NSSymbol)pun; 443 } 444 else if (dll->module) 445 address = NSLookupSymbolInModule(dll->module, name); 446 else if (dll->image) 447 { 448 if (!NSIsSymbolNameDefinedInImage(dll->image, name)) 449 return 0; 450 address = NSLookupSymbolInImage(dll->image, name, 0); 451 } 452 else 453 { 454 if (!NSIsSymbolNameDefined(name)) 455 return 0; 456 address = NSLookupAndBindSymbol(name); 457 } 458 if (address) 459 address = NSAddressOfSymbol(address); 460 return address; 461 } 462 dlsym(void * handle,const char * name)463 extern void* dlsym(void* handle, const char* name) 464 { 465 Dll_t* dll = (Dll_t*)handle; 466 NSSymbol address; 467 char buf[1024]; 468 469 if (!dll || dll != DL_NEXT && (dll->magic != DL_MAGIC || !dll->image && !dll->module)) 470 { 471 dlmessage = e_handle; 472 return 0; 473 } 474 if (!(address = lookup(dll, name)) && name[0] != '_' && strlen(name) < (sizeof(buf) - 1)) 475 { 476 buf[0] = '_'; 477 strcpy(buf + 1, name); 478 address = lookup(dll, buf); 479 } 480 if (!address) 481 { 482 dlmessage = dll == DL_NEXT ? e_cover : e_undefined; 483 return 0; 484 } 485 return (void*)address; 486 } 487 dlerror(void)488 extern char* dlerror(void) 489 { 490 char* msg; 491 492 msg = (char*)dlmessage; 493 dlmessage = 0; 494 return msg; 495 } 496 497 #else 498 /* 499 * punt 500 */ 501 502 static int err; 503 dlopen(const char * path,int mode)504 extern void* dlopen(const char* path, int mode) 505 { 506 err = 1; 507 return 0; 508 } 509 dlclose(void * dll)510 extern int dlclose(void* dll) 511 { 512 err = 1; 513 return 0; 514 } 515 dlsym(void * handle,const char * name)516 extern void* dlsym(void* handle, const char* name) 517 { 518 err = 1; 519 return 0; 520 } 521 dlerror(void)522 extern char* dlerror(void) 523 { 524 if (!err) 525 return 0; 526 err = 0; 527 return "dynamic linking not supported"; 528 } 529 530 #endif 531 #endif 532 #endif 533 #endif 534 #endif 535