| # loadlibrary.at -- test loadlibrary functionality -*- Autotest -*- |
| # |
| # Copyright (C) 2010-2019, 2021-2025 Free Software Foundation, Inc. |
| # This file is part of GNU Libtool. |
| # |
| # GNU Libtool is free software; you can redistribute it and/or |
| # modify it under the terms of the GNU General Public License as |
| # published by the Free Software Foundation; either version 2 of |
| # the License, or (at your option) any later version. |
| # |
| # GNU Libtool 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 General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with GNU Libtool. If not, see <https://www.gnu.org/licenses/>. |
| #### |
| |
| AT_SETUP([loadlibrary error messages]) |
| AT_KEYWORDS([libltdl]) |
| |
| eval "`$LIBTOOL --config | $EGREP '^(objdir)='`" |
| |
| AT_DATA([main.c], |
| [[#include <ltdl.h> |
| #include <stdio.h> |
| |
| static int |
| standard_error_message(const char *error) |
| { |
| int error_number; |
| |
| for (error_number = 0; error_number < LT_ERROR_MAX; ++error_number) |
| { |
| lt_dlseterror (error_number); |
| if (error == lt_dlerror ()) |
| { |
| return 1; |
| } |
| } |
| |
| lt_dlseterror (LT_ERROR_UNKNOWN); |
| return 0; |
| } |
| |
| int |
| main (int argc, char* argv[]) |
| { |
| int err = 0; |
| lt_dlhandle module = NULL; |
| const lt_dlvtable *loadlibrary; |
| const lt_dlvtable *preopen; |
| lt_dlloader loader = NULL; |
| lt_dlloader next; |
| const lt_dlvtable *vtable; |
| void *symbol; |
| const char *error; |
| |
| if (argc < 2) |
| { |
| fprintf (stderr, "usage: %s plugin [symbol]\n", argv[0]); |
| return 1; |
| } |
| |
| lt_dlinit (); |
| |
| loadlibrary = lt_dlloader_find ("lt_loadlibrary"); |
| if (!loadlibrary) |
| { |
| /* Skip if the loadlibrary loader isn't supported */ |
| printf ("loadlibrary loader not found\n"); |
| err = 77; |
| goto cleanup; |
| } |
| |
| preopen = lt_dlloader_find ("lt_preopen"); |
| if (!loadlibrary) |
| { |
| printf ("preopen loader not found\n"); |
| err = 2; |
| goto cleanup; |
| } |
| |
| /* Remove all loaders except the preopen and loadlibrary loaders. */ |
| while (next = lt_dlloader_next (loader)) |
| { |
| if (lt_dlloader_get (next) == loadlibrary) |
| { |
| loader = next; |
| continue; |
| } |
| |
| if (lt_dlloader_get (next) == preopen) |
| { |
| loader = next; |
| continue; |
| } |
| |
| lt_dlloader_remove (lt_dlloader_get (next)->name); |
| } |
| |
| module = lt_dlopen (argv[1]); |
| error = lt_dlerror (); |
| |
| if (module) |
| { |
| printf ("lt_dlopen: success!\n"); |
| |
| if (argc == 2) |
| { |
| /* But failure was the desired result... */ |
| printf ("expected failure\n"); |
| err = 2; |
| goto cleanup; |
| } |
| } |
| else if (argc > 2) |
| { |
| /* Didn't expect failure... */ |
| printf ("lt_dlopen: failure: %s\n", error); |
| err = 2; |
| goto cleanup; |
| } |
| else if (standard_error_message (error)) |
| { |
| /* Expected custom error message... */ |
| printf ("lt_dlopen: standard error (bad): %s\n", error); |
| err = 1; |
| goto cleanup; |
| } |
| else |
| { |
| printf ("lt_dlopen: custom error (good): %s\n", error); |
| goto cleanup; |
| } |
| |
| symbol = lt_dlsym (module, argv[2]); |
| error = lt_dlerror (); |
| |
| if (symbol) |
| { |
| printf ("lt_dlsym: success!\n"); |
| } |
| else if (standard_error_message (error)) |
| { |
| /* Expected custom failure message... */ |
| printf ("lt_dlsym: standard error (bad): %s\n", error); |
| err = 1; |
| } |
| else |
| { |
| printf ("lt_dlsym: custom error (good): %s\n", error); |
| } |
| |
| cleanup: |
| if (module) |
| { |
| lt_dlclose (module); |
| } |
| lt_dlexit (); |
| return err; |
| } |
| ]]) |
| |
| AT_DATA([foomod.c], |
| [[ |
| #ifdef __cplusplus |
| extern "C" |
| #endif |
| int foosym (void); |
| int |
| foosym (void) |
| { |
| return 0; |
| } |
| ]]) |
| |
| AT_DATA([bardep.c], |
| [[ |
| #ifdef __cplusplus |
| extern "C" |
| #endif |
| int bardep (void); |
| int |
| bardep (void) |
| { |
| return 0; |
| } |
| ]]) |
| |
| AT_DATA([barmod.c], |
| [[ |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| int bardep (void); |
| int barsym (void); |
| #ifdef __cplusplus |
| } |
| #endif |
| int |
| barsym (void) |
| { |
| return bardep (); |
| } |
| ]]) |
| |
| : ${LTDLINCL="-I$abs_top_srcdir/libltdl"} |
| : ${LIBLTDL="$abs_builddir/../libltdl/libltdlc.la"} |
| |
| # Skip this test when called from: |
| # make distcheck DISTCHECK_CONFIGURE_FLAGS=--disable-ltdl-install |
| AT_CHECK([case $LIBLTDL in #( |
| */_inst/lib/*) test -f "$LIBLTDL" || (exit 77) ;; |
| esac], [], [ignore]) |
| |
| CPPFLAGS="$LTDLINCL $CPPFLAGS" |
| inst=`pwd`/inst |
| libdir=$inst/lib |
| |
| AT_CHECK([$CC $CPPFLAGS $CFLAGS -c main.c], [], [ignore], [ignore]) |
| for file in foomod.c bardep.c barmod.c; do |
| AT_CHECK([$LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c $file], |
| [], [ignore], [ignore]) |
| done |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o foomod.la ]dnl |
| [-rpath $libdir -module -avoid-version -no-undefined ]dnl |
| [foomod.lo], |
| [], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o libbardep.la ]dnl |
| [-rpath $libdir -avoid-version -no-undefined ]dnl |
| [bardep.lo], |
| [], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o barmod.la ]dnl |
| [-rpath $libdir -module -avoid-version -no-undefined ]dnl |
| [barmod.lo ./libbardep.la], |
| [], [ignore], [ignore]) |
| |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main$EXEEXT ]dnl |
| [main.$OBJEXT $LIBLTDL], |
| [], [ignore], [ignore]) |
| |
| . ./foomod.la |
| AT_CHECK([test -n "$dlname" || (exit 77)]) |
| |
| LT_AT_EXEC_CHECK([./main], [], [ignore], [ignore], [./foomod.la no_symbol]) |
| |
| # chmod -x doesn't appear to work in MSYS, and Wine can load no-exec dlls. |
| dnl chmod -x $objdir/$dlname |
| dnl LT_AT_EXEC_CHECK([./main], [], [ignore], [ignore], [./foomod.la]) |
| |
| rm -f $objdir/$dlname |
| LT_AT_EXEC_CHECK([./main], [], [ignore], [ignore], [./foomod.la]) |
| |
| LT_AT_EXEC_CHECK([./main], [], [ignore], [ignore], [./barmod.la no_symbol]) |
| |
| . ./libbardep.la |
| # chmod -x doesn't appear to work in MSYS, and Wine can load no-exec dlls. |
| dnl chmod -x $objdir/$dlname |
| dnl LT_AT_EXEC_CHECK([./main], [], [ignore], [ignore], [./barmod.la]) |
| |
| rm -f $objdir/$dlname |
| LT_AT_EXEC_CHECK([./main], [], [ignore], [ignore], [./barmod.la]) |
| |
| AT_CLEANUP |