Updated to fedora-glibc-20040930T0838
[glibc/history.git] / sysdeps / unix / sysv / aix / start-libc.c
blob0cbe79d0b120e2450554465d2dfae4f29a715105
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
42 void *stack;
43 void *toc;
44 int argc;
45 char **argv;
46 char **envp;
47 char *data;
48 char *text;
49 unsigned int mcount;
50 unsigned int special;
51 int (*main) (int, char **, char **);
52 void (*init) (void);
53 void (*fini) (void);
54 void (*rtld_fini) (void);
57 extern struct __libc_start_data_rec __libc_start_data;
58 extern int errno;
60 /* The first piece of initialized data. */
61 int __data_start = 0;
63 #ifndef HAVE_ELF
64 /* Since gcc/crtstuff.c won't define it unless the ELF format is used
65 we will need to define it here. */
66 void *__dso_handle = NULL;
67 #endif
69 /* AIX kernel function */
70 extern int __loadx (int flag, void *module, void *arg1, void *arg2,
71 void *arg3);
72 /* Needed by setenv */
73 char **__environ;
76 Find __rtinit symbol
78 __RTINIT *find_rtinit()
80 __RTINIT *rti - pointer to __rtinit data structure
83 static __RTINIT *
84 find_rtinit (void)
86 struct xcoffhdr *xcoff_hdr;
87 SCNHDR *sec_hdr;
88 SCNHDR *ldr_sec_hdr;
89 SCNHDR *data_sec_hdr;
90 LDSYM *ldsym_hdr;
91 __RTINIT *rtl;
93 xcoff_hdr = (struct xcoffhdr *) __libc_start_data.text;
94 sec_hdr = (SCNHDR *) ((caddr_t) &xcoff_hdr->aouthdr
95 + xcoff_hdr->filehdr.f_opthdr);
96 ldr_sec_hdr = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_snloader - 1));
97 ldsym_hdr = (LDSYM *) ((caddr_t)xcoff_hdr + ldr_sec_hdr->s_scnptr
98 + LDHDRSZ);
100 if ( __libc_start_data.mcount <= 0)
102 if (!ldr_sec_hdr->s_scnptr)
103 return (__RTINIT *) 0;
105 if (memcmp (ldsym_hdr, RTINIT_NAME, sizeof (RTINIT_NAME) - 1))
106 return (__RTINIT *) 0;
109 data_sec_hdr = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_sndata - 1));
110 rtl = (__RTINIT *) (ldsym_hdr->l_value
111 + (__libc_start_data.data - data_sec_hdr->s_vaddr));
112 return rtl;
116 The mod_init1 calls every initialization function for a given module.
118 void mod_init1(handler, rti)
120 void *handler - if NULL init funtions for modules loaded at exec time
121 are being executed. Otherwise, the handler points to the
122 module loaded.
124 __RTINIT *rti - pointer to __rtinit data structure (with rti->init_offset
125 not equal to zero)
128 static void
129 mod_init1 (void *handler,__RTINIT *rtl)
131 __RTINIT_DESCRIPTOR *descriptor;
133 descriptor = (__RTINIT_DESCRIPTOR *) ((caddr_t) &rtl->rtl
134 + rtl->init_offset);
135 while (descriptor->f != NULL)
137 if (!(descriptor->flags & _RT_CALLED))
139 descriptor->flags |= _RT_CALLED;
140 (descriptor->f) (handler, rtl, descriptor); /* execute init/fini */
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 #define DL_BUFFER_SIZE 1000
152 static int
153 modinit (void)
155 int *handler = 0;
156 __RTINIT *rtinit_info = 0;
157 int flag;
158 DL_INFO dl_buffer[DL_BUFFER_SIZE];
159 DL_INFO *dl_info = dl_buffer;
160 int i;
162 /* Find __rtinit symbols */
163 rtinit_info = find_rtinit ();
165 flag = DL_EXECQ;
166 if (rtinit_info && rtinit_info->rtl)
167 flag |= DL_LOAD_RTL;
169 /* Get a list of modules that have __rtinit */
170 if (__loadx (flag, dl_info, (void *) sizeof (dl_buffer), NULL, NULL))
171 exit (0x90);
173 if (dl_info[0].dlinfo_xflags & DL_INFO_OK)
175 rtinit_info = find_rtinit ();
176 if ((rtinit_info != NULL) & (rtinit_info->rtl != NULL))
178 if ((*rtinit_info->rtl) (dl_info, 0))
179 exit (0x90);
183 /* Initialization each module loaded that has __rtinit. */
184 if (dl_info[0].dlinfo_xflags & DL_INFO_OK)
186 for (i = 1; i < dl_info[0].dlinfo_arraylen + 1; ++i)
187 if (dl_info[i].dlinfo_flags & DL_HAS_RTINIT)
189 rtinit_info = find_rtini t();
190 if (rtinit_info)
191 mod_init1 (handler, rtinit_info);
195 return 0;
199 void
200 __libc_start_init (void)
202 /* Do run-time linking, if enabled and call the init()
203 for all loaded modules. */
204 if (__libc_start_data.mcount != __libc_start_data.special)
205 modinit ();
208 /* For now these are just stubs. */
209 void
210 __libc_start_fini (void)
214 void
215 __libc_start_rtld_fini (void)
221 __libc_start_main (void)
223 /* Store the lowest stack address. */
224 __libc_stack_end = __libc_start_data.stack;
226 /* Used by setenv */
227 __environ = __libc_start_data.envp;
229 #ifndef SHARED
230 /* Clear errno. */
231 errno = 0;
233 /* Some security at this point. Prevent starting a SUID binary where
234 the standard file descriptors are not opened. We have to do this
235 only for statically linked applications since otherwise the dynamic
236 loader did the work already. */
237 if (__builtin_expect (__libc_enable_secure, 0))
238 __libc_check_standard_fds ();
240 #endif
242 /* Register the destructor of the dynamic linker if there is any. */
243 if (__builtin_expect (__libc_start_data.rtld_fini != NULL, 1))
244 __cxa_atexit ((void (*) (void *)) __libc_start_data.rtld_fini, NULL, NULL);
246 /* Call the initializer of the libc. This is only needed here if we
247 are compiling for the static library in which case we haven't
248 run the constructors in `_dl_start_user'. */
249 #ifndef SHARED
250 __libc_init_first (__libc_start_data.argc, __libc_start_data.argv,
251 __libc_start_data.envp);
252 #endif
254 /* Register the destructor of the program, if any. */
255 if (__libc_start_data.fini)
256 __cxa_atexit ((void (*) (void *)) __libc_start_data.fini, NULL, NULL);
258 /* Call the initializer of the program, if any. */
259 if (__libc_start_data.init)
260 (*__libc_start_data.init) ();
262 exit ((*__libc_start_data.main) (__libc_start_data.argc,
263 __libc_start_data.argv,
264 __libc_start_data.envp));