about summary refs log tree commit diff
path: root/sysdeps/unix
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2001-04-04 01:54:59 +0000
committerUlrich Drepper <drepper@redhat.com>2001-04-04 01:54:59 +0000
commit468946739b3f7e6031d4843fc9a9d5a6e8a16114 (patch)
treeed9798b68f273f0c295d89fec150292fd6688fb7 /sysdeps/unix
parent194c5f8d0f6da9d84211b479adb58e118f302ae3 (diff)
downloadglibc-468946739b3f7e6031d4843fc9a9d5a6e8a16114.tar.gz
glibc-468946739b3f7e6031d4843fc9a9d5a6e8a16114.tar.xz
glibc-468946739b3f7e6031d4843fc9a9d5a6e8a16114.zip
Update.
2001-03-29  Michael Keezer  <mkeezer@redhat.com>

	* posix/tst-gnuglob.c: Added ifdef _DIRENT_HAVE_D_TYPE.
	* login/tst-utmp.c: Handle case where ut_tv is not available but
	ut_time is.
	* sysdeps/unix/sysv/aix/utmpx.h: New file.
	* sysdeps/unix/sysv/aix/bits/utmpx.h: Added
	_HAVE_UT_TYPE/PID/ID/TV/HOST defines.
	* sysdeps/unix/sysv/aix/libc-start.c: Removed temp code and made stub.
	* sysdeps/unix/sysv/aix/gettimeofday.c: New file added routines
	to access RTCU timer reg.
	* sysdeps/unix/sysv/aix/Makefile: Remove /usr/lib/crt0.o
	added dl-libc, dl-open,dl-sym, dl-close to misc.
	* sysdeps/unix/sysv/aix/start.c: New file.  Start code.
	* sysdeps/unix/sysv/aix/dlldr.h: New file.  AIX __loadx defines.
	* sysdeps/unix/sysv/aix/dl-close.c: New file.  AIX dl-close.
	* sysdeps/unix/sysv/aix/dl-open.c: New file.  AIX dl-open.
	* sysdeps/unix/sysv/aix/dl-sym.c: New file.  AIX dl-sym.
	* sysdeps/unix/sysv/aix/dl-libc.c: New file.  libc_dl-xxx support.
	* sysdeps/generic/strtoll.c: Added SHLIB_COMPAT(libc,GLIBC_2_0,
	GLIBC_2_2).
	* sysdeps/generic/strtoull.c: Likewise.
	* sysdeps/powerpc/ppc-mcount.S: Added nop after bl instruction.
	* sysdeps/unix/sysv/aix/powerpc/memset.c: New file to include
	sysdeps/generic/memset.c.
	* sysdeps/unix/sysv/aix/getpeername.c: Define __getpeername.
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/aix/Makefile8
-rw-r--r--sysdeps/unix/sysv/aix/bits/utmpx.h7
-rw-r--r--sysdeps/unix/sysv/aix/dl-close.c47
-rw-r--r--sysdeps/unix/sysv/aix/dl-libc.c1
-rw-r--r--sysdeps/unix/sysv/aix/dl-open.c132
-rw-r--r--sysdeps/unix/sysv/aix/dl-sym.c57
-rw-r--r--sysdeps/unix/sysv/aix/dlldr.h112
-rw-r--r--sysdeps/unix/sysv/aix/getpeername.c3
-rw-r--r--sysdeps/unix/sysv/aix/gettimeofday.c94
-rw-r--r--sysdeps/unix/sysv/aix/libc-start.c21
-rw-r--r--sysdeps/unix/sysv/aix/powerpc/memset.c21
-rw-r--r--sysdeps/unix/sysv/aix/start.c290
-rw-r--r--sysdeps/unix/sysv/aix/utmpx.h89
13 files changed, 843 insertions, 39 deletions
diff --git a/sysdeps/unix/sysv/aix/Makefile b/sysdeps/unix/sysv/aix/Makefile
index 9aa48d1680..dc91f8f241 100644
--- a/sysdeps/unix/sysv/aix/Makefile
+++ b/sysdeps/unix/sysv/aix/Makefile
@@ -2,18 +2,16 @@
 # This is a hack until the import/export stuff is worked out.
 +postctor += /lib/syscalls.exp
 
