os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclLoadAix.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* 
sl@0
     2
 * tclLoadAix.c --
sl@0
     3
 *
sl@0
     4
 *	This file implements the dlopen and dlsym APIs under the
sl@0
     5
 *	AIX operating system, to enable the Tcl "load" command to
sl@0
     6
 *	work.  This code was provided by Jens-Uwe Mager.
sl@0
     7
 *
sl@0
     8
 *	This file is subject to the following copyright notice, which is
sl@0
     9
 *	different from the notice used elsewhere in Tcl.  The file has
sl@0
    10
 *	been modified to incorporate the file dlfcn.h in-line.
sl@0
    11
 *
sl@0
    12
 *	Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH
sl@0
    13
 *	Not derived from licensed software.
sl@0
    14
sl@0
    15
 *	Permission is granted to freely use, copy, modify, and redistribute
sl@0
    16
 *	this software, provided that the author is not construed to be liable
sl@0
    17
 *	for any results of using the software, alterations are clearly marked
sl@0
    18
 *	as such, and this notice is not modified.
sl@0
    19
 *
sl@0
    20
 * RCS: @(#) $Id: tclLoadAix.c,v 1.3 1999/04/16 00:48:04 stanton Exp $
sl@0
    21
 *
sl@0
    22
 * Note:  this file has been altered from the original in a few
sl@0
    23
 * ways in order to work properly with Tcl.
sl@0
    24
 */
sl@0
    25
sl@0
    26
/*
sl@0
    27
 * @(#)dlfcn.c	1.7 revision of 95/08/14  19:08:38
sl@0
    28
 * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH
sl@0
    29
 * 30159 Hannover, Germany
sl@0
    30
 */
sl@0
    31
sl@0
    32
#include <stdio.h>
sl@0
    33
#include <errno.h>
sl@0
    34
#include <string.h>
sl@0
    35
#include <stdlib.h>
sl@0
    36
#include <sys/types.h>
sl@0
    37
#include <sys/ldr.h>
sl@0
    38
#include <a.out.h>
sl@0
    39
#include <ldfcn.h>
sl@0
    40
#include "../compat/dlfcn.h"
sl@0
    41
sl@0
    42
/*
sl@0
    43
 * We simulate dlopen() et al. through a call to load. Because AIX has
sl@0
    44
 * no call to find an exported symbol we read the loader section of the
sl@0
    45
 * loaded module and build a list of exported symbols and their virtual
sl@0
    46
 * address.
sl@0
    47
 */
sl@0
    48
sl@0
    49
typedef struct {
sl@0
    50
	char		*name;		/* the symbols's name */
sl@0
    51
	void		*addr;		/* its relocated virtual address */
sl@0
    52
} Export, *ExportPtr;
sl@0
    53
sl@0
    54
/*
sl@0
    55
 * xlC uses the following structure to list its constructors and
sl@0
    56
 * destructors. This is gleaned from the output of munch.
sl@0
    57
 */
sl@0
    58
typedef struct {
sl@0
    59
	void (*init)(void);		/* call static constructors */
sl@0
    60
	void (*term)(void);		/* call static destructors */
sl@0
    61
} Cdtor, *CdtorPtr;
sl@0
    62
sl@0
    63
/*
sl@0
    64
 * The void * handle returned from dlopen is actually a ModulePtr.
sl@0
    65
 */
sl@0
    66
typedef struct Module {
sl@0
    67
	struct Module	*next;
sl@0
    68
	char		*name;		/* module name for refcounting */
sl@0
    69
	int		refCnt;		/* the number of references */
sl@0
    70
	void		*entry;		/* entry point from load */
sl@0
    71
	struct dl_info	*info;		/* optional init/terminate functions */
sl@0
    72
	CdtorPtr	cdtors;		/* optional C++ constructors */
sl@0
    73
	int		nExports;	/* the number of exports found */
sl@0
    74
	ExportPtr	exports;	/* the array of exports */
sl@0
    75
} Module, *ModulePtr;
sl@0
    76
sl@0
    77
/*
sl@0
    78
 * We keep a list of all loaded modules to be able to call the fini
sl@0
    79
 * handlers and destructors at atexit() time.
sl@0
    80
 */
sl@0
    81
static ModulePtr modList;
sl@0
    82
sl@0
    83
/*
sl@0
    84
 * The last error from one of the dl* routines is kept in static
sl@0
    85
 * variables here. Each error is returned only once to the caller.
sl@0
    86
 */
sl@0
    87
static char errbuf[BUFSIZ];
sl@0
    88
static int errvalid;
sl@0
    89
sl@0
    90
static void caterr(char *);
sl@0
    91
static int readExports(ModulePtr);
sl@0
    92
static void terminate(void);
sl@0
    93
static void *findMain(void);
sl@0
    94
sl@0
    95
VOID *dlopen(const char *path, int mode)
sl@0
    96
{
sl@0
    97
	register ModulePtr mp;
sl@0
    98
	static void *mainModule;
sl@0
    99
sl@0
   100
	/*
sl@0
   101
	 * Upon the first call register a terminate handler that will
sl@0
   102
	 * close all libraries. Also get a reference to the main module
sl@0
   103
	 * for use with loadbind.
sl@0
   104
	 */
sl@0
   105
	if (!mainModule) {
sl@0
   106
		if ((mainModule = findMain()) == NULL)
sl@0
   107
			return NULL;
sl@0
   108
		atexit(terminate);
sl@0
   109
	}
sl@0
   110
	/*
sl@0
   111
	 * Scan the list of modules if we have the module already loaded.
sl@0
   112
	 */
sl@0
   113
	for (mp = modList; mp; mp = mp->next)
sl@0
   114
		if (strcmp(mp->name, path) == 0) {
sl@0
   115
			mp->refCnt++;
sl@0
   116
			return (VOID *) mp;
sl@0
   117
		}
sl@0
   118
	if ((mp = (ModulePtr)calloc(1, sizeof(*mp))) == NULL) {
sl@0
   119
		errvalid++;
sl@0
   120
		strcpy(errbuf, "calloc: ");
sl@0
   121
		strcat(errbuf, strerror(errno));
sl@0
   122
		return (VOID *) NULL;
sl@0
   123
	}
sl@0
   124
	mp->name = malloc((unsigned) (strlen(path) + 1));
sl@0
   125
	strcpy(mp->name, path);
sl@0
   126
	/*
sl@0
   127
	 * load should be declared load(const char *...). Thus we
sl@0
   128
	 * cast the path to a normal char *. Ugly.
sl@0
   129
	 */
sl@0
   130
	if ((mp->entry = (void *)load((char *)path, L_NOAUTODEFER, NULL)) == NULL) {
sl@0
   131
		free(mp->name);
sl@0
   132
		free(mp);
sl@0
   133
		errvalid++;
sl@0
   134
		strcpy(errbuf, "dlopen: ");
sl@0
   135
		strcat(errbuf, path);
sl@0
   136
		strcat(errbuf, ": ");
sl@0
   137
		/*
sl@0
   138
		 * If AIX says the file is not executable, the error
sl@0
   139
		 * can be further described by querying the loader about
sl@0
   140
		 * the last error.
sl@0
   141
		 */
sl@0
   142
		if (errno == ENOEXEC) {
sl@0
   143
			char *tmp[BUFSIZ/sizeof(char *)];
sl@0
   144
			if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1)
sl@0
   145
				strcpy(errbuf, strerror(errno));
sl@0
   146
			else {
sl@0
   147
				char **p;
sl@0
   148
				for (p = tmp; *p; p++)
sl@0
   149
					caterr(*p);
sl@0
   150
			}
sl@0
   151
		} else
sl@0
   152
			strcat(errbuf, strerror(errno));
sl@0
   153
		return (VOID *) NULL;
sl@0
   154
	}
sl@0
   155
	mp->refCnt = 1;
sl@0
   156
	mp->next = modList;
sl@0
   157
	modList = mp;
sl@0
   158
	if (loadbind(0, mainModule, mp->entry) == -1) {
sl@0
   159
		dlclose(mp);
sl@0
   160
		errvalid++;
sl@0
   161
		strcpy(errbuf, "loadbind: ");
sl@0
   162
		strcat(errbuf, strerror(errno));
sl@0
   163
		return (VOID *) NULL;
sl@0
   164
	}
sl@0
   165
	/*
sl@0
   166
	 * If the user wants global binding, loadbind against all other
sl@0
   167
	 * loaded modules.
sl@0
   168
	 */
sl@0
   169
	if (mode & RTLD_GLOBAL) {
sl@0
   170
		register ModulePtr mp1;
sl@0
   171
		for (mp1 = mp->next; mp1; mp1 = mp1->next)
sl@0
   172
			if (loadbind(0, mp1->entry, mp->entry) == -1) {
sl@0
   173
				dlclose(mp);
sl@0
   174
				errvalid++;
sl@0
   175
				strcpy(errbuf, "loadbind: ");
sl@0
   176
				strcat(errbuf, strerror(errno));
sl@0
   177
				return (VOID *) NULL;
sl@0
   178
			}
sl@0
   179
	}
sl@0
   180
	if (readExports(mp) == -1) {
sl@0
   181
		dlclose(mp);
sl@0
   182
		return (VOID *) NULL;
sl@0
   183
	}
sl@0
   184
	/*
sl@0
   185
	 * If there is a dl_info structure, call the init function.
sl@0
   186
	 */
sl@0
   187
	if (mp->info = (struct dl_info *)dlsym(mp, "dl_info")) {
sl@0
   188
		if (mp->info->init)
sl@0
   189
			(*mp->info->init)();
sl@0
   190
	} else
sl@0
   191
		errvalid = 0;
sl@0
   192
	/*
sl@0
   193
	 * If the shared object was compiled using xlC we will need
sl@0
   194
	 * to call static constructors (and later on dlclose destructors).
sl@0
   195
	 */
sl@0
   196
	if (mp->cdtors = (CdtorPtr)dlsym(mp, "__cdtors")) {
sl@0
   197
		while (mp->cdtors->init) {
sl@0
   198
			(*mp->cdtors->init)();
sl@0
   199
			mp->cdtors++;
sl@0
   200
		}
sl@0
   201
	} else
sl@0
   202
		errvalid = 0;
sl@0
   203
	return (VOID *) mp;
sl@0
   204
}
sl@0
   205
