(Retracted by #9155)
[p5sagit/p5-mst-13.2.git] / ext / DynaLoader / dl_aix.xs
CommitLineData
a0d0e21e 1/* dl_aix.xs
2 *
3 * Written: 8/31/94 by Wayne Scott (wscott@ichips.intel.com)
4 *
5 * All I did was take Jens-Uwe Mager's libdl emulation library for
6 * AIX and merged it with the dl_dlopen.xs file to create a dynamic library
7 * package that works for AIX.
8 *
9 * I did change all malloc's, free's, strdup's, calloc's to use the perl
10 * equilvant. I also removed some stuff we will not need. Call fini()
11 * on statup... It can probably be trimmed more.
12 */
13
077440d8 14#define PERLIO_NOT_STDIO 0
15
a0d0e21e 16/*
30def704 17 * On AIX 4.3 and above the emulation layer is not needed any more, and
18 * indeed if perl uses its emulation and perl is linked into apache
19 * which is supposed to use the native dlopen conflicts arise.
20 * Jens-Uwe Mager jum@helios.de
21 */
22#ifdef USE_NATIVE_DLOPEN
23
24#include "EXTERN.h"
25#include "perl.h"
26#include "XSUB.h"
27#include <dlfcn.h>
28
29#else
30
31/*
a0d0e21e 32 * @(#)dlfcn.c 1.5 revision of 93/02/14 20:14:17
33 * This is an unpublished work copyright (c) 1992 Helios Software GmbH
34 * 3000 Hannover 1, Germany
35 */
36#include "EXTERN.h"
37#include "perl.h"
38#include "XSUB.h"
39
19e194ad 40/* When building as a 64-bit binary on AIX, define this to get the
41 * correct structure definitions. Also determines the field-name
42 * macros and gates some logic in readEntries(). -- Steven N. Hirsch
43 * <hirschs@btv.ibm.com> */
44#ifdef USE_64_BIT_ALL
45# define __XCOFF64__
46# define __XCOFF32__
47#endif
48
a0d0e21e 49#include <stdio.h>
50#include <errno.h>
51#include <string.h>
52#include <stdlib.h>
53#include <sys/types.h>
54#include <sys/ldr.h>
55#include <a.out.h>
7ca86468 56#undef FREAD
57#undef FWRITE
a0d0e21e 58#include <ldfcn.h>
59
19e194ad 60#ifdef USE_64_BIT_ALL
61# define AIX_SCNHDR SCNHDR_64
62# define AIX_LDHDR LDHDR_64
63# define AIX_LDSYM LDSYM_64
64# define AIX_LDHDRSZ LDHDRSZ_64
65#else
66# define AIX_SCNHDR SCNHDR
67# define AIX_LDHDR LDHDR
68# define AIX_LDSYM LDSYM
69# define AIX_LDHDRSZ LDHDRSZ
70#endif
71
4e774c84 72/* When using Perl extensions written in C++ the longer versions
73 * of load() and unload() from libC and libC_r need to be used,
74 * otherwise statics in the extensions won't get initialized right.
75 * -- Stephanie Beals <bealzy@us.ibm.com> */
bab3591f 76
77/* Older AIX C compilers cannot deal with C++ double-slash comments in
78 the ibmcxx and/or xlC includes. Since we only need a single file,
79 be more fine-grained about what's included <hirschs@btv.ibm.com> */
c88be79f 80#ifdef USE_libC /* The define comes, when it comes, from hints/aix.pl. */
81# define LOAD loadAndInit
4e774c84 82# define UNLOAD terminateAndUnload
bab3591f 83# if defined(USE_xlC_load_h)
84# include "/usr/lpp/xlC/include/load.h"
85# elif defined(USE_ibmcxx_load_h)
86# include "/usr/ibmcxx/include/load.h"
c88be79f 87# endif
4e774c84 88#else
89# define LOAD load
90# define UNLOAD unload
91#endif
92
ee580363 93/*
94 * AIX 4.3 does remove some useful definitions from ldfcn.h. Define
95 * these here to compensate for that lossage.
96 */
97#ifndef BEGINNING
98# define BEGINNING SEEK_SET
99#endif
100#ifndef FSEEK
101# define FSEEK(ldptr,o,p) fseek(IOPTR(ldptr),(p==BEGINNING)?(OFFSET(ldptr) +o):o,p)
102#endif
103#ifndef FREAD
104# define FREAD(p,s,n,ldptr) fread(p,s,n,IOPTR(ldptr))
105#endif
106
30def704 107#ifndef RTLD_LAZY
108# define RTLD_LAZY 0
109#endif
110#ifndef RTLD_GLOBAL
111# define RTLD_GLOBAL 0
112#endif
113
a0d0e21e 114/*
115 * We simulate dlopen() et al. through a call to load. Because AIX has
116 * no call to find an exported symbol we read the loader section of the
117 * loaded module and build a list of exported symbols and their virtual
118 * address.
119 */
120
121typedef struct {
122 char *name; /* the symbols's name */
123 void *addr; /* its relocated virtual address */
124} Export, *ExportPtr;
125
126/*
127 * The void * handle returned from dlopen is actually a ModulePtr.
128 */
129typedef struct Module {
130 struct Module *next;
131 char *name; /* module name for refcounting */
132 int refCnt; /* the number of references */
133 void *entry; /* entry point from load */
134 int nExports; /* the number of exports found */
135 ExportPtr exports; /* the array of exports */
136} Module, *ModulePtr;
137
138/*
7ca86468 139 * We keep a list of all loaded modules to be able to reference count
140 * duplicate dlopen's.
a0d0e21e 141 */
549a6b10 142static ModulePtr modList; /* XXX threaded */
a0d0e21e 143
144/*
145 * The last error from one of the dl* routines is kept in static
146 * variables here. Each error is returned only once to the caller.
147 */
549a6b10 148static char errbuf[BUFSIZ]; /* XXX threaded */
149static int errvalid; /* XXX threaded */
a0d0e21e 150
151static void caterr(char *);
152static int readExports(ModulePtr);
7ca86468 153static void *findMain(void);
a0d0e21e 154
ce637636 155static char *strerror_failed = "(strerror failed)";
156static char *strerror_r_failed = "(strerror_r failed)";
157
fd206186 158char *strerrorcat(char *str, int err) {
ce637636 159 int strsiz = strlen(str);
160 int msgsiz;
161 char *msg;
162
163#ifdef USE_THREADS
164 char *buf = malloc(BUFSIZ);
165
166 if (buf == 0)
167 return 0;
549a6b10 168 if (strerror_r(err, buf, BUFSIZ) == 0)
ce637636 169 msg = buf;
170 else
171 msg = strerror_r_failed;
172 msgsiz = strlen(msg);
173 if (strsiz + msgsiz < BUFSIZ)
174 strcat(str, msg);
175 free(buf);
176#else
177 if ((msg = strerror(err)) == 0)
178 msg = strerror_failed;
179 msgsiz = strlen(msg); /* Note msg = buf and free() above. */
180 if (strsiz + msgsiz < BUFSIZ) /* Do not move this after #endif. */
181 strcat(str, msg);
182#endif
183
fd206186 184 return str;
185}
ce637636 186
fd206186 187char *strerrorcpy(char *str, int err) {
ce637636 188 int msgsiz;
189 char *msg;
190
191#ifdef USE_THREADS
192 char *buf = malloc(BUFSIZ);
193
194 if (buf == 0)
195 return 0;
549a6b10 196 if (strerror_r(err, buf, BUFSIZ) == 0)
ce637636 197 msg = buf;
198 else
199 msg = strerror_r_failed;
200 msgsiz = strlen(msg);
201 if (msgsiz < BUFSIZ)
202 strcpy(str, msg);
203 free(buf);
204#else
205 if ((msg = strerror(err)) == 0)
206 msg = strerror_failed;
207 msgsiz = strlen(msg); /* Note msg = buf and free() above. */
208 if (msgsiz < BUFSIZ) /* Do not move this after #endif. */
209 strcpy(str, msg);
210#endif
211
fd206186 212 return str;
213}
a0d0e21e 214
215/* ARGSUSED */
216void *dlopen(char *path, int mode)
217{
5b877257 218 dTHX;
a0d0e21e 219 register ModulePtr mp;
7ca86468 220 static void *mainModule; /* XXX threaded */
a0d0e21e 221
222 /*
223 * Upon the first call register a terminate handler that will
f6b3007c 224 * close all libraries.
a0d0e21e 225 */
7ca86468 226 if (mainModule == NULL) {
227 if ((mainModule = findMain()) == NULL)
228 return NULL;
a0d0e21e 229 }
230 /*
231 * Scan the list of modules if have the module already loaded.
232 */
233 for (mp = modList; mp; mp = mp->next)
234 if (strcmp(mp->name, path) == 0) {
235 mp->refCnt++;
236 return mp;
237 }
238 Newz(1000,mp,1,Module);
239 if (mp == NULL) {
240 errvalid++;
241 strcpy(errbuf, "Newz: ");
fd206186 242 strerrorcat(errbuf, errno);
a0d0e21e 243 return NULL;
244 }
245
246 if ((mp->name = savepv(path)) == NULL) {
247 errvalid++;
248 strcpy(errbuf, "savepv: ");
fd206186 249 strerrorcat(errbuf, errno);
a0d0e21e 250 safefree(mp);
251 return NULL;
252 }
549a6b10 253
a0d0e21e 254 /*
255 * load should be declared load(const char *...). Thus we
256 * cast the path to a normal char *. Ugly.
257 */
4e774c84 258 if ((mp->entry = (void *)LOAD((char *)path,
549a6b10 259#ifdef L_LIBPATH_EXEC
260 L_LIBPATH_EXEC |
261#endif
262 L_NOAUTODEFER,
263 NULL)) == NULL) {
264 int saverrno = errno;
265
a0d0e21e 266 safefree(mp->name);
267 safefree(mp);
268 errvalid++;
269 strcpy(errbuf, "dlopen: ");
270 strcat(errbuf, path);
271 strcat(errbuf, ": ");
272 /*
273 * If AIX says the file is not executable, the error
274 * can be further described by querying the loader about
275 * the last error.
276 */
549a6b10 277 if (saverrno == ENOEXEC) {
278 char *moreinfo[BUFSIZ/sizeof(char *)];
279 if (loadquery(L_GETMESSAGES, moreinfo, sizeof(moreinfo)) == -1)
280 strerrorcpy(errbuf, saverrno);
a0d0e21e 281 else {
282 char **p;
549a6b10 283 for (p = moreinfo; *p; p++)
a0d0e21e 284 caterr(*p);
285 }
286 } else
549a6b10 287 strerrorcat(errbuf, saverrno);
a0d0e21e 288 return NULL;
289 }
290 mp->refCnt = 1;
291 mp->next = modList;
292 modList = mp;
f6b3007c 293 /*
294 * Assume anonymous exports come from the module this dlopen
295 * is linked into, that holds true as long as dlopen and all
7ca86468 296 * of the perl core are in the same shared object. Also bind
297 * against the main part, in the case a perl is not the main
298 * part, e.g mod_perl as DSO in Apache so perl modules can
299 * also reference Apache symbols.
f6b3007c 300 */
7ca86468 301 if (loadbind(0, (void *)dlopen, mp->entry) == -1 ||
302 loadbind(0, mainModule, mp->entry)) {
549a6b10 303 int saverrno = errno;
304
a0d0e21e 305 dlclose(mp);
306 errvalid++;
307 strcpy(errbuf, "loadbind: ");
549a6b10 308 strerrorcat(errbuf, saverrno);
a0d0e21e 309 return NULL;
310 }
311 if (readExports(mp) == -1) {
312 dlclose(mp);
313 return NULL;
314 }
315 return mp;
316}
317
318/*
319 * Attempt to decipher an AIX loader error message and append it
320 * to our static error message buffer.
321 */
322static void caterr(char *s)
323{
324 register char *p = s;
325
326 while (*p >= '0' && *p <= '9')
327 p++;
328 switch(atoi(s)) {
329 case L_ERROR_TOOMANY:
42eb1a87 330 strcat(errbuf, "too many errors");
a0d0e21e 331 break;
332 case L_ERROR_NOLIB:
333 strcat(errbuf, "can't load library");
334 strcat(errbuf, p);
335 break;
336 case L_ERROR_UNDEF:
337 strcat(errbuf, "can't find symbol");
338 strcat(errbuf, p);
339 break;
340 case L_ERROR_RLDBAD:
341 strcat(errbuf, "bad RLD");
342 strcat(errbuf, p);
343 break;
344 case L_ERROR_FORMAT:
345 strcat(errbuf, "bad exec format in");
346 strcat(errbuf, p);
347 break;
348 case L_ERROR_ERRNO:
fd206186 349 strerrorcat(errbuf, atoi(++p));
a0d0e21e 350 break;
351 default:
352 strcat(errbuf, s);
353 break;
354 }
355}
356
357void *dlsym(void *handle, const char *symbol)
358{
359 register ModulePtr mp = (ModulePtr)handle;
360 register ExportPtr ep;
361 register int i;
362
363 /*
364 * Could speed up search, but I assume that one assigns
365 * the result to function pointers anyways.
366 */
367 for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
368 if (strcmp(ep->name, symbol) == 0)
369 return ep->addr;
370 errvalid++;
371 strcpy(errbuf, "dlsym: undefined symbol ");
372 strcat(errbuf, symbol);
373 return NULL;
374}
375
376char *dlerror(void)
377{
378 if (errvalid) {
379 errvalid = 0;
380 return errbuf;
381 }
382 return NULL;
383}
384
385int dlclose(void *handle)
386{
387 register ModulePtr mp = (ModulePtr)handle;
388 int result;
389 register ModulePtr mp1;
390
391 if (--mp->refCnt > 0)
392 return 0;
4e774c84 393 result = UNLOAD(mp->entry);
a0d0e21e 394 if (result == -1) {
395 errvalid++;
fd206186 396 strerrorcpy(errbuf, errno);
a0d0e21e 397 }
398 if (mp->exports) {
399 register ExportPtr ep;
400 register int i;
401 for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
402 if (ep->name)
403 safefree(ep->name);
404 safefree(mp->exports);
405 }
406 if (mp == modList)
407 modList = mp->next;
408 else {
409 for (mp1 = modList; mp1; mp1 = mp1->next)
410 if (mp1->next == mp) {
411 mp1->next = mp->next;
412 break;
413 }
414 }
415 safefree(mp->name);
416 safefree(mp);
417 return result;
418}
419
a0d0e21e 420/* Added by Wayne Scott
421 * This is needed because the ldopen system call calls
422 * calloc to allocated a block of date. The ldclose call calls free.
423 * Without this we get this system calloc and perl's free, resulting
424 * in a "Bad free" message. This way we always use perl's malloc.
425 */
426void *calloc(size_t ne, size_t sz)
427{
428 void *out;
429
430 out = (void *) safemalloc(ne*sz);
431 memzero(out, ne*sz);
432 return(out);
433}
434
435/*
436 * Build the export table from the XCOFF .loader section.
437 */
438static int readExports(ModulePtr mp)
439{
5b877257 440 dTHX;
a0d0e21e 441 LDFILE *ldp = NULL;
19e194ad 442 AIX_SCNHDR sh;
443 AIX_LDHDR *lhp;
a0d0e21e 444 char *ldbuf;
19e194ad 445 AIX_LDSYM *ls;
a0d0e21e 446 int i;
447 ExportPtr ep;
448
449 if ((ldp = ldopen(mp->name, ldp)) == NULL) {
450 struct ld_info *lp;
451 char *buf;
452 int size = 4*1024;
453 if (errno != ENOENT) {
454 errvalid++;
455 strcpy(errbuf, "readExports: ");
fd206186 456 strerrorcat(errbuf, errno);
a0d0e21e 457 return -1;
458 }
459 /*
460 * The module might be loaded due to the LIBPATH
461 * environment variable. Search for the loaded
462 * module using L_GETINFO.
463 */
464 if ((buf = safemalloc(size)) == NULL) {
465 errvalid++;
466 strcpy(errbuf, "readExports: ");
fd206186 467 strerrorcat(errbuf, errno);
a0d0e21e 468 return -1;
469 }
470 while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
471 safefree(buf);
472 size += 4*1024;
473 if ((buf = safemalloc(size)) == NULL) {
474 errvalid++;
475 strcpy(errbuf, "readExports: ");
fd206186 476 strerrorcat(errbuf, errno);
a0d0e21e 477 return -1;
478 }
479 }
480 if (i == -1) {
481 errvalid++;
482 strcpy(errbuf, "readExports: ");
fd206186 483 strerrorcat(errbuf, errno);
a0d0e21e 484 safefree(buf);
485 return -1;
486 }
487 /*
488 * Traverse the list of loaded modules. The entry point
4e774c84 489 * returned by LOAD() does actually point to the data
a0d0e21e 490 * segment origin.
491 */
492 lp = (struct ld_info *)buf;
493 while (lp) {
494 if (lp->ldinfo_dataorg == mp->entry) {
495 ldp = ldopen(lp->ldinfo_filename, ldp);
496 break;
497 }
498 if (lp->ldinfo_next == 0)
499 lp = NULL;
500 else
501 lp = (struct ld_info *)((char *)lp + lp->ldinfo_next);
502 }
503 safefree(buf);
504 if (!ldp) {
505 errvalid++;
506 strcpy(errbuf, "readExports: ");
fd206186 507 strerrorcat(errbuf, errno);
a0d0e21e 508 return -1;
509 }
510 }
19e194ad 511#ifdef USE_64_BIT_ALL
512 if (TYPE(ldp) != U803XTOCMAGIC) {
513#else
a0d0e21e 514 if (TYPE(ldp) != U802TOCMAGIC) {
19e194ad 515#endif
a0d0e21e 516 errvalid++;
517 strcpy(errbuf, "readExports: bad magic");
518 while(ldclose(ldp) == FAILURE)
519 ;
520 return -1;
521 }
522 if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) {
523 errvalid++;
524 strcpy(errbuf, "readExports: cannot read loader section header");
525 while(ldclose(ldp) == FAILURE)
526 ;
527 return -1;
528 }
529 /*
530 * We read the complete loader section in one chunk, this makes
531 * finding long symbol names residing in the string table easier.
532 */
533 if ((ldbuf = (char *)safemalloc(sh.s_size)) == NULL) {
534 errvalid++;
535 strcpy(errbuf, "readExports: ");
fd206186 536 strerrorcat(errbuf, errno);
a0d0e21e 537 while(ldclose(ldp) == FAILURE)
538 ;
539 return -1;
540 }
541 if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) {
542 errvalid++;
543 strcpy(errbuf, "readExports: cannot seek to loader section");
544 safefree(ldbuf);
545 while(ldclose(ldp) == FAILURE)
546 ;
547 return -1;
548 }
1553ab04 549/* This first case is a hack, since it assumes that the 3rd parameter to
550 FREAD is 1. See the redefinition of FREAD above to see how this works. */
a0d0e21e 551 if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) {
552 errvalid++;
553 strcpy(errbuf, "readExports: cannot read loader section");
554 safefree(ldbuf);
555 while(ldclose(ldp) == FAILURE)
556 ;
557 return -1;
558 }
19e194ad 559 lhp = (AIX_LDHDR *)ldbuf;
560 ls = (AIX_LDSYM *)(ldbuf+AIX_LDHDRSZ);
a0d0e21e 561 /*
562 * Count the number of exports to include in our export table.
563 */
564 for (i = lhp->l_nsyms; i; i--, ls++) {
565 if (!LDR_EXPORT(*ls))
566 continue;
567 mp->nExports++;
568 }
569 Newz(1001, mp->exports, mp->nExports, Export);
570 if (mp->exports == NULL) {
571 errvalid++;
572 strcpy(errbuf, "readExports: ");
fd206186 573 strerrorcat(errbuf, errno);
a0d0e21e 574 safefree(ldbuf);
575 while(ldclose(ldp) == FAILURE)
576 ;
577 return -1;
578 }
579 /*
580 * Fill in the export table. All entries are relative to
581 * the entry point we got from load.
582 */
583 ep = mp->exports;
19e194ad 584 ls = (AIX_LDSYM *)(ldbuf+AIX_LDHDRSZ);
a0d0e21e 585 for (i = lhp->l_nsyms; i; i--, ls++) {
586 char *symname;
587 if (!LDR_EXPORT(*ls))
588 continue;
19e194ad 589#ifndef USE_64_BIT_ALL
a0d0e21e 590 if (ls->l_zeroes == 0)
19e194ad 591#endif
a0d0e21e 592 symname = ls->l_offset+lhp->l_stoff+ldbuf;
19e194ad 593#ifndef USE_64_BIT_ALL
a0d0e21e 594 else
595 symname = ls->l_name;
19e194ad 596#endif
a0d0e21e 597 ep->name = savepv(symname);
598 ep->addr = (void *)((unsigned long)mp->entry + ls->l_value);
599 ep++;
600 }
601 safefree(ldbuf);
602 while(ldclose(ldp) == FAILURE)
603 ;
604 return 0;
605}
606
7ca86468 607/*
608 * Find the main modules entry point. This is used as export pointer
609 * for loadbind() to be able to resolve references to the main part.
610 */
611static void * findMain(void)
612{
613 struct ld_info *lp;
614 char *buf;
615 int size = 4*1024;
616 int i;
617 void *ret;
618
619 if ((buf = safemalloc(size)) == NULL) {
620 errvalid++;
621 strcpy(errbuf, "findMain: ");
622 strerrorcat(errbuf, errno);
623 return NULL;
624 }
625 while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
626 safefree(buf);
627 size += 4*1024;
628 if ((buf = safemalloc(size)) == NULL) {
629 errvalid++;
630 strcpy(errbuf, "findMain: ");
631 strerrorcat(errbuf, errno);
632 return NULL;
633 }
634 }
635 if (i == -1) {
636 errvalid++;
637 strcpy(errbuf, "findMain: ");
638 strerrorcat(errbuf, errno);
639 safefree(buf);
640 return NULL;
641 }
642 /*
643 * The first entry is the main module. The entry point
644 * returned by load() does actually point to the data
645 * segment origin.
646 */
647 lp = (struct ld_info *)buf;
648 ret = lp->ldinfo_dataorg;
649 safefree(buf);
650 return ret;
651}
30def704 652#endif /* USE_NATIVE_DLOPEN */
7ca86468 653
a0d0e21e 654/* dl_dlopen.xs
655 *
656 * Platform: SunOS/Solaris, possibly others which use dlopen.
0536e0eb 657 * Author: Paul Marquess (Paul.Marquess@btinternet.com)
a0d0e21e 658 * Created: 10th July 1994
659 *
660 * Modified:
661 * 15th July 1994 - Added code to explicitly save any error messages.
662 * 3rd August 1994 - Upgraded to v3 spec.
663 * 9th August 1994 - Changed to use IV
664 * 10th August 1994 - Tim Bunce: Added RTLD_LAZY, switchable debugging,
665 * basic FreeBSD support, removed ClearError
666 *
667 */
668
669/* Porting notes:
670
671 see dl_dlopen.xs
672
673*/
674
675#include "dlutils.c" /* SaveError() etc */
676
677
678static void
cea2e8a9 679dl_private_init(pTHX)
a0d0e21e 680{
cea2e8a9 681 (void)dl_generic_private_init(aTHX);
a0d0e21e 682}
683
684MODULE = DynaLoader PACKAGE = DynaLoader
685
686BOOT:
cea2e8a9 687 (void)dl_private_init(aTHX);
a0d0e21e 688
689
690void *
ff7f3c60 691dl_load_file(filename, flags=0)
692 char * filename
693 int flags
a0d0e21e 694 CODE:
bf49b057 695 DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_load_file(%s,%x):\n", filename,flags));
ff7f3c60 696 if (flags & 0x01)
cea2e8a9 697 Perl_warn(aTHX_ "Can't make loaded symbols global on this platform while loading %s",filename);
30def704 698 RETVAL = dlopen(filename, RTLD_GLOBAL|RTLD_LAZY) ;
bf49b057 699 DLDEBUG(2,PerlIO_printf(Perl_debug_log, " libref=%x\n", RETVAL));
a0d0e21e 700 ST(0) = sv_newmortal() ;
701 if (RETVAL == NULL)
cea2e8a9 702 SaveError(aTHX_ "%s",dlerror()) ;
a0d0e21e 703 else
3175b8cd 704 sv_setiv( ST(0), PTR2IV(RETVAL) );
a0d0e21e 705
7ca86468 706int
707dl_unload_file(libref)
708 void * libref
709 CODE:
710 DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_unload_file(%lx):\n", libref));
711 RETVAL = (dlclose(libref) == 0 ? 1 : 0);
712 if (!RETVAL)
713 SaveError(aTHX_ "%s", dlerror()) ;
714 DLDEBUG(2,PerlIO_printf(Perl_debug_log, " retval = %d\n", RETVAL));
715 OUTPUT:
716 RETVAL
a0d0e21e 717
718void *
719dl_find_symbol(libhandle, symbolname)
720 void * libhandle
721 char * symbolname
722 CODE:
bf49b057 723 DLDEBUG(2,PerlIO_printf(Perl_debug_log, "dl_find_symbol(handle=%x, symbol=%s)\n",
a0d0e21e 724 libhandle, symbolname));
725 RETVAL = dlsym(libhandle, symbolname);
bf49b057 726 DLDEBUG(2,PerlIO_printf(Perl_debug_log, " symbolref = %x\n", RETVAL));
a0d0e21e 727 ST(0) = sv_newmortal() ;
728 if (RETVAL == NULL)
cea2e8a9 729 SaveError(aTHX_ "%s",dlerror()) ;
a0d0e21e 730 else
f66f545a 731 sv_setiv( ST(0), PTR2IV(RETVAL));
a0d0e21e 732
733
734void
735dl_undef_symbols()
736 PPCODE:
737
738
739
740# These functions should not need changing on any platform:
741
742void
743dl_install_xsub(perl_name, symref, filename="$Package")
744 char * perl_name
745 void * symref
746 char * filename
747 CODE:
bf49b057 748 DLDEBUG(2,PerlIO_printf(Perl_debug_log, "dl_install_xsub(name=%s, symref=%x)\n",
a0d0e21e 749 perl_name, symref));
cea2e8a9 750 ST(0) = sv_2mortal(newRV((SV*)newXS(perl_name,
751 (void(*)(pTHX_ CV *))symref,
752 filename)));
a0d0e21e 753
754
755char *
756dl_error()
757 CODE:
758 RETVAL = LastError ;
759 OUTPUT:
760 RETVAL
761
762# end.