155682Smarkm/* 255682Smarkm * @(#)dlfcn.c 1.11 revision of 96/04/10 20:12:51 355682Smarkm * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH 455682Smarkm * 30159 Hannover, Germany 555682Smarkm */ 655682Smarkm 755682Smarkm/* 855682Smarkm * Changes marked with `--jwe' were made on April 7 1996 by John W. Eaton 955682Smarkm * <jwe@bevo.che.wisc.edu> to support g++ and/or use with Octave. 1055682Smarkm */ 1155682Smarkm 1255682Smarkm/* 1355682Smarkm * This makes my life easier with Octave. --jwe 1455682Smarkm */ 1555682Smarkm#ifdef HAVE_CONFIG_H 1655682Smarkm#include <config.h> 1755682Smarkm#endif 1855682Smarkm 1955682Smarkm#include <stdio.h> 2055682Smarkm#include <errno.h> 2155682Smarkm#include <string.h> 2255682Smarkm#include <stdlib.h> 2355682Smarkm#include <sys/types.h> 2455682Smarkm#include <sys/ldr.h> 2555682Smarkm#include <a.out.h> 2655682Smarkm#include <ldfcn.h> 2755682Smarkm#include "dlfcn.h" 2855682Smarkm 2955682Smarkm/* 3055682Smarkm * We simulate dlopen() et al. through a call to load. Because AIX has 3155682Smarkm * no call to find an exported symbol we read the loader section of the 3255682Smarkm * loaded module and build a list of exported symbols and their virtual 3355682Smarkm * address. 3455682Smarkm */ 3555682Smarkm 3655682Smarkmtypedef struct { 3755682Smarkm char *name; /* the symbols's name */ 3855682Smarkm void *addr; /* its relocated virtual address */ 3955682Smarkm} Export, *ExportPtr; 4055682Smarkm 4155682Smarkm/* 4255682Smarkm * xlC uses the following structure to list its constructors and 4355682Smarkm * destructors. This is gleaned from the output of munch. 4455682Smarkm */ 4555682Smarkmtypedef struct { 4655682Smarkm void (*init)(void); /* call static constructors */ 4755682Smarkm void (*term)(void); /* call static destructors */ 4855682Smarkm} Cdtor, *CdtorPtr; 4955682Smarkm 5055682Smarkmtypedef void (*GccCDtorPtr)(void); 5155682Smarkm 5255682Smarkm/* 5355682Smarkm * The void * handle returned from dlopen is actually a ModulePtr. 5455682Smarkm */ 5555682Smarkmtypedef struct Module { 5655682Smarkm struct Module *next; 5755682Smarkm char *name; /* module name for refcounting */ 5855682Smarkm int refCnt; /* the number of references */ 5955682Smarkm void *entry; /* entry point from load */ 6055682Smarkm struct dl_info *info; /* optional init/terminate functions */ 6155682Smarkm CdtorPtr cdtors; /* optional C++ constructors */ 6255682Smarkm GccCDtorPtr gcc_ctor; /* g++ constructors --jwe */ 6355682Smarkm GccCDtorPtr gcc_dtor; /* g++ destructors --jwe */ 6455682Smarkm int nExports; /* the number of exports found */ 6555682Smarkm ExportPtr exports; /* the array of exports */ 6655682Smarkm} Module, *ModulePtr; 6755682Smarkm 6855682Smarkm/* 6955682Smarkm * We keep a list of all loaded modules to be able to call the fini 7055682Smarkm * handlers and destructors at atexit() time. 7155682Smarkm */ 7255682Smarkmstatic ModulePtr modList; 7355682Smarkm 7455682Smarkm/* 7555682Smarkm * The last error from one of the dl* routines is kept in static 7655682Smarkm * variables here. Each error is returned only once to the caller. 7755682Smarkm */ 7855682Smarkmstatic char errbuf[BUFSIZ]; 7955682Smarkmstatic int errvalid; 8055682Smarkm 8155682Smarkm/* 8255682Smarkm * The `fixed' gcc header files on AIX 3.2.5 provide a prototype for 8355682Smarkm * strdup(). --jwe 8455682Smarkm */ 8555682Smarkm#ifndef HAVE_STRDUP 8655682Smarkmextern char *strdup(const char *); 8755682Smarkm#endif 8855682Smarkmstatic void caterr(char *); 8955682Smarkmstatic int readExports(ModulePtr); 9055682Smarkmstatic void terminate(void); 9155682Smarkmstatic void *findMain(void); 9255682Smarkm 9355682Smarkmvoid *dlopen(const char *path, int mode) 9455682Smarkm{ 9555682Smarkm ModulePtr mp; 9655682Smarkm static void *mainModule; 9755682Smarkm 9855682Smarkm /* 9955682Smarkm * Upon the first call register a terminate handler that will 10055682Smarkm * close all libraries. Also get a reference to the main module 10155682Smarkm * for use with loadbind. 10255682Smarkm */ 10355682Smarkm if (!mainModule) { 10455682Smarkm if ((mainModule = findMain()) == NULL) 10555682Smarkm return NULL; 10655682Smarkm atexit(terminate); 10755682Smarkm } 10855682Smarkm /* 10955682Smarkm * Scan the list of modules if we have the module already loaded. 11055682Smarkm */ 11155682Smarkm for (mp = modList; mp; mp = mp->next) 11255682Smarkm if (strcmp(mp->name, path) == 0) { 11355682Smarkm mp->refCnt++; 11455682Smarkm return mp; 11555682Smarkm } 11655682Smarkm if ((mp = (ModulePtr)calloc(1, sizeof(*mp))) == NULL) { 11755682Smarkm errvalid++; 11872445Sassar snprintf (errbuf, sizeof(errbuf), "calloc: %s", strerror(errno)); 11955682Smarkm return NULL; 12055682Smarkm } 12155682Smarkm if ((mp->name = strdup(path)) == NULL) { 12255682Smarkm errvalid++; 12372445Sassar snprintf (errbuf, sizeof(errbuf), "strdup: %s", strerror(errno)); 12455682Smarkm free(mp); 12555682Smarkm return NULL; 12655682Smarkm } 12755682Smarkm /* 12855682Smarkm * load should be declared load(const char *...). Thus we 12955682Smarkm * cast the path to a normal char *. Ugly. 13055682Smarkm */ 13155682Smarkm if ((mp->entry = (void *)load((char *)path, L_NOAUTODEFER, NULL)) == NULL) { 13255682Smarkm free(mp->name); 13355682Smarkm free(mp); 13455682Smarkm errvalid++; 13555682Smarkm snprintf (errbuf, sizeof(errbuf), 13655682Smarkm "dlopen: %s: ", path); 13755682Smarkm /* 13855682Smarkm * If AIX says the file is not executable, the error 13955682Smarkm * can be further described by querying the loader about 14055682Smarkm * the last error. 14155682Smarkm */ 14255682Smarkm if (errno == ENOEXEC) { 14355682Smarkm char *tmp[BUFSIZ/sizeof(char *)]; 14455682Smarkm if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1) 14555682Smarkm strlcpy(errbuf, 14655682Smarkm strerror(errno), 14755682Smarkm sizeof(errbuf)); 14855682Smarkm else { 14955682Smarkm char **p; 15055682Smarkm for (p = tmp; *p; p++) 15155682Smarkm caterr(*p); 15255682Smarkm } 15355682Smarkm } else 15455682Smarkm strlcat(errbuf, 15555682Smarkm strerror(errno), 15655682Smarkm sizeof(errbuf)); 15755682Smarkm return NULL; 15855682Smarkm } 15955682Smarkm mp->refCnt = 1; 16055682Smarkm mp->next = modList; 16155682Smarkm modList = mp; 16255682Smarkm if (loadbind(0, mainModule, mp->entry) == -1) { 16355682Smarkm dlclose(mp); 16455682Smarkm errvalid++; 16555682Smarkm snprintf (errbuf, sizeof(errbuf), 16655682Smarkm "loadbind: %s", strerror(errno)); 16755682Smarkm return NULL; 16855682Smarkm } 16955682Smarkm /* 17055682Smarkm * If the user wants global binding, loadbind against all other 17155682Smarkm * loaded modules. 17255682Smarkm */ 17355682Smarkm if (mode & RTLD_GLOBAL) { 17455682Smarkm ModulePtr mp1; 17555682Smarkm for (mp1 = mp->next; mp1; mp1 = mp1->next) 17655682Smarkm if (loadbind(0, mp1->entry, mp->entry) == -1) { 17755682Smarkm dlclose(mp); 17855682Smarkm errvalid++; 17955682Smarkm snprintf (errbuf, sizeof(errbuf), 18055682Smarkm "loadbind: %s", 18155682Smarkm strerror(errno)); 18255682Smarkm return NULL; 18355682Smarkm } 18455682Smarkm } 18555682Smarkm if (readExports(mp) == -1) { 18655682Smarkm dlclose(mp); 18755682Smarkm return NULL; 18855682Smarkm } 18955682Smarkm /* 19055682Smarkm * If there is a dl_info structure, call the init function. 19155682Smarkm */ 19255682Smarkm if (mp->info = (struct dl_info *)dlsym(mp, "dl_info")) { 19355682Smarkm if (mp->info->init) 19455682Smarkm (*mp->info->init)(); 19555682Smarkm } else 19655682Smarkm errvalid = 0; 19755682Smarkm /* 19855682Smarkm * If the shared object was compiled using xlC we will need 19955682Smarkm * to call static constructors (and later on dlclose destructors). 20055682Smarkm */ 20155682Smarkm if (mp->cdtors = (CdtorPtr)dlsym(mp, "__cdtors")) { 20255682Smarkm CdtorPtr cp = mp->cdtors; 20355682Smarkm while (cp->init || cp->term) { 20455682Smarkm if (cp->init && cp->init != (void (*)(void))0xffffffff) 20555682Smarkm (*cp->init)(); 20655682Smarkm cp++; 20755682Smarkm } 20855682Smarkm /* 20955682Smarkm * If the shared object was compiled using g++, we will need 21055682Smarkm * to call global constructors using the _GLOBAL__DI function, 21155682Smarkm * and later, global destructors using the _GLOBAL_DD 21255682Smarkm * funciton. --jwe 21355682Smarkm */ 21455682Smarkm } else if (mp->gcc_ctor = (GccCDtorPtr)dlsym(mp, "_GLOBAL__DI")) { 21555682Smarkm (*mp->gcc_ctor)(); 21655682Smarkm mp->gcc_dtor = (GccCDtorPtr)dlsym(mp, "_GLOBAL__DD"); 21755682Smarkm } else 21855682Smarkm errvalid = 0; 21955682Smarkm return mp; 22055682Smarkm} 22155682Smarkm 22255682Smarkm/* 22355682Smarkm * Attempt to decipher an AIX loader error message and append it 22455682Smarkm * to our static error message buffer. 22555682Smarkm */ 22655682Smarkmstatic void caterr(char *s) 22755682Smarkm{ 22855682Smarkm char *p = s; 22955682Smarkm 23055682Smarkm while (*p >= '0' && *p <= '9') 23155682Smarkm p++; 23255682Smarkm switch(atoi(s)) { 23355682Smarkm case L_ERROR_TOOMANY: 23455682Smarkm strlcat(errbuf, "to many errors", sizeof(errbuf)); 23555682Smarkm break; 23655682Smarkm case L_ERROR_NOLIB: 23755682Smarkm strlcat(errbuf, "can't load library", sizeof(errbuf)); 23855682Smarkm strlcat(errbuf, p, sizeof(errbuf)); 23955682Smarkm break; 24055682Smarkm case L_ERROR_UNDEF: 24155682Smarkm strlcat(errbuf, "can't find symbol", sizeof(errbuf)); 24255682Smarkm strlcat(errbuf, p, sizeof(errbuf)); 24355682Smarkm break; 24455682Smarkm case L_ERROR_RLDBAD: 24555682Smarkm strlcat(errbuf, "bad RLD", sizeof(errbuf)); 24655682Smarkm strlcat(errbuf, p, sizeof(errbuf)); 24755682Smarkm break; 24855682Smarkm case L_ERROR_FORMAT: 24955682Smarkm strlcat(errbuf, "bad exec format in", sizeof(errbuf)); 25055682Smarkm strlcat(errbuf, p, sizeof(errbuf)); 25155682Smarkm break; 25255682Smarkm case L_ERROR_ERRNO: 25355682Smarkm strlcat(errbuf, strerror(atoi(++p)), sizeof(errbuf)); 25455682Smarkm break; 25555682Smarkm default: 25655682Smarkm strlcat(errbuf, s, sizeof(errbuf)); 25755682Smarkm break; 25855682Smarkm } 25955682Smarkm} 26055682Smarkm 26155682Smarkmvoid *dlsym(void *handle, const char *symbol) 26255682Smarkm{ 26355682Smarkm ModulePtr mp = (ModulePtr)handle; 26455682Smarkm ExportPtr ep; 26555682Smarkm int i; 26655682Smarkm 26755682Smarkm /* 26855682Smarkm * Could speed up the search, but I assume that one assigns 26955682Smarkm * the result to function pointers anyways. 27055682Smarkm */ 27155682Smarkm for (ep = mp->exports, i = mp->nExports; i; i--, ep++) 27255682Smarkm if (strcmp(ep->name, symbol) == 0) 27355682Smarkm return ep->addr; 27455682Smarkm errvalid++; 27555682Smarkm snprintf (errbuf, sizeof(errbuf), 27655682Smarkm "dlsym: undefined symbol %s", symbol); 27755682Smarkm return NULL; 27855682Smarkm} 27955682Smarkm 28055682Smarkmchar *dlerror(void) 28155682Smarkm{ 28255682Smarkm if (errvalid) { 28355682Smarkm errvalid = 0; 28455682Smarkm return errbuf; 28555682Smarkm } 28655682Smarkm return NULL; 28755682Smarkm} 28855682Smarkm 28955682Smarkmint dlclose(void *handle) 29055682Smarkm{ 29155682Smarkm ModulePtr mp = (ModulePtr)handle; 29255682Smarkm int result; 29355682Smarkm ModulePtr mp1; 29455682Smarkm 29555682Smarkm if (--mp->refCnt > 0) 29655682Smarkm return 0; 29755682Smarkm if (mp->info && mp->info->fini) 29855682Smarkm (*mp->info->fini)(); 29955682Smarkm if (mp->cdtors) { 30055682Smarkm CdtorPtr cp = mp->cdtors; 30155682Smarkm while (cp->init || cp->term) { 30255682Smarkm if (cp->term && cp->init != (void (*)(void))0xffffffff) 30355682Smarkm (*cp->term)(); 30455682Smarkm cp++; 30555682Smarkm } 30655682Smarkm /* 30755682Smarkm * If the function to handle global destructors for g++ 30855682Smarkm * exists, call it. --jwe 30955682Smarkm */ 31055682Smarkm } else if (mp->gcc_dtor) { 31155682Smarkm (*mp->gcc_dtor)(); 31255682Smarkm } 31355682Smarkm result = unload(mp->entry); 31455682Smarkm if (result == -1) { 31555682Smarkm errvalid++; 31655682Smarkm snprintf (errbuf, sizeof(errbuf), 31755682Smarkm "%s", strerror(errno)); 31855682Smarkm } 31955682Smarkm if (mp->exports) { 32055682Smarkm ExportPtr ep; 32155682Smarkm int i; 32255682Smarkm for (ep = mp->exports, i = mp->nExports; i; i--, ep++) 32355682Smarkm if (ep->name) 32455682Smarkm free(ep->name); 32555682Smarkm free(mp->exports); 32655682Smarkm } 32755682Smarkm if (mp == modList) 32855682Smarkm modList = mp->next; 32955682Smarkm else { 33055682Smarkm for (mp1 = modList; mp1; mp1 = mp1->next) 33155682Smarkm if (mp1->next == mp) { 33255682Smarkm mp1->next = mp->next; 33355682Smarkm break; 33455682Smarkm } 33555682Smarkm } 33655682Smarkm free(mp->name); 33755682Smarkm free(mp); 33855682Smarkm return result; 33955682Smarkm} 34055682Smarkm 34155682Smarkmstatic void terminate(void) 34255682Smarkm{ 34355682Smarkm while (modList) 34455682Smarkm dlclose(modList); 34555682Smarkm} 34655682Smarkm 34755682Smarkm/* 34855682Smarkm * Build the export table from the XCOFF .loader section. 34955682Smarkm */ 35055682Smarkmstatic int readExports(ModulePtr mp) 35155682Smarkm{ 35255682Smarkm LDFILE *ldp = NULL; 35355682Smarkm SCNHDR sh, shdata; 35455682Smarkm LDHDR *lhp; 35555682Smarkm char *ldbuf; 35655682Smarkm LDSYM *ls; 35755682Smarkm int i; 35855682Smarkm ExportPtr ep; 35955682Smarkm 36055682Smarkm if ((ldp = ldopen(mp->name, ldp)) == NULL) { 36155682Smarkm struct ld_info *lp; 36255682Smarkm char *buf; 36355682Smarkm int size = 4*1024; 36455682Smarkm if (errno != ENOENT) { 36555682Smarkm errvalid++; 36655682Smarkm snprintf(errbuf, sizeof(errbuf), 36755682Smarkm "readExports: %s", 36855682Smarkm strerror(errno)); 36955682Smarkm return -1; 37055682Smarkm } 37155682Smarkm /* 37255682Smarkm * The module might be loaded due to the LIBPATH 37355682Smarkm * environment variable. Search for the loaded 37455682Smarkm * module using L_GETINFO. 37555682Smarkm */ 37655682Smarkm if ((buf = malloc(size)) == NULL) { 37755682Smarkm errvalid++; 37855682Smarkm snprintf(errbuf, sizeof(errbuf), 37955682Smarkm "readExports: %s", 38055682Smarkm strerror(errno)); 38155682Smarkm return -1; 38255682Smarkm } 38355682Smarkm while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) { 38455682Smarkm free(buf); 38555682Smarkm size += 4*1024; 38655682Smarkm if ((buf = malloc(size)) == NULL) { 38755682Smarkm errvalid++; 38855682Smarkm snprintf(errbuf, sizeof(errbuf), 38955682Smarkm "readExports: %s", 39055682Smarkm strerror(errno)); 39155682Smarkm return -1; 39255682Smarkm } 39355682Smarkm } 39455682Smarkm if (i == -1) { 39555682Smarkm errvalid++; 39655682Smarkm snprintf(errbuf, sizeof(errbuf), 39755682Smarkm "readExports: %s", 39855682Smarkm strerror(errno)); 39955682Smarkm free(buf); 40055682Smarkm return -1; 40155682Smarkm } 40255682Smarkm /* 40355682Smarkm * Traverse the list of loaded modules. The entry point 40455682Smarkm * returned by load() does actually point to the data 40555682Smarkm * segment origin. 40655682Smarkm */ 40755682Smarkm lp = (struct ld_info *)buf; 40855682Smarkm while (lp) { 40955682Smarkm if (lp->ldinfo_dataorg == mp->entry) { 41055682Smarkm ldp = ldopen(lp->ldinfo_filename, ldp); 41155682Smarkm break; 41255682Smarkm } 41355682Smarkm if (lp->ldinfo_next == 0) 41455682Smarkm lp = NULL; 41555682Smarkm else 41655682Smarkm lp = (struct ld_info *)((char *)lp + lp->ldinfo_next); 41755682Smarkm } 41855682Smarkm free(buf); 41955682Smarkm if (!ldp) { 42055682Smarkm errvalid++; 42155682Smarkm snprintf (errbuf, sizeof(errbuf), 42255682Smarkm "readExports: %s", strerror(errno)); 42355682Smarkm return -1; 42455682Smarkm } 42555682Smarkm } 42655682Smarkm if (TYPE(ldp) != U802TOCMAGIC) { 42755682Smarkm errvalid++; 42855682Smarkm snprintf(errbuf, sizeof(errbuf), "readExports: bad magic"); 42955682Smarkm while(ldclose(ldp) == FAILURE) 43055682Smarkm ; 43155682Smarkm return -1; 43255682Smarkm } 43355682Smarkm /* 43455682Smarkm * Get the padding for the data section. This is needed for 43555682Smarkm * AIX 4.1 compilers. This is used when building the final 43655682Smarkm * function pointer to the exported symbol. 43755682Smarkm */ 43855682Smarkm if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) { 43955682Smarkm errvalid++; 44055682Smarkm snprintf(errbuf, sizeof(errbuf), 44155682Smarkm "readExports: cannot read data section header"); 44255682Smarkm while(ldclose(ldp) == FAILURE) 44355682Smarkm ; 44455682Smarkm return -1; 44555682Smarkm } 44655682Smarkm if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) { 44755682Smarkm errvalid++; 44855682Smarkm snprintf(errbuf, sizeof(errbuf), 44955682Smarkm "readExports: cannot read loader section header"); 45055682Smarkm while(ldclose(ldp) == FAILURE) 45155682Smarkm ; 45255682Smarkm return -1; 45355682Smarkm } 45455682Smarkm /* 45555682Smarkm * We read the complete loader section in one chunk, this makes 45655682Smarkm * finding long symbol names residing in the string table easier. 45755682Smarkm */ 45855682Smarkm if ((ldbuf = (char *)malloc(sh.s_size)) == NULL) { 45955682Smarkm errvalid++; 46055682Smarkm snprintf (errbuf, sizeof(errbuf), 46155682Smarkm "readExports: %s", strerror(errno)); 46255682Smarkm while(ldclose(ldp) == FAILURE) 46355682Smarkm ; 46455682Smarkm return -1; 46555682Smarkm } 46655682Smarkm if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) { 46755682Smarkm errvalid++; 46855682Smarkm snprintf(errbuf, sizeof(errbuf), 46955682Smarkm "readExports: cannot seek to loader section"); 47055682Smarkm free(ldbuf); 47155682Smarkm while(ldclose(ldp) == FAILURE) 47255682Smarkm ; 47355682Smarkm return -1; 47455682Smarkm } 47555682Smarkm if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) { 47655682Smarkm errvalid++; 47755682Smarkm snprintf(errbuf, sizeof(errbuf), 47855682Smarkm "readExports: cannot read loader section"); 47955682Smarkm free(ldbuf); 48055682Smarkm while(ldclose(ldp) == FAILURE) 48155682Smarkm ; 48255682Smarkm return -1; 48355682Smarkm } 48455682Smarkm lhp = (LDHDR *)ldbuf; 48555682Smarkm ls = (LDSYM *)(ldbuf+LDHDRSZ); 48655682Smarkm /* 48755682Smarkm * Count the number of exports to include in our export table. 48855682Smarkm */ 48955682Smarkm for (i = lhp->l_nsyms; i; i--, ls++) { 49055682Smarkm if (!LDR_EXPORT(*ls)) 49155682Smarkm continue; 49255682Smarkm mp->nExports++; 49355682Smarkm } 49455682Smarkm if ((mp->exports = (ExportPtr)calloc(mp->nExports, sizeof(*mp->exports))) == NULL) { 49555682Smarkm errvalid++; 49655682Smarkm snprintf (errbuf, sizeof(errbuf), 49755682Smarkm "readExports: %s", strerror(errno)); 49855682Smarkm free(ldbuf); 49955682Smarkm while(ldclose(ldp) == FAILURE) 50055682Smarkm ; 50155682Smarkm return -1; 50255682Smarkm } 50355682Smarkm /* 50455682Smarkm * Fill in the export table. All entries are relative to 50555682Smarkm * the entry point we got from load. 50655682Smarkm */ 50755682Smarkm ep = mp->exports; 50855682Smarkm ls = (LDSYM *)(ldbuf+LDHDRSZ); 50955682Smarkm for (i = lhp->l_nsyms; i; i--, ls++) { 51055682Smarkm char *symname; 51155682Smarkm char tmpsym[SYMNMLEN+1]; 51255682Smarkm if (!LDR_EXPORT(*ls)) 51355682Smarkm continue; 51455682Smarkm if (ls->l_zeroes == 0) 51555682Smarkm symname = ls->l_offset+lhp->l_stoff+ldbuf; 51655682Smarkm else { 51755682Smarkm /* 51855682Smarkm * The l_name member is not zero terminated, we 51955682Smarkm * must copy the first SYMNMLEN chars and make 52055682Smarkm * sure we have a zero byte at the end. 52155682Smarkm */ 52255682Smarkm strlcpy (tmpsym, ls->l_name, 52355682Smarkm SYMNMLEN + 1); 52455682Smarkm symname = tmpsym; 52555682Smarkm } 52655682Smarkm ep->name = strdup(symname); 52755682Smarkm ep->addr = (void *)((unsigned long)mp->entry + 52855682Smarkm ls->l_value - shdata.s_vaddr); 52955682Smarkm ep++; 53055682Smarkm } 53155682Smarkm free(ldbuf); 53255682Smarkm while(ldclose(ldp) == FAILURE) 53355682Smarkm ; 53455682Smarkm return 0; 53555682Smarkm} 53655682Smarkm 53755682Smarkm/* 53855682Smarkm * Find the main modules entry point. This is used as export pointer 53955682Smarkm * for loadbind() to be able to resolve references to the main part. 54055682Smarkm */ 54155682Smarkmstatic void * findMain(void) 54255682Smarkm{ 54355682Smarkm struct ld_info *lp; 54455682Smarkm char *buf; 54555682Smarkm int size = 4*1024; 54655682Smarkm int i; 54755682Smarkm void *ret; 54855682Smarkm 54955682Smarkm if ((buf = malloc(size)) == NULL) { 55055682Smarkm errvalid++; 55155682Smarkm snprintf (errbuf, sizeof(errbuf), 55255682Smarkm "findMail: %s", strerror(errno)); 55355682Smarkm return NULL; 55455682Smarkm } 55555682Smarkm while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) { 55655682Smarkm free(buf); 55755682Smarkm size += 4*1024; 55855682Smarkm if ((buf = malloc(size)) == NULL) { 55955682Smarkm errvalid++; 56055682Smarkm snprintf (errbuf, sizeof(errbuf), 56155682Smarkm "findMail: %s", strerror(errno)); 56255682Smarkm return NULL; 56355682Smarkm } 56455682Smarkm } 56555682Smarkm if (i == -1) { 56655682Smarkm errvalid++; 56755682Smarkm snprintf (errbuf, sizeof(errbuf), 56855682Smarkm "findMail: %s", strerror(errno)); 56955682Smarkm free(buf); 57055682Smarkm return NULL; 57155682Smarkm } 57255682Smarkm /* 57355682Smarkm * The first entry is the main module. The entry point 57455682Smarkm * returned by load() does actually point to the data 57555682Smarkm * segment origin. 57655682Smarkm */ 57755682Smarkm lp = (struct ld_info *)buf; 57855682Smarkm ret = lp->ldinfo_dataorg; 57955682Smarkm free(buf); 58055682Smarkm return ret; 58155682Smarkm} 582