sl@0
   206
/*
sl@0
   207
 * Attempt to decipher an AIX loader error message and append it
sl@0
   208
 * to our static error message buffer.
sl@0
   209
 */
sl@0
   210
static void caterr(char *s)
sl@0
   211
{
sl@0
   212
	register char *p = s;
sl@0
   213
sl@0
   214
	while (*p >= '0' && *p <= '9')
sl@0
   215
		p++;
sl@0
   216
	switch(atoi(s)) {		/* INTL: "C", UTF safe. */
sl@0
   217
	case L_ERROR_TOOMANY:
sl@0
   218
		strcat(errbuf, "to many errors");
sl@0
   219
		break;
sl@0
   220
	case L_ERROR_NOLIB:
sl@0
   221
		strcat(errbuf, "can't load library");
sl@0
   222
		strcat(errbuf, p);
sl@0
   223
		break;
sl@0
   224
	case L_ERROR_UNDEF:
sl@0
   225
		strcat(errbuf, "can't find symbol");
sl@0
   226
		strcat(errbuf, p);
sl@0
   227
		break;
sl@0
   228
	case L_ERROR_RLDBAD:
sl@0
   229
		strcat(errbuf, "bad RLD");
sl@0
   230
		strcat(errbuf, p);
sl@0
   231
		break;
sl@0
   232
	case L_ERROR_FORMAT:
sl@0
   233
		strcat(errbuf, "bad exec format in");
sl@0
   234
		strcat(errbuf, p);
sl@0
   235
		break;
sl@0
   236
	case L_ERROR_ERRNO:
sl@0
   237
		strcat(errbuf, strerror(atoi(++p)));	/* INTL: "C", UTF safe. */
sl@0
   238
		break;
sl@0
   239
	default:
sl@0
   240
		strcat(errbuf, s);
sl@0
   241
		break;
sl@0
   242
	}
sl@0
   243
}
sl@0
   244
