Get reason that LoadLibrary cannot load DLL - c++

On Linux and Mac, when using dlopen() to load a shared library that links to another library, if linking fails because of a missing symbol, you can get the name of the missing symbol with dlerror(). It says something like
dlopen failed: cannot locate symbol "foo"
On Windows, when using LoadLibrary() to load a DLL with a missing symbol, you can only get an error code from GetLastError() which for this type of issue will always be 127. How can I figure out which symbol is missing, or a more verbose error message from LoadLibrary() that explains why the function failed?

I figured out a way using the MSYS2 terminal. Other methods might work with GUI software.
A major caveat is that this can't be done in pure C/C++ and released for end users. It's for developers only, but it's better than nothing.
Install Debugging Tools for Windows by downloading the Windows SDK and unchecking everything except Debugging Tools.
I could be wrong, but it seems that installing this software installs a hook into the Windows kernel to allow LoadLibrary() to write verbose information to stderr.
Open the MSYS2 Mingw64 terminal as an administrator and run
'/c/Program Files (x86)/Windows Kits/10/Debuggers/x64/gflags.exe' -i main.exe +sls
This prints the following to the terminal to confirm that the registry has been changed.
Current Registry Settings for main.exe executable are: 00000002
sls - Show Loader Snaps
Use -sls instead of +sls if you need to undo, since I believe that the change takes place for all programs called main.exe in Windows globally, not just for your file.
Then running main.exe should print debug information to stderr, but since I'm debugging an -mwindows application, it's not working for me.
But for some reason, running the binary with MSYS2's gdb allows this debug information to be printed to stderr.
Install mingw-w64-x86_64-gdb with MSYS2 and run gdb ./main.exe and type run or r.
Search for a section similar to the following.
warning: 1ec8:43a0 # 764081125 - LdrpNameToOrdinal - WARNING: Procedure "foo" could not be located in DLL at base 0x000000006FC40000.
warning: 1ec8:43a0 # 764081125 - LdrpReportError - ERROR: Locating export "foo" for DLL "C:\whatever\plugin.dll" failed with status: 0xc0000139.
warning: 1ec8:43a0 # 764081125 - LdrpGenericExceptionFilter - ERROR: Function LdrpSnapModule raised exception 0xc0000139
Exception record: .exr 00000000050BE5F0
Context record: .cxr 00000000050BE100
warning: 1ec8:43a0 # 764081125 - LdrpProcessWork - ERROR: Unable to load DLL: "C:\whatever\plugin.dll", Parent Module: "(null)", Status: 0xc0000139
warning: 1ec8:43a0 # 764081171 - LdrpLoadDllInternal - RETURN: Status: 0xc0000139
warning: 1ec8:43a0 # 764081171 - LdrLoadDll - RETURN: Status: 0xc0000139
Great! It says Procedure "foo" could not be located in DLL so we have our missing symbol, just like in POSIX/UNIX's dlopen().

While the answer from Remy Lebeau is technically correct, determining the missing symbol from GetLastError() is still possible on a Windows platform. To understand what exactly is missing, understanding the terminology is critical.
Symbol:
When a DLL is compiled, it's functions are referenced by symbols.
These symbols directly relate to the functions name (the symbols are
represented by visible and readable strings), its return type, and
it's parameters. The symbols can actually be read directly through a
text editor although difficult to find in large DLLs.DLL Symbols - C++ Forum
To have a missing symbol implies that a function within cannot be found. If this error occurs prior to using GetProcAddress(), then it's possible that any number of functions cannot be loaded due to missing prerequisites. This means it is possible that a library that you are attempting to load also requires a library that the first cannot load. These levels of dependency may go on for an unknown number of layers, but the only answer that GetLastError() can determine is that there was a missing symbol. One such method is by using Dependency Walker to determine the missing library the first library requires. Once all required libraries are available and can be found by that library (which can be its own can of worms), that library can be loaded via LoadLibrary().

Related

Why is gdb refusing to load my shared objects and what is the validation operation

