Back to index

glibc  2.9
start-libc.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 {
00042   void *stack;
00043   void *toc;
00044   int argc;
00045   char **argv;
00046   char **envp;
00047   char *data;
00048   char *text;
00049   unsigned int mcount;
00050   unsigned int special;
00051   int (*main) (int, char **, char **);
00052   void (*init) (void);
00053   void (*fini) (void);
00054   void (*rtld_fini) (void);
00055 };
00056 
00057 extern struct __libc_start_data_rec __libc_start_data;
00058 extern int errno;
00059 
00060 /* The first piece of initialized data.  */
00061 int __data_start = 0;
00062 
00063 #ifndef HAVE_ELF
00064 /* Since gcc/crtstuff.c won't define it unless the ELF format is used
00065    we will need to define it here.  */
00066 void *__dso_handle = NULL;
00067 #endif
00068 
00069 /* AIX kernel function */
00070 extern int __loadx (int flag, void *module, void *arg1, void *arg2,
00071                   void *arg3);
00072 /* Needed by setenv */
00073 char  **__environ;
00074 
00075 /*
00076    Find __rtinit symbol
00077 
00078    __RTINIT *find_rtinit()
00079 
00080    __RTINIT        *rti - pointer to __rtinit data structure
00081  */
00082 
00083 static __RTINIT *
00084 find_rtinit (void)
00085 {
00086   struct xcoffhdr *xcoff_hdr;
00087   SCNHDR *sec_hdr;
00088   SCNHDR *ldr_sec_hdr;
00089   SCNHDR *data_sec_hdr;
00090   LDSYM *ldsym_hdr;
00091   __RTINIT *rtl;
00092 
00093   xcoff_hdr = (struct xcoffhdr *) __libc_start_data.text;
00094   sec_hdr = (SCNHDR *) ((caddr_t) &xcoff_hdr->aouthdr
00095                      + xcoff_hdr->filehdr.f_opthdr);
00096   ldr_sec_hdr = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_snloader - 1));
00097   ldsym_hdr = (LDSYM  *) ((caddr_t)xcoff_hdr + ldr_sec_hdr->s_scnptr
00098                        + LDHDRSZ);
00099 
00100   if ( __libc_start_data.mcount <= 0)
00101     {
00102       if (!ldr_sec_hdr->s_scnptr)
00103        return (__RTINIT *) 0;
00104 
00105       if (memcmp (ldsym_hdr, RTINIT_NAME, sizeof (RTINIT_NAME) - 1))
00106        return (__RTINIT *) 0;
00107     }
00108 
00109   data_sec_hdr   = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_sndata - 1));
00110   rtl = (__RTINIT *) (ldsym_hdr->l_value
00111                     + (__libc_start_data.data - data_sec_hdr->s_vaddr));
00112   return rtl;
00113 }
00114 
00115 /*
00116    The mod_init1 calls every initialization function for a given module.
00117 
00118     void mod_init1(handler, rti)
00119 
00120     void *handler - if NULL init funtions for modules loaded at exec time
00121                     are being executed. Otherwise, the handler points to the
00122                     module loaded.
00123 
00124     __RTINIT *rti - pointer to __rtinit data structure (with rti->init_offset
00125                     not equal to zero)
00126  */
00127 
00128 static void
00129 mod_init1 (void *handler,__RTINIT *rtl)
00130 {
00131   __RTINIT_DESCRIPTOR  *descriptor;
00132 
00133   descriptor = (__RTINIT_DESCRIPTOR *) ((caddr_t) &rtl->rtl
00134                                    + rtl->init_offset);
00135   while (descriptor->f != NULL)
00136     {
00137       if (!(descriptor->flags & _RT_CALLED))
00138        {
00139          descriptor->flags |= _RT_CALLED;
00140          (descriptor->f) (handler, rtl, descriptor);  /* execute init/fini */
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 #define DL_BUFFER_SIZE 1000
00151 
00152 static int
00153 modinit (void)
00154 {
00155   int *handler = 0;
00156   __RTINIT *rtinit_info = 0;
00157   int flag;
00158   DL_INFO dl_buffer[DL_BUFFER_SIZE];
00159   DL_INFO *dl_info = dl_buffer;
00160   int i;
00161 
00162   /* Find __rtinit symbols */
00163   rtinit_info = find_rtinit ();
00164 
00165   flag = DL_EXECQ;
00166   if (rtinit_info && rtinit_info->rtl)
00167     flag |= DL_LOAD_RTL;
00168 
00169   /* Get a list of modules that have __rtinit */
00170   if (__loadx (flag, dl_info, (void *) sizeof (dl_buffer), NULL, NULL))
00171     exit (0x90);
00172 
00173   if (dl_info[0].dlinfo_xflags & DL_INFO_OK)
00174     {
00175       rtinit_info = find_rtinit ();
00176       if ((rtinit_info != NULL) & (rtinit_info->rtl != NULL))
00177        {
00178          if ((*rtinit_info->rtl) (dl_info, 0))
00179            exit (0x90);
00180        }
00181     }
00182 
00183   /* Initialization each module loaded that has __rtinit. */
00184   if (dl_info[0].dlinfo_xflags & DL_INFO_OK)
00185     {
00186       for (i = 1; i < dl_info[0].dlinfo_arraylen + 1; ++i)
00187        if (dl_info[i].dlinfo_flags & DL_HAS_RTINIT)
00188          {
00189            rtinit_info = find_rtini t();
00190            if (rtinit_info)
00191              mod_init1 (handler, rtinit_info);
00192          }
00193     }
00194 
00195   return 0;
00196 }
00197 
00198 
00199 void
00200 __libc_start_init (void)
00201 {
00202   /* Do run-time linking, if enabled and call the init()
00203      for all loaded modules. */
00204   if (__libc_start_data.mcount != __libc_start_data.special)
00205     modinit ();
00206 }
00207 
00208 /* For now these are just stubs. */
00209 void
00210 __libc_start_fini (void)
00211 {
00212 }
00213 
00214 void
00215 __libc_start_rtld_fini (void)
00216 {
00217 }
00218 
00219 
00220 int
00221 __libc_start_main (void)
00222 {
00223   /* Store the lowest stack address.  */
00224   __libc_stack_end = __libc_start_data.stack;
00225 
00226   /* Used by setenv */
00227   __environ = __libc_start_data.envp;
00228 
00229 #ifndef SHARED
00230   /* Clear errno. */
00231     errno = 0;
00232 
00233   /* Some security at this point.  Prevent starting a SUID binary where
00234      the standard file descriptors are not opened.  We have to do this
00235      only for statically linked applications since otherwise the dynamic
00236      loader did the work already.  */
00237   if (__builtin_expect (__libc_enable_secure, 0))
00238     __libc_check_standard_fds ();
00239 
00240 #endif
00241 
00242   /* Register the destructor of the dynamic linker if there is any.  */
00243   if (__builtin_expect (__libc_start_data.rtld_fini != NULL, 1))
00244     __cxa_atexit ((void (*) (void *)) __libc_start_data.rtld_fini, NULL, NULL);
00245 
00246   /* Call the initializer of the libc.  This is only needed here if we
00247      are compiling for the static library in which case we haven't
00248      run the constructors in `_dl_start_user'.  */
00249 #ifndef SHARED
00250   __libc_init_first (__libc_start_data.argc, __libc_start_data.argv,
00251                    __libc_start_data.envp);
00252 #endif
00253 
00254   /* Register the destructor of the program, if any.  */
00255   if (__libc_start_data.fini)
00256     __cxa_atexit ((void (*) (void *)) __libc_start_data.fini, NULL, NULL);
00257 
00258   /* Call the initializer of the program, if any.  */
00259   if (__libc_start_data.init)
00260     (*__libc_start_data.init) ();
00261 
00262   exit ((*__libc_start_data.main) (__libc_start_data.argc,
00263                                __libc_start_data.argv,
00264                                __libc_start_data.envp));
00265 }