-# XXX This is a hack until we have the possibility to generate out own crt0.
-static-start-installed-name = /usr/lib/crt0.o
-
 ifeq ($(subdir),misc)
-sysdep_routines += dl-open dl-sym dl-close uitrunc
+sysdep_routines  += dl-libc dl-open dl-sym dl-close uitrunc 
 endif
 
 ifeq ($(subdir),login)
 sysdep_routines += setutxent getutxent endutxent getutxid getutxline \
                    pututxline utmpxname
 
-sysdep_headers += utmpx.h bits/utmpx.h
+#sysdep_headers += utmpx.h bits/utmpx.h
+#sysdep_headers += bits/utmp.h bits/utmpx.h
 endif
 
 # Don't compile the ctype glue code, since there is no old non-GNU C library.
diff --git a/sysdeps/unix/sysv/aix/bits/utmpx.h b/sysdeps/unix/sysv/aix/bits/utmpx.h
index 7a7bce2f70..f8bd66574f 100644
--- a/sysdeps/unix/sysv/aix/bits/utmpx.h
+++ b/sysdeps/unix/sysv/aix/bits/utmpx.h
@@ -65,3 +65,10 @@ struct utmpx
 #ifdef __USE_GNU
 # define ACCOUNTING	9	/* System accounting.  */
 #endif
+
+#define _HAVE_UT_TYPE   1
+#define _HAVE_UT_PID    1
+#define _HAVE_UT_ID     1
+#define _HAVE_UT_TV     1
+#define _HAVE_UT_HOST   1
+
diff --git a/sysdeps/unix/sysv/aix/dl-close.c b/sysdeps/unix/sysv/aix/dl-close.c
index a9a492a9c7..50986d5528 100644
--- a/sysdeps/unix/sysv/aix/dl-close.c
+++ b/sysdeps/unix/sysv/aix/dl-close.c
@@ -1,9 +1,46 @@
-/* XXX The implementation of dlopen should somehow use the __loadx system
-   call but how?  */
+/* Copyright (C) 2001 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.  */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
 #include <dlfcn.h>
+#include <dlldr.h>
 
-int
-__libc_dlclose (void *handle)
+extern int _dl_numso;
+extern DL_SODATA *_dl_sotable;
+
+void
+_dl_close (void *handle)
 {
-  return 0;
+  if ((int) handle < 0 || (int) handle >= _dl_numso || _dl_sotable == NULL)
+    {
+      errno = EINVAL;
+      return;
+    }
+
+  if (_dl_sotable[(int) handle].handle != 0)
+    __unload (_dl_sotable[(int) handle].handle);
+
+  _dl_sotable[(int) handle].index = 0;
+  _dl_sotable[(int) handle].dataorg = 0;
+  _dl_sotable[(int) handle].handle = 0;
+  _dl_sotable[(int) handle].type = 0;
 }
+
diff --git a/sysdeps/unix/sysv/aix/dl-libc.c b/sysdeps/unix/sysv/aix/dl-libc.c
new file mode 100644
index 0000000000..9a25fc809e
--- /dev/null
+++ b/sysdeps/unix/sysv/aix/dl-libc.c
@@ -0,0 +1 @@
+#include <elf/dl-libc.c>
diff --git a/sysdeps/unix/sysv/aix/dl-open.c b/sysdeps/unix/sysv/aix/dl-open.c
index 50fd7120c5..0189ab465d 100644
--- a/sysdeps/unix/sysv/aix/dl-open.c
+++ b/sysdeps/unix/sysv/aix/dl-open.c
@@ -1,9 +1,133 @@
-/* XXX The implementation of dlopen should somehow use the __loadx system
-   call but how?  */
+/* Copyright (C) 1999, 2000, 2001 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.  */
+
+#include <malloc.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
 #include <dlfcn.h>
+#include <dlldr.h>
+
+#define NUM_SHARED_OBJECTS 32
+
+int _dl_numso = NUM_SHARED_OBJECTS;
+DL_SODATA *_dl_sotable = NULL;
 
 void *