Main question:
In Ubuntu trying to debug an embedded application running in QNX, I am getting the following error message from gdb:
warning: Shared object "$SOLIB_PATH/libc.so.4" could not be validated and will be ignored.,
Q: What is the "validation" operation going on ?
After some research I found that the information reported by readelf -n libfoo.so contains a build-id and that this is compared against something and there could be a mismatch causing gdb to refuse to load the library. If that's the case what ELF file's build-id is the shared object's build-id compared against ? Can I find this information parsing the executable file ?
More context:
I have a .core file for this executable. I am using a version of gdb provided by QNX and making sure I use set sysroot and set solib-search-path to where I installed the QNX toolchain.
My full command to launch gdb in Ubuntu is :
$QNX_TOOLCHAIN_PATH/ntox86_64-gdb --init-eval-command 'set sysroot $SYSROOT_PATH' --init-eval-command 'set solib-search-path $SOLIB_PATH --init-eval-command 'python sys.path.append("/usr/share/gcc-8/python");' -c path-to-exe.core path-to-executable-bin
Gdb is complaining that it cannot load shared objects :
warning: Shared object "$SOLIB_PATH/libc.so.4" could not be validated and will be ignored.
The big thing here is to make sure you're using the exact same binary that is on the target (that the program runs over). This is often quite difficult with libc, especially because libc/ldqnx are sometimes "the same thing" and it confuses gdb.
The easiest way to do this is to log your mkifs output (on the linux host):
make 2>&1 | tee build-out.txt
and read through that, search for libc.so.4, and copy the binary that's being pulled onto the target into . (wherever you're running gdb) so you don't need to mess with SOLIB paths (the lazy solution).
Alternatively, scp/ftp a new libc (one that you want to use, and ideally one that you have associated symbols for) into /tmp and use LD_LIBRARY_PATH to pull that one (and DL_DEBUG=libs to confirm, if you need). Use that same libc to debug
source: I work at QNX and even we struggle with gdb + libc sometimes

Exit 1 when calling mono_jit_init