sl@0
   245
VOID *dlsym(void *handle, const char *symbol)
sl@0
   246
{
sl@0
   247
	register ModulePtr mp = (ModulePtr)handle;
sl@0
   248
	register ExportPtr ep;
sl@0
   249
	register int i;
sl@0
   250
sl@0
   251
	/*
sl@0
   252
	 * Could speed up the search, but I assume that one assigns
sl@0
   253
	 * the result to function pointers anyways.
sl@0
   254
	 */
sl@0
   255
	for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
sl@0
   256
		if (strcmp(ep->name, symbol) == 0)
sl@0
   257
			return ep->addr;
sl@0
   258
	errvalid++;
sl@0
   259
	strcpy(errbuf, "dlsym: undefined symbol ");
sl@0
   260
	strcat(errbuf, symbol);
sl@0
   261
	return NULL;
sl@0
   262
}
sl@0
   263
sl@0
   264
char *dlerror(void)
sl@0
   265
{
sl@0
   266
	if (errvalid) {
sl@0
   267
		errvalid = 0;
sl@0
   268
		return errbuf;
sl@0
   269
	}
sl@0
   270
	return NULL;
sl@0
   271
}
sl@0
   272
sl@0
   273
int dlclose(void *handle)
sl@0
   274
{
sl@0
   275
	register ModulePtr mp = (ModulePtr)handle;
sl@0
   276
	int result;
sl@0
   277
	register ModulePtr mp1;
sl@0
   278
sl@0
   279
	if (--mp->refCnt > 0)
sl@0
   280
		return 0;
sl@0
   281
	if (mp->info && mp->info->fini)
sl@0
   282
		(*mp->info->fini)();
sl@0
   283
	if (mp->cdtors)
sl@0
   284
		while (mp->cdtors->term) {
sl@0
   285
			(*mp->cdtors->term)();
sl@0
   286
			mp->cdtors++;
sl@0
   287
		}
sl@0
   288
	result = unload(mp->entry);
sl@0
   289
	if (result == -1) {
sl@0
   290
		errvalid++;
sl@0
   291
		strcpy(errbuf, strerror(errno));
sl@0
   292
	}
sl@0
   293
	if (mp->exports) {
sl@0
   294
		register ExportPtr ep;
sl@0
   295
		register int i;
sl@0
   296
		for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
sl@0
   297
			if (ep->name)
sl@0
   298
				free(ep->name);
sl@0
   299
		free(mp->exports);
sl@0
   300
	}
sl@0
   301
	if (mp == modList)
sl@0
   302
		modList = mp->next;
sl@0
   303
	else {
sl@0
   304
		for (mp1 = modList; mp1; mp1 = mp1->next)
sl@0
   305
			if (mp1->next == mp) {
sl@0
   306
				mp1->next = mp->next;
sl@0
   307
				break;
sl@0
   308
			}
sl@0
   309
	}
sl@0
   310
	free(mp->name);
sl@0
   311
	free(mp);
sl@0
   312
	return result;
sl@0
   313
}
sl@0
   314
sl@0
   315
static void terminate(void)
sl@0
   316
{
sl@0
   317
	while (modList)
sl@0
   318
		dlclose(modList);
sl@0
   319
}
sl@0
   320
sl@0
   321
/*
sl@0
   322
 * Build the export table from the XCOFF .loader section.
sl@0
   323
 */
sl@0
   324
static int readExports(ModulePtr mp)
sl@0
   325
{
sl@0
   326
	LDFILE *ldp = NULL;
sl@0
   327
	SCNHDR sh, shdata;
sl@0
   328
	LDHDR *lhp;
sl@0
   329
	char *ldbuf;
sl@0
   330
	LDSYM *ls;
sl@0
   331
	int i;
sl@0
   332
	ExportPtr ep;
sl@0
   333
sl@0
   334
	if ((ldp = ldopen(mp->name, ldp)) == NULL) {
sl@0
   335
		struct ld_info *lp;
sl@0
   336
		char *buf;
sl@0
   337
		int size = 4*1024;
sl@0
   338
		if (errno != ENOENT) {
sl@0
   339
			errvalid++;
sl@0
   340
			strcpy(errbuf, "readExports: ");
sl@0
   341
			strcat(errbuf, strerror(errno));
sl@0
   342
			return -1;
sl@0
   343
		}
sl@0
   344
		/*
sl@0
   345
		 * The module might be loaded due to the LIBPATH
sl@0
   346
		 * environment variable. Search for the loaded
sl@0
   347
		 * module using L_GETINFO.
sl@0
   348
		 */
sl@0
   349
		if ((buf = malloc(size)) == NULL) {
sl@0
   350
			errvalid++;
sl@0
   351
			strcpy(errbuf, "readExports: ");
sl@0
   352
			strcat(errbuf, strerror(errno));
sl@0
   353
			return -1;
sl@0
   354
		}
sl@0
   355
		while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
sl@0
   356
			free(buf);
sl@0
   357
			size += 4*1024;
sl@0
   358
			if ((buf = malloc(size)) == NULL) {
sl@0
   359
				errvalid++;
sl@0
   360
				strcpy(errbuf, "readExports: ");
sl@0
   361
				strcat(errbuf, strerror(errno));
sl@0
   362
				return -1;
sl@0
   363
			}
sl@0
   364
		}
sl@0
   365
		if (i == -1) {
sl@0
   366
			errvalid++;
sl@0
   367
			strcpy(errbuf, "readExports: ");
sl@0
   368
			strcat(errbuf, strerror(errno));
sl@0
   369
			free(buf);
sl@0
   370
			return -1;
sl@0
   371
		}
sl@0
   372
		/*
sl@0
   373
		 * Traverse the list of loaded modules. The entry point
sl@0
   374
		 * returned by load() does actually point to the data
sl@0
   375
		 * segment origin.
sl@0
   376
		 */
sl@0
   377
		lp = (struct ld_info *)buf;
sl@0
   378
		while (lp) {
sl@0
   379
			if (lp->ldinfo_dataorg == mp->entry) {
sl@0
   380
				ldp = ldopen(lp->ldinfo_filename, ldp);
sl@0
   381
				break;
sl@0
   382
			}
sl@0
   383
			if (lp->ldinfo_next == 0)
sl@0
   384
				lp = NULL;
sl@0
   385
			else
sl@0
   386
				lp = (struct ld_info *)((char *)lp + lp->ldinfo_next);
sl@0
   387
		}
sl@0
   388
		free(buf);
sl@0
   389
		if (!ldp) {
sl@0
   390
			errvalid++;
sl@0
   391
			strcpy(errbuf, "readExports: ");
sl@0
   392
			strcat(errbuf, strerror(errno));
sl@0
   393
			return -1;
sl@0
   394
		}
sl@0
   395
	}