-__libc_dlopen (const char *file)
+_dl_open (const char *file, int mode, const void *caller)
 {
-  return (void *) 0;
+  DL_SODATA *new_so;
+  void *handle;
+  int entry;
+  int bsize = _dl_numso * sizeof (DL_INFO);
+  DL_INFO *dl_info = malloc (bsize);
+
+  if (dl_info == NULL)
+    return NULL;
+
+  /* 1st time thru initial shared object data table.  */
+  if (_dl_sotable == NULL)
+    {
+      _dl_sotable = (DL_SODATA *) calloc (_dl_numso, sizeof (DL_SODATA));
+      if (_dl_sotable == NULL)
+	return NULL;
+
+      __loadx (DL_POSTLOADQ, dl_info, bsize, NULL);
+      while (!(dl_info[0].dlinfo_xflags & DL_INFO_OK)
+	     || dl_info[0].dlinfo_arraylen == 0)
+	{
+	  bsize *= 2;
+	  dl_info = realloc (dl_info, bsize);
+	  if (dl_info == NULL)
+	    return NULL;
+
+	  __loadx (DL_POSTLOADQ, dl_info, bsize, NULL);
+	}
+    }
+
+  /* Validate mode bits.  */
+  if (!(mode & RTLD_NOW) && !(mode & RTLD_LAZY))
+    {
+      free (dl_info);
+      errno = EINVAL;
+      return NULL;
+    }
+
+  /* Load the module.  */
+  handle = (void *) __loadx (DL_LOAD | DL_LOAD_RTL | DL_LOAD_LDX1,
+                             dl_info, bsize, file, NULL);
+  if (handle == NULL)
+    {
+      free (dl_info);
+      errno = EINVAL;
+      return NULL;
+    }
+
+  /* Was dl_info buffer to small to get info.  */
+  while (!(dl_info[0].dlinfo_xflags & DL_INFO_OK)
+	 || dl_info[0].dlinfo_arraylen == 0)
+    {
+      bsize *= 2;
+      dl_info = realloc (dl_info, bsize);
+      if (new_dl_info == NULL)
+        {
+	  (void) __unload ((void *) handle);
+          errno = ENOMEM;
+          return NULL;
+        }
+      __loadx (DL_POSTLOADQ | DL_LOAD_RTL, dl_info, bsize, handle);
+    }
+
+  /* Get an empty entry in the shared object table.  */
+  for (entry = 0; entry < _dl_numso; ++entry)
+    if (_dl_sotable[entry].type == 0)
+      break;
+
+  /* See if the table needs to be increased.  */
+  if (entry == _dl_numso)
+    {
+      new_so = (DL_SODATA *) realloc (_dl_sotable,
+				      _dl_numso * 2 * sizeof (DL_SODATA));
+      if (new_so == NULL)
+	return NULL;
+
+      memset (new_so + _dl_numso, '\0', _dl_numso * sizeof (DL_SODATA));
+      _dl_numso  *= 2;
+      _dl_sotable = new_so;
+    }
+
+  /* See if this is syscall (look for /unix in file).  */
+  if (strcmp ("/unix", file) == 0)
+    {
+      _dl_sotable[entry].index = dl_info[1].dlinfo_index;
+      _dl_sotable[entry].dataorg = dl_info[1].dlinfo_dataorg;
+      _dl_sotable[entry].handle = handle;
+      _dl_sotable[entry].type = DL_UNIX_SYSCALL;
+    }
+  else
+    {
+      _dl_sotable[entry].index = dl_info[1].dlinfo_index;
+      _dl_sotable[entry].dataorg = dl_info[1].dlinfo_dataorg;
+      _dl_sotable[entry].handle = handle;
+      _dl_sotable[entry].type = DL_GETSYM;
+    }
+
+  free (dl_info);
+  return (void *) entry;
 }
diff --git a/sysdeps/unix/sysv/aix/dl-sym.c b/sysdeps/unix/sysv/aix/dl-sym.c
index 7e10ba10b0..642c2e2ad4 100644
--- a/sysdeps/unix/sysv/aix/dl-sym.c
+++ b/sysdeps/unix/sysv/aix/dl-sym.c
@@ -1,9 +1,58 @@
-/* XXX The implementation of dlopen should somehow use the __loadx system
-   call but how?  */
+/* Copyright (C) 2001 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.  */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
 #include <dlfcn.h>
+#include <dlldr.h>
+
+extern int _dl_numso;
+extern DL_SODATA *_dl_sotable;
 
 void *
