📄 dl_aix.xs
字号:
/* dl_aix.xs * * Written: 8/31/94 by Wayne Scott (wscott@ichips.intel.com) * * All I did was take Jens-Uwe Mager's libdl emulation library for * AIX and merged it with the dl_dlopen.xs file to create a dynamic library * package that works for AIX. * * I did change all malloc's, free's, strdup's, calloc's to use the perl * equilvant. I also removed some stuff we will not need. Call fini() * on statup... It can probably be trimmed more. */#define PERLIO_NOT_STDIO 0/* * @(#)dlfcn.c 1.5 revision of 93/02/14 20:14:17 * This is an unpublished work copyright (c) 1992 Helios Software GmbH * 3000 Hannover 1, Germany */#include "EXTERN.h"#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 * <hirschs@btv.ibm.com> */#ifdef USE_64_BIT_ALL# define __XCOFF64__# define __XCOFF32__#endif#include <stdio.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/ldr.h>#include <a.out.h>#undef FREAD#undef FWRITE#include <ldfcn.h>#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 <bealzy@us.ibm.com> *//* 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 <hirschs@btv.ibm.com> */#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. */#ifndef BEGINNING# define BEGINNING SEEK_SET#endif#ifndef FSEEK# define FSEEK(ldptr,o,p) fseek(IOPTR(ldptr),(p==BEGINNING)?(OFFSET(ldptr) +o):o,p)#endif#ifndef FREAD# define FREAD(p,s,n,ldptr) fread(p,s,n,IOPTR(ldptr))#endif/* * We simulate dlopen() et al. through a call to load. Because AIX has * no call to find an exported symbol we read the loader section of the * loaded module and build a list of exported symbols and their virtual * address. */typedef struct { char *name; /* the symbols's name */ void *addr; /* its relocated virtual address */} Export, *ExportPtr;/* * The void * handle returned from dlopen is actually a ModulePtr. */typedef struct Module { struct Module *next; char *name; /* module name for refcounting */ int refCnt; /* the number of references */ void *entry; /* entry point from load */ int nExports; /* the number of exports found */ ExportPtr exports; /* the array of exports */} Module, *ModulePtr;/* * We keep a list of all loaded modules to be able to reference count * duplicate dlopen's. */static ModulePtr modList; /* XXX threaded *//* * 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 */static void caterr(char *);static int readExports(ModulePtr);static void *findMain(void);static char *strerror_failed = "(strerror failed)";static char *strerror_r_failed = "(strerror_r failed)";char *strerrorcat(char *str, int err) { int strsiz = strlen(str); 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 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;}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 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;} /* ARGSUSED */void *dlopen(char *path, int mode){ dTHX; register ModulePtr mp; static void *mainModule; /* XXX threaded */ /* * Upon the first call register a terminate handler that will * close all libraries. */ if (mainModule == NULL) { if ((mainModule = findMain()) == NULL) return NULL; } /* * Scan the list of modules if have the module already loaded. */ for (mp = modList; mp; mp = mp->next) if (strcmp(mp->name, path) == 0) { mp->refCnt++; return mp; } Newz(1000,mp,1,Module); if (mp == NULL) { errvalid++; strcpy(errbuf, "Newz: "); strerrorcat(errbuf, errno); return NULL; } if ((mp->name = savepv(path)) == NULL) { errvalid++; strcpy(errbuf, "savepv: "); strerrorcat(errbuf, errno); safefree(mp); return NULL; } /* * load should be declared load(const char *...). Thus we * cast the path to a normal char *. Ugly. */ if ((mp->entry = (void *)LOAD((char *)path,#ifdef L_LIBPATH_EXEC L_LIBPATH_EXEC |#endif L_NOAUTODEFER, NULL)) == NULL) { int saverrno = errno; safefree(mp->name); safefree(mp); errvalid++; strcpy(errbuf, "dlopen: "); strcat(errbuf, path); strcat(errbuf, ": "); /* * If AIX says the file is not executable, the error * can be further described by querying the loader about * the last error. */ if (saverrno == ENOEXEC) { char *moreinfo[BUFSIZ/sizeof(char *)]; if (loadquery(L_GETMESSAGES, moreinfo, sizeof(moreinfo)) == -1) strerrorcpy(errbuf, saverrno); else { char **p; for (p = moreinfo; *p; p++) caterr(*p); } } else strerrorcat(errbuf, saverrno); return NULL; } mp->refCnt = 1; mp->next = modList; 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. 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 || loadbind(0, mainModule, mp->entry)) { int saverrno = errno; dlclose(mp); errvalid++; strcpy(errbuf, "loadbind: "); strerrorcat(errbuf, saverrno); return NULL; } if (readExports(mp) == -1) { dlclose(mp); return NULL; } return mp;}/* * Attempt to decipher an AIX loader error message and append it * to our static error message buffer. */static void caterr(char *s){ register char *p = s; while (*p >= '0' && *p <= '9') p++; switch(atoi(s)) { case L_ERROR_TOOMANY: strcat(errbuf, "too many errors"); break; case L_ERROR_NOLIB: strcat(errbuf, "can't load library"); strcat(errbuf, p); break; case L_ERROR_UNDEF: strcat(errbuf, "can't find symbol"); strcat(errbuf, p); break; case L_ERROR_RLDBAD: strcat(errbuf, "bad RLD"); strcat(errbuf, p); break; case L_ERROR_FORMAT: strcat(errbuf, "bad exec format in"); strcat(errbuf, p); break; case L_ERROR_ERRNO: strerrorcat(errbuf, atoi(++p)); break; default: strcat(errbuf, s); break; }}void *dlsym(void *handle, const char *symbol){ register ModulePtr mp = (ModulePtr)handle; register ExportPtr ep; register int i; /* * Could speed up search, but I assume that one assigns * the result to function pointers anyways. */ 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); return NULL;}char *dlerror(void){ if (errvalid) { errvalid = 0; return errbuf; } return NULL;}int dlclose(void *handle){ register ModulePtr mp = (ModulePtr)handle; int result; register ModulePtr mp1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -