Fix manual page lines so they work correctly.
[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
17 * derived from this software withough specific prior written permission
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 *
5e358090 30 * $Id: crt0.c,v 1.6 1993/11/09 04:26:11 paul 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
61extern struct link_dynamic _DYNAMIC;
62static void __do_dynamic_link ();
63static char *_getenv();
64static int _strncmp();
65
66#ifdef sparc
67static __call();
68#endif
15637ed4 69
90c075bb
PR
70#ifdef sun
71#define LDSO "/usr/lib/ld.so"
72#endif
73#ifdef BSD
74#define LDSO "/usr/libexec/ld.so"
75#endif
c90fc599 76
90c075bb 77#endif /* DYNAMIC */
15637ed4 78
90c075bb
PR
79static char *_strrchr();
80
81char **environ;
82
83#ifdef BSD
15637ed4
RG
84extern unsigned char etext;
85extern unsigned char eprol asm ("eprol");
86extern start() asm("start");
87extern mcount() asm ("mcount");
88
90c075bb
PR
89int errno;
90static char empty[1];
91char *__progname = empty;
92#endif
93
94/*
95 * We need these system calls, but can't use library stubs
96 */
97#define _exit(v) __syscall(SYS_exit, (v))
98#define open(name, f, m) __syscall(SYS_open, (name), (f), (m))
99#define close(fd) __syscall(SYS_close, (fd))
100#define read(fd, s, n) __syscall(SYS_read, (fd), (s), (n))
101#define write(fd, s, n) __syscall(SYS_write, (fd), (s), (n))
102#define dup(fd) __syscall(SYS_dup, (fd))
103#define dup2(fd, fdnew) __syscall(SYS_dup2, (fd), (fdnew))
104#ifdef sun
105#define mmap(addr, len, prot, flags, fd, off) \
106 __syscall(SYS_mmap, (addr), (len), (prot), _MAP_NEW|(flags), (fd), (off))
107#else
108#define mmap(addr, len, prot, flags, fd, off) \
109 __syscall(SYS_mmap, (addr), (len), (prot), (flags), (fd), (off))
110#endif
111
112#define _FATAL(str) \
113 write(2, str, sizeof(str)), \
114 _exit(1);
115
116
117#ifdef sparc
118asm (" .global start");
119asm (" .text");
120asm (" start:");
121
122/* Set up `argc', `argv', and `envp' into local registers (from GNU Emacs). */
123asm (" mov 0, %fp");
124asm (" ld [%sp + 64], %l0"); /* argc */
125asm (" add %sp, 68, %l1"); /* argv */
126asm (" sll %l0, 2, %l2"); /**/
127asm (" add %l2, 4, %l2"); /* envp = argv + (argc << 2) + 4 */
128asm (" add %l1, %l2, %l2"); /**/
129asm (" sethi %hi(_environ), %l3");
130asm (" st %l2, [%l3+%lo(_environ)]"); /* *environ = l2 */
131
132/* Finish diddling with stack. */
133asm (" andn %sp, 7, %sp");
134asm (" sub %sp, 24, %sp");
135
136#ifdef DYNAMIC
137/* Resolve symbols in dynamic libraries */
138asm (" call ___do_dynamic_link");
139asm (" nop");
140#endif
141
142/* From here, all symbols should have been resolved, so we can use libc */
143#ifdef MCRT0
144asm (" call ___do_mcrt");
145asm (" nop");
146#endif
147
148/* Stay Sun compatible (currently (SunOS 4.1.2) does nothing on sun4) */
149asm (" call start_float");
150asm (" nop");
151
152/* Move `argc', `argv', and `envp' from locals to parameters for `main'. */
153asm (" mov %l0,%o0");
154asm (" mov %l1,%o1");
155asm ("__callmain:"); /* Defined for the benefit of debuggers */
156asm (" call _main");
157asm (" mov %l2,%o2");
158
159asm (" call _exit");
160asm (" nop");
161
162#ifdef MCRT0
163static void
164__do_mcrt ()
165{
166 extern unsigned char eprol, etext;
167 extern void _mcleanup();
168
169 on_exit(_mcleanup, 0);
170 monstartup(&eprol, &etext);
171 return;
172}
173#endif
174
175#endif /* sparc */
176
177
178#ifdef i386
15637ed4
RG
179start()
180{
181 struct kframe {
182 int kargc;
183 char *kargv[1]; /* size depends on kargc */
184 char kargstr[1]; /* size varies */
185 char kenvstr[1]; /* size varies */
186 };
187 /*
188 * ALL REGISTER VARIABLES!!!
189 */
190 register struct kframe *kfp;
191 register char **targv;
192 register char **argv;
193 extern void _mcleanup();
90c075bb
PR
194#ifdef DYNAMIC
195 volatile caddr_t x;
196#endif
15637ed4
RG
197
198#ifdef lint
199 kfp = 0;
200 initcode = initcode = 0;
90c075bb 201#else /* not lint */
15637ed4
RG
202 /* just above the saved frame pointer */
203 asm ("lea 4(%%ebp), %0" : "=r" (kfp) );
90c075bb 204#endif /* not lint */
15637ed4
RG
205 for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
206 /* void */ ;
207 if (targv >= (char **)(*argv))
208 --targv;
209 environ = targv;
90c075bb
PR
210
211#ifdef DYNAMIC
1781f4aa 212 /* ld(1) convention: if DYNAMIC = 0 then statically linked */
90c075bb
PR
213#ifdef stupid_gcc
214 if (&_DYNAMIC)
215 __do_dynamic_link();
216#else
217 x = (caddr_t)&_DYNAMIC;
218 if (x)
219 __do_dynamic_link();
220#endif
221#endif /* DYNAMIC */
222
15637ed4
RG
223asm("eprol:");
224
225#ifdef MCRT0
226 atexit(_mcleanup);
227 monstartup(&eprol, &etext);
228#endif MCRT0
90c075bb
PR
229#if 0
230 errno = 0;
231#endif
232 if (argv[0])
233 if ((__progname = _strrchr(argv[0], '/')) == NULL)
234 __progname = argv[0];
235 else
236 ++__progname;
237asm ("__callmain:"); /* Defined for the benefit of debuggers */
15637ed4
RG
238 exit(main(kfp->kargc, argv, environ));
239}
90c075bb
PR
240#endif /* i386 */
241
242#ifdef DYNAMIC
243static void
244__do_dynamic_link ()
245{
246 struct crt_ldso crt;
247 struct exec hdr;
248 char *ldso;
249 int dupzfd;
250 void (*entry)();
251
1781f4aa 252#ifdef DEBUG
90c075bb
PR
253 /* Provision for alternate ld.so - security risk! */
254 if (!(ldso = _getenv("LDSO")))
1781f4aa 255#endif
90c075bb
PR
256 ldso = LDSO;
257
258 crt.crt_ldfd = open(ldso, 0, 0);
259 if (crt.crt_ldfd == -1) {
260 _FATAL("No ld.so\n");
261 }
262
263 /* Read LDSO exec header */
264 if (read(crt.crt_ldfd, &hdr, sizeof hdr) < sizeof hdr) {
265 _FATAL("Failure reading ld.so\n");
266 }
5e358090 267 if ((N_GETMAGIC_NET(hdr) != ZMAGIC) && (N_GETMAGIC(hdr) != QMAGIC)) {
90c075bb
PR
268 _FATAL("Bad magic: ld.so\n");
269 }
270
271#ifdef sun
272 /* Get bucket of zeroes */
273 crt.crt_dzfd = open("/dev/zero", 0, 0);
274 if (crt.crt_dzfd == -1) {
275 _FATAL("No /dev/zero\n");
276 }
277#endif
278#ifdef BSD
279 /* We use MAP_ANON */
280 crt.crt_dzfd = -1;
281#endif
282
283#if defined(sun) && defined(DUPZFD)
284 if ((dupzfd = dup(crt.crt_dzfd)) < 0) {
285 _FATAL("Cannot dup /dev/zero\n");
286 }
287#endif
288
289 /* Map in ld.so */
5e358090 290 crt.crt_ba = mmap(0, hdr.a_text,
90c075bb
PR
291 PROT_READ|PROT_EXEC,
292 MAP_FILE|MAP_COPY,
293 crt.crt_ldfd, N_TXTOFF(hdr));
294 if (crt.crt_ba == -1) {
295 _FATAL("Cannot map ld.so\n");
296 }
297
298#ifdef BSD
299/* !!!
300 * This is gross, ld.so is a ZMAGIC a.out, but has `sizeof(hdr)' for
301 * an entry point and not at PAGSIZ as the N_*ADDR macros assume.
302 */
303#undef N_DATADDR
304#undef N_BSSADDR
305#define N_DATADDR(x) ((x).a_text)
306#define N_BSSADDR(x) ((x).a_text + (x).a_data)
307#endif
308
309 /* Map in data segment of ld.so writable */
310 if (mmap(crt.crt_ba+N_DATADDR(hdr), hdr.a_data,
5e358090 311 PROT_READ|PROT_WRITE,
90c075bb
PR
312 MAP_FIXED|MAP_FILE|MAP_COPY,
313 crt.crt_ldfd, N_DATOFF(hdr)) == -1) {
314 _FATAL("Cannot map ld.so\n");
315 }
316
317 /* Map bss segment of ld.so zero */
318 if (hdr.a_bss && mmap(crt.crt_ba+N_BSSADDR(hdr), hdr.a_bss,
5e358090 319 PROT_READ|PROT_WRITE,
90c075bb
PR
320 MAP_FIXED|MAP_ANON|MAP_COPY,
321 crt.crt_dzfd, 0) == -1) {
322 _FATAL("Cannot map ld.so\n");
323 }
324
325 crt.crt_dp = &_DYNAMIC;
326 crt.crt_ep = environ;
327 crt.crt_bp = (caddr_t)_callmain;
328
329#if defined(sparc) && defined(SUN_COMPAT)
330 /* Call Sun's ld.so entry point: version 1, offset crt */
331 __call(CRT_VERSION_SUN, &crt, crt.crt_ba + sizeof hdr);
332#else
333 entry = (void (*)())(crt.crt_ba + sizeof hdr);
334#ifdef SUN_COMPAT
335 (*entry)(CRT_VERSION_SUN, &crt);
336#else
337 (*entry)(CRT_VERSION_BSD, &crt);
338#endif
339#endif
340
341#if defined(sun) && defined(DUPZFD)
342 if (dup2(dupzfd, crt.crt_dzfd) < 0) {
343 _FATAL("Cannot dup2 /dev/zero\n");
344 }
345 (void)close(dupzfd);
346#endif
347 return;
348}
349
350#ifdef sparc
351static
352__call()
353{
354 /*
355 * adjust the C generated pointer to the crt struct to the
356 * likings of ld.so, which is an offset relative to its %fp
357 */
358#if 0
359 asm("___call:");
360 asm("call %o2");
361 asm("sub %o1, %sp, %o1"); /* adjust parameter */
362#else Hmmm...
363 asm("mov %i0, %o0");
364 asm("mov %i1, %o1");
365 asm("call %i2");
366 asm("sub %o1, %sp, %o1");
367 /*NOTREACHED, control is transferred directly to our caller */
368#endif
369}
370#endif
15637ed4 371
15637ed4 372/*
90c075bb 373 * Support routines
15637ed4 374 */
90c075bb
PR
375
376static int
377_strncmp(s1, s2, n)
378 register char *s1, *s2;
379 register n;
15637ed4
RG
380{
381
90c075bb
PR
382 if (n == 0)
383 return (0);
384 do {
385 if (*s1 != *s2++)
386 return (*(unsigned char *)s1 - *(unsigned char *)--s2);
387 if (*s1++ == 0)
388 break;
389 } while (--n != 0);
390 return (0);
15637ed4
RG
391}
392
90c075bb
PR
393static char *
394_getenv(name)
395 register char *name;
396{
397 extern char **environ;
398 register int len;
399 register char **P, *C;
400
401 for (C = name, len = 0; *C && *C != '='; ++C, ++len);
402 for (P = environ; *P; ++P)
403 if (!_strncmp(*P, name, len))
404 if (*(C = *P + len) == '=') {
405 return(++C);
406 }
407 return (char *)0;
408}
409
410#ifdef sparc
411 /* System call entry */
412 asm("___syscall:");
413 asm("clr %g1");
414 asm("ta %g0");
415 asm("bgeu Lsyscallx"); /* good result ? */
416 asm("nop");
417 asm("mov -0x1, %o0"); /* Note: no `errno' */
418 asm("Lsyscallx:");
419 asm("jmp %o7 + 0x8");
420 asm("nop");
421#endif /* sparc */
422#ifdef i386
423 asm(" ___syscall:");
424 asm(" popl %ecx");
425 asm(" popl %eax");
426 asm(" pushl %ecx");
427 asm(" .byte 0x9a");
428 asm(" .long 0");
429 asm(" .word 7");
430 asm(" pushl %ecx");
431 asm(" jc 1f");
432 asm(" ret");
433 asm(" 1:");
434 asm(" movl $-1,%eax");
435 asm(" ret");
436#endif /* i386 */
437
438#endif /* DYNAMIC */
439
440static char *
441_strrchr(p, ch)
442register char *p, ch;
443{
444 register char *save;
445
446 for (save = NULL;; ++p) {
447 if (*p == ch)
448 save = (char *)p;
449 if (!*p)
450 return(save);
451 }
452/* NOTREACHED */
453}
454
455#ifdef MCRT0
456asm (" .text");
457asm ("_eprol:");
458#endif