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: