.
[glibc-ports.git] / sysdeps / unix / sysv / aix / libc-start.c
blob813e28d09bc0b00232e76cd0c111bebb37919781
1 /* Initialization code run first thing by the XCOFF startup code. AIX version.
2 Copyright (C) 2001, 2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/types.h>
24 /* hack to use uchar's */
25 typedef unsigned char uchar;
26 #include <xcoff.h>
27 #include <rtinit.h>
28 #include <dlldr.h>
29 #include <bits/libc-lock.h>
31 extern void __libc_init_first (int argc, char **argv, char **envp);
33 /* XXX disable for now
34 extern int __libc_multiple_libcs; */
36 /* XXX normally defined in generic/dl-sydep.c, hack it into existance
37 extern void *__libc_stack_end; */
38 void *__libc_stack_end;
40 struct __libc_start_data_rec {
41 void *stack;
42 void *toc;
43 int argc;
44 char **argv;
45 char **envp;
46 char *data;
47 char *text;
48 unsigned mcount;
49 unsigned special;
50 int (*main)(int, char **, char **);
51 void (*init)(void);
52 void (*fini)(void);
53 void (*rtld_fini)(void);
56 extern struct __libc_start_data_rec __libc_start_data;
57 extern int errno;
59 /* The first piece of initialized data. */
60 int __data_start = 0;
62 #ifndef HAVE_ELF
63 /* Since gcc/crtstuff.c won't define it unless the ELF format is used
64 we will need to define it here. */
65 void *__dso_handle = NULL;
66 #endif
68 /* AIX kernel function */
69 extern int __loadx (int flag, void *module, void *arg1, void *arg2,
70 void *arg3);
71 /* Needed by setenv */
72 char **__environ;
75 * Find __rtinit symbol
77 * __RTINIT *find_rtinit()
79 * __RTINIT *rti - pointer to __rtinit data structure
82 static __RTINIT *
83 find_rtinit (void)
85 struct xcoffhdr *xcoff_hdr;
86 SCNHDR *sec_hdr;
87 SCNHDR *ldr_sec_hdr;
88 SCNHDR *data_sec_hdr;
89 LDSYM *ldsym_hdr;
90 __RTINIT *rtl;
92 xcoff_hdr = (struct xcoffhdr *) __libc_start_data.text;
93 sec_hdr = (SCNHDR *) ((caddr_t) &xcoff_hdr->aouthdr
94 + xcoff_hdr->filehdr.f_opthdr);
95 ldr_sec_hdr = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_snloader - 1));
96 ldsym_hdr = (LDSYM *) ((caddr_t) xcoff_hdr + ldr_sec_hdr->s_scnptr
97 + LDHDRSZ);
99 if (__libc_start_data.mcount <= 0)
101 if (!ldr_sec_hdr->s_scnptr)
102 return NULL;
104 if (memcmp (ldsym_hdr, RTINIT_NAME, sizeof(RTINIT_NAME) - 1) != 0)
105 return NULL;
108 data_sec_hdr = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_sndata - 1));
109 rtl = (__RTINIT *) (ldsym_hdr->l_value
110 + (__libc_start_data.data - data_sec_hdr->s_vaddr));
111 return rtl;
114 /* The mod_init1 calls every initialization function
115 for a given module.
117 void mod_init1(handler, rti)
119 void *handler - if NULL init funtions for modules loaded at exec time
120 are being executed. Otherwise, the handler points to the
121 module loaded.
123 __RTINIT *rti - pointer to __rtinit data structure (with rti->init_offset
124 not equal to zero)
127 static void
128 mod_init1 (void *handler,__RTINIT *rtl)
130 __RTINIT_DESCRIPTOR *descriptor;
132 descriptor = (__RTINIT_DESCRIPTOR *) ((caddr_t) &rtl->rtl
133 + rtl->init_offset);
134 while (descriptor->f != NULL)
136 if (!(descriptor->flags & _RT_CALLED))
138 descriptor->flags |= _RT_CALLED;
139 /* Execute init/fini. */
140 descriptor->f (handler, rtl, descriptor);
142 descriptor = (__RTINIT_DESCRIPTOR *) ((caddr_t) descriptor
143 + rtl->__rtinit_descriptor_size);
147 /* The modinit() function performs run-time linking, if enabled, and calling
148 the init() function for all loaded modules.
150 int modinit()
153 #define DL_BUFFER_SIZE 1000
155 static int
156 modinit (void)
158 int *handler = NULL;
159 __RTINIT *rtinit_info = NULL;
160 int flag;
161 DL_INFO dl_buffer[DL_BUFFER_SIZE];
162 DL_INFO *dl_info = dl_buffer;
163 int i;
165 /* Find __rtinit symbols */
166 rtinit_info = find_rtinit ();
168 flag = DL_EXECQ;
169 if (rtinit_info && rtinit_info->rtl)
170 flag |= DL_LOAD_RTL;
172 /* Get a list of modules that have __rtinit. */
173 if (__loadx (flag, dl_info, (void *) sizeof (dl_buffer), NULL, NULL))
174 exit (0x90);
176 if (( dl_info[0].dlinfo_xflags & DL_INFO_OK))
178 rtinit_info = find_rtinit ();
179 if ((rtinit_info != NULL) & (rtinit_info->rtl != NULL))
181 if ((*rtinit_info->rtl) (dl_info, 0))
182 exit (0x90);
186 /* Initialization each module loaded that has __rtinit. */
187 if (dl_info[0].dlinfo_xflags & DL_INFO_OK)
189 for (i = 1; i < dl_info[0].dlinfo_arraylen + 1; ++i)
190 if (dl_info[i].dlinfo_flags & DL_HAS_RTINIT)
192 rtinit_info = find_rtinit ();
193 if (rtinit_info)
194 mod_init1 (handler, rtinit_info);
198 return 0;
202 void
203 __libc_start_init (void)
205 /* Do run-time linking, if enabled and call the init()
206 for all loaded modules. */
207 if (__libc_start_data.mcount != __libc_start_data.special)
208 modinit ();
211 /* For now these are just stubs. */
212 void
213 __libc_start_fini (void)
217 void
218 __libc_start_rtld_fini (void)
222 void
223 __libc_start_main (void)
225 #ifndef SHARED
227 /* The next variable is only here to work around a bug in gcc <= 2.7.2.2.
228 If the address would be taken inside the expression the optimizer
229 would try to be too smart and throws it away. Grrr. */
231 /* XXX disable for now
232 int *dummy_addr = &_dl_starting_up;
234 __libc_multiple_libcs = dummy_addr && !_dl_starting_up; */
235 #endif
237 /* Store the lowest stack address. */
238 __libc_stack_end = __libc_start_data.stack;
240 /* Used by setenv */
241 __environ = __libc_start_data.envp;
243 #ifndef SHARED
244 /* Clear errno. */
245 errno = 0;
247 /* Some security at this point. Prevent starting a SUID binary where
248 the standard file descriptors are not opened. We have to do this
249 only for statically linked applications since otherwise the dynamic
250 loader did the work already. */
251 if (__builtin_expect (__libc_enable_secure, 0))
252 __libc_check_standard_fds ();
254 #endif
256 /* Register the destructor of the dynamic linker if there is any. */
257 if (__builtin_expect (__libc_start_data.rtld_fini != NULL, 1))
258 __cxa_atexit ((void (*) (void *)) __libc_start_data.rtld_fini, NULL, NULL);
260 /* Call the initializer of the libc. This is only needed here if we
261 are compiling for the static library in which case we haven't
262 run the constructors in `_dl_start_user'. */
263 #ifndef SHARED
264 __libc_init_first (__libc_start_data.argc, __libc_start_data.argv,
265 __libc_start_data.envp);
266 #endif
268 /* Register the destructor of the program, if any. */
269 if (__libc_start_data.fini)
270 __cxa_atexit ((void (*) (void *)) __libc_start_data.fini, NULL, NULL);
272 /* Call the initializer of the program, if any. */
273 #ifdef SHARED
274 if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
275 _dl_debug_printf ("\ninitialize program: %s\n\n",
276 __libc_start_data.argv[0]);
277 #endif
278 if (__libc_start_data.init)
279 (*__libc_start_data.init) ();
281 #ifdef SHARED
282 if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
283 _dl_debug_printf ("\ntransferring control: %s\n\n",
284 __libc_start_data.argv[0]);
285 #endif
287 exit ((*__libc_start_data.main) (__libc_start_data.argc,
288 __libc_start_data.argv,
289 __libc_start_data.envp));