-__libc_dlsym (void *handle, const char *name)
+_dl_sym (void *handle, const char *symbol, void *who)
 {
-  return (void *) 0;
+  void *rt_function;
+
+  if ((int) handle < 0 || (int) handle >= _dl_numso || _dl_sotable == NULL)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  switch (_dl_sotable[(int) handle].type)
+    {
+    case DL_UNIX_SYSCALL:
+      rt_function = (void *) __loadx (DL_UNIX_SYSCALL, (void *) symbol);
+      break;
+
+    case DL_GETSYM:
+      rt_function = (void *) __loadx (DL_GETSYM, (void *) symbol,
+				      _dl_sotable[(int) handle].index,
+				      _dl_sotable[(int) handle].dataorg);
+      break;
+
+    default:
+      errno = EINVAL;
+      return NULL;
+    }
+
+  return rt_function;
 }
diff --git a/sysdeps/unix/sysv/aix/dlldr.h b/sysdeps/unix/sysv/aix/dlldr.h
new file mode 100644
index 0000000000..d729244c52
--- /dev/null
+++ b/sysdeps/unix/sysv/aix/dlldr.h
@@ -0,0 +1,112 @@
+/* Copyright (C) 2001 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.
+*/
+
+
+/*
+
+ int __loadx(flag, module, arg1, arg2, arg3)
+
+ The __loadx() is a call to ld_loadutil() kernel function, which 
+ does the real work. Note ld_loadutil() is not exported an cannot be
+ called directly from user space.
+
+ void *ld_loadutil() call is a utility function used for loader extensions
+ supporting run-time linking and dl*() functions.
+
+ void *   - will return the modules entry point if it succeds of NULL
+                on failure.
+
+ int flag - the flag field performas a dual role: the top 8 bits specify
+            the work for __loadx() to perform, the bottom 8 bits are
+            used to pass flags to the work routines, all other bits are
+            reserved.
+
+*/
+
+#define DL_LOAD       0x1000000 /* __loadx(flag,buf, buf_len, filename, libr_path) */
+#define DL_POSTLOADQ  0x2000000 /* __loadx(flag,buf, buf_len, module_handle) */
+#define DL_EXECQ      0x3000000 /* __loadx(flag,buf, buf_len) */
+#define DL_EXITQ      0x4000000 /* __loadx(flag,buf, buf_len) */
+#define DL_PREUNLOADQ 0x5000000 /* __loadx(flag,buf, buf_len, module_handle) */
+#define DL_INIT       0x6000000 /* __loadx(flag,NULL) */
+#define DL_GETSYM     0x7000000 /* __loadx(flag,symbol, index, modules_data_origin) */
+#define DL_SETDEPEND  0x8000000 /* __loadx(flag,import_data_org, import_index, */
+                                /*              export_data_org, export_index) */
+#define DL_DELDEPEND  0x9000000 /* __loadx(flag,import_data_org, import_index, */
+                                /*              export_data_org, export_index) */
+#define DL_GLOBALSYM  0xA000000 /* __loadx(flag,symbol_name, ptr_to_rec_index, */
+                                /*                        ptr_to_rec_data_org) */
+#define DL_UNIX_SYSCALL 0xB000000 /* __loadx(flag,syscall_symbol_name) */
+
+#define DL_FUNCTION_MASK 0xFF000000
+#define DL_SRCHDEPENDS   0x00100000
+#define DL_SRCHMODULE    0x00080000
+#define DL_SRCHLOADLIST  0x00040000
+#define DL_LOAD_LDX1     0x00040000
+#define DL_LOAD_RTL      0x00020000
+#define DL_HASHSTRING    0x00020000
+#define DL_INFO_OK       0x00010000
+#define DL_LOAD_DLINFO   0x00010000
+#define DL_UNLOADED      0x00020000
+
+typedef union _dl_info
+{
+  struct {
+           uint      _xflags;   /* flag bits in the array         */
+           uint      _size;     /* size of this structure         */
+           uint      _arraylen; /* number of following elements   */
+         } _dl_stat;
+  struct {
+           caddr_t   _textorg;  /* start of loaded program image  */
+           caddr_t   _dataorg;  /* start of data instance         */
+           uint      _datasize; /* size of data instance          */
+           ushort    _index;    /* index of this le in la_dynlist */
+           ushort    _mflags;   /* info about module from load()  */
+         } _dl_array;
+} DL_INFO;
+
+#define dlinfo_xflags   _dl_stat._xflags
+#define dlinfo_arraylen _dl_stat._arraylen
+#define dlinfo_size     _dl_stat._size
+
+#define dlinfo_textorg  _dl_array._textorg
+#define dlinfo_datasize _dl_array._datasize
+#define dlinfo_dataorg  _dl_array._dataorg
+#define dlinfo_index    _dl_array._index
+#define dlinfo_flags    _dl_array._mflags
+
+#define DL_HAS_RTINIT  0x1  /* indicates the module __rtinit symbols */
+#define DL_IS_NEW      0x2  /* indicates that the module is newly loaded */
+
+struct _xArgs
+{
+   char    *libpath;
+   DL_INFO *info;
+   uint     infosize;
+};
+
+/* Shared Object DATA used for dl-open,dl-sym & dl-close support */
+typedef struct
+{
+  void   *handle;         /* handle for __loadx    */
+  uint    type;           /* type of __loadx flag  */
+  ushort  index;          /* dlinfo_index          */
+  caddr_t dataorg;        /* dlinfo_dataorg        */
+} DL_SODATA;
+
diff --git a/sysdeps/unix/sysv/aix/getpeername.c b/sysdeps/unix/sysv/aix/getpeername.c
index d227e286cd..82a9941ebf 100644
--- a/sysdeps/unix/sysv/aix/getpeername.c
+++ b/sysdeps/unix/sysv/aix/getpeername.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001 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
@@ -25,3 +25,4 @@ getpeername (int fd, __SOCKADDR_ARG addr, socklen_t *len)
 {
   return ngetpeername (fd, addr.__sockaddr__, len);
 }
