X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/5bc28da93666e223bb56098f72517273bc8bcbf9..77004dee2553ce034a8a58b2b2849e3656df46c3:/ext/DynaLoader/dl_aix.xs diff --git a/ext/DynaLoader/dl_aix.xs b/ext/DynaLoader/dl_aix.xs index 96bce4e..8529097 100644 --- a/ext/DynaLoader/dl_aix.xs +++ b/ext/DynaLoader/dl_aix.xs @@ -11,6 +11,25 @@ * on statup... It can probably be trimmed more. */ +#define PERLIO_NOT_STDIO 0 + +/* + * On AIX 4.3 and above the emulation layer is not needed any more, and + * indeed if perl uses its emulation and perl is linked into apache + * which is supposed to use the native dlopen conflicts arise. + * Jens-Uwe Mager jum@helios.de + */ +#ifdef USE_NATIVE_DLOPEN + +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#include + +#include "dlutils.c" /* SaveError() etc */ + +#else + /* * @(#)dlfcn.c 1.5 revision of 93/02/14 20:14:17 * This is an unpublished work copyright (c) 1992 Helios Software GmbH @@ -20,6 +39,15 @@ #include "perl.h" #include "XSUB.h" +/* When building as a 64-bit binary on AIX, define this to get the + * correct structure definitions. Also determines the field-name + * macros and gates some logic in readEntries(). -- Steven N. Hirsch + * */ +#ifdef USE_64_BIT_ALL +# define __XCOFF64__ +# define __XCOFF32__ +#endif + #include #include #include @@ -27,8 +55,48 @@ #include #include #include +#undef FREAD +#undef FWRITE #include +#ifdef USE_64_BIT_ALL +# define AIX_SCNHDR SCNHDR_64 +# define AIX_LDHDR LDHDR_64 +# define AIX_LDSYM LDSYM_64 +# define AIX_LDHDRSZ LDHDRSZ_64 +#else +# define AIX_SCNHDR SCNHDR +# define AIX_LDHDR LDHDR +# define AIX_LDSYM LDSYM +# define AIX_LDHDRSZ LDHDRSZ +#endif + +/* When using Perl extensions written in C++ the longer versions + * of load() and unload() from libC and libC_r need to be used, + * otherwise statics in the extensions won't get initialized right. + * -- Stephanie Beals */ + +/* Older AIX C compilers cannot deal with C++ double-slash comments in + the ibmcxx and/or xlC includes. Since we only need a single file, + be more fine-grained about what's included */ + +#ifdef USE_libC /* The define comes, when it comes, from hints/aix.pl. */ +# define LOAD loadAndInit +# define UNLOAD terminateAndUnload +# if defined(USE_vacpp_load_h) +# include "/usr/vacpp/include/load.h" +# elif defined(USE_ibmcxx_load_h) +# include "/usr/ibmcxx/include/load.h" +# elif defined(USE_xlC_load_h) +# include "/usr/lpp/xlC/include/load.h" +# elif defined(USE_load_h) +# include "/usr/include/load.h" +# endif +#else +# define LOAD load +# define UNLOAD unload +#endif + /* * AIX 4.3 does remove some useful definitions from ldfcn.h. Define * these here to compensate for that lossage. @@ -43,10 +111,11 @@ # define FREAD(p,s,n,ldptr) fread(p,s,n,IOPTR(ldptr)) #endif -/* If using PerlIO, redefine these macros from */ -#ifdef USE_PERLIO -#define FSEEK(ldptr,o,p) PerlIO_seek(IOPTR(ldptr),(p==BEGINNING)?(OFFSET(ldptr)+o):o,p) -#define FREAD(p,s,n,ldptr) PerlIO_read(IOPTR(ldptr),p,s*n) +#ifndef RTLD_LAZY +# define RTLD_LAZY 0 +#endif +#ifndef RTLD_GLOBAL +# define RTLD_GLOBAL 0 #endif /* @@ -73,23 +142,35 @@ typedef struct Module { ExportPtr exports; /* the array of exports */ } Module, *ModulePtr; -/* - * We keep a list of all loaded modules to be able to call the fini - * handlers at atexit() time. - */ -static ModulePtr modList; /* XXX threaded */ +typedef struct { + /* + * We keep a list of all loaded modules to be able to reference count + * duplicate dlopen's. + */ + ModulePtr x_modList; + + /* + * The last error from one of the dl* routines is kept in static + * variables here. Each error is returned only once to the caller. + */ + char x_errbuf[BUFSIZ]; + int x_errvalid; + void * x_mainModule; +} my_cxtx_t; /* this *must* be named my_cxtx_t */ + +#define DL_CXT_EXTRA /* ask for dl_cxtx to be defined in dlutils.c */ +#include "dlutils.c" /* SaveError() etc */ -/* - * The last error from one of the dl* routines is kept in static - * variables here. Each error is returned only once to the caller. - */ -static char errbuf[BUFSIZ]; /* XXX threaded */ -static int errvalid; /* XXX threaded */ +#define dl_modList (dl_cxtx.x_modList) +#define dl_errbuf (dl_cxtx.x_errbuf) +#define dl_errvalid (dl_cxtx.x_errvalid) +#define dl_mainModule (dl_cxtx.x_mainModule) static void caterr(char *); static int readExports(ModulePtr); -static void terminate(void); +static void *findMain(void); +/* these statics are ok because they're constants */ static char *strerror_failed = "(strerror failed)"; static char *strerror_r_failed = "(strerror_r failed)"; @@ -98,26 +179,13 @@ char *strerrorcat(char *str, int err) { int msgsiz; char *msg; -#ifdef USE_THREADS - char *buf = malloc(BUFSIZ); - - if (buf == 0) - return 0; - if (strerror_r(err, buf, BUFSIZ) == 0) - msg = buf; - else - msg = strerror_r_failed; - msgsiz = strlen(msg); - if (strsiz + msgsiz < BUFSIZ) - strcat(str, msg); - free(buf); -#else + dTHX; + if ((msg = strerror(err)) == 0) msg = strerror_failed; msgsiz = strlen(msg); /* Note msg = buf and free() above. */ if (strsiz + msgsiz < BUFSIZ) /* Do not move this after #endif. */ strcat(str, msg); -#endif return str; } @@ -126,26 +194,13 @@ char *strerrorcpy(char *str, int err) { int msgsiz; char *msg; -#ifdef USE_THREADS - char *buf = malloc(BUFSIZ); - - if (buf == 0) - return 0; - if (strerror_r(err, buf, BUFSIZ) == 0) - msg = buf; - else - msg = strerror_r_failed; - msgsiz = strlen(msg); - if (msgsiz < BUFSIZ) - strcpy(str, msg); - free(buf); -#else + dTHX; + if ((msg = strerror(err)) == 0) msg = strerror_failed; msgsiz = strlen(msg); /* Note msg = buf and free() above. */ if (msgsiz < BUFSIZ) /* Do not move this after #endif. */ strcpy(str, msg); -#endif return str; } @@ -154,37 +209,37 @@ char *strerrorcpy(char *str, int err) { void *dlopen(char *path, int mode) { dTHX; + dMY_CXT; register ModulePtr mp; - static int inited; /* XXX threaded */ /* * Upon the first call register a terminate handler that will * close all libraries. */ - if (!inited) { - inited++; - atexit(terminate); + if (dl_mainModule == NULL) { + if ((dl_mainModule = findMain()) == NULL) + return NULL; } /* * Scan the list of modules if have the module already loaded. */ - for (mp = modList; mp; mp = mp->next) + for (mp = dl_modList; mp; mp = mp->next) if (strcmp(mp->name, path) == 0) { mp->refCnt++; return mp; } - Newz(1000,mp,1,Module); + Newxz(mp,1,Module); if (mp == NULL) { - errvalid++; - strcpy(errbuf, "Newz: "); - strerrorcat(errbuf, errno); + dl_errvalid++; + strcpy(dl_errbuf, "Newz: "); + strerrorcat(dl_errbuf, errno); return NULL; } if ((mp->name = savepv(path)) == NULL) { - errvalid++; - strcpy(errbuf, "savepv: "); - strerrorcat(errbuf, errno); + dl_errvalid++; + strcpy(dl_errbuf, "savepv: "); + strerrorcat(dl_errbuf, errno); safefree(mp); return NULL; } @@ -193,7 +248,7 @@ void *dlopen(char *path, int mode) * load should be declared load(const char *...). Thus we * cast the path to a normal char *. Ugly. */ - if ((mp->entry = (void *)load((char *)path, + if ((mp->entry = (void *)LOAD((char *)path, #ifdef L_LIBPATH_EXEC L_LIBPATH_EXEC | #endif @@ -203,10 +258,10 @@ void *dlopen(char *path, int mode) safefree(mp->name); safefree(mp); - errvalid++; - strcpy(errbuf, "dlopen: "); - strcat(errbuf, path); - strcat(errbuf, ": "); + dl_errvalid++; + strcpy(dl_errbuf, "dlopen: "); + strcat(dl_errbuf, path); + strcat(dl_errbuf, ": "); /* * If AIX says the file is not executable, the error * can be further described by querying the loader about @@ -215,31 +270,35 @@ void *dlopen(char *path, int mode) if (saverrno == ENOEXEC) { char *moreinfo[BUFSIZ/sizeof(char *)]; if (loadquery(L_GETMESSAGES, moreinfo, sizeof(moreinfo)) == -1) - strerrorcpy(errbuf, saverrno); + strerrorcpy(dl_errbuf, saverrno); else { char **p; for (p = moreinfo; *p; p++) caterr(*p); } } else - strerrorcat(errbuf, saverrno); + strerrorcat(dl_errbuf, saverrno); return NULL; } mp->refCnt = 1; - mp->next = modList; - modList = mp; + mp->next = dl_modList; + dl_modList = mp; /* * Assume anonymous exports come from the module this dlopen * is linked into, that holds true as long as dlopen and all - * of the perl core are in the same shared object. + * of the perl core are in the same shared object. Also bind + * against the main part, in the case a perl is not the main + * part, e.g mod_perl as DSO in Apache so perl modules can + * also reference Apache symbols. */ - if (loadbind(0, (void *)dlopen, mp->entry) == -1) { + if (loadbind(0, (void *)dlopen, mp->entry) == -1 || + loadbind(0, dl_mainModule, mp->entry)) { int saverrno = errno; dlclose(mp); - errvalid++; - strcpy(errbuf, "loadbind: "); - strerrorcat(errbuf, saverrno); + dl_errvalid++; + strcpy(dl_errbuf, "loadbind: "); + strerrorcat(dl_errbuf, saverrno); return NULL; } if (readExports(mp) == -1) { @@ -255,41 +314,45 @@ void *dlopen(char *path, int mode) */ static void caterr(char *s) { + dTHX; + dMY_CXT; register char *p = s; while (*p >= '0' && *p <= '9') p++; switch(atoi(s)) { case L_ERROR_TOOMANY: - strcat(errbuf, "to many errors"); + strcat(dl_errbuf, "too many errors"); break; case L_ERROR_NOLIB: - strcat(errbuf, "can't load library"); - strcat(errbuf, p); + strcat(dl_errbuf, "can't load library"); + strcat(dl_errbuf, p); break; case L_ERROR_UNDEF: - strcat(errbuf, "can't find symbol"); - strcat(errbuf, p); + strcat(dl_errbuf, "can't find symbol"); + strcat(dl_errbuf, p); break; case L_ERROR_RLDBAD: - strcat(errbuf, "bad RLD"); - strcat(errbuf, p); + strcat(dl_errbuf, "bad RLD"); + strcat(dl_errbuf, p); break; case L_ERROR_FORMAT: - strcat(errbuf, "bad exec format in"); - strcat(errbuf, p); + strcat(dl_errbuf, "bad exec format in"); + strcat(dl_errbuf, p); break; case L_ERROR_ERRNO: - strerrorcat(errbuf, atoi(++p)); + strerrorcat(dl_errbuf, atoi(++p)); break; default: - strcat(errbuf, s); + strcat(dl_errbuf, s); break; } } void *dlsym(void *handle, const char *symbol) { + dTHX; + dMY_CXT; register ModulePtr mp = (ModulePtr)handle; register ExportPtr ep; register int i; @@ -301,33 +364,37 @@ void *dlsym(void *handle, const char *symbol) for (ep = mp->exports, i = mp->nExports; i; i--, ep++) if (strcmp(ep->name, symbol) == 0) return ep->addr; - errvalid++; - strcpy(errbuf, "dlsym: undefined symbol "); - strcat(errbuf, symbol); + dl_errvalid++; + strcpy(dl_errbuf, "dlsym: undefined symbol "); + strcat(dl_errbuf, symbol); return NULL; } char *dlerror(void) { - if (errvalid) { - errvalid = 0; - return errbuf; + dTHX; + dMY_CXT; + if (dl_errvalid) { + dl_errvalid = 0; + return dl_errbuf; } return NULL; } int dlclose(void *handle) { + dTHX; + dMY_CXT; register ModulePtr mp = (ModulePtr)handle; int result; register ModulePtr mp1; if (--mp->refCnt > 0) return 0; - result = unload(mp->entry); + result = UNLOAD(mp->entry); if (result == -1) { - errvalid++; - strerrorcpy(errbuf, errno); + dl_errvalid++; + strerrorcpy(dl_errbuf, errno); } if (mp->exports) { register ExportPtr ep; @@ -337,10 +404,10 @@ int dlclose(void *handle) safefree(ep->name); safefree(mp->exports); } - if (mp == modList) - modList = mp->next; + if (mp == dl_modList) + dl_modList = mp->next; else { - for (mp1 = modList; mp1; mp1 = mp1->next) + for (mp1 = dl_modList; mp1; mp1 = mp1->next) if (mp1->next == mp) { mp1->next = mp->next; break; @@ -351,12 +418,6 @@ int dlclose(void *handle) return result; } -static void terminate(void) -{ - while (modList) - dlclose(modList); -} - /* Added by Wayne Scott * This is needed because the ldopen system call calls * calloc to allocated a block of date. The ldclose call calls free. @@ -378,11 +439,12 @@ void *calloc(size_t ne, size_t sz) static int readExports(ModulePtr mp) { dTHX; + dMY_CXT; LDFILE *ldp = NULL; - SCNHDR sh; - LDHDR *lhp; + AIX_SCNHDR sh; + AIX_LDHDR *lhp; char *ldbuf; - LDSYM *ls; + AIX_LDSYM *ls; int i; ExportPtr ep; @@ -391,9 +453,9 @@ static int readExports(ModulePtr mp) char *buf; int size = 4*1024; if (errno != ENOENT) { - errvalid++; - strcpy(errbuf, "readExports: "); - strerrorcat(errbuf, errno); + dl_errvalid++; + strcpy(dl_errbuf, "readExports: "); + strerrorcat(dl_errbuf, errno); return -1; } /* @@ -402,31 +464,31 @@ static int readExports(ModulePtr mp) * module using L_GETINFO. */ if ((buf = safemalloc(size)) == NULL) { - errvalid++; - strcpy(errbuf, "readExports: "); - strerrorcat(errbuf, errno); + dl_errvalid++; + strcpy(dl_errbuf, "readExports: "); + strerrorcat(dl_errbuf, errno); return -1; } while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) { safefree(buf); size += 4*1024; if ((buf = safemalloc(size)) == NULL) { - errvalid++; - strcpy(errbuf, "readExports: "); - strerrorcat(errbuf, errno); + dl_errvalid++; + strcpy(dl_errbuf, "readExports: "); + strerrorcat(dl_errbuf, errno); return -1; } } if (i == -1) { - errvalid++; - strcpy(errbuf, "readExports: "); - strerrorcat(errbuf, errno); + dl_errvalid++; + strcpy(dl_errbuf, "readExports: "); + strerrorcat(dl_errbuf, errno); safefree(buf); return -1; } /* * Traverse the list of loaded modules. The entry point - * returned by load() does actually point to the data + * returned by LOAD() does actually point to the data * segment origin. */ lp = (struct ld_info *)buf; @@ -442,22 +504,26 @@ static int readExports(ModulePtr mp) } safefree(buf); if (!ldp) { - errvalid++; - strcpy(errbuf, "readExports: "); - strerrorcat(errbuf, errno); + dl_errvalid++; + strcpy(dl_errbuf, "readExports: "); + strerrorcat(dl_errbuf, errno); return -1; } } +#ifdef USE_64_BIT_ALL + if (TYPE(ldp) != U803XTOCMAGIC) { +#else if (TYPE(ldp) != U802TOCMAGIC) { - errvalid++; - strcpy(errbuf, "readExports: bad magic"); +#endif + dl_errvalid++; + strcpy(dl_errbuf, "readExports: bad magic"); while(ldclose(ldp) == FAILURE) ; return -1; } if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) { - errvalid++; - strcpy(errbuf, "readExports: cannot read loader section header"); + dl_errvalid++; + strcpy(dl_errbuf, "readExports: cannot read loader section header"); while(ldclose(ldp) == FAILURE) ; return -1; @@ -467,16 +533,16 @@ static int readExports(ModulePtr mp) * finding long symbol names residing in the string table easier. */ if ((ldbuf = (char *)safemalloc(sh.s_size)) == NULL) { - errvalid++; - strcpy(errbuf, "readExports: "); - strerrorcat(errbuf, errno); + dl_errvalid++; + strcpy(dl_errbuf, "readExports: "); + strerrorcat(dl_errbuf, errno); while(ldclose(ldp) == FAILURE) ; return -1; } if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) { - errvalid++; - strcpy(errbuf, "readExports: cannot seek to loader section"); + dl_errvalid++; + strcpy(dl_errbuf, "readExports: cannot seek to loader section"); safefree(ldbuf); while(ldclose(ldp) == FAILURE) ; @@ -484,20 +550,16 @@ static int readExports(ModulePtr mp) } /* This first case is a hack, since it assumes that the 3rd parameter to FREAD is 1. See the redefinition of FREAD above to see how this works. */ -#ifdef USE_PERLIO - if (FREAD(ldbuf, sh.s_size, 1, ldp) != sh.s_size) { -#else if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) { -#endif - errvalid++; - strcpy(errbuf, "readExports: cannot read loader section"); + dl_errvalid++; + strcpy(dl_errbuf, "readExports: cannot read loader section"); safefree(ldbuf); while(ldclose(ldp) == FAILURE) ; return -1; } - lhp = (LDHDR *)ldbuf; - ls = (LDSYM *)(ldbuf+LDHDRSZ); + lhp = (AIX_LDHDR *)ldbuf; + ls = (AIX_LDSYM *)(ldbuf+AIX_LDHDRSZ); /* * Count the number of exports to include in our export table. */ @@ -506,11 +568,11 @@ static int readExports(ModulePtr mp) continue; mp->nExports++; } - Newz(1001, mp->exports, mp->nExports, Export); + Newxz(mp->exports, mp->nExports, Export); if (mp->exports == NULL) { - errvalid++; - strcpy(errbuf, "readExports: "); - strerrorcat(errbuf, errno); + dl_errvalid++; + strcpy(dl_errbuf, "readExports: "); + strerrorcat(dl_errbuf, errno); safefree(ldbuf); while(ldclose(ldp) == FAILURE) ; @@ -521,15 +583,19 @@ static int readExports(ModulePtr mp) * the entry point we got from load. */ ep = mp->exports; - ls = (LDSYM *)(ldbuf+LDHDRSZ); + ls = (AIX_LDSYM *)(ldbuf+AIX_LDHDRSZ); for (i = lhp->l_nsyms; i; i--, ls++) { char *symname; if (!LDR_EXPORT(*ls)) continue; +#ifndef USE_64_BIT_ALL if (ls->l_zeroes == 0) +#endif symname = ls->l_offset+lhp->l_stoff+ldbuf; +#ifndef USE_64_BIT_ALL else symname = ls->l_name; +#endif ep->name = savepv(symname); ep->addr = (void *)((unsigned long)mp->entry + ls->l_value); ep++; @@ -540,10 +606,59 @@ static int readExports(ModulePtr mp) return 0; } +/* + * Find the main modules entry point. This is used as export pointer + * for loadbind() to be able to resolve references to the main part. + */ +static void * findMain(void) +{ + dTHX; + dMY_CXT; + struct ld_info *lp; + char *buf; + int size = 4*1024; + int i; + void *ret; + + if ((buf = safemalloc(size)) == NULL) { + dl_errvalid++; + strcpy(dl_errbuf, "findMain: "); + strerrorcat(dl_errbuf, errno); + return NULL; + } + while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) { + safefree(buf); + size += 4*1024; + if ((buf = safemalloc(size)) == NULL) { + dl_errvalid++; + strcpy(dl_errbuf, "findMain: "); + strerrorcat(dl_errbuf, errno); + return NULL; + } + } + if (i == -1) { + dl_errvalid++; + strcpy(dl_errbuf, "findMain: "); + strerrorcat(dl_errbuf, errno); + safefree(buf); + return NULL; + } + /* + * The first entry is the main module. The entry point + * returned by load() does actually point to the data + * segment origin. + */ + lp = (struct ld_info *)buf; + ret = lp->ldinfo_dataorg; + safefree(buf); + return ret; +} +#endif /* USE_NATIVE_DLOPEN */ + /* dl_dlopen.xs * * Platform: SunOS/Solaris, possibly others which use dlopen. - * Author: Paul Marquess (pmarquess@bfsec.bt.co.uk) + * Author: Paul Marquess (Paul.Marquess@btinternet.com) * Created: 10th July 1994 * * Modified: @@ -561,9 +676,6 @@ static int readExports(ModulePtr mp) */ -#include "dlutils.c" /* SaveError() etc */ - - static void dl_private_init(pTHX) { @@ -581,27 +693,38 @@ dl_load_file(filename, flags=0) char * filename int flags CODE: - DLDEBUG(1,PerlIO_printf(PerlIO_stderr(), "dl_load_file(%s,%x):\n", filename,flags)); + DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_load_file(%s,%x):\n", filename,flags)); if (flags & 0x01) Perl_warn(aTHX_ "Can't make loaded symbols global on this platform while loading %s",filename); - RETVAL = dlopen(filename, 1) ; - DLDEBUG(2,PerlIO_printf(PerlIO_stderr(), " libref=%x\n", RETVAL)); + RETVAL = dlopen(filename, RTLD_GLOBAL|RTLD_LAZY) ; + DLDEBUG(2,PerlIO_printf(Perl_debug_log, " libref=%x\n", RETVAL)); ST(0) = sv_newmortal() ; if (RETVAL == NULL) SaveError(aTHX_ "%s",dlerror()) ; else sv_setiv( ST(0), PTR2IV(RETVAL) ); +int +dl_unload_file(libref) + void * libref + CODE: + DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_unload_file(%lx):\n", libref)); + RETVAL = (dlclose(libref) == 0 ? 1 : 0); + if (!RETVAL) + SaveError(aTHX_ "%s", dlerror()) ; + DLDEBUG(2,PerlIO_printf(Perl_debug_log, " retval = %d\n", RETVAL)); + OUTPUT: + RETVAL void * dl_find_symbol(libhandle, symbolname) void * libhandle char * symbolname CODE: - DLDEBUG(2,PerlIO_printf(PerlIO_stderr(), "dl_find_symbol(handle=%x, symbol=%s)\n", + DLDEBUG(2,PerlIO_printf(Perl_debug_log, "dl_find_symbol(handle=%x, symbol=%s)\n", libhandle, symbolname)); RETVAL = dlsym(libhandle, symbolname); - DLDEBUG(2,PerlIO_printf(PerlIO_stderr(), " symbolref = %x\n", RETVAL)); + DLDEBUG(2,PerlIO_printf(Perl_debug_log, " symbolref = %x\n", RETVAL)); ST(0) = sv_newmortal() ; if (RETVAL == NULL) SaveError(aTHX_ "%s",dlerror()) ; @@ -623,17 +746,19 @@ dl_install_xsub(perl_name, symref, filename="$Package") void * symref char * filename CODE: - DLDEBUG(2,PerlIO_printf(PerlIO_stderr(), "dl_install_xsub(name=%s, symref=%x)\n", + DLDEBUG(2,PerlIO_printf(Perl_debug_log, "dl_install_xsub(name=%s, symref=%x)\n", perl_name, symref)); - ST(0) = sv_2mortal(newRV((SV*)newXS(perl_name, - (void(*)(pTHX_ CV *))symref, - filename))); + ST(0) = sv_2mortal(newRV((SV*)newXS_flags(perl_name, + (void(*)(pTHX_ CV *))symref, + filename, NULL, + XS_DYNAMIC_FILENAME))); char * dl_error() CODE: - RETVAL = LastError ; + dMY_CXT; + RETVAL = dl_last_error ; OUTPUT: RETVAL