sl@0
   396
	if (TYPE(ldp) != U802TOCMAGIC) {
sl@0
   397
		errvalid++;
sl@0
   398
		strcpy(errbuf, "readExports: bad magic");
sl@0
   399
		while(ldclose(ldp) == FAILURE)
sl@0
   400
			;
sl@0
   401
		return -1;
sl@0
   402
	}
sl@0
   403
	/*
sl@0
   404
	 * Get the padding for the data section. This is needed for
sl@0
   405
	 * AIX 4.1 compilers. This is used when building the final
sl@0
   406
	 * function pointer to the exported symbol.
sl@0
   407
	 */
sl@0
   408
	if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) {
sl@0
   409
		errvalid++;
sl@0
   410
		strcpy(errbuf, "readExports: cannot read data section header");
sl@0
   411
		while(ldclose(ldp) == FAILURE)
sl@0
   412
			;
sl@0
   413
		return -1;
sl@0
   414
	}
sl@0
   415
	if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) {
sl@0
   416
		errvalid++;
sl@0
   417
		strcpy(errbuf, "readExports: cannot read loader section header");
sl@0
   418
		while(ldclose(ldp) == FAILURE)
sl@0
   419
			;
sl@0
   420
		return -1;
sl@0
   421
	}
sl@0
   422
	/*
sl@0
   423
	 * We read the complete loader section in one chunk, this makes
sl@0
   424
	 * finding long symbol names residing in the string table easier.
sl@0
   425
	 */
sl@0
   426
	if ((ldbuf = (char *)malloc(sh.s_size)) == NULL) {
sl@0
   427
		errvalid++;
sl@0
   428
		strcpy(errbuf, "readExports: ");
sl@0
   429
		strcat(errbuf, strerror(errno));
sl@0
   430
		while(ldclose(ldp) == FAILURE)
sl@0
   431
			;
sl@0
   432
		return -1;
sl@0
   433
	}
sl@0
   434
	if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) {
sl@0
   435
		errvalid++;
sl@0
   436
		strcpy(errbuf, "readExports: cannot seek to loader section");
sl@0
   437
		free(ldbuf);
sl@0
   438
		while(ldclose(ldp) == FAILURE)
sl@0
   439
			;
sl@0
   440
		return -1;
sl@0
   441
	}
sl@0
   442
	if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) {
sl@0
   443
		errvalid++;
sl@0
   444
		strcpy(errbuf, "readExports: cannot read loader section");
sl@0
   445
		free(ldbuf);
sl@0
   446
		while(ldclose(ldp) == FAILURE)
sl@0
   447
			;
sl@0
   448
		return -1;
sl@0
   449
	}
sl@0
   450
	lhp = (LDHDR *)ldbuf;
sl@0
   451
	ls = (LDSYM *)(ldbuf+LDHDRSZ);
sl@0
   452
	/*
sl@0
   453
	 * Count the number of exports to include in our export table.
sl@0
   454
	 */
sl@0
   455
	for (i = lhp->l_nsyms; i; i--, ls++) {
sl@0
   456
		if (!LDR_EXPORT(*ls))
sl@0
   457
			continue;
sl@0
   458
		mp->nExports++;
sl@0
   459
	}