+weak_alias (getpeername,__getpeername)
diff --git a/sysdeps/unix/sysv/aix/gettimeofday.c b/sysdeps/unix/sysv/aix/gettimeofday.c
new file mode 100644
index 0000000000..6b5bd48085
--- /dev/null
+++ b/sysdeps/unix/sysv/aix/gettimeofday.c
@@ -0,0 +1,94 @@
+/* Copyright (C) 1991, 92, 94, 95, 96, 97 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.  */
+
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+
+#ifndef HAVE_GNU_LD
+#define __daylight	daylight
+#define __timezone	timezone
+#define __tzname	tzname
+#endif
+
+/* Assembler Routines to access the timer registers */
+asm("
+.rtc_upper: mfspr   3,4         # copy RTCU to return register
+            blr
+
+.rtc_lower: mfspr   3,5         # copy RTCL to return register
+            blr
+");
+
+/* Get the current time of day and timezone information,
+   putting it into *TV and *TZ.  If TZ is NULL, *TZ is not filled.
+   Returns 0 on success, -1 on errors.  */
+int
+__gettimeofday (tv, tz)
+     struct timeval  *tv;
+     struct timezone *tz;
+{
+  int ts, tl, tu;
+
+  if (tv == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  ts = rtc_upper();      /* seconds                         */
+  tl = rtc_lower();      /* nanoseconds                     */
+  tu = rtc_upper();      /* Check for a carry from          */
+  if (ts != tu)          /* the lower reg to the upper      */
+      tl  = rtc_lower(); /* Recover from the race condition */
+
+  tv->tv_sec  = (long int) (tu + (double)tl/1000000000); 
+  tv->tv_usec = (long int) ((double)tl/1000);
+
+#if 0
+  if (tz != NULL)
+    {
+      const  time_t timer = tv->tv_sec;
+      struct tm tm;
+      const  struct tm *tmp;
+
+      const long int save_timezone = __timezone;
+      const long int save_daylight = __daylight;
+      char *save_tzname[2];
+      save_tzname[0] = __tzname[0];
+      save_tzname[1] = __tzname[1];
+
+      tmp = localtime_r (&timer, &tm);
+
+      tz->tz_minuteswest = __timezone / 60;
+      tz->tz_dsttime     = __daylight;
+
+      __timezone  = save_timezone;
+      __daylight  = save_daylight;
+      __tzname[0] = save_tzname[0];
+      __tzname[1] = save_tzname[1];
+
+      if (tmp == NULL)
+	return -1;
+    }
+#endif
+
+  return 0;
+}
+
+weak_alias (__gettimeofday, gettimeofday)
diff --git a/sysdeps/unix/sysv/aix/libc-start.c b/sysdeps/unix/sysv/aix/libc-start.c
index f7eb65e8b4..2dfc0251ba 100644
--- a/sysdeps/unix/sysv/aix/libc-start.c
+++ b/sysdeps/unix/sysv/aix/libc-start.c
@@ -1,20 +1 @@
-/* We don't need the usual code since we are using the AIX crt code.  */
-
-/* This function is called in the AIX crt0.  */
-void
-__mod_init (void)
-{
-  /* XXX What has to be done?  */
-}
-
-/* This variable is reference in the AIX crt0 code.
-   XXX Since I don't know how it is used make it a pointer to a function.  */
-void *__crt0v = __mod_init;
-
-
-/* XXX Another weird function from the C library.  I have no idea what
-   it does but it is needed by libgcc.  */
-void
-_savef14 (void)
-{
-}
+/* stub libc-start.c */
diff --git a/sysdeps/unix/sysv/aix/powerpc/memset.c b/sysdeps/unix/sysv/aix/powerpc/memset.c
new file mode 100644
index 0000000000..ef04283430
--- /dev/null
+++ b/sysdeps/unix/sysv/aix/powerpc/memset.c
@@ -0,0 +1,21 @@
+/* Copyright (C) 2001 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.  */
+
+
+/* Until the cache line issues are resolved use the generic implementation.  */
+#include <sysdeps/generic/memset.c>
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);
+}
+
diff --git a/sysdeps/unix/sysv/aix/utmpx.h b/sysdeps/unix/sysv/aix/utmpx.h
new file mode 100644
index 0000000000..f7a7a3eeb0
--- /dev/null
+++ b/sysdeps/unix/sysv/aix/utmpx.h
@@ -0,0 +1,89 @@
+/* Copyright (C) 1997, 1998, 1999 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.  */
+
+#ifndef	_UTMPX_H
+#define	_UTMPX_H	1
+
+#include <features.h>
+#include <sys/time.h>
+
+/* Required according to Unix98.  */
+#ifndef __pid_t_defined
+typedef __pid_t pid_t;
+# define __pid_t_defined
+#endif
+
+/* Get system dependent values and data structures.  */
+#include <bits/utmpx.h>
+
+#ifdef __USE_GNU
+/* Compatibility names for the strings of the canonical file names.  */
+# define UTMPX_FILE	_PATH_UTMPX
+# define UTMPX_FILENAME	_PATH_UTMPX
+# define WTMPX_FILE	_PATH_WTMPX
+# define WTMPX_FILENAME	_PATH_WTMPX
+#endif
+
+/* For the getutmp{,x} functions we need the `struct utmp'.  */
+#ifdef __USE_GNU
+struct utmp;
+#endif
+
+
+__BEGIN_DECLS
+
+/* Open user accounting database.  */
+extern void setutxent (void) __THROW;
+
+/* Close user accounting database.  */
+extern void endutxent (void) __THROW;
+
+/* Get the next entry from the user accounting database.  */
+extern struct utmpx *getutxent (void) __THROW;
+
+/* Get the user accounting database entry corresponding to ID.  */
+extern struct utmpx *getutxid (__const struct utmpx *__id) __THROW;
+
+/* Get the user accounting database entry corresponding to LINE.  */
+extern struct utmpx *getutxline (__const struct utmpx *__line) __THROW;
+
+/* Write the entry UTMPX into the user accounting database.  */
+extern struct utmpx *pututxline (__const struct utmpx *__utmpx) __THROW;
+
+
+#ifdef __USE_GNU
+/* Change name of the utmpx file to be examined.  */
+extern int utmpxname (__const char *__file) __THROW;
+
+/* Append entry UTMP to the wtmpx-like file WTMPX_FILE.  */
+extern void updwtmpx (__const char *__wtmpx_file,
+		      __const struct utmpx *__utmpx) __THROW;
+
+
+/* Copy the information in UTMPX to UTMP. */
+extern void getutmp (__const struct utmpx *__utmpx,
+		     struct utmp *__utmp) __THROW;
+
+/* Copy the information in UTMP to UTMPX. */
+extern void getutmpx (__const struct utmp *__utmp,
+		      struct utmpx *__utmpx) __THROW;
+#endif
+
+__END_DECLS
+
+#endif /* utmpx.h  */