diff options
author | 2013-02-02 13:47:17 +0000 | |
---|---|---|
committer | 2013-02-02 13:47:17 +0000 | |
commit | 0ed90aa07badd60d9efb8b6f1e017dafd4b7cf83 (patch) | |
tree | 475529ad6f0d4c6a9be0e00c320f27fbbe1c500b | |
parent | m68k has switched to ELF. (diff) | |
download | wireguard-openbsd-0ed90aa07badd60d9efb8b6f1e017dafd4b7cf83.tar.xz wireguard-openbsd-0ed90aa07badd60d9efb8b6f1e017dafd4b7cf83.zip |
The a.out rtld is no longer used.
-rw-r--r-- | gnu/usr.bin/ld/Makefile | 4 | ||||
-rw-r--r-- | gnu/usr.bin/ld/rtld/Makefile | 34 | ||||
-rw-r--r-- | gnu/usr.bin/ld/rtld/ld.so.1 | 225 | ||||
-rw-r--r-- | gnu/usr.bin/ld/rtld/malloc.c | 488 | ||||
-rw-r--r-- | gnu/usr.bin/ld/rtld/md-prologue.c | 39 | ||||
-rw-r--r-- | gnu/usr.bin/ld/rtld/rtld.c | 1669 |
6 files changed, 2 insertions, 2457 deletions
diff --git a/gnu/usr.bin/ld/Makefile b/gnu/usr.bin/ld/Makefile index 57daf33b27d..33785945b12 100644 --- a/gnu/usr.bin/ld/Makefile +++ b/gnu/usr.bin/ld/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.13 2005/09/28 23:54:03 deraadt Exp $ +# $OpenBSD: Makefile,v 1.14 2013/02/02 13:47:17 miod Exp $ # $NetBSD: Makefile,v 1.13 1995/04/23 07:58:46 cgd Exp $ TARGET_MACHINE_ARCH?= $(MACHINE_ARCH) @@ -27,7 +27,7 @@ beforedepend: ln -sf ${.CURDIR}/../../../sys/arch/${TARGET}/include \ cross-include/machine .else -SUBDIR= ldconfig ldd rtld +SUBDIR= ldconfig ldd .endif .PATH: $(.CURDIR)/$(TARGET_MACHINE_ARCH) diff --git a/gnu/usr.bin/ld/rtld/Makefile b/gnu/usr.bin/ld/rtld/Makefile deleted file mode 100644 index 4ba617dc6cd..00000000000 --- a/gnu/usr.bin/ld/rtld/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# $OpenBSD: Makefile,v 1.9 2005/09/28 23:54:03 deraadt Exp $ -# $NetBSD: Makefile,v 1.11 1995/10/09 00:11:24 pk Exp $ - -.include <bsd.own.mk> - -TARGET_MACHINE_ARCH?= $(MACHINE_ARCH) - -.if !defined(NOPIC) && ($(TARGET_MACHINE_ARCH) == $(MACHINE_ARCH)) -PROG= ld.so -SRCS= mdprologue.S rtld.c malloc.c shlib.c etc.c md.c vfprintf.c -LDDIR?= $(.CURDIR)/.. -LIBCRT0= -#PICFLAG=-pic -# As there is relocation going on behind GCC's back, don't cache function addresses. -PICFLAG=-fpic -fno-function-cse -CFLAGS+=-I$(LDDIR) -I$(.CURDIR) -I$(LDDIR)/$(MACHINE_ARCH) $(PICFLAG) -DRTLD -DLIBC_SCCS -LDFLAGS+=-nostartfiles -nostdlib -Wl,-Bshareable,-Bsymbolic,-assert,nosymbolic -ASFLAGS+=-k -DPADD+= ${LIBC} -LDADD+= -lc_pic -BINDIR= /usr/libexec - -.else -NOPROG= -.endif - -MAN= ld.so.1 - -.PATH: $(LDDIR) $(LDDIR)/$(MACHINE_ARCH) ${.CURDIR}/../../../../lib/libc/stdio - -.S.o: - ${CPP} ${.IMPSRC} | ${AS} ${ASFLAGS} -o ${.TARGET} - - -.include <bsd.prog.mk> diff --git a/gnu/usr.bin/ld/rtld/ld.so.1 b/gnu/usr.bin/ld/rtld/ld.so.1 deleted file mode 100644 index af72efe9b45..00000000000 --- a/gnu/usr.bin/ld/rtld/ld.so.1 +++ /dev/null @@ -1,225 +0,0 @@ -.\" $OpenBSD: ld.so.1,v 1.5 2007/05/31 19:19:24 jmc Exp $ -.\" $NetBSD: rtld.1,v 1.2 1995/10/08 23:43:28 pk Exp $ -.\" -.\" Copyright (c) 1995 Paul Kranenburg -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Paul Kranenburg. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd $Mdocdate: May 31 2007 $ -.Dt LD.SO 1 -.Os -.Sh NAME -.Nm ld.so -.Nd run-time link-editor -.Sh DESCRIPTION -.Nm -is a self-contained, position independent program image providing run-time -support for loading and link-editing shared objects into a process's -address space. -It uses the data structures -.Po -see -.Xr link 5 -.Pc -contained within dynamically linked programs to determine which shared -libraries are needed and loads them at a convenient virtual address -using the -.Xr mmap 2 -system call. -.Pp -After all shared libraries have been successfully loaded, -.Nm -proceeds to resolve external references from both the main program and -all objects loaded. -A mechanism is provided for initialization routines -to be called, on a per-object basis, giving a shared object an opportunity -to perform any extra set-up, before execution of the program proper begins. -.Nm -looks for a symbol named -.Em .init -in each object's symbol table. -If present, this symbol is assumed to -represent a C-function declared as -.Ft void -.Fn .init "void" , -which is then called. -Similarly, a -.Ft void -.Fn .fini "void" -function is called just before an object is unloaded from the process -address space as a result of calling -.Xr dlclose 3 . -Note that while an object's -.Em .init -is always called, whether the object is loaded automatically at program -startup or programatically by using -.Xr dlopen 3 , -the -.Em .fini -function is called only on -.Sq last Xr dlclose 3 . -.Pp -This mechanism is exploited by the system-supplied C++ constructor -initialization code located in -.Pa /usr/lib/c++rt.o . -This file should be included in the list of object-code files passed to -.Xr ld 1 -when building a shared C++ library. -.Pp -.Nm -is itself a shared object that is initially loaded by the startup module -.Em crt0 . -Since -.Xr a.out 5 -formats do not provide easy access to the file header from within a running -process, -.Em crt0 -uses the special symbol -.Va _DYNAMIC -to determine whether a program is in fact dynamically linked or not. -Whenever the linker -.Xr ld 1 -has relocated this symbol to a location other than 0, -.Em crt0 -assumes the services of -.Nm -are needed -.Po -see -.Xr link 5 -for details -.Pc . -.Em crt0 -passes control to -.Nm ld.so Ns 's -entry point before the program's -.Fn main -routine is called. -Thus, -.Nm -can complete the link-editing process before the dynamic program calls upon -services of any dynamic library. -.Pp -To quickly locate the required shared objects in the filesystem, -.Nm -may use a -.Dq hints -file, prepared by the -.Xr ldconfig 8 -utility, in which the full path specification of the shared objects can be -looked up by hashing on the 3-tuple -.Ao -library-name, major-version-number, minor-version-number -.Ac Ns \&. -.Pp -.Nm -recognises a number of environment variables that can be used to modify -its behaviour as follows: -.Bl -tag -width "LD_TRACE_LOADED_OBJECTS_FMT1" -.It Ev LD_LIBRARY_PATH -A colon separated list of directories, overriding the default search path -for shared libraries. -This variable is ignored for set-user-ID and set-group-ID executables. -.It Ev LD_PRELOAD -A colon separate list of library names to load before any of the regular -libraries are loaded. -This variable is ignored for set-user-ID and set-group-ID executables. -.It Ev LD_WARN_NON_PURE_CODE -When set, issue a warning whenever a link-editing operation requires -modification of the text segment of some loaded object. -This is usually indicative of an incorrectly built library. -.It Ev LD_SUPPRESS_WARNINGS -When set, no warning messages of any kind are issued. -Normally, a warning -is given if satisfactorily versioned library could not be found. -.It Ev LD_TRACE_LOADED_OBJECTS -When set, causes -.Nm -to exit after loading the shared objects and printing a summary which includes -the absolute pathnames of all objects, to standard output. -.It Ev LD_TRACE_LOADED_OBJECTS_FMT1 -.It Ev LD_TRACE_LOADED_OBJECTS_FMT2 -When set, these variables are interpreted as format strings a la -.Xr printf 3 -to customize the trace output and are used by -.Xr ldd 1 Ns 's -.Fl f -option and allows -.Xr ldd 1 -to be operated as a filter more conveniently. -The following conversions can be used: -.Bl -tag -width "xxxx" -.It \&%a -The main program's name -.Po also known as -.Dq __progname -.Pc . -.It \&%A -The value of the environment variable -.Ev LD_TRACE_LOADED_OBJECTS_PROGNAME -.It \&%o -The library name. -.It \&%m -The library's major version number. -.It \&%n -The library's minor version number. -.It \&%p -The full pathname as determined by -.Nm ld.so Ns 's -library search rules. -.It \&%x -The library's load address. -.El -.Pp -Additionally, -.Sy \en -and -.Sy \et -are recognised and have their usual meaning. -.It Ev LD_NO_INTERN_SEARCH -When set, -.Nm -does not process any internal search paths that were recorded in the -executable. -.It Ev LD_NOSTD_PATH -When set, do not include a set of built-in standard directory paths for -searching. -This might be useful when running on a system with a completely -non-standard filesystem layout. -.El -.Sh FILES -.Bl -tag -width /var/run/ld.so.hintsXXX -compact -.It Pa /var/run/ld.so.hints -library location hints built by -.Xr ldconfig 8 -.El -.Sh SEE ALSO -.Xr ld 1 , -.Xr link 5 , -.Xr ldconfig 8 -.Sh HISTORY -The shared library model employed first appeared in SunOS 4.0. diff --git a/gnu/usr.bin/ld/rtld/malloc.c b/gnu/usr.bin/ld/rtld/malloc.c deleted file mode 100644 index af8fc1b7630..00000000000 --- a/gnu/usr.bin/ld/rtld/malloc.c +++ /dev/null @@ -1,488 +0,0 @@ -/* $OpenBSD: malloc.c,v 1.10 2008/09/03 21:29:30 miod Exp $ */ - -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/ -static char *rcsid = "$OpenBSD: malloc.c,v 1.10 2008/09/03 21:29:30 miod Exp $"; -#endif /* LIBC_SCCS and not lint */ - -/* - * malloc.c (Caltech) 2/21/82 - * Chris Kingsley, kingsley@cit-20. - * - * This is a very fast storage allocator. It allocates blocks of a small - * number of different sizes, and keeps free lists of each size. Blocks that - * don't exactly fit are passed up to the next larger size. In this - * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long. - * This is designed for use in a virtual memory environment. - */ - -#include <sys/types.h> -#include <err.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/param.h> -#include <sys/mman.h> - -#ifndef BSD -#define MAP_COPY MAP_PRIVATE -#define MAP_FILE 0 -#define MAP_ANON 0 -#endif - -#ifndef BSD /* Need do better than this */ -#define NEED_DEV_ZERO 1 -#endif - -#ifndef NULL -#define NULL 0 -#endif - -/* - * Pre-allocate mmap'ed pages - */ -#define NPOOLPAGES (32*1024/pagesz) -static caddr_t pagepool_start, pagepool_end; -static int morepages(int); -extern void xprintf(char *, ...); - -/* - * The overhead on a block is at least 4 bytes. When free, this space - * contains a pointer to the next free block, and the bottom two bits must - * be zero. When in use, the first byte is set to MAGIC, and the second - * byte is the size index. The remaining bytes are for alignment. - * If range checking is enabled then a second word holds the size of the - * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC). - * The order of elements is critical: ov_magic must overlay the low order - * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern. - */ -union overhead { - union overhead *ov_next; /* when free */ - struct { - u_char ovu_magic; /* magic number */ - u_char ovu_index; /* bucket # */ -#ifdef RCHECK - u_short ovu_rmagic; /* range magic number */ - u_int ovu_size; /* actual block size */ -#endif - } ovu; -#define ov_magic ovu.ovu_magic -#define ov_index ovu.ovu_index -#define ov_rmagic ovu.ovu_rmagic -#define ov_size ovu.ovu_size -}; - -#define MAGIC 0xef /* magic # on accounting info */ -#define RMAGIC 0x5555 /* magic # on range info */ - -#ifdef RCHECK -#define RSLOP sizeof (u_short) -#else -#define RSLOP 0 -#endif - -static void morecore(int); -static int findbucket(union overhead *freep, int srchlen); - -/* - * nextf[i] is the pointer to the next free block of size 2^(i+3). The - * smallest allocatable block is 8 bytes. The overhead information - * precedes the data area returned to the user. - */ -#define NBUCKETS 30 -static union overhead *nextf[NBUCKETS]; - -static int pagesz; /* page size */ -static int pagebucket; /* page size bucket */ - -#ifdef MSTATS -/* - * nmalloc[i] is the difference between the number of mallocs and frees - * for a given block size. - */ -static u_int nmalloc[NBUCKETS]; -#include <stdio.h> -#endif - -#if defined(DEBUG) || defined(RCHECK) -#define ASSERT(p) if (!(p)) botch("p") -#include <stdio.h> -static -botch(s) - char *s; -{ - fprintf(stderr, "\r\nassertion botched: %s\r\n", s); - (void) fflush(stderr); /* just in case user buffered it */ - abort(); -} -#else -#define ASSERT(p) -#endif - -void * -malloc(size_t nbytes) -{ - union overhead *op; - int bucket, n; - unsigned amt; - - /* - * First time malloc is called, setup page size and - * align break pointer so all data will be page aligned. - */ - if (pagesz == 0) { - pagesz = n = getpagesize(); - if (morepages(NPOOLPAGES) == 0) - return NULL; - op = (union overhead *)(pagepool_start); - n = n - sizeof (*op) - ((int)op & (n - 1)); - if (n < 0) - n += pagesz; - if (n) { - pagepool_start += n; - } - bucket = 0; - amt = 8; - while (pagesz > amt) { - amt <<= 1; - bucket++; - } - pagebucket = bucket; - } - /* - * Convert amount of memory requested into closest block size - * stored in hash buckets which satisfies request. - * Account for space used per block for accounting. - */ - if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) { -#ifndef RCHECK - amt = 8; /* size of first bucket */ - bucket = 0; -#else - amt = 16; /* size of first bucket */ - bucket = 1; -#endif - n = -(sizeof (*op) + RSLOP); - } else { - amt = pagesz; - bucket = pagebucket; - } - while (nbytes > amt + n) { - amt <<= 1; - if (amt == 0) - return (NULL); - bucket++; - } - /* - * If nothing in hash bucket right now, - * request more memory from the system. - */ - if ((op = nextf[bucket]) == NULL) { - morecore(bucket); - if ((op = nextf[bucket]) == NULL) - return (NULL); - } - /* remove from linked list */ - nextf[bucket] = op->ov_next; - op->ov_magic = MAGIC; - op->ov_index = bucket; -#ifdef MSTATS - nmalloc[bucket]++; -#endif -#ifdef RCHECK - /* - * Record allocated size of block and - * bound space with magic numbers. - */ - op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); - op->ov_rmagic = RMAGIC; - *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; -#endif - return ((char *)(op + 1)); -} - -/* - * Allocate more memory to the indicated bucket. - */ -static void -morecore(int bucket) -{ - union overhead *op; - int sz; /* size of desired block */ - int amt; /* amount to allocate */ - int nblks; /* how many blocks we get */ - - /* - * sbrk_size <= 0 only for big, FLUFFY, requests (about - * 2^30 bytes on a VAX, I think) or for a negative arg. - */ - sz = 1 << (bucket + 3); -#ifdef DEBUG - ASSERT(sz > 0); -#else - if (sz <= 0) - return; -#endif - if (sz < pagesz) { - amt = pagesz; - nblks = amt / sz; - } else { - amt = sz + pagesz; - nblks = 1; - } - if (amt > pagepool_end - pagepool_start) - if (morepages(amt/pagesz + NPOOLPAGES) == 0) - return; - op = (union overhead *)pagepool_start; - pagepool_start += amt; - - /* - * Add new memory allocated to that on - * free list for this hash bucket. - */ - nextf[bucket] = op; - while (--nblks > 0) { - op->ov_next = (union overhead *)((caddr_t)op + sz); - op = (union overhead *)((caddr_t)op + sz); - } -} - -void -free(void *cp) -{ - int size; - union overhead *op; - - if (cp == NULL) - return; - op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); -#ifdef DEBUG - ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ -#else - if (op->ov_magic != MAGIC) - return; /* sanity */ -#endif -#ifdef RCHECK - ASSERT(op->ov_rmagic == RMAGIC); - ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); -#endif - size = op->ov_index; - ASSERT(size < NBUCKETS); - op->ov_next = nextf[size]; /* also clobbers ov_magic */ - nextf[size] = op; -#ifdef MSTATS - nmalloc[size]--; -#endif -} - -/* - * When a program attempts "storage compaction" as mentioned in the - * old malloc man page, it realloc's an already freed block. Usually - * this is the last block it freed; occasionally it might be farther - * back. We have to search all the free lists for the block in order - * to determine its bucket: 1st we make one pass thru the lists - * checking only the first block in each; if that fails we search - * ``realloc_srchlen'' blocks in each list for a match (the variable - * is extern so the caller can modify it). If that fails we just copy - * however many bytes was given to realloc() and hope it's not huge. - */ -int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ - -void * -realloc(void *cp, size_t nbytes) -{ - u_int onb; - int i; - union overhead *op; - char *res; - int was_alloced = 0; - - if (cp == NULL) - return (malloc(nbytes)); - op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); - if (op->ov_magic == MAGIC) { - was_alloced++; - i = op->ov_index; - } else { - /* - * Already free, doing "compaction". - * - * Search for the old block of memory on the - * free list. First, check the most common - * case (last element free'd), then (this failing) - * the last ``realloc_srchlen'' items free'd. - * If all lookups fail, then assume the size of - * the memory block being realloc'd is the - * largest possible (so that all "nbytes" of new - * memory are copied into). Note that this could cause - * a memory fault if the old area was tiny, and the moon - * is gibbous. However, that is very unlikely. - */ - if ((i = findbucket(op, 1)) < 0 && - (i = findbucket(op, realloc_srchlen)) < 0) - i = NBUCKETS; - } - onb = 1 << (i + 3); - if (onb < pagesz) - onb -= sizeof (*op) + RSLOP; - else - onb += pagesz - sizeof (*op) - RSLOP; - /* avoid the copy if same size block */ - if (was_alloced) { - if (i) { - i = 1 << (i + 2); - if (i < pagesz) - i -= sizeof (*op) + RSLOP; - else - i += pagesz - sizeof (*op) - RSLOP; - } - if (nbytes <= onb && nbytes > i) { -#ifdef RCHECK - op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); - *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; -#endif - return(cp); - } else - free(cp); - } - if ((res = malloc(nbytes)) == NULL) - return (NULL); - if (cp != res) /* common optimization if "compacting" */ - bcopy(cp, res, (nbytes < onb) ? nbytes : onb); - return (res); -} - -/* - * Search ``srchlen'' elements of each free list for a block whose - * header starts at ``freep''. If srchlen is -1 search the whole list. - * Return bucket number, or -1 if not found. - */ -static int -findbucket(union overhead *freep, int srchlen) -{ - union overhead *p; - int i, j; - - for (i = 0; i < NBUCKETS; i++) { - j = 0; - for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { - if (p == freep) - return (i); - j++; - } - } - return (-1); -} - -#ifdef MSTATS -/* - * mstats - print out statistics about malloc - * - * Prints two lines of numbers, one showing the length of the free list - * for each size category, the second showing the number of mallocs - - * frees for each size category. - */ -mstats(char *s) -{ - int i, j; - union overhead *p; - int totfree = 0, - totused = 0; - - fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s); - for (i = 0; i < NBUCKETS; i++) { - for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) - ; - fprintf(stderr, " %d", j); - totfree += j * (1 << (i + 3)); - } - fprintf(stderr, "\nused:\t"); - for (i = 0; i < NBUCKETS; i++) { - fprintf(stderr, " %d", nmalloc[i]); - totused += nmalloc[i] * (1 << (i + 3)); - } - fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n", - totused, totfree); -} -#endif - - -static int -morepages(int n) -{ - int fd = -1; - int offset; - -#ifdef NEED_DEV_ZERO - fd = open("/dev/zero", O_RDWR, 0); - if (fd == -1) - perror("/dev/zero"); -#endif - - if (pagepool_end - pagepool_start > pagesz) { - caddr_t addr = (caddr_t) - (((int)pagepool_start + pagesz - 1) & ~(pagesz - 1)); - if (munmap(addr, pagepool_end - addr) != 0) - warn("morepages: munmap %p", addr); - } - - offset = (int)pagepool_start - ((int)pagepool_start & ~(pagesz - 1)); - - if ((pagepool_start = mmap(0, n * pagesz, - PROT_READ|PROT_WRITE, - MAP_ANON|MAP_COPY, fd, 0)) == (caddr_t)MAP_FAILED) { - xprintf("Cannot map anonymous memory"); - return 0; - } - pagepool_end = pagepool_start + n * pagesz; - pagepool_start += offset; - -#ifdef NEED_DEV_ZERO - close(fd); -#endif - return n; -} - -void * -calloc(size_t num, size_t size) -{ - void *p; - - if (num && SIZE_MAX / num < size) { - return NULL; - } - size *= num; - p = malloc(size); - if (p) - memset(p, 0, size); - return(p); -} diff --git a/gnu/usr.bin/ld/rtld/md-prologue.c b/gnu/usr.bin/ld/rtld/md-prologue.c deleted file mode 100644 index e19a4990db7..00000000000 --- a/gnu/usr.bin/ld/rtld/md-prologue.c +++ /dev/null @@ -1,39 +0,0 @@ -/* $OpenBSD: md-prologue.c,v 1.4 2002/07/19 19:28:12 marc Exp $ */ - -/* - * rtld entry pseudo code - turn into assembler and tweak it - */ - -#include <sys/types.h> -#include <sys/types.h> -#include <a.out.h> -#include "link.h" -#include "md.h" - -extern long _GOT_[]; -extern void (*rtld)(); -extern void (*binder())(); - -void -rtld_entry(int version, struct crt *crtp) -{ - struct link_dynamic *dp; - void (*f)(); - - /* __DYNAMIC is first entry in GOT */ - dp = (struct link_dynamic *) (_GOT_[0]+crtp->crt_ba); - - f = (void (*)())((long)rtld + crtp->crt_ba); - (*f)(version, crtp, dp); -} - -void -binder_entry(void) -{ - extern int PC; - struct jmpslot *sp; - void (*func)(); - - func = binder(PC, sp->reloc_index & 0x003fffff); - (*func)(); -} diff --git a/gnu/usr.bin/ld/rtld/rtld.c b/gnu/usr.bin/ld/rtld/rtld.c deleted file mode 100644 index f2708757304..00000000000 --- a/gnu/usr.bin/ld/rtld/rtld.c +++ /dev/null @@ -1,1669 +0,0 @@ -/* $OpenBSD: rtld.c,v 1.42 2012/04/16 19:40:01 miod Exp $ */ -/* $NetBSD: rtld.c,v 1.43 1996/01/14 00:35:17 pk Exp $ */ -/* - * Copyright (c) 1993 Paul Kranenburg - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Paul Kranenburg. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/file.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/mman.h> -#ifndef MAP_COPY -#define MAP_COPY MAP_PRIVATE -#endif -#include <err.h> -#include <errno.h> -#include <dlfcn.h> -#include <fcntl.h> -#include <a.out.h> -#include <limits.h> -#include <stab.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#if __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -#include "ld.h" - -/* - * Stack protector dummies. - * Ideally, a scheme to compile these stubs from libc should be used, but - * this would end up dragging too much code from libc here. - */ -long __guard[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -void -__stack_smash_handler(char func[], int damaged) -{ - _exit(127); -} - -#ifndef MAP_ANON -#define MAP_ANON 0 -#define anon_open() do { \ - if ((anon_fd = open("/dev/zero", O_RDWR, 0)) == -1) \ - err("open: %s", "/dev/zero"); \ -} while (0) -#define anon_close() do { \ - (void)close(anon_fd); \ - anon_fd = -1; \ -} while (0) -#else -#define anon_open() -#define anon_close() -#endif - -/* - * Loader private data, hung off <so_map>->som_spd - */ -struct somap_private { - int spd_version; - struct so_map *spd_parent; - int spd_refcount; - int spd_flags; -#define RTLD_MAIN 1 -#define RTLD_RTLD 2 -#define RTLD_DL 4 -#define RTLD_INITED 8 - size_t spd_size; - -#ifdef SUN_COMPAT - long spd_offset; /* Correction for Sun main programs */ -#endif - struct dep_node *first_child; - struct dep_node *last_child; -}; - -struct dep_node { - struct dep_node *next_sibling; - struct so_map *data; -}; - -#define LM_PRIVATE(smp) ((struct somap_private *)(smp)->som_spd) - -#ifdef SUN_COMPAT -#define LM_OFFSET(smp) (LM_PRIVATE(smp)->spd_offset) -#else -#define LM_OFFSET(smp) (0) -#endif - -/* Base address for section_dispatch_table entries */ -#define LM_LDBASE(smp) (smp->som_addr + LM_OFFSET(smp)) - -/* Start of text segment */ -#define LM_TXTADDR(smp) (smp->som_addr == (caddr_t)0 ? PAGSIZ : 0) - -/* Start of run-time relocation_info */ -#define LM_REL(smp) ((struct relocation_info *) \ - (smp->som_addr + LM_OFFSET(smp) + LD_REL((smp)->som_dynamic))) - -/* Start of symbols */ -#define LM_SYMBOL(smp, i) ((struct nzlist *) \ - (smp->som_addr + LM_OFFSET(smp) + LD_SYMBOL((smp)->som_dynamic) + \ - i * (LD_VERSION_NZLIST_P(smp->som_dynamic->d_version) ? \ - sizeof(struct nzlist) : sizeof(struct nlist)))) - -/* Start of hash table */ -#define LM_HASH(smp) ((struct rrs_hash *) \ - ((smp)->som_addr + LM_OFFSET(smp) + LD_HASH((smp)->som_dynamic))) - -/* Start of strings */ -#define LM_STRINGS(smp) ((char *) \ - ((smp)->som_addr + LM_OFFSET(smp) + LD_STRINGS((smp)->som_dynamic))) - -/* Start of search paths */ -#define LM_PATHS(smp) ((char *) \ - ((smp)->som_addr + LM_OFFSET(smp) + LD_PATHS((smp)->som_dynamic))) - -/* End of text */ -#define LM_ETEXT(smp) ((char *) \ - ((smp)->som_addr + LM_TXTADDR(smp) + LD_TEXTSZ((smp)->som_dynamic))) - -/* PLT is in data segment, so don't use LM_OFFSET here */ -#define LM_PLT(smp) ((jmpslot_t *) \ - ((smp)->som_addr + LD_PLT((smp)->som_dynamic))) - -/* Parent of link map */ -#define LM_PARENT(smp) (LM_PRIVATE(smp)->spd_parent) - -static char __main_progname[] = "main"; -static char *main_progname = __main_progname; -static char us[] = "/usr/libexec/ld.so"; - -char **environ; -char *__progname = us; -/* int errno; */ - -static int careful; -static int anon_fd = -1; - -struct so_map *link_map_head, *main_map; -struct so_map **link_map_tail = &link_map_head; -struct rt_symbol *rt_symbol_head; - -static char *ld_library_path; -static char *ld_preload_path; -static int no_intern_search; -static int ld_suppress_warnings; -static int ld_warn_non_pure_code; - -static int ld_tracing; - -static void *__dlopen(const char *, int); -static int __dlclose(void *); -static void *__dlsym(void *, const char *); -static int __dlctl(void *, int, void *); -static void __dlexit(void); - -static struct ld_entry ld_entry = { - __dlopen, __dlclose, __dlsym, __dlctl, __dlexit -}; - - void xprintf(char *, ...); - int rtld(int, struct crt_ldso *, struct _dynamic *); - void binder_entry(void); - long binder(jmpslot_t *); -static int load_subs(struct so_map *); -static struct so_map *map_object(struct sod *, struct so_map *); -static void unmap_object(struct so_map *); -static struct so_map *alloc_link_map( char *, struct sod *, - struct so_map *, caddr_t, - size_t, struct _dynamic *); -static void free_link_map(struct so_map *); -static inline void check_text_reloc( struct relocation_info *, - struct so_map *, - caddr_t); -static void init_maps(struct so_map *); -static void reloc_map(struct so_map *); -static void reloc_copy(struct so_map *); -static void call_map(struct so_map *, char *); -static char *rtfindlib(char *, int, int, int *, char *); -static struct nzlist *lookup(const char *, struct so_map **, int); -static inline struct rt_symbol *lookup_rts(const char *); -static struct rt_symbol *enter_rts(const char *, long, int, caddr_t, - long, struct so_map *); -static void maphints(void); -static void unmaphints(void); - -static void preload(char *); -static void ld_trace(struct so_map *); - -static inline int -strcmp (const char *s1, const char *s2) -{ - while (*s1 == *s2++) - if (*s1++ == 0) - return (0); - return (*(unsigned char *)s1 - *(unsigned char *)--s2); -} - -#include "md-static-funcs.c" - -/* - * Called from assembler stub that has set up crtp (passed from crt0) - * and dp (our __DYNAMIC). - */ -int -rtld(int version, struct crt_ldso *crtp, struct _dynamic *dp) -{ - int n; - int nreloc; /* # of ld.so relocations */ - struct relocation_info *reloc; - struct so_debug *ddp; - struct so_map *smp; - - /* Check version */ - if ( version != CRT_VERSION_BSD_2 && - version != CRT_VERSION_BSD_3 && - version != CRT_VERSION_BSD_4 && - 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++; - - - /* Relocate ourselves */ - for (reloc = (struct relocation_info *)(LD_REL(dp) + crtp->crt_ba); - nreloc; nreloc--, reloc++) { - long addr = reloc->r_address + crtp->crt_ba; - md_relocate_simple(reloc, crtp->crt_ba, (char*)addr); - } - - if (version >= CRT_VERSION_BSD_4) - __progname = crtp->crt_ldso; - - if (version >= CRT_VERSION_BSD_3) - main_progname = crtp->crt_prog; - - /* Setup out (private) environ variable */ - environ = crtp->crt_ep; - - if (issetugid()) - careful = 1; - - if (careful) { - unsetenv("LD_LIBRARY_PATH"); - unsetenv("LD_PRELOAD"); - } - - /* Setup directory search */ - ld_library_path = getenv("LD_LIBRARY_PATH"); - add_search_path(ld_library_path); - if (getenv("LD_NOSTD_PATH") == NULL) - std_search_path(); - - ld_suppress_warnings = getenv("LD_SUPPRESS_WARNINGS") != NULL; - ld_warn_non_pure_code = getenv("LD_WARN_NON_PURE_CODE") != NULL; - - no_intern_search = careful || getenv("LD_NO_INTERN_SEARCH") != 0; - - anon_open(); - - /* - * Init object administration. We start off with a map description - * for `main' and `rtld'. - */ - smp = alloc_link_map(main_progname, (struct sod *)0, (struct so_map *)0, - (caddr_t)0, 0, crtp->crt_dp); - LM_PRIVATE(smp)->spd_refcount++; - LM_PRIVATE(smp)->spd_flags |= RTLD_MAIN; - main_map = smp; - - smp = alloc_link_map(us, (struct sod *)0, (struct so_map *)0, - (caddr_t)crtp->crt_ba, 0, dp); - LM_PRIVATE(smp)->spd_refcount++; - LM_PRIVATE(smp)->spd_flags |= RTLD_RTLD; - - /* Fill in some field in main's __DYNAMIC structure */ - if (version >= CRT_VERSION_BSD_4) - crtp->crt_ldentry = &ld_entry; - else - crtp->crt_dp->d_entry = &ld_entry; - - /* Handle LD_PRELOAD's here */ - ld_preload_path = getenv("LD_PRELOAD"); - if (ld_preload_path != NULL) - preload(ld_preload_path); - - /* Load subsidiary objects into the process address space */ - ld_tracing = (int)getenv("LD_TRACE_LOADED_OBJECTS"); - load_subs(link_map_head); - if (ld_tracing) { - ld_trace(link_map_head); - exit(0); - } - - init_maps(link_map_head); - - crtp->crt_dp->d_un.d_sdt->sdt_loaded = link_map_head->som_next; - - ddp = crtp->crt_dp->d_debug; - ddp->dd_cc = rt_symbol_head; - if (ddp->dd_in_debugger) { - caddr_t addr = (caddr_t)((long)crtp->crt_bp & (~(PAGSIZ - 1))); - - /* Set breakpoint for the benefit of debuggers */ - if (mprotect(addr, PAGSIZ, - PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { - err(1, "Cannot set breakpoint (%s)", main_progname); - } - md_set_breakpoint((long)crtp->crt_bp, (long *)&ddp->dd_bpt_shadow); - if (mprotect(addr, PAGSIZ, PROT_READ|PROT_EXEC) == -1) { - err(1, "Cannot re-protect breakpoint (%s)", - main_progname); - } - - ddp->dd_bpt_addr = crtp->crt_bp; - if (link_map_head) - ddp->dd_sym_loaded = 1; - } - - /* Close the hints file */ - unmaphints(); - - /* Close our file descriptor */ - (void)close(crtp->crt_ldfd); - anon_close(); - return 0; -} - -static void -link_sub(struct so_map *dep, struct so_map *p) -{ - struct dep_node *n; - struct somap_private *pp; - - n = xmalloc(sizeof *n); - n->data = dep; - n->next_sibling = NULL; - pp = LM_PRIVATE(p); - if (pp->first_child) { - pp->last_child->next_sibling = n; - pp->last_child = n; - } else { - pp->first_child = pp->last_child = n; - } -} - -static int -load_subs(struct so_map *smp) -{ - - for (; smp; smp = smp->som_next) { - struct sod *sodp; - long next = 0; - - if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) - continue; - - if (smp->som_dynamic) - next = LD_NEED(smp->som_dynamic); - - while (next) { - struct so_map *newmap; - - sodp = (struct sod *)(LM_LDBASE(smp) + next); - - if ((newmap = map_object(sodp, smp)) == NULL) { - if (!ld_tracing) { - if (smp != main_map) - if (sodp->sod_library) - err(1, "%s(%s): lib%s.so.%d.%d", - main_progname, - smp->som_path, - sodp->sod_name+LM_LDBASE(smp), - sodp->sod_major, - sodp->sod_minor); - else - err(1, "%s(%s): %s", - main_progname, - smp->som_path, - sodp->sod_name+LM_LDBASE(smp)); - else - if (sodp->sod_library) - err(1, "%s: lib%s.so.%d.%d", - main_progname, - sodp->sod_name+LM_LDBASE(smp), - sodp->sod_major, - sodp->sod_minor); - else - err(1, "%s: %s", - main_progname, - sodp->sod_name+LM_LDBASE(smp)); - } - newmap = alloc_link_map(NULL, sodp, smp, - 0, 0, 0); - } else { - link_sub(newmap, smp); - } - LM_PRIVATE(newmap)->spd_refcount++; - next = sodp->sod_next; - } - } - return 0; -} - -void -ld_trace(struct so_map *smp) -{ - char *fmt1, *fmt2, *fmt, *main_local; - int c; - - if ((main_local = getenv("LD_TRACE_LOADED_OBJECTS_PROGNAME")) == NULL) - main_local = ""; - - if ((fmt1 = getenv("LD_TRACE_LOADED_OBJECTS_FMT1")) == NULL) - fmt1 = "\t-l%o.%m => %p (%x)\n"; - - if ((fmt2 = getenv("LD_TRACE_LOADED_OBJECTS_FMT2")) == NULL) - fmt2 = "\t%o (%x)\n"; - - for (; smp; smp = smp->som_next) { - struct sod *sodp; - char *name, *path; - - if ((sodp = smp->som_sod) == NULL) - continue; - - name = (char *)sodp->sod_name; - if (LM_PARENT(smp)) - name += (long)LM_LDBASE(LM_PARENT(smp)); - - if ((path = smp->som_path) == NULL) - path = "not found"; - - fmt = sodp->sod_library ? fmt1 : fmt2; - while ((c = *fmt++) != '\0') { - switch (c) { - default: - putchar(c); - continue; - case '\\': - switch (c = *fmt) { - case '\0': - continue; - case 'n': - putchar('\n'); - break; - case 't': - putchar('\t'); - break; - } - break; - case '%': - switch (c = *fmt) { - case '\0': - continue; - case '%': - default: - putchar(c); - break; - case 'A': - printf("%s", main_local); - break; - case 'a': - printf("%s", main_progname); - break; - case 'o': - printf("%s", name); - break; - case 'm': - printf("%d", sodp->sod_major); - break; - case 'n': - printf("%d", sodp->sod_minor); - break; - case 'p': - printf("%s", path); - break; - case 'x': - printf("%p", smp->som_addr); - break; - } - break; - } - ++fmt; - } - } -} - -/* - * Allocate a new link map for shared object NAME loaded at ADDR as a - * result of the presence of link object LOP in the link map PARENT. - */ -static struct so_map * -alloc_link_map(char *path, struct sod *sodp, struct so_map *parent, - caddr_t addr, size_t size, struct _dynamic *dp) -{ - struct so_map *smp; - struct somap_private *smpp; - - smpp = (struct somap_private *)xmalloc(sizeof(struct somap_private)); - smp = (struct so_map *)xmalloc(sizeof(struct so_map)); - smp->som_next = NULL; - *link_map_tail = smp; - link_map_tail = &smp->som_next; - - /*smp->som_sodbase = 0; NOT USED */ - smp->som_write = 0; - smp->som_addr = addr; - smp->som_path = path?strdup(path):NULL; - smp->som_sod = sodp; - smp->som_dynamic = dp; - smp->som_spd = (caddr_t)smpp; - - smpp->spd_refcount = 0; - smpp->spd_flags = 0; - smpp->spd_parent = parent; - smpp->spd_size = size; - smpp->first_child = NULL; - smpp->last_child = NULL; - -#ifdef SUN_COMPAT - smpp->spd_offset = - (addr==0 && dp && dp->d_version==LD_VERSION_SUN) ? PAGSIZ : 0; -#endif - return smp; -} - -/* - * Free the link map for an object being unmapped. The link map - * has already been removed from the link map list, so it can't be used - * after it's been unmapped. - */ -static void -free_link_map(struct so_map *smp) -{ - - if ((LM_PRIVATE(smp)->spd_flags & RTLD_DL) != 0) { - /* free synthetic sod structure allocated in __dlopen() */ - free((char *)smp->som_sod->sod_name); - free(smp->som_sod); - } - - /* free the link map structure. */ - free(smp->som_spd); - if (smp->som_path != NULL) - free(smp->som_path); - free(smp); -} - -/* - * Map object identified by link object SODP which was found - * in link map SMP. - */ -static struct so_map * -map_object(struct sod *sodp, struct so_map *smp) -{ - char *name; - struct _dynamic *dp; - char *path, *ipath; - int fd, sverrno; - caddr_t addr; - struct exec hdr; - int usehints = 0; - struct so_map *p; - - name = (char *)sodp->sod_name; - if (smp) - name += (long)LM_LDBASE(smp); - - if (sodp->sod_library) { - usehints = 1; -again: - if (smp == NULL || no_intern_search || - LD_PATHS(smp->som_dynamic) == 0) { - ipath = NULL; - } else { - ipath = LM_PATHS(smp); - add_search_path(ipath); - } - - path = rtfindlib(name, sodp->sod_major, - sodp->sod_minor, &usehints, ipath); - if (ipath) - remove_search_path(ipath); - - if (path == NULL && smp != main_map && main_map != NULL && - !no_intern_search && - LD_PATHS(main_map->som_dynamic) != 0) { - ipath = LM_PATHS(main_map); - add_search_path(ipath); - path = rtfindlib(name, sodp->sod_major, - sodp->sod_minor, &usehints, ipath); - remove_search_path(ipath); - } - - if (path == NULL) { - errno = ENOENT; - return NULL; - } - } else { - if (careful && *name != '/') { - errno = EACCES; - return NULL; - } - path = name; - } - - /* Check if already loaded */ - for (p = link_map_head; p; p = p->som_next) - if (p->som_path && strcmp(p->som_path, path) == 0) - break; - - if (p != NULL) - return p; - - if ((fd = open(path, O_RDONLY, 0)) == -1) { - if (usehints) { - usehints = 0; - goto again; - } - return NULL; - } - - if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - sverrno = errno; - (void)close(fd); - errno = sverrno; - return NULL; - } - - if (N_BADMAG(hdr)) { - (void)close(fd); - errno = EFTYPE; - return NULL; - } - - if ((addr = mmap(0, hdr.a_text + hdr.a_data + hdr.a_bss, - PROT_READ|PROT_EXEC, - MAP_COPY, fd, 0)) == (caddr_t)MAP_FAILED) { - sverrno = errno; - (void)close(fd); - errno = sverrno; - return NULL; - } - -#if DEBUG - xprintf("map1: 0x%x for 0x%x\n", addr, hdr.a_text + hdr.a_data + hdr.a_bss); -#endif - - if (mprotect(addr + hdr.a_text, hdr.a_data, - PROT_READ|PROT_WRITE|PROT_EXEC) != 0) { - sverrno = errno; - (void)close(fd); - errno = sverrno; - return NULL; - } - - if (hdr.a_bss && mmap(addr + hdr.a_text + hdr.a_data, hdr.a_bss, - PROT_READ|PROT_WRITE, - MAP_ANON|MAP_COPY|MAP_FIXED, - anon_fd, 0) == (caddr_t)MAP_FAILED) { - sverrno = errno; - (void)close(fd); - errno = sverrno; - return NULL; - } - - (void)close(fd); - - /* Assume _DYNAMIC is the first data item */ - dp = (struct _dynamic *)(addr+hdr.a_text); - - /* Fixup __DYNAMIC structure */ - (long)dp->d_un.d_sdt += (long)addr; - - return alloc_link_map(path, sodp, smp, addr, - hdr.a_text + hdr.a_data + hdr.a_bss, dp); -} - -/* - * Unmap a mapped object. - */ -static void -unmap_object(struct so_map *smp) -{ - struct so_map *p, **pp; - - /* remove from link map list */ - pp = &link_map_head; - while ((p = *pp) != NULL) { - if (p == smp) - break; - pp = &p->som_next; - } - if (p == NULL) { - warnx("warning: link map entry for %s not on link map list!", - smp->som_path); - return; - } - - *pp = smp->som_next; /* make list skip it */ - if (link_map_tail == &smp->som_next) /* and readjust tail pointer */ - link_map_tail = pp; - - /* unmap from address space */ - (void)munmap(smp->som_addr, LM_PRIVATE(smp)->spd_size); -} - -void init_dependent_before_main(struct so_map *smp) -{ - struct dep_node *n; - - LM_PRIVATE(smp)->spd_flags |= RTLD_INITED; - - for (n = LM_PRIVATE(smp)->first_child; n; n = n->next_sibling) { - if (LM_PRIVATE(n->data)->spd_flags & RTLD_INITED) - continue; - init_dependent_before_main(n->data); - } - - call_map(smp, ".init"); - call_map(smp, "__init"); - call_map(smp, "__GLOBAL__DI"); -} - -void -init_maps(struct so_map *head) -{ - struct so_map *smp; - - /* Relocate all loaded objects according to their RRS segments */ - for (smp = head; smp; smp = smp->som_next) { - if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) - continue; - reloc_map(smp); - } - - /* Copy any relocated initialized data. */ - for (smp = head; smp; smp = smp->som_next) { - if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) - continue; - reloc_copy(smp); - } - - /* Call any object initialization routines. */ - for (smp = head; smp; smp = smp->som_next) { - if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) - continue; - if (LM_PRIVATE(smp)->spd_flags & RTLD_INITED) - continue; - init_dependent_before_main(smp); - } -} - -static inline void -check_text_reloc(struct relocation_info *r, struct so_map *smp, caddr_t addr) -{ - char *sym; - - if (addr >= LM_ETEXT(smp)) - return; - - if (RELOC_EXTERN_P(r)) - sym = LM_STRINGS(smp) + - LM_SYMBOL(smp, RELOC_SYMBOL(r))->nz_strx; - else - sym = ""; - - if (ld_warn_non_pure_code && !ld_suppress_warnings) - warnx("warning: non pure code in %s at %x (%s)", - smp->som_path, r->r_address, sym); - - if (smp->som_write == 0 && - 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); - } - - smp->som_write = 1; -} - -static void -reloc_map(struct so_map *smp) -{ - struct _dynamic *dp = smp->som_dynamic; - struct relocation_info *r = LM_REL(smp); - struct relocation_info *rend = r + LD_RELSZ(dp)/sizeof(*r); - long symbolbase = (long)LM_SYMBOL(smp, 0); - char *stringbase = LM_STRINGS(smp); - int symsize = LD_VERSION_NZLIST_P(dp->d_version) ? - sizeof(struct nzlist) : - sizeof(struct nlist); - - if (LD_PLTSZ(dp)) - md_fix_jmpslot(LM_PLT(smp), - (long)LM_PLT(smp), (long)binder_entry); - - for (; r < rend; r++) { - char *sym; - caddr_t addr = smp->som_addr + r->r_address; - - check_text_reloc(r, smp, addr); - - if (RELOC_EXTERN_P(r)) { - struct so_map *src_map = NULL; - struct nzlist *p, *np; - long relocation = md_get_addend(r, addr); - - if (RELOC_LAZY_P(r)) - continue; - - p = (struct nzlist *) - (symbolbase + symsize * RELOC_SYMBOL(r)); - - if (p->nz_type == (N_SETV + N_EXT)) - src_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", - sym, main_progname, smp->som_path); - - /* - * Found symbol definition. - * If it's in a link map, adjust value - * according to the load address of that map. - * Otherwise it's a run-time allocated common - * whose value is already up-to-date. - */ - relocation += np->nz_value; - if (src_map) - relocation += (long)src_map->som_addr; - - if (RELOC_PCREL_P(r)) - relocation -= (long)smp->som_addr; - - if (RELOC_COPY_P(r) && src_map) { - (void)enter_rts(sym, - (long)addr, - N_DATA + N_EXT, - src_map->som_addr + np->nz_value, - np->nz_size, src_map); - continue; - } - md_relocate(r, relocation, addr, 0); - - } else { - md_relocate(r, -#ifdef SUN_COMPAT - md_get_rt_segment_addend(r, addr) -#else - md_get_addend(r, addr) -#endif - + (long)smp->som_addr, addr, 0); - } - - } - - if (smp->som_write) { - 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", - main_progname, smp->som_path); - } - smp->som_write = 0; - } -} - -static void -reloc_copy(struct so_map *smp) -{ - struct rt_symbol *rtsp; - - for (rtsp = rt_symbol_head; rtsp; rtsp = rtsp->rt_next) - if ((rtsp->rt_smp == NULL || rtsp->rt_smp == smp) && - rtsp->rt_sp->nz_type == N_DATA + N_EXT) { - bcopy(rtsp->rt_srcaddr, (caddr_t)rtsp->rt_sp->nz_value, - rtsp->rt_sp->nz_size); - } -} - -static void -call_map(struct so_map *smp, char *sym) -{ - struct so_map *src_map = smp; - struct nzlist *np; - - np = lookup(sym, &src_map, 1); - if (np) - (*(void (*) (void))(src_map->som_addr + np->nz_value))(); -} - -/* - * Run-time common symbol table. - */ - -#define RTC_TABSIZE 57 -static struct rt_symbol *rt_symtab[RTC_TABSIZE]; - -/* - * Compute hash value for run-time symbol table - */ -static inline int -hash_string(const char *key) -{ - const char *cp; - int k; - - cp = key; - k = 0; - while (*cp) - k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; - - return k; -} - -/* - * Lookup KEY in the run-time common symbol table. - */ - -static inline struct rt_symbol * -lookup_rts(const char *key) -{ - int hashval; - struct rt_symbol *rtsp; - - /* Determine which bucket. */ - - hashval = hash_string(key) % RTC_TABSIZE; - - /* Search the bucket. */ - - for (rtsp = rt_symtab[hashval]; rtsp; rtsp = rtsp->rt_link) - if (strcmp(key, rtsp->rt_sp->nz_name) == 0) - return rtsp; - - return NULL; -} - -static struct rt_symbol * -enter_rts(const char *name, long value, int type, caddr_t srcaddr, long size, - struct so_map *smp) -{ - int hashval; - struct rt_symbol *rtsp, **rpp; - - /* Determine which bucket */ - hashval = hash_string(name) % RTC_TABSIZE; - - /* Find end of bucket */ - for (rpp = &rt_symtab[hashval]; *rpp; rpp = &(*rpp)->rt_link) - ; - - /* Allocate new common symbol */ - rtsp = (struct rt_symbol *)malloc(sizeof(struct rt_symbol)); - rtsp->rt_sp = (struct nzlist *)malloc(sizeof(struct nzlist)); - rtsp->rt_sp->nz_name = strdup(name); - rtsp->rt_sp->nz_value = value; - rtsp->rt_sp->nz_type = type; - rtsp->rt_sp->nz_size = size; - rtsp->rt_srcaddr = srcaddr; - rtsp->rt_smp = smp; - rtsp->rt_link = NULL; - - /* Link onto linear list as well */ - rtsp->rt_next = rt_symbol_head; - rt_symbol_head = rtsp; - - *rpp = rtsp; - - return rtsp; -} - - -/* - * Lookup NAME in the link maps. The link map producing a definition - * is returned in SRC_MAP. If SRC_MAP is not NULL on entry the search is - * confined to that map. If STRONG is set, the symbol returned must - * have a proper type (used by binder()). - */ -static struct nzlist * -lookup(const char *name, struct so_map **src_map, int strong) -{ - long common_size = 0; - struct so_map *smp, *weak_smp; - struct rt_symbol *rtsp; - struct nzlist *weak_np = 0; - - if ((rtsp = lookup_rts(name)) != NULL) { - /* Common symbol is not a member of particular shlib. */ - *src_map = NULL; - return rtsp->rt_sp; - } - - weak_smp = NULL; /* XXX - gcc! */ - - /* - * Search all maps for a definition of NAME - */ - for (smp = link_map_head; smp; smp = smp->som_next) { - int buckets; - long hashval; - struct rrs_hash *hp; - const char *cp; - struct nzlist *np; - - /* Some local caching */ - long symbolbase; - struct rrs_hash *hashbase; - char *stringbase; - int symsize; - - if (*src_map && smp != *src_map) - continue; - - if ((buckets = LD_BUCKETS(smp->som_dynamic)) == 0) - continue; - - if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) - continue; - -restart: - /* - * Compute bucket in which the symbol might be found. - */ - for (hashval = 0, cp = name; *cp; cp++) - hashval = (hashval << 1) + *cp; - - hashval = (hashval & 0x7fffffff) % buckets; - - hashbase = LM_HASH(smp); - hp = hashbase + hashval; - if (hp->rh_symbolnum == -1) - /* Nothing in this bucket */ - continue; - - symbolbase = (long)LM_SYMBOL(smp, 0); - stringbase = LM_STRINGS(smp); - symsize = LD_VERSION_NZLIST_P(smp->som_dynamic->d_version)? - sizeof(struct nzlist) : - sizeof(struct nlist); - while (hp) { - np = (struct nzlist *) - (symbolbase + hp->rh_symbolnum * symsize); - cp = stringbase + np->nz_strx; - if (strcmp(cp, name) == 0) - break; - if (hp->rh_next == 0) - hp = NULL; - else - hp = hashbase + hp->rh_next; - } - if (hp == NULL) - /* Nothing in this bucket */ - continue; - - /* - * We have a symbol with the name we're looking for. - */ - if (np->nz_type == N_INDR+N_EXT) { - /* - * Next symbol gives the aliased name. Restart - * search with new name and confine to this map. - */ - name = stringbase + (++np)->nz_strx; - *src_map = smp; - goto restart; - } - - if (np->nz_value == 0) - /* It's not a definition */ - continue; - - if (np->nz_type == N_UNDF+N_EXT && np->nz_value != 0) { - if (N_AUX(&np->nlist) == AUX_FUNC) { - /* It's a weak function definition */ - if (strong) - continue; - } else { - /* It's a common, note value and continue search */ - if (common_size < np->nz_value) - common_size = np->nz_value; - continue; - } - } - if (N_BIND(&np->nlist) != BIND_WEAK) { - *src_map = smp; - return np; - } - if (N_BIND(&np->nlist) == BIND_WEAK && weak_np == 0) { - weak_np = np; - weak_smp = smp; - continue; - } - } - - if (weak_np) { - *src_map = weak_smp; - return weak_np; - } - - if (common_size == 0) - /* Not found */ - return NULL; - - /* - * It's a common, enter into run-time common symbol table. - */ - rtsp = enter_rts(name, (long)calloc(1, common_size), - N_UNDF + N_EXT, 0, common_size, NULL); - - /* Common symbol is not a member of particular shlib. */ - *src_map = NULL; - -#if DEBUG -xprintf("Allocating common: %s size %d at %#x\n", name, common_size, rtsp->rt_sp->nz_value); -#endif - - return rtsp->rt_sp; -} - - -/* - * This routine is called from the jumptable to resolve - * procedure calls to shared objects. - */ -long -binder(jmpslot_t *jsp) -{ - struct so_map *smp, *src_map = NULL; - long addr; - char *sym; - struct nzlist *np; - int index; - - /* - * Find the PLT map that contains JSP. - */ - for (smp = link_map_head; smp; smp = smp->som_next) { - if (LM_PLT(smp) < jsp && - jsp < LM_PLT(smp) + LD_PLTSZ(smp->som_dynamic)/sizeof(*jsp)) - break; - } - - if (smp == NULL) - errx(1, "Call to binder from unknown location: %p", jsp); - - index = jsp->reloc_index & JMPSLOT_RELOC_MASK; - - /* Get the local symbol this jmpslot refers to */ - sym = LM_STRINGS(smp) + - LM_SYMBOL(smp,RELOC_SYMBOL(&LM_REL(smp)[index]))->nz_strx; - - np = lookup(sym, &src_map, 1); - if (np == NULL) - errx(1, "Undefined symbol \"%s\" called from %s:%s at %p", - sym, main_progname, smp->som_path, jsp); - - /* Fixup jmpslot so future calls transfer directly to target */ - addr = np->nz_value; - if (src_map) - addr += (long)src_map->som_addr; - - md_fix_jmpslot(jsp, (long)jsp, addr); - -#if DEBUG -xprintf(" BINDER: %s located at = %#x in %s\n", sym, addr, src_map->som_path); -#endif - return addr; -} - - -static int hfd; -static long hsize; -static struct hints_header *hheader; -static struct hints_bucket *hbuckets; -static char *hstrtab; -static char *hint_search_path = ""; - -#define HINTS_VALID (hheader != NULL && hheader != (struct hints_header *)-1) - -static void -maphints(void) -{ - struct stat sb; - caddr_t addr = MAP_FAILED; - - if ((hfd = open(_PATH_LD_HINTS, O_RDONLY, 0)) < 0) - goto bad_hints; - - if (fstat(hfd, &sb) != 0 || !S_ISREG(sb.st_mode) || - sb.st_size < sizeof(struct hints_header) || sb.st_size > LONG_MAX) - goto bad_hints; - - hsize = (long)sb.st_size; - addr = mmap(0, hsize, PROT_READ, MAP_COPY, hfd, 0); - if (addr == MAP_FAILED) - goto bad_hints; - - hheader = (struct hints_header *)addr; - if (HH_BADMAG(*hheader) || hheader->hh_ehints > hsize) - goto bad_hints; - - if (hheader->hh_version != LD_HINTS_VERSION_1 && - hheader->hh_version != LD_HINTS_VERSION_2) - goto bad_hints; - - hbuckets = (struct hints_bucket *)(addr + hheader->hh_hashtab); - hstrtab = (char *)(addr + hheader->hh_strtab); - if (hheader->hh_version >= LD_HINTS_VERSION_2) - hint_search_path = hstrtab + hheader->hh_dirlist; - - return; - -bad_hints: - if (addr != MAP_FAILED) - munmap(addr, hsize); - if (hfd != -1) - close(hfd); - hheader = (struct hints_header *)-1; -} - -static void -unmaphints(void) -{ - - if (HINTS_VALID) { - munmap((caddr_t)hheader, hsize); - close(hfd); - hheader = NULL; - } -} - -static int -hinthash(char *cp, int vmajor, int vminor) -{ - int k = 0; - - while (*cp) - k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; - - k = (((k << 1) + (k >> 14)) ^ (vmajor*257)) & 0x3fff; - if (hheader->hh_version == LD_HINTS_VERSION_1) - k = (((k << 1) + (k >> 14)) ^ (vminor*167)) & 0x3fff; - - return k; -} - -#undef major -#undef minor - -static char * -findhint(char *name, int major, int minor, char *prefered_path) -{ - struct hints_bucket *bp; - - bp = hbuckets + (hinthash(name, major, minor) % hheader->hh_nbucket); - - while (1) { - /* Sanity check */ - if (bp->hi_namex >= hheader->hh_strtab_sz) { - warnx("Bad name index: %#x", bp->hi_namex); - break; - } - if (bp->hi_pathx >= hheader->hh_strtab_sz) { - warnx("Bad path index: %#x", bp->hi_pathx); - break; - } - - if (strcmp(name, hstrtab + bp->hi_namex) == 0) { - /* It's `name', check version numbers */ - if (bp->hi_major == major && - (bp->hi_ndewey < 2 || bp->hi_minor >= minor)) { - if (prefered_path == NULL || - strncmp(prefered_path, - hstrtab + bp->hi_pathx, - strlen(prefered_path)) == 0) { - return hstrtab + bp->hi_pathx; - } - } - } - - if (bp->hi_next == -1) - break; - - /* Move on to next in bucket */ - bp = &hbuckets[bp->hi_next]; - } - - /* No hints available for name */ - return NULL; -} - -static char * -rtfindlib(char *name, int major, int minor, int *usehints, char *ipath) -{ - char *cp; - int realminor; - - if (hheader == NULL) - maphints(); - - if (!HINTS_VALID || !(*usehints)) - goto lose; - - /* NOTE: `ipath' may reside in a piece of read-only memory */ - - if (ld_library_path || ipath) { - /* Prefer paths from some explicit LD_LIBRARY_PATH */ - char *lpath; - char *dp; - - dp = lpath = concat(ld_library_path ? ld_library_path : "", - (ld_library_path && ipath) ? ":" : "", - ipath ? ipath : ""); - - while ((cp = strsep(&dp, ":")) != NULL) { - if (*cp) { - cp = findhint(name, major, minor, cp); - if (cp) { - free(lpath); - return cp; - } - } - } - free(lpath); - - /* - * Not found in hints; try directory search now, before - * we get a spurious hint match below (i.e. a match not - * on one of the paths we're supposed to search first. - */ - realminor = -1; - cp = (char *)findshlib(name, &major, &realminor, 0); - if (cp && realminor >= minor) - return cp; - } - - /* No LD_LIBRARY_PATH or lib not found in there; check default */ - cp = findhint(name, major, minor, NULL); - if (cp) - return cp; - -lose: - /* No hints available for name */ - *usehints = 0; - realminor = -1; - add_search_path(hint_search_path); - cp = (char *)findshlib(name, &major, &realminor, 0); - remove_search_path(hint_search_path); - if (cp) { - if (realminor < minor && !ld_suppress_warnings) - warnx("warning: lib%s.so.%d.%d: " - "minor version >= %d expected, using it anyway", - name, major, realminor, minor); - return cp; - } - return NULL; -} - -void -preload(char *paths) -{ - struct so_map *nsmp; - struct sod *sodp; - char *cp, *dp; - - dp = paths = strdup(paths); - if (dp == NULL) { - errx(1, "preload: out of memory"); - } - - while ((cp = strsep(&dp, ":")) != NULL) { - if ((sodp = (struct sod *)malloc(sizeof(struct sod))) == NULL) { - errx(1, "preload: %s: out of memory", cp); - return; - } - - sodp->sod_name = (long)strdup(cp); - sodp->sod_library = 0; - sodp->sod_major = sodp->sod_minor = 0; - - if ((nsmp = map_object(sodp, 0)) == NULL) { - errx(1, "preload: %s: cannot map object", cp); - } - LM_PRIVATE(nsmp)->spd_refcount++; - } - free(paths); - return; -} - -static int dlerrno; - -/* - * Populate sod struct for dlopen's call to map_object - */ -static void -build_sod(const char *name, struct sod *sodp) -{ - unsigned int tuplet; - int major, minor; - char *realname, *tok, *etok, *cp; - - /* default is an absolute or relative path */ - sodp->sod_name = (long)strdup(name); /* strtok is destructive */ - sodp->sod_library = 0; - sodp->sod_major = sodp->sod_minor = 0; - - /* does it look like /^lib/ ? */ - if (strncmp((char *)sodp->sod_name, "lib", 3) != 0) - return; - - /* is this a filename? */ - if (strchr((char *)sodp->sod_name, '/')) - return; - - /* skip over 'lib' */ - cp = (char *)sodp->sod_name + 3; - - /* dot guardian */ - if ((strchr(cp, '.') == NULL) || (*(cp+strlen(cp)-1) == '.')) - return; - - /* default */ - major = minor = -1; - - /* loop through name - parse skipping name */ - for (tuplet = 0; (tok = strsep(&cp, ".")) != NULL; tuplet++) { - switch (tuplet) { - case 0: - /* removed 'lib' and extensions from name */ - realname = tok; - break; - case 1: - /* 'so' extension */ - if (strcmp(tok, "so") != 0) - goto backout; - break; - case 2: - /* major version extension */ - major = strtol(tok, &etok, 10); - if (*tok == '\0' || *etok != '\0') - goto backout; - break; - case 3: - /* minor version extension */ - minor = strtol(tok, &etok, 10); - if (*tok == '\0' || *etok != '\0') - goto backout; - break; - /* if we get here, it must be weird */ - default: - goto backout; - } - } - cp = (char *)sodp->sod_name; - sodp->sod_name = (long)strdup(realname); - free(cp); - sodp->sod_library = 1; - sodp->sod_major = major; - sodp->sod_minor = minor; - return; - -backout: - free((char *)sodp->sod_name); - sodp->sod_name = (long)strdup(name); -} - -static void * -__dlopen(const char *name, int mode) -{ - struct sod *sodp; - struct so_map *smp; - - /* - * A NULL argument returns the current set of mapped objects. - */ - 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; - return NULL; - } - - build_sod(name, sodp); - - if ((smp = map_object(sodp, main_map)) == NULL) { -#ifdef DEBUG -xprintf("%s: %s\n", name, strerror(errno)); -#endif - dlerrno = errno; - free((char *)sodp->sod_name); - free(sodp); - return NULL; - } - - LM_PRIVATE(smp)->spd_flags |= RTLD_DL; - - if (LM_PRIVATE(smp)->spd_refcount++ > 0) { - free((char *)sodp->sod_name); - free(sodp); - return smp; - } - - if (load_subs(smp) != 0) { - if (--LM_PRIVATE(smp)->spd_refcount == 0) { - unmap_object(smp); - free_link_map(smp); - } - return NULL; - } - - init_maps(smp); - return smp; -} - -static int -__dlclose(void *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); -#endif - if (--LM_PRIVATE(smp)->spd_refcount != 0) - return 0; - - if ((LM_PRIVATE(smp)->spd_flags & RTLD_DL) == 0) - return 0; - - /* Dismantle shared object map and descriptor */ - call_map(smp, "__fini"); - call_map(smp, "__GLOBAL__DD"); -#if 0 - unload_subs(smp); /* XXX should unload implied objects */ -#endif - unmap_object(smp); - free_link_map(smp); - return 0; -} - -static void * -__dlsym(void *fd, const char *sym) -{ - struct so_map *smp, *src_map = NULL; - struct nzlist *np; - long addr; - - /* - * Restrict search to passed map if dlopen()ed. - */ - if (fd == NULL) - smp = link_map_head; - else - src_map = smp = (struct so_map *)fd; - - np = lookup(sym, &src_map, 1); - if (np == NULL) { - dlerrno = ENOENT; - return NULL; - } - - /* Fixup jmpslot so future calls transfer directly to target */ - addr = np->nz_value; - if (src_map) - addr += (long)src_map->som_addr; - - return (void *)addr; -} - -static int -__dlctl(void *fd, int cmd, void *arg) -{ - switch (cmd) { - case DL_GETERRNO: - *(int *)arg = dlerrno; - dlerrno = 0; - return 0; - default: - dlerrno = EOPNOTSUPP; - return -1; - } - return 0; -} - -static void -__dlexit(void) -{ - struct so_map *smp; - - /* Call any object initialization routines. */ - for (smp = link_map_head; smp; smp = smp->som_next) { - if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) - continue; - call_map(smp, ".fini"); - call_map(smp, "__GLOBAL__DD"); - } -} - -void -#if __STDC__ -xprintf(char *fmt, ...) -#else -xprintf(fmt, va_alist) -char *fmt; -#endif -{ - char buf[256]; - va_list ap; -#if __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - - vsnprintf(buf, sizeof buf, fmt, ap); - (void)write(1, buf, strlen(buf)); - va_end(ap); -} |