mirror of https://github.com/postgres/postgres
Remove the long-obsolete homebrew dl*() functions for AIX, in favor of just
using the system functions all the time. (These files are now just copies of the osf.* files.) The homebrew functions were not getting used anyway on AIX versions that have dlopen(), that is 4.3 and up, so they are not needed on any AIX that is even remotely supported by the vendor anymore. We'd have probably left them here anyway, except some questions were raised about the copyright.
This commit is contained in:
parent
fea168823a
commit
f2cc453dd7
|
@ -1,172 +0,0 @@
|
|||
$PostgreSQL: pgsql/src/backend/port/dynloader/README.dlfcn.aix,v 1.3 2008/03/21 13:23:28 momjian Exp $
|
||||
|
||||
dynaloader
|
||||
==========
|
||||
|
||||
Copyright (c) 1992,1993,1995, Jens-Uwe Mager, Helios Software GmbH
|
||||
Not derived from licensed software.
|
||||
|
||||
Permission is granted to freely use, copy, modify, and redistribute
|
||||
this software, provided that no attempt is made to gain profit from it,
|
||||
the author is not construed to be liable for any results of using the
|
||||
software, alterations are clearly marked as such, and this notice is
|
||||
not modified.
|
||||
|
||||
libdl.a
|
||||
-------
|
||||
|
||||
This is an emulation library to emulate the SunOS/System V.4 functions
|
||||
to access the runtime linker. The functions are emulated by using the
|
||||
AIX load() function and by reading the .loader section of the loaded
|
||||
module to find the exports. The to be loaded module should be linked as
|
||||
follows (if using AIX 3):
|
||||
|
||||
cc -o module.so -bM:SRE -bE:module.exp -e _nostart $(OBJS)
|
||||
|
||||
For AIX 4:
|
||||
|
||||
cc -o module.so -bM:SRE -bE:module.exp -bnoentry $(OBJS)
|
||||
|
||||
The module export file contains the symbols to be exported. Because
|
||||
this library uses the loader section, the final module.so file can be
|
||||
stripped. C++ users should build their shared objects using the script
|
||||
makeC++SharedLib (part of the IBM C++ compiler), this will make sure
|
||||
that constructors and destructors for static and global objects will be
|
||||
called upon loading and unloading the module.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
void *dlopen(const char *path, int mode);
|
||||
|
||||
This routine loads the module pointed to by path and reads its export
|
||||
table. If the path does not contain a '/' character, dlopen will search
|
||||
for the module using the LIBPATH environment variable. It returns an
|
||||
opaque handle to the module or NULL on error. The mode parameter can be
|
||||
either RTLD_LAZY (for lazy function binding) or RTLD_NOW for immediate
|
||||
function binding. The AIX implementation currently behaves as RTLD_NOW
|
||||
even if RTLD_LAZY is specified. The flag RTLD_GLOBAL might be or'ed into the
|
||||
mode parameter to allow loaded modules to bind to global variables or
|
||||
functions in other loaded modules loaded by dlopen(). If RTLD_GLOBAL is
|
||||
not specified, only globals from the main part of the executable or
|
||||
shared libraries are used to look for undefined symbols in loaded
|
||||
modules.
|
||||
|
||||
|
||||
void *dlsym(void *handle, const char *symbol);
|
||||
|
||||
This routine searches for the symbol in the module referred to by
|
||||
handle and returns its address. If the symbol could not be found, the
|
||||
function returns NULL. The return value must be casted to a proper
|
||||
function pointer before it can be used. SunOS/System V.4 allow handle
|
||||
to be a NULL pointer to refer to the module the call is made from, this
|
||||
is not implemented.
|
||||
|
||||
int dlclose(void *handle);
|
||||
|
||||
This routine unloads the module referred to by the handle and disposes
|
||||
of any local storage. this function returns -1 on failure.
|
||||
|
||||
char *dlerror(void);
|
||||
|
||||
This routine can be used to retrieve a text message describing the most
|
||||
recent error that occured on on of the above routines. This function
|
||||
returns NULL if there is not error information.
|
||||
|
||||
Initialization and termination handlers
|
||||
---------------------------------------
|
||||
|
||||
The emulation provides for an initialization and a termination
|
||||
handler. The dlfcn.h file contains a structure declaration named
|
||||
dl_info with following members:
|
||||
|
||||
void (*init)(void);
|
||||
void (*fini)(void);
|
||||
|
||||
The init function is called upon first referencing the library. The
|
||||
fini function is called at dlclose() time or when the process exits.
|
||||
The module should declare a variable named dl_info that contains this
|
||||
structure which must be exported. These functions correspond to the
|
||||
documented _init() and _fini() functions of SunOS 4.x, but these are
|
||||
appearently not implemented in SunOS. When using SunOS 5.0, these
|
||||
correspond to #pragma init and #pragma fini respectively. At the same
|
||||
time any static or global C++ object's constructors or destructors will
|
||||
be called.
|
||||
|
||||
Jens-Uwe Mager
|
||||
|
||||
HELIOS Software GmbH
|
||||
Lavesstr. 80
|
||||
30159 Hannover
|
||||
Germany
|
||||
|
||||
Phone: +49 511 36482-0
|
||||
FAX: +49 511 36482-69
|
||||
AppleLink: helios.de Attn: Jens-Uwe Mager
|
||||
Internet: jum@helios.de
|
||||
|
||||
Revison History
|
||||
---------------
|
||||
|
||||
SCCS/s.dlfcn.h:
|
||||
|
||||
D 1.4 95/04/25 09:36:52 jum 4 3 00018/00004/00028
|
||||
MRs:
|
||||
COMMENTS:
|
||||
added RTLD_GLOBAL, include and C++ guards
|
||||
|
||||
D 1.3 92/12/27 20:58:32 jum 3 2 00001/00001/00031
|
||||
MRs:
|
||||
COMMENTS:
|
||||
we always have prototypes on RS/6000
|
||||
|
||||
D 1.2 92/08/16 17:45:11 jum 2 1 00009/00000/00023
|
||||
MRs:
|
||||
COMMENTS:
|
||||
added dl_info structure to implement initialize and terminate functions
|
||||
|
||||
D 1.1 92/08/02 18:08:45 jum 1 0 00023/00000/00000
|
||||
MRs:
|
||||
COMMENTS:
|
||||
Erstellungsdatum und -uhrzeit 92/08/02 18:08:45 von jum
|
||||
|
||||
SCCS/s.dlfcn.c:
|
||||
|
||||
D 1.7 95/08/14 19:08:38 jum 8 6 00026/00004/00502
|
||||
MRs:
|
||||
COMMENTS:
|
||||
Integrated the fixes from Kirk Benell (kirk@rsinc.com) to allow loading of
|
||||
shared objects generated under AIX 4. Fixed bug that symbols with exactly
|
||||
8 characters would use garbage characters from the following symbol value.
|
||||
|
||||
D 1.6 95/04/25 09:38:03 jum 6 5 00046/00006/00460
|
||||
MRs:
|
||||
COMMENTS:
|
||||
added handling of C++ static constructors and destructors, added RTLD_GLOBAL to bind against other loaded modules
|
||||
|
||||
D 1.5 93/02/14 20:14:17 jum 5 4 00002/00000/00464
|
||||
MRs:
|
||||
COMMENTS:
|
||||
added path to dlopen error message to make clear where there error occured.
|
||||
|
||||
D 1.4 93/01/03 19:13:56 jum 4 3 00061/00005/00403
|
||||
MRs:
|
||||
COMMENTS:
|
||||
to allow calling symbols in the main module call load with L_NOAUTODEFER and
|
||||
do a loadbind later with the main module.
|
||||
|
||||
D 1.3 92/12/27 20:59:55 jum 3 2 00066/00008/00342
|
||||
MRs:
|
||||
COMMENTS:
|
||||
added search by L_GETINFO if module got loaded by LIBPATH
|
||||
|
||||
D 1.2 92/08/16 17:45:43 jum 2 1 00074/00006/00276
|
||||
MRs:
|
||||
COMMENTS:
|
||||
implemented initialize and terminate functions, added reference counting to avoid multiple loads of the same library
|
||||
|
||||
D 1.1 92/08/02 18:08:45 jum 1 0 00282/00000/00000
|
||||
MRs:
|
||||
COMMENTS:
|
||||
Erstellungsdatum und -uhrzeit 92/08/02 18:08:45 von jum
|
||||
|
|
@ -1,612 +1,7 @@
|
|||
/*
|
||||
* $PostgreSQL: pgsql/src/backend/port/dynloader/aix.c,v 1.20 2008/05/17 01:28:23 adunstan Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/port/dynloader/aix.c,v 1.21 2009/04/21 21:15:50 tgl Exp $
|
||||
*
|
||||
* Dummy file used for nothing at this point
|
||||
*
|
||||
* @(#)dlfcn.c 1.7 revision of 95/08/14 19:08:38
|
||||
* This is an unpublished work copyright (c) 1992 HELIOS Software GmbH
|
||||
* 30159 Hannover, Germany
|
||||
* see aix.h
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "sys/ldr.h"
|
||||
#include <a.out.h>
|
||||
#include "ldfcn.h"
|
||||
|
||||
#include "dynloader.h"
|
||||
|
||||
#ifndef HAVE_DLOPEN
|
||||
|
||||
/*
|
||||
* AIX 4.3 and up has dlopen() and friends in -ldl.
|
||||
* A la long, the homebrewn dl*() functions below should be obsolete.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* xlC uses the following structure to list its constructors and
|
||||
* destructors. This is gleaned from the output of munch.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
void (*init) (void); /* call static constructors */
|
||||
void (*term) (void); /* call static destructors */
|
||||
} Cdtor, *CdtorPtr;
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
struct dl_info *info; /* optional init/terminate functions */
|
||||
CdtorPtr cdtors; /* optional C++ constructors */
|
||||
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 call the fini
|
||||
* handlers and destructors at atexit() time.
|
||||
*/
|
||||
static ModulePtr 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.
|
||||
*/
|
||||
static char errbuf[BUFSIZ];
|
||||
static int errvalid;
|
||||
|
||||
extern char *strdup(const char *);
|
||||
static void caterr(char *);
|
||||
static int readExports(ModulePtr);
|
||||
static void terminate(void);
|
||||
static void *findMain(void);
|
||||
|
||||
void *
|
||||
dlopen(const char *path, int mode)
|
||||
{
|
||||
ModulePtr mp;
|
||||
static void *mainModule;
|
||||
|
||||
/*
|
||||
* Upon the first call register a terminate handler that will close all
|
||||
* libraries. Also get a reference to the main module for use with
|
||||
* loadbind.
|
||||
*/
|
||||
if (!mainModule)
|
||||
{
|
||||
if ((mainModule = findMain()) == NULL)
|
||||
return NULL;
|
||||
atexit(terminate);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the list of modules if we have the module already loaded.
|
||||
*/
|
||||
for (mp = modList; mp; mp = mp->next)
|
||||
if (strcmp(mp->name, path) == 0)
|
||||
{
|
||||
mp->refCnt++;
|
||||
return mp;
|
||||
}
|
||||
if ((mp = (ModulePtr) calloc(1, sizeof(*mp))) == NULL)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "calloc: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if ((mp->name = strdup(path)) == NULL)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "strdup: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
free(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, L_NOAUTODEFER, NULL)) == NULL)
|
||||
{
|
||||
free(mp->name);
|
||||
free(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 (errno == ENOEXEC)
|
||||
{
|
||||
char *tmp[BUFSIZ / sizeof(char *)];
|
||||
|
||||
if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1)
|
||||
strcpy(errbuf, strerror(errno));
|
||||
else
|
||||
{
|
||||
char **p;
|
||||
|
||||
for (p = tmp; *p; p++)
|
||||
caterr(*p);
|
||||
}
|
||||
}
|
||||
else
|
||||
strcat(errbuf, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
mp->refCnt = 1;
|
||||
mp->next = modList;
|
||||
modList = mp;
|
||||
if (loadbind(0, mainModule, mp->entry) == -1)
|
||||
{
|
||||
dlclose(mp);
|
||||
errvalid++;
|
||||
strcpy(errbuf, "loadbind: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the user wants global binding, loadbind against all other loaded
|
||||
* modules.
|
||||
*/
|
||||
if (mode & RTLD_GLOBAL)
|
||||
{
|
||||
ModulePtr mp1;
|
||||
|
||||
for (mp1 = mp->next; mp1; mp1 = mp1->next)
|
||||
if (loadbind(0, mp1->entry, mp->entry) == -1)
|
||||
{
|
||||
dlclose(mp);
|
||||
errvalid++;
|
||||
strcpy(errbuf, "loadbind: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (readExports(mp) == -1)
|
||||
{
|
||||
dlclose(mp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a dl_info structure, call the init function.
|
||||
*/
|
||||
if (mp->info = (struct dl_info *) dlsym(mp, "dl_info"))
|
||||
{
|
||||
if (mp->info->init)
|
||||
(*mp->info->init) ();
|
||||
}
|
||||
else
|
||||
errvalid = 0;
|
||||
|
||||
/*
|
||||
* If the shared object was compiled using xlC we will need to call static
|
||||
* constructors (and later on dlclose destructors).
|
||||
*/
|
||||
if (mp->cdtors = (CdtorPtr) dlsym(mp, "__cdtors"))
|
||||
{
|
||||
while (mp->cdtors->init)
|
||||
{
|
||||
(*mp->cdtors->init) ();
|
||||
mp->cdtors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
errvalid = 0;
|
||||
return mp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to decipher an AIX loader error message and append it
|
||||
* to our static error message buffer.
|
||||
*/
|
||||
static void
|
||||
caterr(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
switch (atoi(s))
|
||||
{
|
||||
case L_ERROR_TOOMANY:
|
||||
strcat(errbuf, "to many errors");
|
||||
break;
|
||||
case L_ERROR_NOLIB:
|
||||
strcat(errbuf, "cannot load library");
|
||||
strcat(errbuf, p);
|
||||
break;
|
||||
case L_ERROR_UNDEF:
|
||||
strcat(errbuf, "cannot 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:
|
||||
strcat(errbuf, strerror(atoi(++p)));
|
||||
break;
|
||||
default:
|
||||
strcat(errbuf, s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
dlsym(void *handle, const char *symbol)
|
||||
{
|
||||
ModulePtr mp = (ModulePtr) handle;
|
||||
ExportPtr ep;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Could speed up the 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)
|
||||
{
|
||||
ModulePtr mp = (ModulePtr) handle;
|
||||
int result;
|
||||
ModulePtr mp1;
|
||||
|
||||
if (--mp->refCnt > 0)
|
||||
return 0;
|
||||
if (mp->info && mp->info->fini)
|
||||
(*mp->info->fini) ();
|
||||
if (mp->cdtors)
|
||||
while (mp->cdtors->term)
|
||||
{
|
||||
(*mp->cdtors->term) ();
|
||||
mp->cdtors++;
|
||||
}
|
||||
result = unload(mp->entry);
|
||||
if (result == -1)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, strerror(errno));
|
||||
}
|
||||
if (mp->exports)
|
||||
{
|
||||
ExportPtr ep;
|
||||
int i;
|
||||
|
||||
for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
|
||||
if (ep->name)
|
||||
free(ep->name);
|
||||
free(mp->exports);
|
||||
}
|
||||
if (mp == modList)
|
||||
modList = mp->next;
|
||||
else
|
||||
{
|
||||
for (mp1 = modList; mp1; mp1 = mp1->next)
|
||||
if (mp1->next == mp)
|
||||
{
|
||||
mp1->next = mp->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(mp->name);
|
||||
free(mp);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
terminate(void)
|
||||
{
|
||||
while (modList)
|
||||
dlclose(modList);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the export table from the XCOFF .loader section.
|
||||
*/
|
||||
static int
|
||||
readExports(ModulePtr mp)
|
||||
{
|
||||
LDFILE *ldp = NULL;
|
||||
SCNHDR sh,
|
||||
shdata;
|
||||
LDHDR *lhp;
|
||||
char *ldbuf;
|
||||
LDSYM *ls;
|
||||
int i;
|
||||
ExportPtr ep;
|
||||
|
||||
if ((ldp = ldopen(mp->name, ldp)) == NULL)
|
||||
{
|
||||
struct ld_info *lp;
|
||||
char *buf;
|
||||
int size = 4 * 1024;
|
||||
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The module might be loaded due to the LIBPATH environment variable.
|
||||
* Search for the loaded module using L_GETINFO.
|
||||
*/
|
||||
if ((buf = malloc(size)) == NULL)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM)
|
||||
{
|
||||
free(buf);
|
||||
size += 4 * 1024;
|
||||
if ((buf = malloc(size)) == NULL)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (i == -1)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Traverse the list of loaded modules. The entry point returned by
|
||||
* load() does actually point to the data segment origin.
|
||||
*/
|
||||
lp = (struct ld_info *) buf;
|
||||
while (lp)
|
||||
{
|
||||
if (lp->ldinfo_dataorg == mp->entry)
|
||||
{
|
||||
ldp = ldopen(lp->ldinfo_filename, ldp);
|
||||
break;
|
||||
}
|
||||
if (lp->ldinfo_next == 0)
|
||||
lp = NULL;
|
||||
else
|
||||
lp = (struct ld_info *) ((char *) lp + lp->ldinfo_next);
|
||||
}
|
||||
free(buf);
|
||||
if (!ldp)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (TYPE(ldp) != U802TOCMAGIC)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: bad magic");
|
||||
while (ldclose(ldp) == FAILURE)
|
||||
;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the padding for the data section. This is needed for AIX 4.1
|
||||
* compilers. This is used when building the final function pointer to the
|
||||
* exported symbol.
|
||||
*/
|
||||
if (ldnshread(ldp, _DATA, &shdata) != SUCCESS)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: cannot read data section header");
|
||||
while (ldclose(ldp) == FAILURE)
|
||||
;
|
||||
return -1;
|
||||
}
|
||||
if (ldnshread(ldp, _LOADER, &sh) != SUCCESS)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: cannot read loader section header");
|
||||
while (ldclose(ldp) == FAILURE)
|
||||
;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We read the complete loader section in one chunk, this makes finding
|
||||
* long symbol names residing in the string table easier.
|
||||
*/
|
||||
if ((ldbuf = (char *) malloc(sh.s_size)) == NULL)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
while (ldclose(ldp) == FAILURE)
|
||||
;
|
||||
return -1;
|
||||
}
|
||||
if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: cannot seek to loader section");
|
||||
free(ldbuf);
|
||||
while (ldclose(ldp) == FAILURE)
|
||||
;
|
||||
return -1;
|
||||
}
|
||||
if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: cannot read loader section");
|
||||
free(ldbuf);
|
||||
while (ldclose(ldp) == FAILURE)
|
||||
;
|
||||
return -1;
|
||||
}
|
||||
lhp = (LDHDR *) ldbuf;
|
||||
ls = (LDSYM *) (ldbuf + LDHDRSZ);
|
||||
|
||||
/*
|
||||
* Count the number of exports to include in our export table.
|
||||
*/
|
||||
for (i = lhp->l_nsyms; i; i--, ls++)
|
||||
{
|
||||
if (!LDR_EXPORT(*ls))
|
||||
continue;
|
||||
mp->nExports++;
|
||||
}
|
||||
if ((mp->exports = (ExportPtr) calloc(mp->nExports, sizeof(*mp->exports))) == NULL)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "readExports: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
free(ldbuf);
|
||||
while (ldclose(ldp) == FAILURE)
|
||||
;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the export table. All entries are relative to the entry point
|
||||
* we got from load.
|
||||
*/
|
||||
ep = mp->exports;
|
||||
ls = (LDSYM *) (ldbuf + LDHDRSZ);
|
||||
for (i = lhp->l_nsyms; i; i--, ls++)
|
||||
{
|
||||
char *symname;
|
||||
char tmpsym[SYMNMLEN + 1];
|
||||
|
||||
if (!LDR_EXPORT(*ls))
|
||||
continue;
|
||||
if (ls->l_zeroes == 0)
|
||||
symname = ls->l_offset + lhp->l_stoff + ldbuf;
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The l_name member is not zero terminated, we must copy the
|
||||
* first SYMNMLEN chars and make sure we have a zero byte at the
|
||||
* end.
|
||||
*/
|
||||
strncpy(tmpsym, ls->l_name, SYMNMLEN);
|
||||
tmpsym[SYMNMLEN] = '\0';
|
||||
symname = tmpsym;
|
||||
}
|
||||
ep->name = strdup(symname);
|
||||
ep->addr = (void *) ((unsigned long) mp->entry +
|
||||
ls->l_value - shdata.s_vaddr);
|
||||
ep++;
|
||||
}
|
||||
free(ldbuf);
|
||||
while (ldclose(ldp) == FAILURE)
|
||||
;
|
||||
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)
|
||||
{
|
||||
struct ld_info *lp;
|
||||
char *buf;
|
||||
int size = 4 * 1024;
|
||||
int i;
|
||||
void *ret;
|
||||
|
||||
if ((buf = malloc(size)) == NULL)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "findMain: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM)
|
||||
{
|
||||
free(buf);
|
||||
size += 4 * 1024;
|
||||
if ((buf = malloc(size)) == NULL)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "findMain: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (i == -1)
|
||||
{
|
||||
errvalid++;
|
||||
strcpy(errbuf, "findMain: ");
|
||||
strcat(errbuf, strerror(errno));
|
||||
free(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;
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DLOPEN */
|
||||
|
|
|
@ -1,63 +1,39 @@
|
|||
/*
|
||||
* $PostgreSQL: pgsql/src/backend/port/dynloader/aix.h,v 1.13 2005/10/15 02:49:23 momjian Exp $
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* @(#)dlfcn.h 1.4 revision of 95/04/25 09:36:52
|
||||
* This is an unpublished work copyright (c) 1992 HELIOS Software GmbH
|
||||
* 30159 Hannover, Germany
|
||||
* aix.h
|
||||
* prototypes for AIX-specific routines
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/port/dynloader/aix.h,v 1.14 2009/04/21 21:15:50 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef PORT_PROTOS_H
|
||||
#define PORT_PROTOS_H
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
|
||||
#include <dlfcn.h>
|
||||
#else /* HAVE_DLOPEN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Mode flags for the dlopen routine.
|
||||
*/
|
||||
#define RTLD_LAZY 1 /* lazy function call binding */
|
||||
#define RTLD_NOW 2 /* immediate function call binding */
|
||||
#define RTLD_GLOBAL 0x100 /* allow symbols to be global */
|
||||
|
||||
/*
|
||||
* To be able to intialize, a library may provide a dl_info structure
|
||||
* that contains functions to be called to initialize and terminate.
|
||||
*/
|
||||
struct dl_info
|
||||
{
|
||||
void (*init) (void);
|
||||
void (*fini) (void);
|
||||
};
|
||||
|
||||
#if __STDC__ || defined(_IBMR2)
|
||||
void *dlopen(const char *path, int mode);
|
||||
void *dlsym(void *handle, const char *symbol);
|
||||
char *dlerror(void);
|
||||
int dlclose(void *handle);
|
||||
#else
|
||||
void *dlopen();
|
||||
void *dlsym();
|
||||
char *dlerror();
|
||||
int dlclose();
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_DLOPEN */
|
||||
|
||||
#include "utils/dynamic_loader.h"
|
||||
|
||||
/*
|
||||
* In some older systems, the RTLD_NOW flag isn't defined and the mode
|
||||
* argument to dlopen must always be 1. The RTLD_GLOBAL flag is wanted
|
||||
* if available, but it doesn't exist everywhere.
|
||||
* If it doesn't exist, set it to 0 so it has no effect.
|
||||
*/
|
||||
#ifndef RTLD_NOW
|
||||
#define RTLD_NOW 1
|
||||
#endif
|
||||
#ifndef RTLD_GLOBAL
|
||||
#define RTLD_GLOBAL 0
|
||||
#endif
|
||||
|
||||
#define pg_dlopen(f) dlopen((f), RTLD_NOW | RTLD_GLOBAL)
|
||||
#define pg_dlsym dlsym
|
||||
#define pg_dlclose dlclose
|
||||
#define pg_dlerror dlerror
|
||||
#define pg_dlsym(h, f) ((PGFunction) dlsym(h, f))
|
||||
#define pg_dlclose(h) dlclose(h)
|
||||
#define pg_dlerror() dlerror()
|
||||
|
||||
#endif /* PORT_PROTOS_H */
|
||||
|
|
Loading…
Reference in New Issue