rtld: Add support for preinit, init, and fini arrays
[dragonfly.git] / lib / csu / x86_64 / crt1.c
CommitLineData
17030342
MD
1/* LINTLIBRARY */
2/*-
984263bc
MD
3 * Copyright 1996-1998 John D. Polstra.
4 * All rights reserved.
984263bc
MD
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
984263bc
MD
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1de703da 25 *
17030342 26 * $FreeBSD: src/lib/csu/amd64/crt1.c,v 1.13 2003/04/30 19:27:07 peter Exp $
984263bc
MD
27 */
28
17030342 29#ifndef lint
984263bc
MD
30#ifndef __GNUC__
31#error "GCC is needed to compile this file"
32#endif
17030342 33#endif /* lint */
984263bc 34
f54055f1 35#include <machine/tls.h>
984263bc 36#include <stdlib.h>
984263bc 37
17030342
MD
38#include "libc_private.h"
39#include "crtbrand.c"
984263bc 40
984263bc 41extern int _DYNAMIC;
17030342
MD
42#pragma weak _DYNAMIC
43
44typedef void (*fptr)(void);
984263bc 45
984263bc 46extern void _fini(void);
17030342 47extern void _init(void);
984263bc 48extern int main(int, char **, char **);
17030342 49extern void _start(char **, void (*)(void));
984263bc 50
b28bf640
JM
51extern void (*__preinit_array_start []) (int, char **, char **) __dso_hidden;
52extern void (*__preinit_array_end []) (int, char **, char **) __dso_hidden;
53extern void (*__init_array_start []) (int, char **, char **) __dso_hidden;
54extern void (*__init_array_end []) (int, char **, char **) __dso_hidden;
55extern void (*__fini_array_start []) (void) __dso_hidden;
56extern void (*__fini_array_end []) (void) __dso_hidden;
57
984263bc
MD
58#ifdef GCRT
59extern void _mcleanup(void);
60extern void monstartup(void *, void *);
61extern int eprol;
62extern int etext;
63#endif
64
65char **environ;
17030342 66const char *__progname = "";
984263bc
MD
67
68/* The entry function. */
69void
17030342 70_start(char **ap, void (*cleanup)(void))
984263bc
MD
71{
72 int argc;
73 char **argv;
74 char **env;
17030342 75 const char *s;
b28bf640 76 size_t n, array_size;
984263bc 77
17030342 78 argc = *(long *)(void *)ap;
984263bc 79 argv = ap + 1;
17030342 80 env = ap + 2 + argc;
984263bc 81 environ = env;
17030342 82 if (argc > 0 && argv[0] != NULL) {
984263bc
MD
83 __progname = argv[0];
84 for (s = __progname; *s != '\0'; s++)
85 if (*s == '/')
86 __progname = s + 1;
87 }
88
e6a7a861
MD
89 /*
90 * Setup the initial TLS space. The RTLD does not set up our TLS
91 * (it can't, it doesn't know how our errno is declared). It simply
92 * does all the groundwork required so that we can call
93 * _rtld_allocate_tls().
94 */
95 _init_tls();
96 _rtld_call_init();
97
984263bc
MD
98 if (&_DYNAMIC != NULL)
99 atexit(cleanup);
100
101#ifdef GCRT
102 atexit(_mcleanup);
103#endif
b28bf640
JM
104 /*
105 * The fini_array needs to be executed in the opposite order of its
106 * definition. However, atexit works like a LIFO stack, so by
107 * pushing functions in array order, they will be executed in the
108 * reverse order as required.
109 */
984263bc 110 atexit(_fini);
b28bf640
JM
111 array_size = __fini_array_end - __fini_array_start;
112 for (n = 0; n < array_size; n++)
113 atexit(*__fini_array_start [n]);
984263bc
MD
114#ifdef GCRT
115 monstartup(&eprol, &etext);
116#endif
b28bf640
JM
117 if (&_DYNAMIC == NULL) {
118 /*
119 * For static executables preinit happens right before init.
120 * Dynamic executable preinit arrays are handled by rtld
121 * before any DSOs are initialized.
122 */
123 array_size = __preinit_array_end - __preinit_array_start;
124 for (n = 0; n < array_size; n++)
125 (*__preinit_array_start [n])(argc, argv, env);
126 }
984263bc 127 _init();
b28bf640
JM
128 array_size = __init_array_end - __init_array_start;
129 for (n = 0; n < array_size; n++)
130 (*__init_array_start [n])(argc, argv, env);
984263bc
MD
131 exit( main(argc, argv, env) );
132}
133
134#ifdef GCRT
135__asm__(".text");
136__asm__("eprol:");
137__asm__(".previous");
138#endif