f49ec8c71c
to do if they cannot be found. - in try_dlopen, after find_handle() is called and returns 0 over and over, it was ignoring the return value of tryall_dlopen. As a result, sometimes the dlopen would fail and return 1 or more errors but nobody would notice. The handle would be returned as if the open had succeed, then any use of the handle would segfault because handle->loader was NULL. I have solved this problem by capturing the return value in errors, and then checking if errors>0 in the next if statement. - fix faulty boolean logic in lt_dlopenext that caused it to only search for libraries ending with .la. Now it says: if try_dlopen created a nonzero handle, return it. Otherwise, if there were any errors OTHER THAN file-not-found, return the NULL handle. If the only errors were file-not-found, continue to search. - just before loading the module in tryall_dlopen, do one final call to access() to check for existence of the file. Without this check, you sometimes get the "can't load module" error when in fact the problem is "file not found". |
||
---|---|---|
.. | ||
libltdl | ||
test1-static | ||
test2-dynamic | ||
test3-twomodules | ||
test4-interdep | ||
test5-execsymbols | ||
test6-ltdlopen | ||
test7-win32dll | ||
aclocal.m4 | ||
config.guess | ||
config.h.in | ||
config.sub | ||
configure | ||
configure.in | ||
install-sh | ||
ltmain.sh | ||
Makefile.in | ||
README |
plugin-test Bryce Denney This is a series of simple programs that test your platform for shared library support. The tests start from something trivial that should work everywhere, and gradually add one feature at a time, until at the end (not done yet) it should test all of the shared library features that Bochs needs to support plugins. test1-static: build a static library and link against it test2-dynamic: with same code, build a shared library and link against it test3-twomodules: build 2 shared libs and link against them test4-interdep: build 2 shared libs, one depends on the other, and link test5-execsymbols: can a shared lib can access a symbol from the executable? test6-ltdlopen: use ltdl library to dlopen modules, should work on many platforms, but doesn't seem to work on win32. test7-win32dll: same as test6-ltdlopen but specific to win32 DLLs Notes for win32 DLLs: *.dll.a is an import library libtool makes an import library when you link against a DLL dlltool --as=as --dllname cygmodule2-0.dll --def .libs/cygmodule2-0.dll-def --output-lib .libs/libimp-cygmodule2-0.a the dll-def file is created at the time that the DLL is created. Exporting a class from a DLL... http://www.codeguru.com/win32/dyndllclass.shtml Win32 DLL Topics http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_dll_topics.asp ------ Mutual DLL imports http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_mutual_imports.asp Exporting or importing to another executable file presents complications when the imports are mutual (or "circular"). For example, two DLLs import symbols from each other, similar to mutually-recursive functions. The problem with mutually-importing executable files (usually DLLs) is that neither can be built without building the other first. Each build process requires, as input, an import library produced by the other build process. The solution is to use the LIB utility with the /DEF option, which produces an import library without building the executable file. Using this utility, you can build all the import libraries you need, no matter how many DLLs are involved or how complicated the dependencies are. The general solution for handling mutual imports is: 1.Take each DLL in turn. (Any order is feasible, although some orders are more optimal.) If all the needed import libraries exist and are current, run LINK to build the executable file (DLL). This produces an import library. Otherwise, run LIB to produce an import library. Running LIB with the /DEF option produces an additional file with an .EXP extension. The .EXP file must be used later to build the executable file. 2.After using either LINK or LIB to build all the import libraries, go back and run LINK to build any executable files that were not built in the previous step. Note that the corresponding .EXP file must be specified on the LINK line. If you had run the LIB utility earlier to produce an import library for DLL1, LIB would have produced the file DLL1.EXP as well. You must use DLL1.EXP as input to LINK when building DLL1.DLL. ----------- this makes a symbol table for a file dlltool.exe --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --output-def def.txt uselib.exe These lines from test4 show that libtool does know how to make import libraries: > generating import library for `cygmodule1-0.dll' > dlltool --as=as --dllname cygmodule1-0.dll --def .libs/cygmodule1-0.dll-def --output-lib .libs/libimp-cygmodule1-0.a Now what I want to see is generation of an import library corresponding to a BINARY. /bin/sh.exe ../libtool g++ -g -O2 -c module1.cc mkdir .libs g++ -g -O2 -c module1.cc -DDLL_EXPORT -DPIC -o .libs/module1.lo In file included from module1.cc:2: module1.h:4: warning: #warning I will export DLL symbols for MODULE1 In file included from module1.cc:3: module2.h:8: warning: #warning I will import DLL symbols for MODULE2 g++ -g -O2 -c module1.cc -o module1.o >/dev/null 2>&1 mv -f .libs/module1.lo module1.lo /bin/sh.exe ../libtool g++ -g -O2 -c module2.cc rm -f .libs/module2.lo g++ -g -O2 -c module2.cc -DDLL_EXPORT -DPIC -o .libs/module2.lo In file included from module2.cc:3: module2.h:4: warning: #warning I will export DLL symbols for MODULE2 g++ -g -O2 -c module2.cc -o module2.o >/dev/null 2>&1 mv -f .libs/module2.lo module2.lo /bin/sh.exe ../libtool g++ -no-undefined -o libmodule2.la module2.lo -rpath `pwd`/lib rm -fr .libs/libmodule2.la .libs/libmodule2.* .libs/libmodule2.* generating symbol list for `libmodule2.la' dlltool --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --output-def .libs/cygmodule2-0.dll-def module2.lo sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < .libs/cygmodule2-0.dll-def > .libs/libmodule2.exp if test "x`head -1 .libs/libmodule2.exp`" = xEXPORTS; then cp .libs/libmodule2.exp .libs/cygmodule2-0.dll-def; else echo EXPORTS > .libs/cygmodule2-0.dll-def; _lt_hint=1; cat .libs/libmodule2.exp | while read symbol; do set dummy $symbol; case $# in 2) echo " $2 @ $_lt_hint ; " >> .libs/cygmodule2-0.dll-def;; *) echo " $2 @ $_lt_hint $3 ; " >> .libs/cygmodule2-0.dll-def;; esac; _lt_hint=`expr 1 + $_lt_hint`; done; fi gcc -Wl,--base-file,.libs/cygmodule2-0.dll-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule2-0.dll module2.lo dlltool --as=as --dllname cygmodule2-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule2-0.dll-def --base-file .libs/cygmodule2-0.dll-base --output-exp .libs/cygmodule2-0.dll-exp gcc -Wl,--base-file,.libs/cygmodule2-0.dll-base .libs/cygmodule2-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule2-0.dll module2.lo dlltool --as=as --dllname cygmodule2-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule2-0.dll-def --base-file .libs/cygmodule2-0.dll-base --output-exp .libs/cygmodule2-0.dll-exp --output-lib .libs/libmodule2.dll.a gcc .libs/cygmodule2-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule2-0.dll module2.lo ar cru .libs/libmodule2.a module2.o ranlib .libs/libmodule2.a creating libmodule2.la (cd .libs && rm -f libmodule2.la && ln -s ../libmodule2.la libmodule2.la) mkdir -p lib bin /bin/sh.exe ../libtool cp libmodule2.la `pwd`/lib cp .libs/libmodule2.dll.a /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule2.dll.a dlpath=`bash 2>&1 -c '. .libs/libmodule2.lai;echo $dlname'` dldir=/home/bryce/bochs-testing/plugin-test/test4-interdep/lib/`dirname $dlpath` test -d $dldir || mkdir -p $dldir cp .libs/cygmodule2-0.dll $dldir/cygmodule2-0.dll cp .libs/libmodule2.lai /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule2.la cp .libs/libmodule2.a /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule2.a ranlib /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule2.a chmod 644 /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule2.a ---------------------------------------------------------------------- Libraries have been installed in: /home/bryce/bochs-testing/plugin-test/test4-interdep/lib If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use the `-LLIBDIR' flag during linking and do at least one of the following: - add LIBDIR to the `PATH' environment variable during execution - add LIBDIR to the `LD_RUN_PATH' environment variable during linking - use the `-Wl,--rpath -Wl,LIBDIR' linker flag See any operating system documentation about shared libraries for more information, such as the ld(1) and ld.so(8) manual pages. ---------------------------------------------------------------------- /bin/sh.exe ../libtool g++ -no-undefined -o libmodule1.la module1.lo -rpath `pwd`/lib libmodule2.la generating import library for `cygmodule2-0.dll' dlltool --as=as --dllname cygmodule2-0.dll --def .libs/cygmodule2-0.dll-def --output-lib .libs/libimp-cygmodule2-0.a rm -fr .libs/libmodule1.la .libs/libmodule1.* .libs/libmodule1.* generating symbol list for `libmodule1.la' dlltool --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --output-def .libs/cygmodule1-0.dll-def module1.lo sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < .libs/cygmodule1-0.dll-def > .libs/libmodule1.exp if test "x`head -1 .libs/libmodule1.exp`" = xEXPORTS; then cp .libs/libmodule1.exp .libs/cygmodule1-0.dll-def; else echo EXPORTS > .libs/cygmodule1-0.dll-def; _lt_hint=1; cat .libs/libmodule1.exp | while read symbol; do set dummy $symbol; case $# in 2) echo " $2 @ $_lt_hint ; " >> .libs/cygmodule1-0.dll-def;; *) echo " $2 @ $_lt_hint $3 ; " >> .libs/cygmodule1-0.dll-def;; esac; _lt_hint=`expr 1 + $_lt_hint`; done; fi gcc -Wl,--base-file,.libs/cygmodule1-0.dll-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo .libs/libimp-cygmodule2-0.a dlltool --as=as --dllname cygmodule1-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule1-0.dll-def --base-file .libs/cygmodule1-0.dll-base --output-exp .libs/cygmodule1-0.dll-exp gcc -Wl,--base-file,.libs/cygmodule1-0.dll-base .libs/cygmodule1-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo .libs/libimp-cygmodule2-0.a dlltool --as=as --dllname cygmodule1-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule1-0.dll-def --base-file .libs/cygmodule1-0.dll-base --output-exp .libs/cygmodule1-0.dll-exp --output-lib .libs/libmodule1.dll.a gcc .libs/cygmodule1-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo .libs/libimp-cygmodule2-0.a ar cru .libs/libmodule1.a module1.o ranlib .libs/libmodule1.a creating libmodule1.la (cd .libs && rm -f libmodule1.la && ln -s ../libmodule1.la libmodule1.la) mkdir -p lib bin /bin/sh.exe ../libtool cp libmodule1.la `pwd`/lib libtool: install: warning: relinking `libmodule1.la' cd /home/bryce/bochs-testing/plugin-test/test4-interdep; /bin/sh ../libtool --mode=relink g++ -no-undefined -o libmodule1.la module1.lo -rpath /home/bryce/bochs-testing/plugin-test/test4-interdep/lib libmodule2.la generating symbol list for `libmodule1.la' dlltool --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --output-def .libs/cygmodule1-0.dll-def module1.lo sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < .libs/cygmodule1-0.dll-def > .libs/libmodule1.exp if test "x`head -1 .libs/libmodule1.exp`" = xEXPORTS; then cp .libs/libmodule1.exp .libs/cygmodule1-0.dll-def; else echo EXPORTS > .libs/cygmodule1-0.dll-def; _lt_hint=1; cat .libs/libmodule1.exp | while read symbol; do set dummy $symbol; case $# in 2) echo " $2 @ $_lt_hint ; " >> .libs/cygmodule1-0.dll-def;; *) echo " $2 @ $_lt_hint $3 ; " >> .libs/cygmodule1-0.dll-def;; esac; _lt_hint=`expr 1 + $_lt_hint`; done; fi gcc -Wl,--base-file,.libs/cygmodule1-0.dll-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo -L/home/bryce/bochs-testing/plugin-test/test4-interdep/lib -lmodule2 dlltool --as=as --dllname cygmodule1-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule1-0.dll-def --base-file .libs/cygmodule1-0.dll-base --output-exp .libs/cygmodule1-0.dll-exp gcc -Wl,--base-file,.libs/cygmodule1-0.dll-base .libs/cygmodule1-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo -L/home/bryce/bochs-testing/plugin-test/test4-interdep/lib -lmodule2 dlltool --as=as --dllname cygmodule1-0.dll --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 --def .libs/cygmodule1-0.dll-def --base-file .libs/cygmodule1-0.dll-base --output-exp .libs/cygmodule1-0.dll-exp --output-lib .libs/libmodule1.dll.a gcc .libs/cygmodule1-0.dll-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o .libs/cygmodule1-0.dll module1.lo -L/home/bryce/bochs-testing/plugin-test/test4-interdep/lib -lmodule2 cp .libs/libmodule1.dll.aT /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule1.dll.a dlpath=`bash 2>&1 -c '. .libs/libmodule1.lai;echo $dlname'` dldir=/home/bryce/bochs-testing/plugin-test/test4-interdep/lib/`dirname $dlpath` test -d $dldir || mkdir -p $dldir cp .libs/cygmodule1-0.dll $dldir/cygmodule1-0.dll cp .libs/libmodule1.lai /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule1.la cp .libs/libmodule1.a /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule1.a ranlib /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule1.a chmod 644 /home/bryce/bochs-testing/plugin-test/test4-interdep/lib/libmodule1.a ---------------------------------------------------------------------- Libraries have been installed in: /home/bryce/bochs-testing/plugin-test/test4-interdep/lib If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use the `-LLIBDIR' flag during linking and do at least one of the following: - add LIBDIR to the `PATH' environment variable during execution - add LIBDIR to the `LD_RUN_PATH' environment variable during linking - use the `-Wl,--rpath -Wl,LIBDIR' linker flag See any operating system documentation about shared libraries for more information, such as the ld(1) and ld.so(8) manual pages. ---------------------------------------------------------------------- /bin/sh.exe ../libtool g++ -no-undefined -o uselib ./uselib.cc libmodule1.la libmodule2.la generating import library for `cygmodule1-0.dll' dlltool --as=as --dllname cygmodule1-0.dll --def .libs/cygmodule1-0.dll-def --output-lib .libs/libimp-cygmodule1-0.a g++ -o .libs/uselib ./uselib.cc .libs/libimp-cygmodule1-0.a .libs/libimp-cygmodule2-0.a -Wl,--rpath -Wl,/home/bryce/bochs-testing/plugin-test/test4-interdep/lib In file included from ./uselib.cc:2: module1.h:8: warning: #warning I will import DLL symbols for MODULE1 In file included from ./uselib.cc:3: module2.h:8: warning: #warning I will import DLL symbols for MODULE2 creating uselib.exe Try making a dll with everything in it, and then a nearly empty object that build libmain.la with main.lo build module1.la with libmain.la build module2.la with libmain.la build .exe from libmain.la Then main.cc can dlopen module1.la