diff options
Diffstat (limited to 'sysdeps/unix/sysv')
-rw-r--r-- | sysdeps/unix/sysv/aix/Makefile | 8 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/bits/utmpx.h | 7 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/dl-close.c | 47 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/dl-libc.c | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/dl-open.c | 132 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/dl-sym.c | 57 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/dlldr.h | 112 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/getpeername.c | 3 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/gettimeofday.c | 94 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/libc-start.c | 21 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/powerpc/memset.c | 21 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/start.c | 290 | ||||
-rw-r--r-- | sysdeps/unix/sysv/aix/utmpx.h | 89 |
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 */ |