Problems enabling RTTI in LLVM JIT-ed code - c++

I'm JIT-ting C++ code in a Windows application. I'm using LLVM/CLang 5.0, and the application was compiled using MsVc 2015.
While DLLs and executable code created with the two toolchains mix and match very well, I'm facing problems with the JIT-ted code that doesn't include variables that LLVM should generate automatically, like ??_7type_info##6B# and associated stuff, like \01??_R0H#8. They are registered as external only, and any use of them will cause the application to crash with
LLVM ERROR: Program used external function '??_7type_info##6B#' which could not be resolved!
While I have found examples of adding user-defined variables to JIT-ted code, I could not find effective solutions to the problem of making JIT code refer to these internal variables, that are generated behind the curtains.
I believe I could provide the missing variables via a DLL compiled with CLang, with the tweaking of .ll but I would prefer a cleaner solution, merely configuring the JIT-ter engine.
Can anybody help me, please ?

??_7type_info##6B# is the mangled name of the vtable for the std::type_info class, which is provided by one or other of the MSVC static libraries that gets linked implicitly, for example:
c:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.15.26726/lib/x64/msvcrt.lib
To fix the LLVM lookup error you can export this symbol from your own DLL or EXE, and you can actually do this from your C++ code like this:
#pragma comment(linker, "/export:??_7type_info##6B#")
See also https://learn.microsoft.com/en-us/cpp/build/reference/export-exports-a-function?view=vs-2017
You may also have to call the utility function below to ensure all your symbols are visible to LLVM
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
Not sure if that's strictly necessary in this case, but it's recommended by the LLVM JIT compiler tutorial.

Related

Linking a MinGW library to a MSVC app with a C interface

I'm trying to link to the OpenAL soft library as compiled with the Media Autobuild Suite, and I'm getting the following error from Visual Studio:
libopenal.a(source.cpp.o) : fatal error LNK1143: invalid or corrupt file: no symbol for COMDAT section 0xA
My application is in C++ and compiled directly in Visual Studio 2019 (however, with the VS2017 toolset). OpenAL soft is written in C++ but exposes a C interface, and the MAB Suite compiles using MinGW/gcc and generates a libopenal.a static library file.
I've read from multiple other questions such as From MinGW static library (.a) to Visual Studio static library (.lib) and How to use libraries compiled with MingW in MSVC? that object files compiled with different compilers are generally not compatible for C++ due to name mangling, but often are compatible with C linkage. Because C does not use name mangling, and because the ABI is (usually) OS-dependent, libraries with a C interface compiled on the same platform are generally compatible.
Nevertheless, I've been running into linker errors, namely the LNK1143 above. I've confirmed that the included headers use extern "C" { to hint C linkage and that the target platform (x64) is the same for both builds. I also linked to libgcc.a as this answer recommends, and did not get any linker errors for it.
Does this mean the claim that C interfaces are generally compatible across compilers is not true? Or is this a special case in which it's not working? If the latter, what could be causing the linking to fail? Would I have better luck if I recompiled as shared libraries (dlls) instead of static libraries (even if I still use MinGW's .a files instead of .lib)?
I cannot change compilers from MSVC for my main app. I intend to use more libraries from the MAB Suite in the future, so I'd prefer to stay with MinGW for those dependencies if possible because I don't want to recompile all 70+ by hand.
Any help is appreciated. Thanks in advance.
Mixing compilers is tricky and prone to issues.
In some very simple cases it may work, but there are definitely a number of cases where you will run in to issues, for example:
if the different components use different runtime libraries
if memory management is being mixed (e.g. forget about freeing memory allocated with malloc() in MSVC using free() in MinGW)
when using exception handling in C++
My advice to do it all with the same compiler (and even the same version of this compiler).
Specifically in your case OpenAL can be built with MinGW-w64. So maybe you should look into that instead of downloading some prebuilt version from the web.
Or - somewhat easier - use MSYS2 and use its pacman package manager to get its own MinGW-w64 build of OpenAL.
I figured out what works for me, so I'll share.
I was not able to link a static library between compilers as I originally attempted. My understanding is that the extra info kept in the lib to allow link-time code generation is compiler-specific. Brecht Sanders's answer outlines a few possible reasons why the code wouldn't be compatible.
I was, however, able to link to a shared library, with a few extra steps.
Using the same suite (see the question), I compiled as shared and got libopenal.dll, libopenal.dll.a, and libopenal.def. In my case, the .def file was generated by the suite. Accoding to this answer, you can generate a .def file with gcc using:
gcc -shared -o your_dll.dll your_dll_src.c -Wl,--output-def,your_dll.def
Trying to link to libopenal.dll.a still gave me errors (I don't know exactly why, and I already discarded the logs.) What I did instead was generate a .lib file from the .def file. In Visual Studio's built-in terminal:
lib /machine:x64 /def:libopenal.def
This generated a libopenal.lib file in the working directory. Linking to this file worked perfectly, and I was able to successfully load the dll at runtime.
I've tested this same method with many other MinGW-compiled libraries from the suite, including libavformat, libavcodec, libavutil, libavdevice, swresample, and swscale, and thus far all of them have worked.
Kind of convoluted, but it seems to work well for me, so I hope this helps anyone else with the same problem.

MS vs Non-MS C++ compiler compatibility

Thinking of using MinGW as an alternative to VC++ on Windows, but am worried about compatibility issues. I am thinking in terms of behaviour, performance on Windows (any chance a MinGW compiled EXE might act up). Also, in terms of calling the Windows API, third-party DLLs, generatic and using compatible static libraries, and other issues encountered with mixing parts of the same application with the two compilers.
First, MinGW is not a compiler, but an environment, it is bundled with gcc.
If you think of using gcc to compile code and have it call the Windows API, it's okay as it's C; but for C++ DLLs generated by MSVC, you might have a harsh wake-up call.
The main issue is that in C++, each compiler has its own name mangling (or more generally ABI) and its own Standard library. You cannot mix two different ABI or two different Standard Libraries. End of the story.
Clang has a specific MSVC compatibility mode, allowing it to accept code that MSVC accepts and to emit code that is binary compatible with code compiled with MSVC. Indeed, it is even officially supported in Visual Studio.
Obviously, you could also simply do the cross-DLL communication in C to circumvent most issues.
EDIT: Kerrek's clarification.
It is possible to compile a large amount of C++ code developed for VC++ with the MinGW toolchain; however, the ease with which you complete this task depends significantly on how C++-standards-compliant the code is.
If the C++ code utilizes VC++ extensions, such as __uuidof, then you will need to rewrite these portions.
You won't be able to compile ATL & MFC code with MinGW because the ATL & MFC headers utilize a number of VC++ extensions and depend on VC++-specific behaviors:
try-except Statements
__uuidof
throw(...)
Calling a function without forward-declaring it.
__declspec(nothrow)
...
You won't be able to use VC++-generated LIB files, so you can't use MinGW's linker, ld, to link static libraries without recompiling the library code as a MinGW A archive.
You can link with closed-source DLLs; however, you will need to export the symbols of the DLL as a DEF file and use dlltool to make the corresponding A archive (similar to the VC++ LIB file for each DLL).
MinGW's inclusion of the w32api project basically means that code using the Windows C API will compile just fine, although some of the newer functions may not be immediately available. For example, a few months ago I was having trouble compiling code that used some of the "secure" functions (the ones with the _s suffix), but I got around this problem by exporting the symbols of the DLL as a DEF, preparing an up-to-date A archive, and writing forward declarations.
In some cases, you will need to adjust the arguments to the MinGW preprocessor, cpp, to make sure that all header files are properly included and that certain macros are predefined correctly.
What I recommend is just trying it. You will definitely encounter problems, but you can usually find a solution to each by searching on the Internet or asking someone. If for no other reason, you should try it to learn more about C++, differences between compilers, and what standards-compliant code is.

How to link to VS2008 generated .libs from g++

I am trying to build a dll using mingw g++ under cygwin.
I have .h files that refer to objects exported by a .dll that was build using MS Visual Studio 2008. I link to the .lib generated with that .dll.
When I run g++ I get lots of errors like this
/cygdrive/c/dev/blox/ulfx/ulfx/JavaInterface.cpp:206: undefined reference to `__imp___ZNK18DLLSafeDoubleArray4sizeEv'
The .dll that I want to link to exposes a function named
?size#DLLSafeDoubleArray##QBEIXZ
And I assume that the problem here is that the g++ name mangling is incompatible with the VS2008 name mangling.
Is there a way I can force g++ to use a compatible mangling ?
I do not have any version of Visual Studio installed on my machine.
G'day,
Not sure if this is going to be possible as there is too much that can vary between compilers from different vendors apart from just the name mangling. Things such as:
this handling,
layout and contents of v-tables,
class layout,
parameter sequence,
register handling,
return value handling,
etc.
I'd be interested to see if it was possible though.
Maybe this page helps:
http://www.mingw.org/wiki/MSVC_and_MinGW_DLLs
I did manage to do something once but it was just a prototype which I abandoned when I found a library doing what I wanted. I did follow their instructions though, but I was producing the dll myself.
I agree with Rob Wells comment, there are a lot of things in C++ that may break.
Something which should be easier, safer, and possible would be to use plain C functions, as the main thing to worry about there is the calling convention and potentially packing and alignment of structs.
Object code produced by different C++ compilers is not link compatible.
This is done on purpose: compilers use different ABI, and if the name maingling didn't prevent you from linking, you'd now be wondering/debugging why the simplest operations are causing your executable to crash.
You should be grateful that the different name mangling scheme spared you that debugging effort.
Better way is to recompile dll with g++. If it is possible.

Error linking with 3rd party static library built with previous version of Visual Studio

I am working on a project that links to a 3rd party static library (herin refered to as EXTERNALLIB). In Visual Studio 2005 I was able to link to EXTERNALLIB and create a usable executable. Now we are using Visual Studio 2008 and I am receiving the following error:
fatal error C1047: The object or library file EXTERNALLIB was created with an older compiler than other objects; rebuild old objects and libraries.
Is there a way for me to tell the compiler to correctly link to EXTERNALLIB? I believe the problem may be related to specific calling conventions (__stdcall, __cdecl, __clrcall, __thiscall). Can I indicate in the new program the correct calling convention for the old library? Is there specific feedback that I can give to our vendor (such as using APIENTRY in the header files) such that this problem does not occur with future compiler upgrades?
The code is writen in C++. I do not have access to the code for EXTERNALLIB and thus I am unable to rebuild it myself.
You problem is likely to result from "the code is written in C++". The ABI for C++ linkage is essentially completely unspecified by any standard, and is notoriously changeable from compiler to compiler. I suspect that VS is trying to tell you that the ABI has changed again, and that as a result it cannot link directly to the library.
This problem is often exacerbated by wanting to implement C++ objects in a DLL, but luckily you don't have that problem here.
One approach to a solution that should work is to skin the published API of EXTERNALLIB with a C-callable adaptor, and to link that whole thing into a DLL. Build the skin with the older VS version (at worst, the free edition should still be findable). Make sure that only extern "C" functions are exposed. Especially make sure that no global objects are exposed from the DLL (although they may need to exist within your skin).
The best answer is go back to the supplier of EXTERNALLIB and politely report the failure to link with the current VS as a bug and request a rebuilt version.

Building C++ source code as a library - where to start?

Over the months I've written some nice generic enough functionality that I want to build as a library and link dynamically against rather than importing 50-odd header/source files.
The project is maintained in Xcode and Dev-C++ (I do understand that I might have to go command line to do what I want) and have to link against OpenGL and SDL (dynamically in SDL's case). Target platforms are Windows and OS X.
What am I looking at at all?
What will be the entry point of my
library if it needs one?
What do I have to change in my code?
(calling conventions?)
How do I release it? My understanding
is that headers and the compiled
library (.dll, .dylib(, .framework),
whatever it'll be) need to be
available for the project -
especially as template functionality
can not be included in the library by
nature.
What else I need to be aware of?
I'd recommend building as a statc library rather than a DLL. A lot of the issues of exporting C++ functions and classes go away if you do this, provided you only intend to link with code produced by the same compiler you built the library with.
Building a static library is very easy as it is just an collection of .o/.obj files - a bit like a ZIP file but without compression. There is no need to export anything - just include the library in the list of files that your application links with. To access specific functions or classes, just include the relevant header file. Note you can't get rid of header files - the C++ compilation model, particularly for templates, depends on them.
It can be problematic to export a C++ class library from a dynamic library, but it is possible.
You need to mark each function to be exported from the DLL (syntax depends on the compiler). I'm poking around to see if I can find how to do this from xcode. In VC it's __declspec(dllexport) and in CodeWarrior it's #pragma export on/#pragma export off.
This is perfectly reasonable if you are only using your binary in-house. However, one issue is that C++ methods are named differently by different compilers. This means that nobody who uses a different compiler will be able to use your DLL, unless you are only exporting C functions.
Also, you need to make sure the calling conventions match in the DLL and the DLL's client. This either means you should have the same default calling convention flag passed to the compiler for both the DLL or the client, or better, explicitly set the calling convention on each exported function in the DLL, so that it won't matter what the default is for the client.
This article explains the naming issue:
http://en.wikipedia.org/wiki/Name_decoration
The C++ standard doesn't define a standard ABI, and that's bad news for people trying to build C++ libraries. This means that you get different behavior from your compiled code depending on which flags were used to compile it, and that can lead to mysterious bugs in code that compiles and links just fine.
This extends beyond just different calling conventions - C++ code can be compiled to support or not support RTTI, exception handling, and with various optimizations that can affect the the memory layout of class instances, which C++ code relies on.
So, what can you do? I would build C++ libraries inside my source tree, and make sure that they're built as part of my project's build, and that all the libraries and the code that links to them use the same compiler flags.
Note that name mangling, which was supposed to at least prevent you from linking object files that were compiled with different compilers/compiler flags only mostly works, and there are certain things you can do, especially with GCC, that will result in code that links just fine and fails at runtime.
You have to be extra careful with vendor supplied dynamic C++ libraries (QT on most Linux distributions, for example.) I've seen instances of vendor supplied libraries that were compiled in ways that prevented certain things from working properly. For example, some Redhat Linux releases (maybe all of them) disabled exceptions in QT, which made it impossible to catch exceptions in main() if the exceptions were thrown in a QT callback. Fun.