1 /* $NetBSD: common.c,v 1.19 2004/08/07 21:33:04 chs Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
34 typedef int (*rtld_entry_fn
) __P((int, struct crt_ldso
*));
35 static struct ld_entry
**ld_entry
;
41 static struct crt_ldso crt
;
44 #if defined(sun) && defined(DUPZFD)
49 /* Provision for alternate ld.so - security risk! */
50 if ((crt
.crt_ldso
= _getenv("LDSO")) == NULL
)
54 crt
.crt_ldfd
= open(crt
.crt_ldso
, 0, 0);
55 if (crt
.crt_ldfd
== -1) {
59 /* Read LDSO exec header */
60 if (read(crt
.crt_ldfd
, &hdr
, sizeof hdr
) < sizeof hdr
) {
61 _FATAL("Failure reading ld.so\n");
63 if (N_GETMAGIC(hdr
) != ZMAGIC
&& N_GETMAGIC(hdr
) != QMAGIC
) {
64 _FATAL("Bad magic: ld.so\n");
68 /* Get bucket of zeroes */
69 crt
.crt_dzfd
= open("/dev/zero", 0, 0);
70 if (crt
.crt_dzfd
== -1) {
71 _FATAL("No /dev/zero\n");
79 #if defined(sun) && defined(DUPZFD)
80 if ((dupzfd
= dup(crt
.crt_dzfd
)) < 0) {
81 _FATAL("Cannot dup /dev/zero\n");
86 crt
.crt_ba
= mmap(0, hdr
.a_text
+hdr
.a_data
+hdr
.a_bss
,
89 crt
.crt_ldfd
, N_TXTOFF(hdr
));
90 if (crt
.crt_ba
== -1) {
91 _FATAL("Cannot map ld.so\n");
96 * This is gross, ld.so is a ZMAGIC a.out, but has `sizeof(hdr)' for
97 * an entry point and not at PAGSIZ as the N_*ADDR macros assume.
101 #define N_DATADDR(x) ((x).a_text)
102 #define N_BSSADDR(x) ((x).a_text + (x).a_data)
105 /* Map in data segment of ld.so writable */
106 if (mmap(crt
.crt_ba
+N_DATADDR(hdr
), hdr
.a_data
,
107 PROT_READ
|PROT_WRITE
|PROT_EXEC
,
108 MAP_FILE
|MAP_PRIVATE
|MAP_FIXED
,
109 crt
.crt_ldfd
, N_DATOFF(hdr
)) == -1) {
110 _FATAL("Cannot map ld.so\n");
113 /* Map bss segment of ld.so zero */
114 if (hdr
.a_bss
&& mmap(crt
.crt_ba
+N_BSSADDR(hdr
), hdr
.a_bss
,
115 PROT_READ
|PROT_WRITE
,
116 MAP_ANON
|MAP_PRIVATE
|MAP_FIXED
,
117 crt
.crt_dzfd
, 0) == -1) {
118 _FATAL("Cannot map ld.so\n");
122 crt
.crt_ep
= environ
;
123 crt
.crt_bp
= (caddr_t
)_callmain
;
124 crt
.crt_prog
= __progname
;
127 /* Call Sun's ld.so entry point: version 1, offset crt */
128 __call(CRT_VERSION_SUN
, &crt
, crt
.crt_ba
+ sizeof hdr
);
130 ld_entry
= &crt
.crt_ldentry
;
131 entry
= (rtld_entry_fn
)(crt
.crt_ba
+ sizeof hdr
);
132 if ((*entry
)(CRT_VERSION_BSD_4
, &crt
) == -1) {
133 /* Feeble attempt to deal with out-dated ld.so */
135 # define str "crt0: update " LDSO "\n"
137 # define str "crt0: update ld.so\n"
139 (void)write(2, str
, sizeof(str
)-1);
141 if ((*entry
)(CRT_VERSION_BSD_3
, &crt
) == -1) {
142 _FATAL("ld.so failed\n");
144 ld_entry
= &dp
->d_entry
;
147 atexit((*ld_entry
)->dlexit
);
150 #if defined(sun) && defined(DUPZFD)
151 if (dup2(dupzfd
, crt
.crt_dzfd
) < 0) {
152 _FATAL("Cannot dup2 /dev/zero\n");
168 if ((*ld_entry
) == NULL
)
171 return ((*ld_entry
)->dlopen
)(name
, mode
);
178 if ((*ld_entry
) == NULL
)
181 return ((*ld_entry
)->dlclose
)(fd
);
189 if ((*ld_entry
) == NULL
)
192 return ((*ld_entry
)->dlsym
)(fd
, name
);
200 if ((*ld_entry
) == NULL
)
203 return ((*ld_entry
)->dlctl
)(fd
, cmd
, arg
);
211 if ((*ld_entry
) == NULL
||
212 (*(*ld_entry
)->dlctl
)(NULL
, DL_GETERRNO
, &error
) == -1)
213 return "Service unavailable";
215 return ((char *)(error
== 0 ? NULL
: strerror(error
)));
223 if ((*ld_entry
) == NULL
|| (*ld_entry
)->dladdr
== NULL
)
226 return ((*ld_entry
)->dladdr
)(addr
, dli
);
244 return (*(unsigned char *)s1
- *(unsigned char *)--s2
);
255 extern char **environ
;
259 for (C
= name
, len
= 0; *C
&& *C
!= '='; ++C
, ++len
);
260 for (P
= environ
; *P
; ++P
)
261 if (!_strncmp(*P
, name
, len
))
262 if (*(C
= *P
+ len
) == '=') {
275 for (save
= NULL
;; ++p
) {