.
[glibc-ports.git] / sysdeps / unix / sysv / aix / dl-open.c
blob070471d51329a9df876374b61b7dab58de7dd3fe
1 /* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
19 #include <malloc.h>
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <errno.h>
24 #include <dlfcn.h>
25 #include <dlldr.h>
27 #define NUM_SHARED_OBJECTS 32
29 int _dl_numso = NUM_SHARED_OBJECTS;
30 DL_SODATA *_dl_sotable = NULL;
32 void *
33 _dl_open (const char *file, int mode, const void *caller)
35 DL_SODATA *new_so;
36 void *handle;
37 int entry;
38 int bsize = _dl_numso * sizeof (DL_INFO);
39 DL_INFO *dl_info = malloc (bsize);
41 if (dl_info == NULL)
42 return NULL;
44 /* 1st time thru initial shared object data table. */
45 if (_dl_sotable == NULL)
47 _dl_sotable = (DL_SODATA *) calloc (_dl_numso, sizeof (DL_SODATA));
48 if (_dl_sotable == NULL)
49 return NULL;
51 __loadx (DL_POSTLOADQ, dl_info, bsize, NULL);
52 while (!(dl_info[0].dlinfo_xflags & DL_INFO_OK)
53 || dl_info[0].dlinfo_arraylen == 0)
55 bsize *= 2;
56 dl_info = realloc (dl_info, bsize);
57 if (dl_info == NULL)
58 return NULL;
60 __loadx (DL_POSTLOADQ, dl_info, bsize, NULL);
64 /* Validate mode bits. */
65 if (!(mode & RTLD_NOW) && !(mode & RTLD_LAZY))
67 free (dl_info);
68 errno = EINVAL;
69 return NULL;
72 /* Load the module. */
73 handle = (void *) __loadx (DL_LOAD | DL_LOAD_RTL | DL_LOAD_LDX1,
74 dl_info, bsize, file, NULL);
75 if (handle == NULL)
77 free (dl_info);
78 errno = EINVAL;
79 return NULL;
82 /* Was dl_info buffer to small to get info. */
83 while (!(dl_info[0].dlinfo_xflags & DL_INFO_OK)
84 || dl_info[0].dlinfo_arraylen == 0)
86 bsize *= 2;
87 dl_info = realloc (dl_info, bsize);
88 if (dl_info == NULL)
90 (void) __unload ((void *) handle);
91 errno = ENOMEM;
92 return NULL;
94 __loadx (DL_POSTLOADQ | DL_LOAD_RTL, dl_info, bsize, handle);
97 /* Get an empty entry in the shared object table. */
98 for (entry = 0; entry < _dl_numso; ++entry)
99 if (_dl_sotable[entry].type == 0)
100 break;
102 /* See if the table needs to be increased. */
103 if (entry == _dl_numso)
105 new_so = (DL_SODATA *) realloc (_dl_sotable,
106 _dl_numso * 2 * sizeof (DL_SODATA));
107 if (new_so == NULL)
108 return NULL;
110 memset (new_so + _dl_numso, '\0', _dl_numso * sizeof (DL_SODATA));
111 _dl_numso *= 2;
112 _dl_sotable = new_so;
115 /* See if this is syscall (look for /unix in file). */
116 if (strcmp ("/unix", file) == 0)
118 _dl_sotable[entry].index = dl_info[1].dlinfo_index;
119 _dl_sotable[entry].dataorg = dl_info[1].dlinfo_dataorg;
120 _dl_sotable[entry].handle = handle;
121 _dl_sotable[entry].type = DL_UNIX_SYSCALL;
123 else
125 _dl_sotable[entry].index = dl_info[1].dlinfo_index;
126 _dl_sotable[entry].dataorg = dl_info[1].dlinfo_dataorg;
127 _dl_sotable[entry].handle = handle;
128 _dl_sotable[entry].type = DL_GETSYM;
131 free (dl_info);
132 return (void *) entry;