Hi, I try to embed mono in a c++ application on windows. I followed http://www.mono-project.com/docs/compiling-mono/windows/ and I have my headers, lib and dll built for win64.
I wrote a simple app that just calls
MonoDomain *domain;
domain = mono_jit_init("ConsoleApplication1.exe");
Everything builds and link find but when I run my program, I can break and step until the mono_jit_init call. Then the apps performs an exit1 and I can't see what's wrong.
I tried both release and debug.
Any ideas on how to find the issue? Properly embed mono?
Thanks, JNQ
Your application probably fails on loading Mono libraries.
You can use Process Monitor (https://learn.microsoft.com/en-us/sysinternals/downloads/procmon) to find out what exactly fails for you:
Run Process Monitor
Set Process Monitor filter to "[Process Name] [is] [Your process name, e.g. ConsoleApplication1.exe] then [Include]"
Run you program and lookup for "CreateFile" operations with "NAME NOT FOUND" Result and see Path column to find out what file is missing
In my case it was a failure on loading mono mscorlib.dll from lib\mono\4.5\mscorlib.dll so copying the files from the Mono installation to the path pointed by Process Monitor has helped.

0xc000007b Error : how to analyze using Process Monitor

Another error at startup of my basic app which only tests my DLL (the core deliverable of my project) by calling its init method. I have analysed what happens using Process Monitor, and filtered according to process name, looking only for events related with my the main executable of my basic app.
What should I be looking for there ? I guess anything that says SUCCESS in the result column does not point to the problem - but what about the rest ? It seems to be looking for my DLL all over the world although it first tried in the current directory and found it there already ...
An excerpt here, saved from ProcMon in CSV format : http://pastebin.com/YHSeQUk0
As I said it tries to open my DLL in many places (following my PATH environment variable ?). When looking for it in the correct folder (which is the same as where the exe is located and running) it goes through a series of actions which mostly end up in SUCCESS (if not otherwise specified):
IRP_MJ_CREATE
IRP_MJ_CLEANUP
IRP_MJ_CLOSE
IRP_MJ_CREATE
FASTIO_ACQUIRE_FOR_SECTION_SYNCHRONIZATION (result is : FILE LOCKED
WITH ONLY READERS)
FASTIO_ACQUIRE_FOR_CC_FLUSH
FASTIO_ACQUIRE_FOR_SECTION_SYNCHRONIZATION (result is SUCCESS)
FASTIO_ACQUIRE_FOR_CC_FLUSH
It does all of this a second time later. To me this looks ok. No other DLL-related event show up.
There is this other event at the top :
RegOpenKey in HKLM\System\CurrentControlSet\Control\Srp\GP\DLL which first results in REPARSE and then in NAME NOT FOUND. But many things happen afterwards, this doesn't look like a blocking point - and anyhow no clue what this is about.
dumpbin /dependents ConsoleApplication1.exe yields the following :
File Type: EXECUTABLE IMAGE
Image has the following dependencies:
uss_map_interface.dll
VCRUNTIME140.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
KERNEL32.dll
The first one is my dll. If I remove it the message at startup turns into "uss_map_interface.dll is missing from your computer" - so I cannot believe this woukld be related to my DLL ... all the other I found in Windows/System32 or SysWOW64.
I am compiling both my DLL and the test basic app with MVS Express 2015 (v140) with x64 configs. The problem also appears if I change to x86 configs. The funny thing also is that if I compile my DLL with MinGW in a Qt project - it works fine. If that can provide a hint, here follow the dependencies of the Qz/MinGW-compiled version :
File Type: DLL
Image has the following dependencies:
libgcc_s_dw2-1.dll
KERNEL32.dll
msvcrt.dll
libstdc++-6.dll
Anyhow, thanks in advance !

`cabal repl` causes GHC panic on simple project with C++ files

I've uploaded the project as a zip file so you can try it out.
https://dl.dropboxusercontent.com/u/35032740/ShareX/2015/11/Buggy.zip
I wanted to write a wrapper around the clipper library. The code compiles fine with cabal build, runs with cabal run but cabal repl produces this error:
Preprocessing executable 'Buggy' for Buggy-0.1.0.0...
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
GHC runtime linker: fatal error: I found a duplicate definition for symbol
_ZNSt6vectorIN10ClipperLib8IntPointESaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_
whilst processing object file
dist\build\Buggy\Buggy-tmp\wrapper.o
This could be caused by:
* Loading two different object files which export the same symbol
* Specifying the same object file twice on the GHCi command line
* An incorrect `package.conf' entry, causing some object to be
loaded twice.
ghc.exe: panic! (the 'impossible' happened)
(GHC version 7.10.2 for x86_64-unknown-mingw32):
loadObj "dist\\build\\Buggy\\Buggy-tmp\\wrapper.o": failed
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
For reference, here's the cabal file
-- Initial Buggy.cabal generated by cabal init. For further documentation,
-- see http://haskell.org/cabal/users-guide/
name: Buggy
version: 0.1.0.0
-- synopsis:
-- description:
-- license:
license-file: LICENSE
author: Luka Horvat
maintainer: lukahorvat9#gmail.com
-- copyright:
-- category:
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10
executable Buggy
main-is: Main.hs
c-sources: clipper.cpp
, wrapper.cpp
-- other-modules:
-- other-extensions:
build-depends: base >=4.8 && <4.9
-- hs-source-dirs:
default-language: Haskell2010
extra-libraries: stdc++
Any ideas what the cause might be here?
I'm running Windows 10, 64bit.
I don't know the details of object file formats on Windows, so I'm guessing a bit.
Probably clipper.o and wrapper.o both define a weak symbol named _ZNSt6vectorIN10ClipperLib8IntPointESaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_. (I see the same on Linux.) This probably came from a template instantiation (of vector). Weak symbols instruct the system linker to just pick any copy of the symbol if it encounters duplicates.
GHCi on Windows doesn't use the system linker, it has its own runtime linker that can load object files into itself while it runs. As a result it is generally not feature compatible with the system linker. Probably the runtime linker does not understand weak symbols, at least on Windows (https://ghc.haskell.org/trac/ghc/ticket/3333). From the error you got, we can assume that it treats them as regular symbols, and two regular symbols are not allowed to have the same name.
As a workaround, you may be able to build your C++ files with -fno-weak as described in https://stackoverflow.com/a/26454930/190376.
If that doesn't work, an alternative is to build your C++ files into a DLL, which you can have GHCi load using the system dynamic loader, avoiding this whole issue. On Linux this would look like
g++ wrapper.cpp clipper.cpp -shared -fPIC -o libclipper.so
ghci -L. -lclipper
though I imagine the details are different on Windows.
The specific error isn't what I'm used to seeing, but those backslashes say you're on Windows, and this otherwise looks like GHC bug #3242 which has been causing pain for years now. Good news: the cause was finally isolated two weeks ago. Bad news: the fix didn't make the deadline for 7.10.3, though at least the 8.0.1 milestone seems secure at this point.
Probably still worth posting your error text to that bug's thread; mine is only an educated guess, someone there will know for sure.

Exe built using pyinstaller on a Django with pylucene app giving JVM error

I am getting an error:
"Error occurred during initialization of VM
Unable to load native library: Can't find dependent libraries"
The error arises when I try to execute my exe file.
I have created exe file through pyinstaller on a django application. Application uses pylucine library. I think it may be the issue of error.
How to fix the error?
Since I can't be certain given you've provided very few details here is a shot in the dark to help solve your problem:
First, try removing the jvm.dll file that gets packaged with the pyinstaller -D youmodule.py command (for now work with the directory command rather than -F option). The reason why is here.
With that jvm.dll file gone, you should start seeing the actual error code - and with that the java class or dependency that isn't being loaded.
If it's a java class that isn't being properly loaded then you know instantly it must not be correcly represented in the classpath environment variable and you should do everything in your power to make sure it is:
e.g.: os.environ['CLASSPATH'] += 'the/path/to/the/jar'
Otherwise, consider bulking up your question with more details, especially if you can get a more meaningful error output.
I had the same error trying to run a .exe built with PyInstaller through wine.
My problem went away by adding C:\Program Files\Java\ [your jdk version here] \jre\bin\server to the PATH environment variable in wine - I suppose it might be the same in Windows.
It also reappeared if I tried to build with C:\Program Files\Java\ [your jdk version here] \jre\bin\server in my PATH, so I had to build without it and then append it before running it (I have no explanation as to why this happens).