Back to index

glibc  2.9
libc-start.c
Go to the documentation of this file.
00001 /* Initialization code run first thing by the XCOFF startup code.  AIX version.
00002    Copyright (C) 2001, 2002 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <stdlib.h>
00021 #include <unistd.h>
00022 #include <sys/types.h>
00023 
00024 /* hack to use uchar's */
00025 typedef unsigned char uchar;
00026 #include <xcoff.h>
00027 #include <rtinit.h>
00028 #include <dlldr.h>
00029 #include <bits/libc-lock.h>
00030 
00031 extern void __libc_init_first (int argc, char **argv, char **envp);
00032 
00033 /* XXX disable for now
00034 extern int __libc_multiple_libcs; */
00035 
00036 /* XXX normally defined in generic/dl-sydep.c, hack it into existance
00037 extern void *__libc_stack_end; */
00038 void *__libc_stack_end;
00039 
00040   struct __libc_start_data_rec {
00041     void *stack;
00042     void *toc;
00043     int argc;
00044     char **argv;
00045     char **envp;
00046     char *data;
00047     char *text;
00048     unsigned mcount;
00049     unsigned special;
00050     int (*main)(int, char **, char **);
00051     void (*init)(void);
00052     void (*fini)(void);
00053     void (*rtld_fini)(void);
00054   };
00055 
00056 extern struct __libc_start_data_rec __libc_start_data;
00057 extern int errno;
00058 
00059 /* The first piece of initialized data.  */
00060 int __data_start = 0;
00061 
00062 #ifndef HAVE_ELF
00063 /* Since gcc/crtstuff.c won't define it unless the ELF format is used
00064    we will need to define it here.  */
00065 void *__dso_handle = NULL;
00066 #endif
00067 
00068 /* AIX kernel function */
00069 extern int __loadx (int flag, void *module, void *arg1, void *arg2,
00070                   void *arg3);
00071 /* Needed by setenv */
00072 char  **__environ;
00073 
00074 /*
00075  * Find __rtinit symbol
00076  *
00077  * __RTINIT *find_rtinit()
00078  *
00079  * __RTINIT        *rti - pointer to __rtinit data structure
00080  */
00081 
00082 static __RTINIT *
00083 find_rtinit (void)
00084 {
00085   struct xcoffhdr *xcoff_hdr;
00086   SCNHDR *sec_hdr;
00087   SCNHDR *ldr_sec_hdr;
00088   SCNHDR *data_sec_hdr;
00089   LDSYM *ldsym_hdr;
00090   __RTINIT *rtl;
00091 
00092   xcoff_hdr = (struct xcoffhdr *) __libc_start_data.text;
00093   sec_hdr   = (SCNHDR *) ((caddr_t) &xcoff_hdr->aouthdr
00094                        + xcoff_hdr->filehdr.f_opthdr);
00095   ldr_sec_hdr = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_snloader - 1));
00096   ldsym_hdr   = (LDSYM  *) ((caddr_t) xcoff_hdr + ldr_sec_hdr->s_scnptr
00097                          + LDHDRSZ);
00098 
00099   if (__libc_start_data.mcount <= 0)
00100     {
00101       if (!ldr_sec_hdr->s_scnptr)
00102        return NULL;
00103 
00104       if (memcmp (ldsym_hdr, RTINIT_NAME, sizeof(RTINIT_NAME) - 1) != 0)
00105        return NULL;
00106     }
00107 
00108   data_sec_hdr   = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_sndata - 1));
00109   rtl = (__RTINIT *) (ldsym_hdr->l_value
00110                     + (__libc_start_data.data - data_sec_hdr->s_vaddr));
00111   return rtl;
00112 }
00113 
00114 /* The mod_init1 calls every initialization function
00115    for a given module.
00116 
00117      void mod_init1(handler, rti)
00118 
00119      void *handler - if NULL init funtions for modules loaded at exec time
00120                      are being executed. Otherwise, the handler points to the
00121                      module loaded.
00122 
00123      __RTINIT *rti - pointer to __rtinit data structure (with rti->init_offset
00124                      not equal to zero)
00125  */
00126 
00127 static void
00128 mod_init1 (void *handler,__RTINIT *rtl)
00129 {
00130   __RTINIT_DESCRIPTOR *descriptor;
00131 
00132   descriptor = (__RTINIT_DESCRIPTOR *) ((caddr_t) &rtl->rtl
00133                                    + rtl->init_offset);
00134   while (descriptor->f != NULL)
00135     {
00136       if (!(descriptor->flags & _RT_CALLED))
00137        {
00138          descriptor->flags |=  _RT_CALLED;
00139          /* Execute init/fini.  */
00140          descriptor->f (handler, rtl, descriptor);
00141        }
00142       descriptor = (__RTINIT_DESCRIPTOR *) ((caddr_t) descriptor
00143                                        + rtl->__rtinit_descriptor_size);
00144     }
00145 }
00146 
00147 /* The modinit() function performs run-time linking, if enabled, and calling
00148    the init() function for all loaded modules.
00149 
00150    int modinit()
00151  */
00152 
00153 #define DL_BUFFER_SIZE 1000
00154 
00155 static int
00156 modinit (void)
00157 {
00158   int *handler = NULL;
00159   __RTINIT *rtinit_info = NULL;
00160   int flag;
00161   DL_INFO dl_buffer[DL_BUFFER_SIZE];
00162   DL_INFO *dl_info = dl_buffer;
00163   int i;
00164 
00165   /* Find __rtinit symbols */
00166   rtinit_info = find_rtinit ();
00167 
00168   flag = DL_EXECQ;
00169   if (rtinit_info && rtinit_info->rtl)
00170     flag |= DL_LOAD_RTL;
00171 
00172   /* Get a list of modules that have __rtinit.  */
00173   if (__loadx (flag, dl_info, (void *) sizeof (dl_buffer), NULL, NULL))
00174     exit (0x90);
00175 
00176   if (( dl_info[0].dlinfo_xflags & DL_INFO_OK))
00177     {
00178       rtinit_info = find_rtinit ();
00179       if ((rtinit_info != NULL) & (rtinit_info->rtl != NULL))
00180        {
00181          if ((*rtinit_info->rtl) (dl_info, 0))
00182            exit (0x90);
00183        }
00184     }
00185 
00186   /* Initialization each module loaded that has __rtinit. */
00187   if (dl_info[0].dlinfo_xflags & DL_INFO_OK)
00188     {
00189       for (i = 1; i < dl_info[0].dlinfo_arraylen + 1; ++i)
00190        if (dl_info[i].dlinfo_flags & DL_HAS_RTINIT)
00191          {
00192            rtinit_info = find_rtinit ();
00193            if (rtinit_info)
00194              mod_init1 (handler, rtinit_info);
00195          }
00196     }
00197 
00198   return 0;
00199 }
00200 
00201 
00202 void
00203 __libc_start_init (void)
00204 {
00205   /* Do run-time linking, if enabled and call the init()
00206      for all loaded modules. */
00207   if (__libc_start_data.mcount != __libc_start_data.special)
00208     modinit ();
00209 }
00210 
00211 /* For now these are just stubs. */
00212 void
00213 __libc_start_fini (void)
00214 {
00215 }
00216 
00217 void
00218 __libc_start_rtld_fini (void)
00219 {
00220 }
00221 
00222 void
00223 __libc_start_main (void)
00224 {
00225 #ifndef SHARED
00226 
00227   /* The next variable is only here to work around a bug in gcc <= 2.7.2.2.
00228      If the address would be taken inside the expression the optimizer
00229      would try to be too smart and throws it away.  Grrr.  */
00230 
00231   /* XXX disable for now
00232   int *dummy_addr = &_dl_starting_up;
00233 
00234   __libc_multiple_libcs = dummy_addr && !_dl_starting_up; */
00235 #endif
00236 
00237   /* Store the lowest stack address.  */
00238   __libc_stack_end = __libc_start_data.stack;
00239 
00240   /* Used by setenv */
00241   __environ = __libc_start_data.envp;
00242 
00243 #ifndef SHARED
00244   /* Clear errno. */
00245     errno = 0;
00246 
00247   /* Some security at this point.  Prevent starting a SUID binary where
00248      the standard file descriptors are not opened.  We have to do this
00249      only for statically linked applications since otherwise the dynamic
00250      loader did the work already.  */
00251   if (__builtin_expect (__libc_enable_secure, 0))
00252     __libc_check_standard_fds ();
00253 
00254 #endif
00255 
00256   /* Register the destructor of the dynamic linker if there is any.  */
00257   if (__builtin_expect (__libc_start_data.rtld_fini != NULL, 1))
00258     __cxa_atexit ((void (*) (void *)) __libc_start_data.rtld_fini, NULL, NULL);
00259 
00260   /* Call the initializer of the libc.  This is only needed here if we
00261      are compiling for the static library in which case we haven't
00262      run the constructors in `_dl_start_user'.  */
00263 #ifndef SHARED
00264   __libc_init_first (__libc_start_data.argc, __libc_start_data.argv,
00265                    __libc_start_data.envp);
00266 #endif
00267 
00268   /* Register the destructor of the program, if any.  */
00269   if (__libc_start_data.fini)
00270     __cxa_atexit ((void (*) (void *)) __libc_start_data.fini, NULL, NULL);
00271 
00272   /* Call the initializer of the program, if any.  */
00273 #ifdef SHARED
00274   if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
00275     _dl_debug_printf ("\ninitialize program: %s\n\n",
00276                     __libc_start_data.argv[0]);
00277 #endif
00278   if (__libc_start_data.init)
00279     (*__libc_start_data.init) ();
00280 
00281 #ifdef SHARED
00282   if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
00283     _dl_debug_printf ("\ntransferring control: %s\n\n",
00284                     __libc_start_data.argv[0]);
00285 #endif
00286 
00287   exit ((*__libc_start_data.main) (__libc_start_data.argc,
00288                                __libc_start_data.argv,
00289                                __libc_start_data.envp));
00290 }