Fix memory barrier in a debug function
[netbsd-mini2440.git] / lib / csu / common_aout / common.c
blob1b07f67ec3994ccff41240f93e4eb9c15652f69d
1 /* $NetBSD: common.c,v 1.19 2004/08/07 21:33:04 chs Exp $ */
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Paul Kranenburg.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
32 #ifdef DYNAMIC
34 typedef int (*rtld_entry_fn) __P((int, struct crt_ldso *));
35 static struct ld_entry **ld_entry;
37 static void
38 __load_rtld(dp)
39 struct _dynamic *dp;
41 static struct crt_ldso crt;
42 struct exec hdr;
43 rtld_entry_fn entry;
44 #if defined(sun) && defined(DUPZFD)
45 int dupzfd;
46 #endif
48 #ifdef DEBUG
49 /* Provision for alternate ld.so - security risk! */
50 if ((crt.crt_ldso = _getenv("LDSO")) == NULL)
51 #endif
52 crt.crt_ldso = LDSO;
54 crt.crt_ldfd = open(crt.crt_ldso, 0, 0);
55 if (crt.crt_ldfd == -1) {
56 _FATAL("No ld.so\n");
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");
67 #ifdef sun
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");
73 #endif
74 #ifdef __NetBSD__
75 /* We use MAP_ANON */
76 crt.crt_dzfd = -1;
77 #endif
79 #if defined(sun) && defined(DUPZFD)
80 if ((dupzfd = dup(crt.crt_dzfd)) < 0) {
81 _FATAL("Cannot dup /dev/zero\n");
83 #endif
85 /* Map in ld.so */
86 crt.crt_ba = mmap(0, hdr.a_text+hdr.a_data+hdr.a_bss,
87 PROT_READ|PROT_EXEC,
88 MAP_FILE|MAP_PRIVATE,
89 crt.crt_ldfd, N_TXTOFF(hdr));
90 if (crt.crt_ba == -1) {
91 _FATAL("Cannot map ld.so\n");
94 #ifdef __NetBSD__
95 /* !!!
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.
99 #undef N_DATADDR
100 #undef N_BSSADDR
101 #define N_DATADDR(x) ((x).a_text)
102 #define N_BSSADDR(x) ((x).a_text + (x).a_data)
103 #endif
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");
121 crt.crt_dp = dp;
122 crt.crt_ep = environ;
123 crt.crt_bp = (caddr_t)_callmain;
124 crt.crt_prog = __progname;
126 #ifdef sun
127 /* Call Sun's ld.so entry point: version 1, offset crt */
128 __call(CRT_VERSION_SUN, &crt, crt.crt_ba + sizeof hdr);
129 #else
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 */
134 #ifdef __STDC__
135 # define str "crt0: update " LDSO "\n"
136 #else
137 # define str "crt0: update ld.so\n"
138 #endif
139 (void)write(2, str, sizeof(str)-1);
140 # undef str
141 if ((*entry)(CRT_VERSION_BSD_3, &crt) == -1) {
142 _FATAL("ld.so failed\n");
144 ld_entry = &dp->d_entry;
145 return;
147 atexit((*ld_entry)->dlexit);
148 #endif
150 #if defined(sun) && defined(DUPZFD)
151 if (dup2(dupzfd, crt.crt_dzfd) < 0) {
152 _FATAL("Cannot dup2 /dev/zero\n");
154 (void)close(dupzfd);
155 #endif
156 return;
160 * DL stubs
163 void *
164 dlopen(name, mode)
165 const char *name;
166 int mode;
168 if ((*ld_entry) == NULL)
169 return NULL;
171 return ((*ld_entry)->dlopen)(name, mode);
175 dlclose(fd)
176 void *fd;
178 if ((*ld_entry) == NULL)
179 return -1;
181 return ((*ld_entry)->dlclose)(fd);
184 void *
185 dlsym(fd, name)
186 void *fd;
187 const char *name;
189 if ((*ld_entry) == NULL)
190 return NULL;
192 return ((*ld_entry)->dlsym)(fd, name);
196 dlctl(fd, cmd, arg)
197 void *fd, *arg;
198 int cmd;
200 if ((*ld_entry) == NULL)
201 return -1;
203 return ((*ld_entry)->dlctl)(fd, cmd, arg);
206 __aconst char *
207 dlerror()
209 int error;
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)));
219 dladdr(addr, dli)
220 const void *addr;
221 Dl_info *dli;
223 if ((*ld_entry) == NULL || (*ld_entry)->dladdr == NULL)
224 return (0);
226 return ((*ld_entry)->dladdr)(addr, dli);
230 * Support routines
233 #ifdef DEBUG
234 static int
235 _strncmp(s1, s2, n)
236 char *s1, *s2;
237 int n;
240 if (n == 0)
241 return (0);
242 do {
243 if (*s1 != *s2++)
244 return (*(unsigned char *)s1 - *(unsigned char *)--s2);
245 if (*s1++ == 0)
246 break;
247 } while (--n != 0);
248 return (0);
251 static char *
252 _getenv(name)
253 char *name;
255 extern char **environ;
256 int len;
257 char **P, *C;
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) == '=') {
263 return(++C);
265 return (char *)0;
267 #endif
269 static char *
270 _strrchr(p, ch)
271 char *p, ch;
273 char *save;
275 for (save = NULL;; ++p) {
276 if (*p == ch)
277 save = (char *)p;
278 if (!*p)
279 return(save);
281 /* NOTREACHED */
284 #endif /* DYNAMIC */