sl@0
   460
	if ((mp->exports = (ExportPtr)calloc(mp->nExports, sizeof(*mp->exports))) == NULL) {
sl@0
   461
		errvalid++;
sl@0
   462
		strcpy(errbuf, "readExports: ");
sl@0
   463
		strcat(errbuf, strerror(errno));
sl@0
   464
		free(ldbuf);
sl@0
   465
		while(ldclose(ldp) == FAILURE)
sl@0
   466
			;
sl@0
   467
		return -1;
sl@0
   468
	}
sl@0
   469
	/*
sl@0
   470
	 * Fill in the export table. All entries are relative to
sl@0
   471
	 * the entry point we got from load.
sl@0
   472
	 */
sl@0
   473
	ep = mp->exports;
sl@0
   474
	ls = (LDSYM *)(ldbuf+LDHDRSZ);
sl@0
   475
	for (i = lhp->l_nsyms; i; i--, ls++) {
sl@0
   476
		char *symname;
sl@0
   477
		char tmpsym[SYMNMLEN+1];
sl@0
   478
		if (!LDR_EXPORT(*ls))
sl@0
   479
			continue;
sl@0
   480
		if (ls->l_zeroes == 0)
sl@0
   481
			symname = ls->l_offset+lhp->l_stoff+ldbuf;
sl@0
   482
		else {
sl@0
   483
			/*
sl@0
   484
			 * The l_name member is not zero terminated, we
sl@0
   485
			 * must copy the first SYMNMLEN chars and make
sl@0
   486
			 * sure we have a zero byte at the end.
sl@0
   487
			 */
sl@0
   488
			strncpy(tmpsym, ls->l_name, SYMNMLEN);
sl@0
   489
			tmpsym[SYMNMLEN] = '\0';
sl@0
   490
			symname = tmpsym;
sl@0
   491
		}
sl@0
   492
		ep->name = malloc((unsigned) (strlen(symname) + 1));
sl@0
   493
		strcpy(ep->name, symname);
sl@0
   494
		ep->addr = (void *)((unsigned long)mp->entry +
sl@0
   495
					ls->l_value - shdata.s_vaddr);
sl@0
   496
		ep++;
sl@0
   497
	}
sl@0
   498
	free(ldbuf);
sl@0
   499
	while(ldclose(ldp) == FAILURE)
sl@0
   500
		;
sl@0
   501
	return 0;
sl@0
   502
}
sl@0
   503
sl@0
   504
/*
sl@0
   505
 * Find the main modules entry point. This is used as export pointer
sl@0
   506
 * for loadbind() to be able to resolve references to the main part.
sl@0
   507
 */
sl@0
   508
static void * findMain(void)
sl@0
   509
{
sl@0
   510
	struct ld_info *lp;
sl@0
   511
	char *buf;
sl@0
   512
	int size = 4*1024;
sl@0
   513
	int i;
sl@0
   514
	void *ret;
sl@0
   515
sl@0
   516
	if ((buf = malloc(size)) == NULL) {
sl@0
   517
		errvalid++;
sl@0
   518
		strcpy(errbuf, "findMain: ");
sl@0
   519
		strcat(errbuf, strerror(errno));
sl@0
   520
		return NULL;
sl@0
   521
	}
sl@0
   522
	while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
sl@0
   523
		free(buf);
sl@0
   524
		size += 4*1024;
sl@0
   525
		if ((buf = malloc(size)) == NULL) {
sl@0
   526
			errvalid++;
sl@0
   527
			strcpy(errbuf, "findMain: ");
sl@0
   528
			strcat(errbuf, strerror(errno));
sl@0
   529
			return NULL;
sl@0
   530
		}
sl@0
   531
	}
sl@0
   532
	if (i == -1) {
sl@0
   533
		errvalid++;
sl@0
   534
		strcpy(errbuf, "findMain: ");
sl@0
   535
		strcat(errbuf, strerror(errno));
sl@0
   536
		free(buf);
sl@0
   537
		return NULL;
sl@0
   538
	}
sl@0
   539
	/*
sl@0
   540
	 * The first entry is the main module. The entry point
sl@0
   541
	 * returned by load() does actually point to the data
sl@0
   542
	 * segment origin.
sl@0
   543
	 */
sl@0
   544
	lp = (struct ld_info *)buf;
sl@0
   545
	ret = lp->ldinfo_dataorg;
sl@0
   546
	free(buf);
sl@0
   547
	return ret;
sl@0
   548
}
sl@0
   549