Annotation of parser3/src/lib/ltdl/loaders/preopen.c, revision 1.2

1.1       moko        1: /* loader-preopen.c -- emulate dynamic linking using preloaded_symbols
                      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     preopen_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_init  (lt_user_data loader_data);
                     46: static int      vl_exit  (lt_user_data loader_data);
                     47: static lt_module vm_open  (lt_user_data loader_data, const char *filename,
                     48:                            lt_dladvise advise);
                     49: static int      vm_close (lt_user_data loader_data, lt_module module);
                     50: static void *   vm_sym   (lt_user_data loader_data, lt_module module,
                     51:                          const char *symbolname);
                     52: 
                     53: static lt_dlvtable *vtable = 0;
                     54: 
                     55: /* Return the vtable for this loader, only the name and sym_prefix
                     56:    attributes (plus the virtual function implementations, obviously)
                     57:    change between loaders.  */
                     58: lt_dlvtable *
                     59: get_vtable (lt_user_data loader_data)
                     60: {
                     61:   if (!vtable)
                     62:     {
                     63:       vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable);
                     64:     }
                     65: 
                     66:   if (vtable && !vtable->name)
                     67:     {
                     68:       vtable->name             = "lt_preopen";
                     69:       vtable->sym_prefix       = 0;
                     70:       vtable->module_open      = vm_open;
                     71:       vtable->module_close     = vm_close;
                     72:       vtable->find_sym         = vm_sym;
                     73:       vtable->dlloader_init    = vl_init;
                     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: 
                     93: /* Wrapper type to chain together symbol lists of various origins.  */
                     94: typedef struct symlist_chain
                     95: {
                     96:   struct symlist_chain *next;
                     97:   const lt_dlsymlist   *symlist;
                     98: } symlist_chain;
                     99: 
                    100: 
                    101: static int add_symlist   (const lt_dlsymlist *symlist);
                    102: static int free_symlists (void);
                    103: 
                    104: /* The start of the symbol lists chain.  */
                    105: static symlist_chain          *preloaded_symlists              = 0;
                    106: 
                    107: /* A symbol list preloaded before lt_init() was called.  */
                    108: static const   lt_dlsymlist   *default_preloaded_symbols       = 0;
                    109: 
                    110: 
                    111: /* A function called through the vtable to initialise this loader.  */
                    112: static int
1.2     ! moko      113: vl_init (lt_user_data loader_data LT__UNUSED)
1.1       moko      114: {
                    115:   int errors = 0;
                    116: 
                    117:   preloaded_symlists = 0;
                    118:   if (default_preloaded_symbols)
                    119:     {
                    120:       errors = lt_dlpreload (default_preloaded_symbols);
                    121:     }
                    122: 
                    123:   return errors;
                    124: }
                    125: 
                    126: 
                    127: /* A function called through the vtable when this loader is no
                    128:    longer needed by the application.  */
                    129: static int
1.2     ! moko      130: vl_exit (lt_user_data loader_data LT__UNUSED)
1.1       moko      131: {
                    132:   vtable = NULL;
                    133:   free_symlists ();
                    134:   return 0;
                    135: }
                    136: 
                    137: 
                    138: /* A function called through the vtable to open a module with this
                    139:    loader.  Returns an opaque representation of the newly opened
                    140:    module for processing with this loader's other vtable functions.  */
                    141: static lt_module
1.2     ! moko      142: vm_open (lt_user_data loader_data LT__UNUSED, const char *filename,
        !           143:          lt_dladvise advise LT__UNUSED)
1.1       moko      144: {
                    145:   symlist_chain *lists;
                    146:   lt_module     module = 0;
                    147: 
                    148:   if (!preloaded_symlists)
                    149:     {
                    150:       LT__SETERROR (NO_SYMBOLS);
                    151:       goto done;
                    152:     }
                    153: 
                    154:   /* Can't use NULL as the reflective symbol header, as NULL is
                    155:      used to mark the end of the entire symbol list.  Self-dlpreopened
                    156:      symbols follow this magic number, chosen to be an unlikely
                    157:      clash with a real module name.  */
                    158:   if (!filename)
                    159:     {
                    160:       filename = "@PROGRAM@";
                    161:     }
                    162: 
                    163:   for (lists = preloaded_symlists; lists; lists = lists->next)
                    164:     {
                    165:       const lt_dlsymlist *symbol;
                    166:       for (symbol= lists->symlist; symbol->name; ++symbol)
                    167:        {
1.2     ! moko      168:          if (!symbol->address && STREQ (symbol->name, filename))
1.1       moko      169:            {
                    170:              /* If the next symbol's name and address is 0, it means
                    171:                 the module just contains the originator and no symbols.
                    172:                 In this case we pretend that we never saw the module and
                    173:                 hope that some other loader will be able to load the module
                    174:                 and have access to its symbols */
                    175:              const lt_dlsymlist *next_symbol = symbol +1;
                    176:              if (next_symbol->address && next_symbol->name)
                    177:                {
                    178:                  module = (lt_module) lists->symlist;
                    179:                  goto done;
                    180:                }
                    181:            }
                    182:        }
                    183:     }
                    184: 
                    185:   LT__SETERROR (FILE_NOT_FOUND);
                    186: 
                    187:  done:
                    188:   return module;
                    189: }
                    190: 
                    191: 
                    192: /* A function called through the vtable when a particular module
                    193:    should be unloaded.  */
                    194: static int
1.2     ! moko      195: vm_close (lt_user_data loader_data LT__UNUSED, lt_module module LT__UNUSED)
1.1       moko      196: {
                    197:   /* Just to silence gcc -Wall */
                    198:   module = 0;
                    199:   return 0;
                    200: }
                    201: 
                    202: 
                    203: /* A function called through the vtable to get the address of
                    204:    a symbol loaded from a particular module.  */
                    205: static void *
1.2     ! moko      206: vm_sym (lt_user_data loader_data LT__UNUSED, lt_module module, const char *name)
1.1       moko      207: {
                    208:   lt_dlsymlist        *symbol = (lt_dlsymlist*) module;
                    209: 
1.2     ! moko      210:   if (symbol[1].name && STREQ (symbol[1].name, "@INIT@"))
        !           211:     {
        !           212:       symbol++;                        /* Skip optional init entry. */
        !           213:     }
        !           214: 
1.1       moko      215:   symbol +=2;                  /* Skip header (originator then libname). */
                    216: 
                    217:   while (symbol->name)
                    218:     {
1.2     ! moko      219:       if (STREQ (symbol->name, name))
1.1       moko      220:        {
                    221:          return symbol->address;
                    222:        }
                    223: 
                    224:     ++symbol;
                    225:   }
                    226: 
                    227:   LT__SETERROR (SYMBOL_NOT_FOUND);
                    228: 
                    229:   return 0;
                    230: }
                    231: 
                    232: 
                    233: 
                    234: /* --- HELPER FUNCTIONS --- */
                    235: 
                    236: 
                    237: /* The symbol lists themselves are not allocated from the heap, but
                    238:    we can unhook them and free up the chain of links between them.  */
                    239: static int
                    240: free_symlists (void)
                    241: {
                    242:   symlist_chain *lists;
                    243: 
                    244:   lists = preloaded_symlists;
                    245:   while (lists)
                    246:     {
                    247:       symlist_chain *next = lists->next;
                    248:       FREE (lists);
                    249:       lists = next;
                    250:     }
                    251:   preloaded_symlists = 0;
                    252: 
                    253:   return 0;
                    254: }
                    255: 
                    256: /* Add a new symbol list to the global chain.  */
                    257: static int
                    258: add_symlist (const lt_dlsymlist *symlist)
                    259: {
                    260:   symlist_chain *lists;
                    261:   int           errors   = 0;
                    262: 
                    263:   /* Search for duplicate entries:  */
                    264:   for (lists = preloaded_symlists;
                    265:        lists && lists->symlist != symlist; lists = lists->next)
                    266:     /*NOWORK*/;
                    267: 
                    268:   /* Don't add the same list twice:  */
                    269:   if (!lists)
                    270:     {
                    271:       symlist_chain *tmp = (symlist_chain *) lt__zalloc (sizeof *tmp);
                    272: 
                    273:       if (tmp)
                    274:        {
                    275:          tmp->symlist = symlist;
                    276:          tmp->next = preloaded_symlists;
                    277:          preloaded_symlists = tmp;
1.2     ! moko      278: 
        !           279:          if (symlist[1].name && STREQ (symlist[1].name, "@INIT@"))
        !           280:            {
        !           281:              void (*init_symlist)(void);
        !           282:              *(void **)(&init_symlist) = symlist[1].address;
        !           283:              (*init_symlist)();
        !           284:            }
1.1       moko      285:        }
                    286:       else
                    287:        {
                    288:          ++errors;
                    289:        }
                    290:     }
                    291: 
                    292:   return errors;
                    293: }
                    294: 
                    295: 
                    296: 
                    297: /* --- PRELOADING API CALL IMPLEMENTATIONS --- */
                    298: 
                    299: 
                    300: /* Save a default symbol list for later.  */
                    301: int
                    302: lt_dlpreload_default (const lt_dlsymlist *preloaded)
                    303: {
                    304:   default_preloaded_symbols = preloaded;
                    305:   return 0;
                    306: }
                    307: 
                    308: 
                    309: /* Add a symbol list to the global chain, or with a NULL argument,
                    310:    revert to just the default list.  */
                    311: int
                    312: lt_dlpreload (const lt_dlsymlist *preloaded)
                    313: {
                    314:   int errors = 0;
                    315: 
                    316:   if (preloaded)
                    317:     {
                    318:       errors = add_symlist (preloaded);
                    319:     }
                    320:   else
                    321:     {
                    322:       free_symlists();
                    323: 
                    324:       if (default_preloaded_symbols)
                    325:        {
                    326:          errors = lt_dlpreload (default_preloaded_symbols);
                    327:        }
                    328:     }
                    329: 
                    330:   return errors;
                    331: }
                    332: 
                    333: 
                    334: /* Open all the preloaded modules from the named originator, executing
                    335:    a callback for each one.  If ORIGINATOR is NULL, then call FUNC for
                    336:    each preloaded module from the program itself.  */
                    337: int
                    338: lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func)
                    339: {
                    340:   symlist_chain *list;
                    341:   int           errors = 0;
                    342:   int           found  = 0;
                    343: 
                    344:   /* For each symlist in the chain...  */
                    345:   for (list = preloaded_symlists; list; list = list->next)
                    346:     {
                    347:       /* ...that was preloaded by the requesting ORIGINATOR... */
1.2     ! moko      348:       if ((originator && STREQ (list->symlist->name, originator))
        !           349:           || (!originator && STREQ (list->symlist->name, "@PROGRAM@")))
1.1       moko      350:        {
                    351:          const lt_dlsymlist *symbol;
                    352:          unsigned int idx = 0;
                    353: 
                    354:          ++found;
                    355: 
                    356:          /* ...load the symbols per source compilation unit:
                    357:             (we preincrement the index to skip over the originator entry)  */
                    358:          while ((symbol = &list->symlist[++idx])->name != 0)
                    359:            {
                    360:              if ((symbol->address == 0)
1.2     ! moko      361:                  && (STRNEQ (symbol->name, "@PROGRAM@")))
1.1       moko      362:                {
                    363:                  lt_dlhandle handle = lt_dlopen (symbol->name);
                    364:                  if (handle == 0)
                    365:                    {
                    366:                      ++errors;
                    367:                    }
                    368:                  else
                    369:                    {
                    370:                      errors += (*func) (handle);
                    371:                    }
                    372:                }
                    373:            }
                    374:        }
                    375:     }
                    376: 
                    377:   if (!found)
                    378:     {
                    379:       LT__SETERROR(CANNOT_OPEN);
                    380:       ++errors;
                    381:     }
                    382: 
                    383:   return errors;
                    384: }

E-mail: