Support for more Sun compatible dlopen() and friends. Also added proper error
handling. Reviewed by: gj Submitted by: Mark Diekhans <markd@grizzly.com>
This commit is contained in:
parent
38f4fb1525
commit
19c408ae08
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=6234
@ -27,7 +27,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: rtld.c,v 1.19 1994/12/23 22:31:35 nate Exp $
|
||||
* $Id: rtld.c,v 1.20 1995/01/12 19:12:29 joerg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -73,6 +73,9 @@ struct somap_private {
|
||||
#define RTLD_MAIN 1
|
||||
#define RTLD_RTLD 2
|
||||
#define RTLD_DL 4
|
||||
unsigned long a_text; /* text size, if known */
|
||||
unsigned long a_data; /* initialized data size */
|
||||
unsigned long a_bss; /* uninitialized data size */
|
||||
|
||||
#ifdef SUN_COMPAT
|
||||
long spd_offset; /* Correction for Sun main programs */
|
||||
@ -140,33 +143,36 @@ struct rt_symbol *rt_symbol_head;
|
||||
static void *__dlopen __P((char *, int));
|
||||
static int __dlclose __P((void *));
|
||||
static void *__dlsym __P((void *, char *));
|
||||
static int __dlctl __P((void *, int, void *));
|
||||
static char *__dlerror __P((void));
|
||||
|
||||
static struct ld_entry ld_entry = {
|
||||
__dlopen, __dlclose, __dlsym, __dlctl
|
||||
__dlopen, __dlclose, __dlsym, __dlerror
|
||||
};
|
||||
|
||||
void xprintf __P((char *, ...));
|
||||
static void load_objects __P(( struct crt_ldso *,
|
||||
struct _dynamic *));
|
||||
static struct so_map *map_object __P((struct sod *, struct so_map *));
|
||||
static int unmap_object __P((struct so_map *));
|
||||
static struct so_map *alloc_link_map __P(( char *, struct sod *,
|
||||
struct so_map *, caddr_t,
|
||||
struct _dynamic *));
|
||||
static inline void check_text_reloc __P(( struct relocation_info *,
|
||||
static inline int check_text_reloc __P(( struct relocation_info *,
|
||||
struct so_map *,
|
||||
caddr_t));
|
||||
static void reloc_map __P((struct so_map *));
|
||||
static int reloc_map __P((struct so_map *));
|
||||
static void reloc_copy __P((struct so_map *));
|
||||
static void init_map __P((struct so_map *, char *));
|
||||
static char *rtfindlib __P((char *, int, int, int *));
|
||||
void binder_entry __P((void));
|
||||
long binder __P((jmpslot_t *));
|
||||
static void maphints __P((void));
|
||||
static void unmaphints __P((void));
|
||||
static struct nzlist *lookup __P((char *, struct so_map **, int));
|
||||
static inline struct rt_symbol *lookup_rts __P((char *));
|
||||
static struct rt_symbol *enter_rts __P((char *, long, int, caddr_t,
|
||||
long, struct so_map *));
|
||||
static void generror __P((char *, ...));
|
||||
|
||||
static inline int
|
||||
strcmp (register const char *s1, register const char *s2)
|
||||
@ -196,28 +202,28 @@ struct _dynamic *dp;
|
||||
struct so_map *smp;
|
||||
|
||||
/* Check version */
|
||||
if ( version != CRT_VERSION_BSD_2 &&
|
||||
version != CRT_VERSION_BSD_3 &&
|
||||
version != CRT_VERSION_SUN)
|
||||
if (version != CRT_VERSION_BSD_2 &&
|
||||
version != CRT_VERSION_BSD_3 &&
|
||||
version != CRT_VERSION_SUN)
|
||||
return -1;
|
||||
|
||||
/* Fixup __DYNAMIC structure */
|
||||
(long)dp->d_un.d_sdt += crtp->crt_ba;
|
||||
|
||||
/* Divide by hand to avoid possible use of library division routine */
|
||||
for ( nreloc = 0, n = LD_RELSZ(dp);
|
||||
n > 0;
|
||||
n -= sizeof(struct relocation_info) ) nreloc++;
|
||||
for (nreloc = 0, n = LD_RELSZ(dp);
|
||||
n > 0;
|
||||
n -= sizeof(struct relocation_info) ) nreloc++;
|
||||
|
||||
|
||||
/* Relocate ourselves */
|
||||
for ( reloc = (struct relocation_info *)(LD_REL(dp) + crtp->crt_ba);
|
||||
nreloc;
|
||||
nreloc--, reloc++) {
|
||||
for (reloc = (struct relocation_info *)(LD_REL(dp) + crtp->crt_ba);
|
||||
nreloc;
|
||||
nreloc--, reloc++) {
|
||||
|
||||
register long addr = reloc->r_address + crtp->crt_ba;
|
||||
register long addr = reloc->r_address + crtp->crt_ba;
|
||||
|
||||
md_relocate_simple(reloc, crtp->crt_ba, addr);
|
||||
md_relocate_simple(reloc, crtp->crt_ba, addr);
|
||||
}
|
||||
|
||||
__progname = "ld.so";
|
||||
@ -252,7 +258,8 @@ struct _dynamic *dp;
|
||||
for (smp = link_map_head; smp; smp = smp->som_next) {
|
||||
if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD)
|
||||
continue;
|
||||
reloc_map(smp);
|
||||
if (reloc_map(smp) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy any relocated initialized data. */
|
||||
@ -395,15 +402,27 @@ alloc_link_map(path, sodp, parent, addr, dp)
|
||||
{
|
||||
struct so_map *smp;
|
||||
struct somap_private *smpp;
|
||||
size_t smp_size;
|
||||
|
||||
smpp = (struct somap_private *)xmalloc(sizeof(struct somap_private));
|
||||
smp = (struct so_map *)xmalloc(sizeof(struct so_map));
|
||||
/*
|
||||
* Allocate so_map and private area with a single malloc. Round
|
||||
* up the size of so_map so the private area is aligned.
|
||||
*/
|
||||
smp_size = ((((sizeof(struct so_map)) + sizeof (void *) - 1) /
|
||||
sizeof (void *)) * sizeof (void *));
|
||||
|
||||
smp = (struct so_map *)xmalloc(smp_size +
|
||||
sizeof (struct somap_private));
|
||||
smpp = (struct somap_private *) (((caddr_t) smp) + smp_size);
|
||||
smp->som_next = NULL;
|
||||
*link_map_tail = smp;
|
||||
link_map_tail = &smp->som_next;
|
||||
|
||||
smp->som_addr = addr;
|
||||
smp->som_path = path?strdup(path):NULL;
|
||||
if (path == NULL)
|
||||
smp->som_path = NULL;
|
||||
else
|
||||
smp->som_path = strdup(path);
|
||||
smp->som_sod = sodp;
|
||||
smp->som_dynamic = dp;
|
||||
smp->som_spd = (caddr_t)smpp;
|
||||
@ -413,7 +432,9 @@ alloc_link_map(path, sodp, parent, addr, dp)
|
||||
smpp->spd_refcount = 0;
|
||||
smpp->spd_flags = 0;
|
||||
smpp->spd_parent = parent;
|
||||
|
||||
smpp->a_text = 0;
|
||||
smpp->a_data = 0;
|
||||
smpp->a_bss = 0;
|
||||
#ifdef SUN_COMPAT
|
||||
smpp->spd_offset =
|
||||
(addr==0 && dp && dp->d_version==LD_VERSION_SUN) ? PAGSIZ : 0;
|
||||
@ -437,6 +458,7 @@ map_object(sodp, smp)
|
||||
struct exec hdr;
|
||||
int usehints = 0;
|
||||
struct so_map *p;
|
||||
struct somap_private *smpp;
|
||||
|
||||
if (sodp->sod_library) {
|
||||
usehints = 1;
|
||||
@ -444,12 +466,14 @@ map_object(sodp, smp)
|
||||
path = rtfindlib(name, sodp->sod_major,
|
||||
sodp->sod_minor, &usehints);
|
||||
if (path == NULL) {
|
||||
errno = ENOENT;
|
||||
generror ("Can't find shared library \"%s\"",
|
||||
name);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (careful && *name != '/') {
|
||||
errno = EACCES;
|
||||
generror ("Shared library path must start with \"/\" for \"%s\"",
|
||||
name);
|
||||
return NULL;
|
||||
}
|
||||
path = name;
|
||||
@ -468,39 +492,38 @@ map_object(sodp, smp)
|
||||
usehints = 0;
|
||||
goto again;
|
||||
}
|
||||
generror ("open failed for \"%s\" : %s",
|
||||
path, strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
|
||||
generror ("header read failed for \"%s\"",
|
||||
path);
|
||||
(void)close(fd);
|
||||
/*errno = x;*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (N_BADMAG(hdr)) {
|
||||
generror ("bad magic number in \"%s\"",
|
||||
path);
|
||||
(void)close(fd);
|
||||
errno = EFTYPE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((addr = mmap(0, hdr.a_text + hdr.a_data,
|
||||
PROT_READ|PROT_EXEC,
|
||||
MAP_COPY, fd, 0)) == (caddr_t)-1) {
|
||||
generror ("mmap failed for \"%s\" : %s",
|
||||
path, strerror (errno));
|
||||
(void)close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (mmap(addr + hdr.a_text, hdr.a_data,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_FIXED|MAP_COPY,
|
||||
fd, hdr.a_text) == (caddr_t)-1) {
|
||||
(void)close(fd);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (mprotect(addr + hdr.a_text, hdr.a_data,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC) != 0) {
|
||||
generror ("mprotect failed for \"%s\" : %s",
|
||||
path, strerror (errno));
|
||||
(void)close(fd);
|
||||
return NULL;
|
||||
}
|
||||
@ -509,14 +532,21 @@ map_object(sodp, smp)
|
||||
|
||||
fd = -1;
|
||||
#ifdef NEED_DEV_ZERO
|
||||
if ((fd = open("/dev/zero", O_RDWR, 0)) == -1)
|
||||
warn("open: %s", "/dev/zero");
|
||||
if ((fd = open("/dev/zero", O_RDWR, 0)) == -1) {
|
||||
generror ("open failed for \"/dev/zero\" : %s",
|
||||
strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (hdr.a_bss && mmap(addr + hdr.a_text + hdr.a_data, hdr.a_bss,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_ANON|MAP_FIXED|MAP_COPY,
|
||||
fd, hdr.a_text + hdr.a_data) == (caddr_t)-1)
|
||||
fd, hdr.a_text + hdr.a_data) == (caddr_t)-1) {
|
||||
generror ("mmap failed for \"%s\" : %s",
|
||||
path, strerror (errno));
|
||||
(void)close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef NEED_DEV_ZERO
|
||||
close(fd);
|
||||
@ -528,10 +558,64 @@ map_object(sodp, smp)
|
||||
/* Fixup __DYNAMIC structure */
|
||||
(long)dp->d_un.d_sdt += (long)addr;
|
||||
|
||||
return alloc_link_map(path, sodp, smp, addr, dp);
|
||||
p = alloc_link_map(path, sodp, smp, addr, dp);
|
||||
|
||||
/* save segment sizes for unmap. */
|
||||
smpp = LM_PRIVATE(p);
|
||||
smpp->a_text = hdr.a_text;
|
||||
smpp->a_data = hdr.a_data;
|
||||
smpp->a_bss = hdr.a_bss;
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline void
|
||||
/*
|
||||
* Unmap an object that is nolonger in use.
|
||||
*/
|
||||
static int
|
||||
unmap_object(smp)
|
||||
struct so_map *smp;
|
||||
{
|
||||
struct so_map *prev, *p;
|
||||
struct somap_private *smpp;
|
||||
|
||||
/* Find the object in the list and unlink it */
|
||||
|
||||
for (prev = NULL, p = link_map_head;
|
||||
p != smp;
|
||||
prev = p, p = p->som_next) continue;
|
||||
|
||||
if (prev == NULL) {
|
||||
link_map_head = smp->som_next;
|
||||
if (smp->som_next == NULL)
|
||||
link_map_tail = &link_map_head;
|
||||
} else {
|
||||
prev->som_next = smp->som_next;
|
||||
if (smp->som_next == NULL)
|
||||
link_map_tail = &prev->som_next;
|
||||
}
|
||||
|
||||
/* Unmap the sections we have mapped */
|
||||
|
||||
smpp = LM_PRIVATE(smp);
|
||||
|
||||
if (munmap(smp->som_addr, smpp->a_text + smpp->a_data) < 0) {
|
||||
generror ("munmap failed: %s", strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
if (smpp->a_bss > 0) {
|
||||
if (munmap(smp->som_addr + smpp->a_text + smpp->a_data,
|
||||
smpp->a_bss) < 0) {
|
||||
generror ("munmap failed: %s", strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
free((caddr_t) smp->som_sod->sod_name);
|
||||
free(smp->som_sod);
|
||||
free(smp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
check_text_reloc(r, smp, addr)
|
||||
struct relocation_info *r;
|
||||
struct so_map *smp;
|
||||
@ -540,7 +624,7 @@ caddr_t addr;
|
||||
char *sym;
|
||||
|
||||
if (addr >= LM_ETEXT(smp))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (RELOC_EXTERN_P(r))
|
||||
sym = LM_STRINGS(smp) +
|
||||
@ -557,15 +641,16 @@ caddr_t addr;
|
||||
mprotect(smp->som_addr + LM_TXTADDR(smp),
|
||||
LD_TEXTSZ(smp->som_dynamic),
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
|
||||
|
||||
err(1, "Cannot enable writes to %s:%s",
|
||||
main_progname, smp->som_path);
|
||||
generror ("mprotect failed for \"%s\" : %s",
|
||||
smp->som_path, strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
smp->som_write = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
reloc_map(smp)
|
||||
struct so_map *smp;
|
||||
{
|
||||
@ -586,7 +671,8 @@ reloc_map(smp)
|
||||
char *sym;
|
||||
caddr_t addr = smp->som_addr + r->r_address;
|
||||
|
||||
check_text_reloc(r, smp, addr);
|
||||
if (check_text_reloc(r, smp, addr) < 0)
|
||||
return -1;
|
||||
|
||||
if (RELOC_EXTERN_P(r)) {
|
||||
struct so_map *src_map = NULL;
|
||||
@ -605,10 +691,11 @@ reloc_map(smp)
|
||||
sym = stringbase + p->nz_strx;
|
||||
|
||||
np = lookup(sym, &src_map, 0/*XXX-jumpslots!*/);
|
||||
if (np == NULL)
|
||||
errx(1, "Undefined symbol \"%s\" in %s:%s\n",
|
||||
if (np == NULL) {
|
||||
generror ("Undefined symbol \"%s\" in %s:%s",
|
||||
sym, main_progname, smp->som_path);
|
||||
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Found symbol definition.
|
||||
* If it's in a link map, adjust value
|
||||
@ -649,12 +736,13 @@ reloc_map(smp)
|
||||
if (mprotect(smp->som_addr + LM_TXTADDR(smp),
|
||||
LD_TEXTSZ(smp->som_dynamic),
|
||||
PROT_READ|PROT_EXEC) == -1) {
|
||||
|
||||
err(1, "Cannot disable writes to %s:%s\n",
|
||||
main_progname, smp->som_path);
|
||||
generror ("mprotect failed for \"%s\" : %s",
|
||||
smp->som_path, strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
smp->som_write = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -750,7 +838,7 @@ enter_rts(name, value, type, srcaddr, size, smp)
|
||||
|
||||
/* Find end of bucket */
|
||||
for (rpp = &rt_symtab[hashval]; *rpp; rpp = &(*rpp)->rt_link)
|
||||
;
|
||||
continue;
|
||||
|
||||
/* Allocate new common symbol */
|
||||
rtsp = (struct rt_symbol *)malloc(sizeof(struct rt_symbol));
|
||||
@ -894,7 +982,8 @@ lookup(name, src_map, strong)
|
||||
N_UNDF + N_EXT, 0, common_size, NULL);
|
||||
|
||||
#if DEBUG
|
||||
xprintf("Allocating common: %s size %d at %#x\n", name, common_size, rtsp->rt_sp->nz_value);
|
||||
xprintf("Allocating common: %s size %d at %#x\n", name, common_size,
|
||||
rtsp->rt_sp->nz_value);
|
||||
#endif
|
||||
|
||||
return rtsp->rt_sp;
|
||||
@ -946,7 +1035,8 @@ binder(jsp)
|
||||
md_fix_jmpslot(jsp, (long)jsp, addr);
|
||||
|
||||
#if DEBUG
|
||||
xprintf(" BINDER: %s located at = %#x in %s\n", sym, addr, src_map->som_path);
|
||||
xprintf(" BINDER: %s located at = %#x in %s\n", sym, addr,
|
||||
src_map->som_path);
|
||||
#endif
|
||||
return addr;
|
||||
}
|
||||
@ -960,7 +1050,7 @@ static char *hstrtab;
|
||||
#define HINTS_VALID (hheader != NULL && hheader != (struct hints_header *)-1)
|
||||
|
||||
static void
|
||||
maphints()
|
||||
maphints __P((void))
|
||||
{
|
||||
caddr_t addr;
|
||||
long msize;
|
||||
@ -1130,10 +1220,12 @@ rtfindlib(name, major, minor, usehints)
|
||||
if (cp) {
|
||||
if (realminor < minor && getenv("LD_SUPPRESS_WARNINGS") == NULL)
|
||||
warnx("warning: lib%s.so.%d.%d: "
|
||||
"minor version >= %d expected, using it anyway",
|
||||
"minor version < %d expected, using it anyway",
|
||||
name, major, realminor, minor);
|
||||
return cp;
|
||||
}
|
||||
generror ("Can't find shared library \"%s\"",
|
||||
name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1156,7 +1248,15 @@ static struct so_map dlmap = {
|
||||
(struct _dynamic *)0,
|
||||
(caddr_t)&dlmap_private
|
||||
};
|
||||
static int dlerrno;
|
||||
|
||||
/*
|
||||
* Buffer for error messages and a pointer that is set to point to the buffer
|
||||
* when a error occurs. It acts as a last error flag, being set to NULL
|
||||
* after an error is returned.
|
||||
*/
|
||||
#define DLERROR_BUF_SIZE 512
|
||||
static char dlerror_buf [DLERROR_BUF_SIZE];
|
||||
static char *dlerror_msg = NULL;
|
||||
|
||||
static void *
|
||||
__dlopen(name, mode)
|
||||
@ -1169,11 +1269,12 @@ __dlopen(name, mode)
|
||||
/*
|
||||
* A NULL argument returns the current set of mapped objects.
|
||||
*/
|
||||
if (name == NULL)
|
||||
if (name == NULL) {
|
||||
LM_PRIVATE(link_map_head)->spd_refcount++;
|
||||
return link_map_head;
|
||||
|
||||
}
|
||||
if ((sodp = (struct sod *)malloc(sizeof(struct sod))) == NULL) {
|
||||
dlerrno = ENOMEM;
|
||||
generror ("malloc failed: %s", strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1183,14 +1284,14 @@ __dlopen(name, mode)
|
||||
|
||||
if ((smp = map_object(sodp, &dlmap)) == NULL) {
|
||||
#ifdef DEBUG
|
||||
xprintf("%s: %s\n", name, strerror(errno));
|
||||
xprintf("%s: %s\n", name, dlerror_buf);
|
||||
#endif
|
||||
dlerrno = errno;
|
||||
return NULL;
|
||||
}
|
||||
if (LM_PRIVATE(smp)->spd_refcount++ == 0) {
|
||||
LM_PRIVATE(smp)->spd_flags |= RTLD_DL;
|
||||
reloc_map(smp);
|
||||
if (reloc_map(smp) < 0)
|
||||
return NULL;
|
||||
reloc_copy(smp);
|
||||
init_map(smp, ".init");
|
||||
init_map(smp, "_init");
|
||||
@ -1206,19 +1307,17 @@ __dlclose(fd)
|
||||
struct so_map *smp = (struct so_map *)fd;
|
||||
|
||||
#ifdef DEBUG
|
||||
xprintf("dlclose(%s): refcount = %d\n", smp->som_path, LM_PRIVATE(smp)->spd_refcount);
|
||||
xprintf("dlclose(%s): refcount = %d\n", smp->som_path,
|
||||
LM_PRIVATE(smp)->spd_refcount);
|
||||
#endif
|
||||
if (--LM_PRIVATE(smp)->spd_refcount != 0)
|
||||
return 0;
|
||||
|
||||
/* Dismantle shared object map and descriptor */
|
||||
init_map(smp, "_fini");
|
||||
#if 0
|
||||
unmap_object(smp);
|
||||
free(smp->som_sod->sod_name);
|
||||
free(smp->som_sod);
|
||||
free(smp);
|
||||
#endif
|
||||
|
||||
if (unmap_object(smp) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1235,13 +1334,14 @@ __dlsym(fd, sym)
|
||||
/*
|
||||
* Restrict search to passed map if dlopen()ed.
|
||||
*/
|
||||
if (LM_PRIVATE(smp)->spd_flags & RTLD_DL)
|
||||
if (smp && LM_PRIVATE(smp)->spd_flags & RTLD_DL)
|
||||
src_map = smp;
|
||||
|
||||
np = lookup(sym, &src_map, 1);
|
||||
if (np == NULL)
|
||||
if (np == NULL) {
|
||||
generror ("Symbol \"%s\" not found", sym);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
/* Fixup jmpslot so future calls transfer directly to target */
|
||||
addr = np->nz_value;
|
||||
if (src_map)
|
||||
@ -1250,20 +1350,38 @@ __dlsym(fd, sym)
|
||||
return (void *)addr;
|
||||
}
|
||||
|
||||
static int
|
||||
__dlctl(fd, cmd, arg)
|
||||
void *fd, *arg;
|
||||
int cmd;
|
||||
static char *
|
||||
__dlerror __P((void))
|
||||
{
|
||||
switch (cmd) {
|
||||
case DL_GETERRNO:
|
||||
*(int *)arg = dlerrno;
|
||||
return 0;
|
||||
default:
|
||||
dlerrno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
char *err;
|
||||
|
||||
err = dlerror_msg;
|
||||
dlerror_msg = NULL; /* Next call will return NULL */
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate an error message that can be later be retrieved via dlerror.
|
||||
*/
|
||||
static void
|
||||
#if __STDC__
|
||||
generror(char *fmt, ...)
|
||||
#else
|
||||
generror(fmt, va_alist)
|
||||
char *fmt;
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
vsnprintf (dlerror_buf, DLERROR_BUF_SIZE, fmt, ap);
|
||||
dlerror_msg = dlerror_buf;
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -27,7 +27,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: rtld.c,v 1.19 1994/12/23 22:31:35 nate Exp $
|
||||
* $Id: rtld.c,v 1.20 1995/01/12 19:12:29 joerg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -73,6 +73,9 @@ struct somap_private {
|
||||
#define RTLD_MAIN 1
|
||||
#define RTLD_RTLD 2
|
||||
#define RTLD_DL 4
|
||||
unsigned long a_text; /* text size, if known */
|
||||
unsigned long a_data; /* initialized data size */
|
||||
unsigned long a_bss; /* uninitialized data size */
|
||||
|
||||
#ifdef SUN_COMPAT
|
||||
long spd_offset; /* Correction for Sun main programs */
|
||||
@ -140,33 +143,36 @@ struct rt_symbol *rt_symbol_head;
|
||||
static void *__dlopen __P((char *, int));
|
||||
static int __dlclose __P((void *));
|
||||
static void *__dlsym __P((void *, char *));
|
||||
static int __dlctl __P((void *, int, void *));
|
||||
static char *__dlerror __P((void));
|
||||
|
||||
static struct ld_entry ld_entry = {
|
||||
__dlopen, __dlclose, __dlsym, __dlctl
|
||||
__dlopen, __dlclose, __dlsym, __dlerror
|
||||
};
|
||||
|
||||
void xprintf __P((char *, ...));
|
||||
static void load_objects __P(( struct crt_ldso *,
|
||||
struct _dynamic *));
|
||||
static struct so_map *map_object __P((struct sod *, struct so_map *));
|
||||
static int unmap_object __P((struct so_map *));
|
||||
static struct so_map *alloc_link_map __P(( char *, struct sod *,
|
||||
struct so_map *, caddr_t,
|
||||
struct _dynamic *));
|
||||
static inline void check_text_reloc __P(( struct relocation_info *,
|
||||
static inline int check_text_reloc __P(( struct relocation_info *,
|
||||
struct so_map *,
|
||||
caddr_t));
|
||||
static void reloc_map __P((struct so_map *));
|
||||
static int reloc_map __P((struct so_map *));
|
||||
static void reloc_copy __P((struct so_map *));
|
||||
static void init_map __P((struct so_map *, char *));
|
||||
static char *rtfindlib __P((char *, int, int, int *));
|
||||
void binder_entry __P((void));
|
||||
long binder __P((jmpslot_t *));
|
||||
static void maphints __P((void));
|
||||
static void unmaphints __P((void));
|
||||
static struct nzlist *lookup __P((char *, struct so_map **, int));
|
||||
static inline struct rt_symbol *lookup_rts __P((char *));
|
||||
static struct rt_symbol *enter_rts __P((char *, long, int, caddr_t,
|
||||
long, struct so_map *));
|
||||
static void generror __P((char *, ...));
|
||||
|
||||
static inline int
|
||||
strcmp (register const char *s1, register const char *s2)
|
||||
@ -196,28 +202,28 @@ struct _dynamic *dp;
|
||||
struct so_map *smp;
|
||||
|
||||
/* Check version */
|
||||
if ( version != CRT_VERSION_BSD_2 &&
|
||||
version != CRT_VERSION_BSD_3 &&
|
||||
version != CRT_VERSION_SUN)
|
||||
if (version != CRT_VERSION_BSD_2 &&
|
||||
version != CRT_VERSION_BSD_3 &&
|
||||
version != CRT_VERSION_SUN)
|
||||
return -1;
|
||||
|
||||
/* Fixup __DYNAMIC structure */
|
||||
(long)dp->d_un.d_sdt += crtp->crt_ba;
|
||||
|
||||
/* Divide by hand to avoid possible use of library division routine */
|
||||
for ( nreloc = 0, n = LD_RELSZ(dp);
|
||||
n > 0;
|
||||
n -= sizeof(struct relocation_info) ) nreloc++;
|
||||
for (nreloc = 0, n = LD_RELSZ(dp);
|
||||
n > 0;
|
||||
n -= sizeof(struct relocation_info) ) nreloc++;
|
||||
|
||||
|
||||
/* Relocate ourselves */
|
||||
for ( reloc = (struct relocation_info *)(LD_REL(dp) + crtp->crt_ba);
|
||||
nreloc;
|
||||
nreloc--, reloc++) {
|
||||
for (reloc = (struct relocation_info *)(LD_REL(dp) + crtp->crt_ba);
|
||||
nreloc;
|
||||
nreloc--, reloc++) {
|
||||
|
||||
register long addr = reloc->r_address + crtp->crt_ba;
|
||||
register long addr = reloc->r_address + crtp->crt_ba;
|
||||
|
||||
md_relocate_simple(reloc, crtp->crt_ba, addr);
|
||||
md_relocate_simple(reloc, crtp->crt_ba, addr);
|
||||
}
|
||||
|
||||
__progname = "ld.so";
|
||||
@ -252,7 +258,8 @@ struct _dynamic *dp;
|
||||
for (smp = link_map_head; smp; smp = smp->som_next) {
|
||||
if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD)
|
||||
continue;
|
||||
reloc_map(smp);
|
||||
if (reloc_map(smp) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy any relocated initialized data. */
|
||||
@ -395,15 +402,27 @@ alloc_link_map(path, sodp, parent, addr, dp)
|
||||
{
|
||||
struct so_map *smp;
|
||||
struct somap_private *smpp;
|
||||
size_t smp_size;
|
||||
|
||||
smpp = (struct somap_private *)xmalloc(sizeof(struct somap_private));
|
||||
smp = (struct so_map *)xmalloc(sizeof(struct so_map));
|
||||
/*
|
||||
* Allocate so_map and private area with a single malloc. Round
|
||||
* up the size of so_map so the private area is aligned.
|
||||
*/
|
||||
smp_size = ((((sizeof(struct so_map)) + sizeof (void *) - 1) /
|
||||
sizeof (void *)) * sizeof (void *));
|
||||
|
||||
smp = (struct so_map *)xmalloc(smp_size +
|
||||
sizeof (struct somap_private));
|
||||
smpp = (struct somap_private *) (((caddr_t) smp) + smp_size);
|
||||
smp->som_next = NULL;
|
||||
*link_map_tail = smp;
|
||||
link_map_tail = &smp->som_next;
|
||||
|
||||
smp->som_addr = addr;
|
||||
smp->som_path = path?strdup(path):NULL;
|
||||
if (path == NULL)
|
||||
smp->som_path = NULL;
|
||||
else
|
||||
smp->som_path = strdup(path);
|
||||
smp->som_sod = sodp;
|
||||
smp->som_dynamic = dp;
|
||||
smp->som_spd = (caddr_t)smpp;
|
||||
@ -413,7 +432,9 @@ alloc_link_map(path, sodp, parent, addr, dp)
|
||||
smpp->spd_refcount = 0;
|
||||
smpp->spd_flags = 0;
|
||||
smpp->spd_parent = parent;
|
||||
|
||||
smpp->a_text = 0;
|
||||
smpp->a_data = 0;
|
||||
smpp->a_bss = 0;
|
||||
#ifdef SUN_COMPAT
|
||||
smpp->spd_offset =
|
||||
(addr==0 && dp && dp->d_version==LD_VERSION_SUN) ? PAGSIZ : 0;
|
||||
@ -437,6 +458,7 @@ map_object(sodp, smp)
|
||||
struct exec hdr;
|
||||
int usehints = 0;
|
||||
struct so_map *p;
|
||||
struct somap_private *smpp;
|
||||
|
||||
if (sodp->sod_library) {
|
||||
usehints = 1;
|
||||
@ -444,12 +466,14 @@ map_object(sodp, smp)
|
||||
path = rtfindlib(name, sodp->sod_major,
|
||||
sodp->sod_minor, &usehints);
|
||||
if (path == NULL) {
|
||||
errno = ENOENT;
|
||||
generror ("Can't find shared library \"%s\"",
|
||||
name);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (careful && *name != '/') {
|
||||
errno = EACCES;
|
||||
generror ("Shared library path must start with \"/\" for \"%s\"",
|
||||
name);
|
||||
return NULL;
|
||||
}
|
||||
path = name;
|
||||
@ -468,39 +492,38 @@ map_object(sodp, smp)
|
||||
usehints = 0;
|
||||
goto again;
|
||||
}
|
||||
generror ("open failed for \"%s\" : %s",
|
||||
path, strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
|
||||
generror ("header read failed for \"%s\"",
|
||||
path);
|
||||
(void)close(fd);
|
||||
/*errno = x;*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (N_BADMAG(hdr)) {
|
||||
generror ("bad magic number in \"%s\"",
|
||||
path);
|
||||
(void)close(fd);
|
||||
errno = EFTYPE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((addr = mmap(0, hdr.a_text + hdr.a_data,
|
||||
PROT_READ|PROT_EXEC,
|
||||
MAP_COPY, fd, 0)) == (caddr_t)-1) {
|
||||
generror ("mmap failed for \"%s\" : %s",
|
||||
path, strerror (errno));
|
||||
(void)close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (mmap(addr + hdr.a_text, hdr.a_data,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_FIXED|MAP_COPY,
|
||||
fd, hdr.a_text) == (caddr_t)-1) {
|
||||
(void)close(fd);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (mprotect(addr + hdr.a_text, hdr.a_data,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC) != 0) {
|
||||
generror ("mprotect failed for \"%s\" : %s",
|
||||
path, strerror (errno));
|
||||
(void)close(fd);
|
||||
return NULL;
|
||||
}
|
||||
@ -509,14 +532,21 @@ map_object(sodp, smp)
|
||||
|
||||
fd = -1;
|
||||
#ifdef NEED_DEV_ZERO
|
||||
if ((fd = open("/dev/zero", O_RDWR, 0)) == -1)
|
||||
warn("open: %s", "/dev/zero");
|
||||
if ((fd = open("/dev/zero", O_RDWR, 0)) == -1) {
|
||||
generror ("open failed for \"/dev/zero\" : %s",
|
||||
strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (hdr.a_bss && mmap(addr + hdr.a_text + hdr.a_data, hdr.a_bss,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_ANON|MAP_FIXED|MAP_COPY,
|
||||
fd, hdr.a_text + hdr.a_data) == (caddr_t)-1)
|
||||
fd, hdr.a_text + hdr.a_data) == (caddr_t)-1) {
|
||||
generror ("mmap failed for \"%s\" : %s",
|
||||
path, strerror (errno));
|
||||
(void)close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef NEED_DEV_ZERO
|
||||
close(fd);
|
||||
@ -528,10 +558,64 @@ map_object(sodp, smp)
|
||||
/* Fixup __DYNAMIC structure */
|
||||
(long)dp->d_un.d_sdt += (long)addr;
|
||||
|
||||
return alloc_link_map(path, sodp, smp, addr, dp);
|
||||
p = alloc_link_map(path, sodp, smp, addr, dp);
|
||||
|
||||
/* save segment sizes for unmap. */
|
||||
smpp = LM_PRIVATE(p);
|
||||
smpp->a_text = hdr.a_text;
|
||||
smpp->a_data = hdr.a_data;
|
||||
smpp->a_bss = hdr.a_bss;
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline void
|
||||
/*
|
||||
* Unmap an object that is nolonger in use.
|
||||
*/
|
||||
static int
|
||||
unmap_object(smp)
|
||||
struct so_map *smp;
|
||||
{
|
||||
struct so_map *prev, *p;
|
||||
struct somap_private *smpp;
|
||||
|
||||
/* Find the object in the list and unlink it */
|
||||
|
||||
for (prev = NULL, p = link_map_head;
|
||||
p != smp;
|
||||
prev = p, p = p->som_next) continue;
|
||||
|
||||
if (prev == NULL) {
|
||||
link_map_head = smp->som_next;
|
||||
if (smp->som_next == NULL)
|
||||
link_map_tail = &link_map_head;
|
||||
} else {
|
||||
prev->som_next = smp->som_next;
|
||||
if (smp->som_next == NULL)
|
||||
link_map_tail = &prev->som_next;
|
||||
}
|
||||
|
||||
/* Unmap the sections we have mapped */
|
||||
|
||||
smpp = LM_PRIVATE(smp);
|
||||
|
||||
if (munmap(smp->som_addr, smpp->a_text + smpp->a_data) < 0) {
|
||||
generror ("munmap failed: %s", strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
if (smpp->a_bss > 0) {
|
||||
if (munmap(smp->som_addr + smpp->a_text + smpp->a_data,
|
||||
smpp->a_bss) < 0) {
|
||||
generror ("munmap failed: %s", strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
free((caddr_t) smp->som_sod->sod_name);
|
||||
free(smp->som_sod);
|
||||
free(smp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
check_text_reloc(r, smp, addr)
|
||||
struct relocation_info *r;
|
||||
struct so_map *smp;
|
||||
@ -540,7 +624,7 @@ caddr_t addr;
|
||||
char *sym;
|
||||
|
||||
if (addr >= LM_ETEXT(smp))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (RELOC_EXTERN_P(r))
|
||||
sym = LM_STRINGS(smp) +
|
||||
@ -557,15 +641,16 @@ caddr_t addr;
|
||||
mprotect(smp->som_addr + LM_TXTADDR(smp),
|
||||
LD_TEXTSZ(smp->som_dynamic),
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
|
||||
|
||||
err(1, "Cannot enable writes to %s:%s",
|
||||
main_progname, smp->som_path);
|
||||
generror ("mprotect failed for \"%s\" : %s",
|
||||
smp->som_path, strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
smp->som_write = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
reloc_map(smp)
|
||||
struct so_map *smp;
|
||||
{
|
||||
@ -586,7 +671,8 @@ reloc_map(smp)
|
||||
char *sym;
|
||||
caddr_t addr = smp->som_addr + r->r_address;
|
||||
|
||||
check_text_reloc(r, smp, addr);
|
||||
if (check_text_reloc(r, smp, addr) < 0)
|
||||
return -1;
|
||||
|
||||
if (RELOC_EXTERN_P(r)) {
|
||||
struct so_map *src_map = NULL;
|
||||
@ -605,10 +691,11 @@ reloc_map(smp)
|
||||
sym = stringbase + p->nz_strx;
|
||||
|
||||
np = lookup(sym, &src_map, 0/*XXX-jumpslots!*/);
|
||||
if (np == NULL)
|
||||
errx(1, "Undefined symbol \"%s\" in %s:%s\n",
|
||||
if (np == NULL) {
|
||||
generror ("Undefined symbol \"%s\" in %s:%s",
|
||||
sym, main_progname, smp->som_path);
|
||||
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Found symbol definition.
|
||||
* If it's in a link map, adjust value
|
||||
@ -649,12 +736,13 @@ reloc_map(smp)
|
||||
if (mprotect(smp->som_addr + LM_TXTADDR(smp),
|
||||
LD_TEXTSZ(smp->som_dynamic),
|
||||
PROT_READ|PROT_EXEC) == -1) {
|
||||
|
||||
err(1, "Cannot disable writes to %s:%s\n",
|
||||
main_progname, smp->som_path);
|
||||
generror ("mprotect failed for \"%s\" : %s",
|
||||
smp->som_path, strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
smp->som_write = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -750,7 +838,7 @@ enter_rts(name, value, type, srcaddr, size, smp)
|
||||
|
||||
/* Find end of bucket */
|
||||
for (rpp = &rt_symtab[hashval]; *rpp; rpp = &(*rpp)->rt_link)
|
||||
;
|
||||
continue;
|
||||
|
||||
/* Allocate new common symbol */
|
||||
rtsp = (struct rt_symbol *)malloc(sizeof(struct rt_symbol));
|
||||
@ -894,7 +982,8 @@ lookup(name, src_map, strong)
|
||||
N_UNDF + N_EXT, 0, common_size, NULL);
|
||||
|
||||
#if DEBUG
|
||||
xprintf("Allocating common: %s size %d at %#x\n", name, common_size, rtsp->rt_sp->nz_value);
|
||||
xprintf("Allocating common: %s size %d at %#x\n", name, common_size,
|
||||
rtsp->rt_sp->nz_value);
|
||||
#endif
|
||||
|
||||
return rtsp->rt_sp;
|
||||
@ -946,7 +1035,8 @@ binder(jsp)
|
||||
md_fix_jmpslot(jsp, (long)jsp, addr);
|
||||
|
||||
#if DEBUG
|
||||
xprintf(" BINDER: %s located at = %#x in %s\n", sym, addr, src_map->som_path);
|
||||
xprintf(" BINDER: %s located at = %#x in %s\n", sym, addr,
|
||||
src_map->som_path);
|
||||
#endif
|
||||
return addr;
|
||||
}
|
||||
@ -960,7 +1050,7 @@ static char *hstrtab;
|
||||
#define HINTS_VALID (hheader != NULL && hheader != (struct hints_header *)-1)
|
||||
|
||||
static void
|
||||
maphints()
|
||||
maphints __P((void))
|
||||
{
|
||||
caddr_t addr;
|
||||
long msize;
|
||||
@ -1130,10 +1220,12 @@ rtfindlib(name, major, minor, usehints)
|
||||
if (cp) {
|
||||
if (realminor < minor && getenv("LD_SUPPRESS_WARNINGS") == NULL)
|
||||
warnx("warning: lib%s.so.%d.%d: "
|
||||
"minor version >= %d expected, using it anyway",
|
||||
"minor version < %d expected, using it anyway",
|
||||
name, major, realminor, minor);
|
||||
return cp;
|
||||
}
|
||||
generror ("Can't find shared library \"%s\"",
|
||||
name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1156,7 +1248,15 @@ static struct so_map dlmap = {
|
||||
(struct _dynamic *)0,
|
||||
(caddr_t)&dlmap_private
|
||||
};
|
||||
static int dlerrno;
|
||||
|
||||
/*
|
||||
* Buffer for error messages and a pointer that is set to point to the buffer
|
||||
* when a error occurs. It acts as a last error flag, being set to NULL
|
||||
* after an error is returned.
|
||||
*/
|
||||
#define DLERROR_BUF_SIZE 512
|
||||
static char dlerror_buf [DLERROR_BUF_SIZE];
|
||||
static char *dlerror_msg = NULL;
|
||||
|
||||
static void *
|
||||
__dlopen(name, mode)
|
||||
@ -1169,11 +1269,12 @@ __dlopen(name, mode)
|
||||
/*
|
||||
* A NULL argument returns the current set of mapped objects.
|
||||
*/
|
||||
if (name == NULL)
|
||||
if (name == NULL) {
|
||||
LM_PRIVATE(link_map_head)->spd_refcount++;
|
||||
return link_map_head;
|
||||
|
||||
}
|
||||
if ((sodp = (struct sod *)malloc(sizeof(struct sod))) == NULL) {
|
||||
dlerrno = ENOMEM;
|
||||
generror ("malloc failed: %s", strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1183,14 +1284,14 @@ __dlopen(name, mode)
|
||||
|
||||
if ((smp = map_object(sodp, &dlmap)) == NULL) {
|
||||
#ifdef DEBUG
|
||||
xprintf("%s: %s\n", name, strerror(errno));
|
||||
xprintf("%s: %s\n", name, dlerror_buf);
|
||||
#endif
|
||||
dlerrno = errno;
|
||||
return NULL;
|
||||
}
|
||||
if (LM_PRIVATE(smp)->spd_refcount++ == 0) {
|
||||
LM_PRIVATE(smp)->spd_flags |= RTLD_DL;
|
||||
reloc_map(smp);
|
||||
if (reloc_map(smp) < 0)
|
||||
return NULL;
|
||||
reloc_copy(smp);
|
||||
init_map(smp, ".init");
|
||||
init_map(smp, "_init");
|
||||
@ -1206,19 +1307,17 @@ __dlclose(fd)
|
||||
struct so_map *smp = (struct so_map *)fd;
|
||||
|
||||
#ifdef DEBUG
|
||||
xprintf("dlclose(%s): refcount = %d\n", smp->som_path, LM_PRIVATE(smp)->spd_refcount);
|
||||
xprintf("dlclose(%s): refcount = %d\n", smp->som_path,
|
||||
LM_PRIVATE(smp)->spd_refcount);
|
||||
#endif
|
||||
if (--LM_PRIVATE(smp)->spd_refcount != 0)
|
||||
return 0;
|
||||
|
||||
/* Dismantle shared object map and descriptor */
|
||||
init_map(smp, "_fini");
|
||||
#if 0
|
||||
unmap_object(smp);
|
||||
free(smp->som_sod->sod_name);
|
||||
free(smp->som_sod);
|
||||
free(smp);
|
||||
#endif
|
||||
|
||||
if (unmap_object(smp) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1235,13 +1334,14 @@ __dlsym(fd, sym)
|
||||
/*
|
||||
* Restrict search to passed map if dlopen()ed.
|
||||
*/
|
||||
if (LM_PRIVATE(smp)->spd_flags & RTLD_DL)
|
||||
if (smp && LM_PRIVATE(smp)->spd_flags & RTLD_DL)
|
||||
src_map = smp;
|
||||
|
||||
np = lookup(sym, &src_map, 1);
|
||||
if (np == NULL)
|
||||
if (np == NULL) {
|
||||
generror ("Symbol \"%s\" not found", sym);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
/* Fixup jmpslot so future calls transfer directly to target */
|
||||
addr = np->nz_value;
|
||||
if (src_map)
|
||||
@ -1250,20 +1350,38 @@ __dlsym(fd, sym)
|
||||
return (void *)addr;
|
||||
}
|
||||
|
||||
static int
|
||||
__dlctl(fd, cmd, arg)
|
||||
void *fd, *arg;
|
||||
int cmd;
|
||||
static char *
|
||||
__dlerror __P((void))
|
||||
{
|
||||
switch (cmd) {
|
||||
case DL_GETERRNO:
|
||||
*(int *)arg = dlerrno;
|
||||
return 0;
|
||||
default:
|
||||
dlerrno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
char *err;
|
||||
|
||||
err = dlerror_msg;
|
||||
dlerror_msg = NULL; /* Next call will return NULL */
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate an error message that can be later be retrieved via dlerror.
|
||||
*/
|
||||
static void
|
||||
#if __STDC__
|
||||
generror(char *fmt, ...)
|
||||
#else
|
||||
generror(fmt, va_alist)
|
||||
char *fmt;
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
vsnprintf (dlerror_buf, DLERROR_BUF_SIZE, fmt, ap);
|
||||
dlerror_msg = dlerror_buf;
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user