New dlopen, dlclose, etc al. For the new ld changes.
[unix-history] / lib / csu.i386 / crt0.c
CommitLineData
90c075bb
PR
1/*
2 * Copyright (c) 1993 Paul Kranenburg
15637ed4
RG
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
90c075bb
PR
15 * This product includes software developed by Paul Kranenburg.
16 * 4. The name of the author may not be used to endorse or promote products
8b0da803 17 * derived from this software without specific prior written permission
90c075bb
PR
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15637ed4 29 *
8b0da803 30 * $Id: crt0.c,v 1.12 1994/01/29 01:58:44 jtc Exp $
15637ed4
RG
31 */
32
90c075bb 33
15637ed4 34#if defined(LIBC_SCCS) && !defined(lint)
90c075bb 35static char sccsid[] = "%W% (Erasmus) %G%";
15637ed4
RG
36#endif /* LIBC_SCCS and not lint */
37
90c075bb
PR
38extern void exit();
39int _callmain();
15637ed4 40
90c075bb
PR
41#include <sys/param.h>
42
43#ifdef DYNAMIC
44#include <sys/types.h>
45#include <sys/syscall.h>
46#include <a.out.h>
47#ifndef N_GETMAGIC
48#define N_GETMAGIC(x) ((x).a_magic)
49#endif
50#ifndef N_BSSADDR
51#define N_BSSADDR(x) (N_DATADDR(x)+(x).a_data)
52#endif
53#include <sys/mman.h>
54#ifdef sun
55#define MAP_COPY MAP_PRIVATE
56#define MAP_FILE 0
57#define MAP_ANON 0
58#endif
59#include <link.h>
60
8b0da803
JH
61extern struct _dynamic _DYNAMIC;
62static struct ld_entry *ld_entry;
90c075bb
PR
63static void __do_dynamic_link ();
64static char *_getenv();
65static int _strncmp();
66
90c075bb
PR
67#ifdef sun
68#define LDSO "/usr/lib/ld.so"
69#endif
70#ifdef BSD
71#define LDSO "/usr/libexec/ld.so"
72#endif
c90fc599 73
90c075bb 74#endif /* DYNAMIC */
15637ed4 75
90c075bb
PR
76static char *_strrchr();
77
78char **environ;
79
80#ifdef BSD
15637ed4
RG
81extern unsigned char etext;
82extern unsigned char eprol asm ("eprol");
83extern start() asm("start");
84extern mcount() asm ("mcount");
85
90c075bb
PR
86int errno;
87static char empty[1];
88char *__progname = empty;
89#endif
90
91/*
92 * We need these system calls, but can't use library stubs
93 */
94#define _exit(v) __syscall(SYS_exit, (v))
95#define open(name, f, m) __syscall(SYS_open, (name), (f), (m))
96#define close(fd) __syscall(SYS_close, (fd))
97#define read(fd, s, n) __syscall(SYS_read, (fd), (s), (n))
98#define write(fd, s, n) __syscall(SYS_write, (fd), (s), (n))
99#define dup(fd) __syscall(SYS_dup, (fd))
100#define dup2(fd, fdnew) __syscall(SYS_dup2, (fd), (fdnew))
101#ifdef sun
102#define mmap(addr, len, prot, flags, fd, off) \
103 __syscall(SYS_mmap, (addr), (len), (prot), _MAP_NEW|(flags), (fd), (off))
104#else
105#define mmap(addr, len, prot, flags, fd, off) \
106 __syscall(SYS_mmap, (addr), (len), (prot), (flags), (fd), (off))
107#endif
108
109#define _FATAL(str) \
110 write(2, str, sizeof(str)), \
111 _exit(1);
112
113
15637ed4
RG
114start()
115{
116 struct kframe {
117 int kargc;
118 char *kargv[1]; /* size depends on kargc */
119 char kargstr[1]; /* size varies */
120 char kenvstr[1]; /* size varies */
121 };
122 /*
123 * ALL REGISTER VARIABLES!!!
124 */
125 register struct kframe *kfp;
126 register char **targv;
127 register char **argv;
128 extern void _mcleanup();
90c075bb
PR
129#ifdef DYNAMIC
130 volatile caddr_t x;
131#endif
15637ed4
RG
132
133#ifdef lint
134 kfp = 0;
135 initcode = initcode = 0;
90c075bb 136#else /* not lint */
15637ed4
RG
137 /* just above the saved frame pointer */
138 asm ("lea 4(%%ebp), %0" : "=r" (kfp) );
90c075bb 139#endif /* not lint */
15637ed4
RG
140 for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
141 /* void */ ;
142 if (targv >= (char **)(*argv))
143 --targv;
144 environ = targv;
90c075bb 145
8b0da803
JH
146 if (argv[0])
147 if ((__progname = _strrchr(argv[0], '/')) == NULL)
148 __progname = argv[0];
149 else
150 ++__progname;
151
90c075bb 152#ifdef DYNAMIC
1781f4aa 153 /* ld(1) convention: if DYNAMIC = 0 then statically linked */
90c075bb
PR
154#ifdef stupid_gcc
155 if (&_DYNAMIC)
156 __do_dynamic_link();
157#else
158 x = (caddr_t)&_DYNAMIC;
159 if (x)
160 __do_dynamic_link();
161#endif
162#endif /* DYNAMIC */
163
15637ed4
RG
164asm("eprol:");
165
166#ifdef MCRT0
167 atexit(_mcleanup);
168 monstartup(&eprol, &etext);
169#endif MCRT0
8b0da803 170
90c075bb 171asm ("__callmain:"); /* Defined for the benefit of debuggers */
15637ed4
RG
172 exit(main(kfp->kargc, argv, environ));
173}
90c075bb
PR
174
175#ifdef DYNAMIC
176static void
177__do_dynamic_link ()
178{
179 struct crt_ldso crt;
180 struct exec hdr;
181 char *ldso;
182 int dupzfd;
8b0da803 183 int (*entry)();
90c075bb 184
1781f4aa 185#ifdef DEBUG
90c075bb
PR
186 /* Provision for alternate ld.so - security risk! */
187 if (!(ldso = _getenv("LDSO")))
1781f4aa 188#endif
90c075bb
PR
189 ldso = LDSO;
190
191 crt.crt_ldfd = open(ldso, 0, 0);
192 if (crt.crt_ldfd == -1) {
193 _FATAL("No ld.so\n");
194 }
195
196 /* Read LDSO exec header */
197 if (read(crt.crt_ldfd, &hdr, sizeof hdr) < sizeof hdr) {
198 _FATAL("Failure reading ld.so\n");
199 }
8b0da803 200 if (N_GETMAGIC(hdr) != ZMAGIC && N_GETMAGIC(hdr) != QMAGIC) {
90c075bb
PR
201 _FATAL("Bad magic: ld.so\n");
202 }
203
90c075bb
PR
204 /* We use MAP_ANON */
205 crt.crt_dzfd = -1;
90c075bb
PR
206
207 /* Map in ld.so */
5e358090 208 crt.crt_ba = mmap(0, hdr.a_text,
90c075bb
PR
209 PROT_READ|PROT_EXEC,
210 MAP_FILE|MAP_COPY,
211 crt.crt_ldfd, N_TXTOFF(hdr));
212 if (crt.crt_ba == -1) {
213 _FATAL("Cannot map ld.so\n");
214 }
215
216#ifdef BSD
217/* !!!
218 * This is gross, ld.so is a ZMAGIC a.out, but has `sizeof(hdr)' for
219 * an entry point and not at PAGSIZ as the N_*ADDR macros assume.
220 */
221#undef N_DATADDR
222#undef N_BSSADDR
223#define N_DATADDR(x) ((x).a_text)
224#define N_BSSADDR(x) ((x).a_text + (x).a_data)
225#endif
226
227 /* Map in data segment of ld.so writable */
228 if (mmap(crt.crt_ba+N_DATADDR(hdr), hdr.a_data,
5e358090 229 PROT_READ|PROT_WRITE,
90c075bb
PR
230 MAP_FIXED|MAP_FILE|MAP_COPY,
231 crt.crt_ldfd, N_DATOFF(hdr)) == -1) {
232 _FATAL("Cannot map ld.so\n");
233 }
234
235 /* Map bss segment of ld.so zero */
236 if (hdr.a_bss && mmap(crt.crt_ba+N_BSSADDR(hdr), hdr.a_bss,
5e358090 237 PROT_READ|PROT_WRITE,
90c075bb
PR
238 MAP_FIXED|MAP_ANON|MAP_COPY,
239 crt.crt_dzfd, 0) == -1) {
240 _FATAL("Cannot map ld.so\n");
241 }
242
243 crt.crt_dp = &_DYNAMIC;
244 crt.crt_ep = environ;
245 crt.crt_bp = (caddr_t)_callmain;
8b0da803 246 crt.crt_prog = __progname;
90c075bb 247
8b0da803
JH
248 entry = (int (*)())(crt.crt_ba + sizeof hdr);
249 if ((*entry)(CRT_VERSION_BSD_3, &crt) == -1) {
250 _FATAL("ld.so failed\n");
90c075bb 251 }
8b0da803
JH
252
253 ld_entry = _DYNAMIC.d_entry;
90c075bb
PR
254 return;
255}
256
8b0da803
JH
257/*
258 * DL stubs
259 */
260
261void *
262dlopen(name, mode)
263char *name;
264int mode;
90c075bb 265{
8b0da803
JH
266 if (ld_entry == NULL)
267 return NULL;
268
269 return (ld_entry->dlopen)(name, mode);
270}
271
272int
273dlclose(fd)
274void *fd;
275{
276 if (ld_entry == NULL)
277 return -1;
278
279 return (ld_entry->dlclose)(fd);
280}
281
282void *
283dlsym(fd, name)
284void *fd;
285char *name;
286{
287 if (ld_entry == NULL)
288 return NULL;
289
290 return (ld_entry->dlsym)(fd, name);
291}
292
293int
294dlctl(fd, cmd, arg)
295void *fd, *arg;
296int cmd;
297{
298 if (ld_entry == NULL)
299 return -1;
300
301 return (ld_entry->dlctl)(fd, cmd, arg);
90c075bb 302}
15637ed4 303
15637ed4 304/*
90c075bb 305 * Support routines
15637ed4 306 */
90c075bb
PR
307
308static int
309_strncmp(s1, s2, n)
310 register char *s1, *s2;
311 register n;
15637ed4
RG
312{
313
90c075bb
PR
314 if (n == 0)
315 return (0);
316 do {
317 if (*s1 != *s2++)
318 return (*(unsigned char *)s1 - *(unsigned char *)--s2);
319 if (*s1++ == 0)
320 break;
321 } while (--n != 0);
322 return (0);
15637ed4
RG
323}
324
90c075bb
PR
325static char *
326_getenv(name)
327 register char *name;
328{
329 extern char **environ;
330 register int len;
331 register char **P, *C;
332
333 for (C = name, len = 0; *C && *C != '='; ++C, ++len);
334 for (P = environ; *P; ++P)
335 if (!_strncmp(*P, name, len))
336 if (*(C = *P + len) == '=') {
337 return(++C);
338 }
339 return (char *)0;
340}
341
90c075bb
PR
342 asm(" ___syscall:");
343 asm(" popl %ecx");
344 asm(" popl %eax");
345 asm(" pushl %ecx");
346 asm(" .byte 0x9a");
347 asm(" .long 0");
348 asm(" .word 7");
349 asm(" pushl %ecx");
350 asm(" jc 1f");
351 asm(" ret");
352 asm(" 1:");
353 asm(" movl $-1,%eax");
354 asm(" ret");
90c075bb
PR
355
356#endif /* DYNAMIC */
357
358static char *
359_strrchr(p, ch)
360register char *p, ch;
361{
362 register char *save;
363
364 for (save = NULL;; ++p) {
365 if (*p == ch)
366 save = (char *)p;
367 if (!*p)
368 return(save);
369 }
370/* NOTREACHED */
371}
372
373#ifdef MCRT0
374asm (" .text");
375asm ("_eprol:");
376#endif