Annotation of parser3/src/lib/ltdl/loaders/dlopen.c, revision 1.2
1.1 moko 1: /* loader-dlopen.c -- dynamic linking with dlopen/dlsym
2:
1.2 ! moko 3: Copyright (C) 1998-2000, 2004, 2006-2008, 2011-2019, 2021-2024 Free
! 4: Software Foundation, Inc.
1.1 moko 5: Written by Thomas Tanner, 1998
6:
7: NOTE: The canonical source of this file is maintained with the
8: GNU Libtool package. Report bugs to bug-libtool@gnu.org.
9:
10: GNU Libltdl is free software; you can redistribute it and/or
11: modify it under the terms of the GNU Lesser General Public
12: License as published by the Free Software Foundation; either
13: version 2 of the License, or (at your option) any later version.
14:
15: As a special exception to the GNU Lesser General Public License,
16: if you distribute this file as part of a program or library that
17: is built using GNU Libtool, you may include this file under the
18: same distribution terms that you use for the rest of that program.
19:
20: GNU Libltdl is distributed in the hope that it will be useful,
21: but WITHOUT ANY WARRANTY; without even the implied warranty of
22: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23: GNU Lesser General Public License for more details.
24:
25: You should have received a copy of the GNU Lesser General Public
1.2 ! moko 26: License along with GNU Libltdl. If not, see <https://www.gnu.org/licenses/>.
1.1 moko 27: */
28:
29: #include "lt__private.h"
30: #include "lt_dlloader.h"
31:
32: /* Use the preprocessor to rename non-static symbols to avoid namespace
33: collisions when the loader code is statically linked into libltdl.
34: Use the "<module_name>_LTX_" prefix so that the symbol addresses can
35: be fetched from the preloaded symbol list by lt_dlsym(): */
36: #define get_vtable dlopen_LTX_get_vtable
37:
38: LT_BEGIN_C_DECLS
39: LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
40: LT_END_C_DECLS
41:
42:
43: /* Boilerplate code to set up the vtable for hooking this loader into
44: libltdl's loader list: */
45: static int vl_exit (lt_user_data loader_data);
46: static lt_module vm_open (lt_user_data loader_data, const char *filename,
47: lt_dladvise advise);
48: static int vm_close (lt_user_data loader_data, lt_module module);
49: static void * vm_sym (lt_user_data loader_data, lt_module module,
50: const char *symbolname);
51:
52: static lt_dlvtable *vtable = 0;
53:
54: /* Return the vtable for this loader, only the name and sym_prefix
55: attributes (plus the virtual function implementations, obviously)
56: change between loaders. */
57: lt_dlvtable *
58: get_vtable (lt_user_data loader_data)
59: {
60: if (!vtable)
61: {
62: vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable);
63: }
64:
65: if (vtable && !vtable->name)
66: {
67: vtable->name = "lt_dlopen";
1.2 ! moko 68: #if defined DLSYM_USCORE
1.1 moko 69: vtable->sym_prefix = "_";
70: #endif
71: vtable->module_open = vm_open;
72: vtable->module_close = vm_close;
73: vtable->find_sym = vm_sym;
74: vtable->dlloader_exit = vl_exit;
75: vtable->dlloader_data = loader_data;
76: vtable->priority = LT_DLLOADER_PREPEND;
77: }
78:
79: if (vtable && (vtable->dlloader_data != loader_data))
80: {
81: LT__SETERROR (INIT_LOADER);
82: return 0;
83: }
84:
85: return vtable;
86: }
87:
88:
89:
90: /* --- IMPLEMENTATION --- */
91:
92:
1.2 ! moko 93: #if defined HAVE_DLFCN_H
1.1 moko 94: # include <dlfcn.h>
95: #endif
96:
1.2 ! moko 97: #if defined HAVE_SYS_DL_H
1.1 moko 98: # include <sys/dl.h>
99: #endif
100:
101:
102: /* We may have to define LT_LAZY_OR_NOW in the command line if we
103: find out it does not work in some platform. */
1.2 ! moko 104: #if !defined LT_LAZY_OR_NOW
! 105: # if defined RTLD_LAZY
1.1 moko 106: # define LT_LAZY_OR_NOW RTLD_LAZY
107: # else
1.2 ! moko 108: # if defined DL_LAZY
1.1 moko 109: # define LT_LAZY_OR_NOW DL_LAZY
110: # endif
111: # endif /* !RTLD_LAZY */
112: #endif
1.2 ! moko 113: #if !defined LT_LAZY_OR_NOW
! 114: # if defined RTLD_NOW
1.1 moko 115: # define LT_LAZY_OR_NOW RTLD_NOW
116: # else
1.2 ! moko 117: # if defined DL_NOW
1.1 moko 118: # define LT_LAZY_OR_NOW DL_NOW
119: # endif
120: # endif /* !RTLD_NOW */
121: #endif
1.2 ! moko 122: #if !defined LT_LAZY_OR_NOW
1.1 moko 123: # define LT_LAZY_OR_NOW 0
124: #endif /* !LT_LAZY_OR_NOW */
125:
126: /* We only support local and global symbols from modules for loaders
127: that provide such a thing, otherwise the system default is used. */
1.2 ! moko 128: #if !defined RTLD_GLOBAL
! 129: # if defined DL_GLOBAL
1.1 moko 130: # define RTLD_GLOBAL DL_GLOBAL
131: # endif
132: #endif /* !RTLD_GLOBAL */
1.2 ! moko 133: #if !defined RTLD_LOCAL
! 134: # if defined DL_LOCAL
1.1 moko 135: # define RTLD_LOCAL DL_LOCAL
136: # endif
137: #endif /* !RTLD_LOCAL */
138:
1.2 ! moko 139: #if defined HAVE_DLERROR
1.1 moko 140: # define DLERROR(arg) dlerror ()
141: #else
142: # define DLERROR(arg) LT__STRERROR (arg)
143: #endif
144:
145: #define DL__SETERROR(errorcode) \
146: LT__SETERRORSTR (DLERROR (errorcode))
147:
148:
149: /* A function called through the vtable when this loader is no
150: longer needed by the application. */
151: static int
1.2 ! moko 152: vl_exit (lt_user_data loader_data LT__UNUSED)
1.1 moko 153: {
154: vtable = NULL;
155: return 0;
156: }
157:
158:
159: /* A function called through the vtable to open a module with this
160: loader. Returns an opaque representation of the newly opened
161: module for processing with this loader's other vtable functions. */
162: static lt_module
1.2 ! moko 163: vm_open (lt_user_data loader_data LT__UNUSED, const char *filename,
1.1 moko 164: lt_dladvise advise)
165: {
166: int module_flags = LT_LAZY_OR_NOW;
167: lt_module module;
1.2 ! moko 168: #ifdef RTLD_MEMBER
! 169: int len = LT_STRLEN (filename);
! 170: #endif
1.1 moko 171:
172: if (advise)
173: {
174: #ifdef RTLD_GLOBAL
175: /* If there is some means of asking for global symbol resolution,
176: do so. */
177: if (advise->is_symglobal)
178: module_flags |= RTLD_GLOBAL;
179: #else
180: /* Otherwise, reset that bit so the caller can tell it wasn't
181: acted on. */
182: advise->is_symglobal = 0;
183: #endif
184:
185: /* And similarly for local only symbol resolution. */
186: #ifdef RTLD_LOCAL
187: if (advise->is_symlocal)
188: module_flags |= RTLD_LOCAL;
189: #else
190: advise->is_symlocal = 0;
191: #endif
192: }
193:
1.2 ! moko 194: #ifdef RTLD_MEMBER /* AIX */
! 195: if (len >= 4) /* at least "l(m)" */
! 196: {
! 197: /* Advise loading an archive member only if the filename really
! 198: contains both the opening and closing parent, and a member. */
! 199: if (filename[len-1] == ')')
! 200: {
! 201: const char *opening = strrchr(filename, '(');
! 202: if (opening && opening < (filename+len-2) && strchr(opening+1, '/') == NULL)
! 203: module_flags |= RTLD_MEMBER;
! 204: }
! 205: }
! 206: #endif
! 207:
1.1 moko 208: module = dlopen (filename, module_flags);
209:
1.2 ! moko 210: #if defined RTLD_MEMBER && defined LT_SHARED_LIB_MEMBER
! 211: if (!module && len && !(module_flags & RTLD_MEMBER) && errno == ENOEXEC)
! 212: {
! 213: /* Loading without a member specified failed with "Exec format error".
! 214: So the file is there, but either has wrong bitwidth, or is an
! 215: archive eventually containing the default shared archive member.
! 216: Retry with default member, getting same error in worst case. */
! 217: const char *member = LT_SHARED_LIB_MEMBER;
! 218:
! 219: char *attempt = MALLOC (char, len + strlen (member) + 1);
! 220: if (!attempt)
! 221: {
! 222: LT__SETERROR (NO_MEMORY);
! 223: return module;
! 224: }
! 225:
! 226: sprintf (attempt, "%s%s", filename, member);
! 227: module = vm_open (loader_data, attempt, advise);
! 228: FREE (attempt);
! 229: return module;
! 230: }
! 231: #endif
! 232:
1.1 moko 233: if (!module)
234: {
235: DL__SETERROR (CANNOT_OPEN);
236: }
237:
238: return module;
239: }
240:
241:
242: /* A function called through the vtable when a particular module
243: should be unloaded. */
244: static int
1.2 ! moko 245: vm_close (lt_user_data loader_data LT__UNUSED, lt_module module)
1.1 moko 246: {
247: int errors = 0;
248:
249: if (dlclose (module) != 0)
250: {
251: DL__SETERROR (CANNOT_CLOSE);
252: ++errors;
253: }
254:
255: return errors;
256: }
257:
258:
259: /* A function called through the vtable to get the address of
260: a symbol loaded from a particular module. */
261: static void *
1.2 ! moko 262: vm_sym (lt_user_data loader_data LT__UNUSED, lt_module module, const char *name)
1.1 moko 263: {
264: void *address = dlsym (module, name);
265:
266: if (!address)
267: {
268: DL__SETERROR (SYMBOL_NOT_FOUND);
269: }
270:
271: return address;
272: }
E-mail: