about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/aix/start.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/aix/start.c')
-rw-r--r--sysdeps/unix/sysv/aix/start.c290
1 files changed, 290 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/aix/start.c b/sysdeps/unix/sysv/aix/start.c
new file mode 100644
index 0000000000..d854a55f42
--- /dev/null
+++ b/sysdeps/unix/sysv/aix/start.c
@@ -0,0 +1,290 @@
+/* Copyright (C) 1991, 93, 1995-1998, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+*/
+
+
+/* Old compatibility names for C types.  */
+typedef unsigned char   uchar;   /* sb in libc/posix/types.h */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <xcoff.h>
+#include <rtinit.h>
+#include <dlldr.h>
+#include <bits/libc-lock.h>
+
+/* The first piece of initialized data.  */
+int __data_start = 0;
+
+extern int errno;
+
+/* extern __pthread_init; */
+
+typedef void (*FPV)(void);
+
+typedef struct crt0_info
+{
+   int *p_argc;
+   FPV threads_init;
+} INFO;
+
+
+INFO    crt0_info;
+int     argc;
+char  **argv;
+char  **__environ;
+int     module_count;
+caddr_t text_origin;
+caddr_t data_origin;
+
+asm("
+       .toc
+LL..0: .tc argc[TC],argc
+LL..1: .tc argv[TC],argv
+LL..2: .tc __environ[TC],__environ
+LL..3: .tc module_count[TC],module_count
+LL..4: .tc text_origin[TC],text_origin
+LL..5: .tc data_origin[TC],data_origin
+");
+
+int main (int argc,char **argv,char **__environ);
+int modinit(int argc,INFO *crt0_info, int module_count,
+                     caddr_t text_origin, caddr_t data_origin);
+
+void mod_init1(void *handler,__RTINIT *rti);
+
+__RTINIT *find_rtinit(caddr_t text_origin,caddr_t data_origin, int module_count);
+
+extern int *__loadx();
+
+void __start(void)
+{
+#ifdef __64BIT__
+asm("
+      ld  17,LL..0(2)    # argc
+      std 14,0(17)       # copy reg14 to argc
+      ld  17,LL..1(2)    # argv
+      std 15,0(17)       # copy reg15 to argv
+      ld  17,LL..2(2)    # envp
+      std 16,0(17)       # copy reg16 to envp
+      ld  17,LL..3(2)    # module_count
+      std  30,0(17)      # copy reg30 to module_count
+      ld  17,LL..4(2)    # text_origin
+      std  29,0(17)      # copy reg29 to text_origin
+      ld  17,LL..5(2)    # data_origin
+      std  28,0(17)      # copy reg28 to data_origin
+");
+#else
+asm("
+      lwz  17,LL..0(2)    # argc
+      stw  3,0(17)        # copy reg3 to argc
+      lwz  17,LL..1(2)    # argv
+      stw  4,0(17)        # copy reg4 to argv
+      lwz  17,LL..2(2)    # envp
+      stw  5,0(17)        # copy reg5 to envp
+      lwz  17,LL..3(2)    # module_count
+      stw  30,0(17)       # copy reg30 to module_count
+      lwz  17,LL..4(2)    # text_origin
+      stw  29,0(17)       # copy reg29 to text_origin
+      lwz  17,LL..5(2)    # data_origin
+      stw  28,0(17)       # copy reg28 to data_origin
+");
+#endif
+       crt0_info.p_argc = (int*)&argc;
+
+/*     crt0_info.threads_init = (FPV) &__pthread_init;  */  
+
+     /*
+      * Do run-time linking, if enabled and call the init()
+      * for all loaded modules.
+      */ 
+      argc = modinit(argc,&crt0_info,module_count,text_origin,data_origin);
+
+      errno=0;
+     /*
+      *   Call the user program.
+      */
+      exit (main (argc, argv, __environ));
+}
+
+/*
+ *  The modinit() function performs run-time linking,
+ *  if enabled, and calling the init() function for
+ *  all loaded modules.
+ *
+ * int modinit(argc,crt0_info,module_count,text,data)
+ *
+ * argc         - current value of argc.
+ * info         - crt0 information passed 
+ * module_count - number of modules loaded.
+ * text         - Beginning of text address 
+ * data         - Beginning of data address
+ */
+
+#define DL_BUFFER_SIZE 1000
+
+int modinit(int argc,INFO *crt0_info, int module_count,
+                  caddr_t text_origin, caddr_t data_origin)
+{
+    int      *handler     = 0;
+    __RTINIT *rtinit_info = 0;
+    int flag;
+    DL_INFO dl_buffer[DL_BUFFER_SIZE];
+    DL_INFO *dl_info = dl_buffer;
+    int i;
+    FPV p;
+    __libc_lock_define_initialized(static,modinit_lock);
+
+  /*
+   *   try to find __rtinit symbols
+   */
+   rtinit_info = find_rtinit(text_origin,data_origin,module_count);
+
+   flag = DL_EXECQ;
+   if (rtinit_info && rtinit_info->rtl) flag |= DL_LOAD_RTL;
+
+   /*
+    * get a list of modules that have __rtinit
+    */
+   if (__loadx(flag, dl_info, sizeof(dl_buffer))) exit(0x90);
+
+   if (( dl_info[0].dlinfo_xflags & DL_INFO_OK))
+   {
+     rtinit_info = find_rtinit(dl_info[1].dlinfo_textorg,
+                                  dl_info[1].dlinfo_dataorg,
+                                  module_count);
+     if ((rtinit_info != NULL) & (rtinit_info->rtl != NULL))
+     {
+        if((*rtinit_info->rtl)(dl_info,0)) exit(0x90);
+     }
+   }
+
+  /*
+   *    initialize threads in case any init
+   *    functions need thread functions
+   */
+   if (crt0_info->threads_init)
+     (*crt0_info->threads_init)();
+
+   p = (FPV) __loadx(DL_GLOBALSYM | DL_SRCHLOADLIST,"pthread_init");
+   if (p)
+     (*p)();
+
+   __libc_lock_lock(modinit_lock);
+
+  /*
+   *    initialization each module loaded that has __rtinit.
+   */
+   if (( dl_info[0].dlinfo_xflags & DL_INFO_OK))
+   {
+     for (i=1; i < dl_info[0].dlinfo_arraylen + 1; i++)
+     {
+      if (dl_info[i].dlinfo_flags & DL_HAS_RTINIT)
+      {
+       rtinit_info = find_rtinit(dl_info[i].dlinfo_textorg,
+                                 dl_info[i].dlinfo_dataorg,
+                                 module_count);
+       if (rtinit_info)
+       {
+        mod_init1(handler,rtinit_info);
+       }
+      }
+     }
+   }
+
+  __libc_lock_unlock(modinit_lock);
+  /*
+   *    reload argc if needed.
+   */
+  return((int) (*crt0_info->p_argc));
+}
+
+/*
+ * The mod_init1 calls every initialization function
+ * for a given module.
+ *
+ *   void mod_init1(handler, rti)
+ *
+ *   void *handler - if NULL init funtions for modules loaded at exec time
+ *                   are being executed. Otherwise, the handler points to the
+ *                   module loaded.
+ *
+ *   __RTINIT *rti - pointer to __rtinit data structure (with rti->init_offset
+ *                   not equal to zero)
+ */
+
+void mod_init1(void *handler,__RTINIT *rtl)
+{
+   __RTINIT_DESCRIPTOR  *descriptor;
+
+   descriptor =(__RTINIT_DESCRIPTOR *) ((caddr_t)&rtl->rtl + rtl->init_offset);
+   while (descriptor->f)
+   {
+     if (!(descriptor->flags & _RT_CALLED))
+     {
+        descriptor->flags |=  _RT_CALLED;
+        ( descriptor->f )(handler,rtl,descriptor);  /* execute init/fini */
+     }
+     descriptor = (__RTINIT_DESCRIPTOR *) ((caddr_t)descriptor +
+                                            rtl->__rtinit_descriptor_size);
+   }
+}
+
+
+/*
+ *  Find __rtinit symbol
+ *
+ * __RTINIT *find_rtinit(caddr_t text_origin)
+ *
+ * caddr_t  text_origin - Beginning of text area
+ * caddr_t  data_origin - Beginning of data area
+ * int     module_count - Number of modules loaded
+ * __RTINIT        *rti - pointer to __rtinit data structure
+ */
+
+__RTINIT *find_rtinit(caddr_t text_origin, caddr_t data_origin, int module_count)
+{
+  struct xcoffhdr *xcoff_hdr;
+  SCNHDR          *sec_hdr;
+  SCNHDR          *ldr_sec_hdr;
+  SCNHDR          *data_sec_hdr;
+  LDSYM           *ldsym_hdr;
+  __RTINIT        *rtl;
+
+  xcoff_hdr = (struct xcoffhdr *) text_origin;
+  sec_hdr   = (SCNHDR *) ((caddr_t)&xcoff_hdr->aouthdr +
+                                    xcoff_hdr->filehdr.f_opthdr);
+  ldr_sec_hdr = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_snloader - 1));
+  ldsym_hdr   = (LDSYM  *) ((caddr_t)xcoff_hdr + ldr_sec_hdr->s_scnptr +
+                                                                   LDHDRSZ);
+
+  if ( module_count <= 0)
+  {
+    if ( !(ldr_sec_hdr->s_scnptr) ) return ((__RTINIT *) 0);
+
+    if ( memcmp(ldsym_hdr,RTINIT_NAME,sizeof(RTINIT_NAME)-1))
+             return ((__RTINIT *) 0);
+  }
+
+  data_sec_hdr   = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_sndata - 1));
+  rtl = (__RTINIT *) (ldsym_hdr->l_value +
+                     (data_origin - data_sec_hdr->s_vaddr));
+  return(rtl);
+}
+