Forcing name mangling in x64 DLL - c

I am porting a 32-bit application to 64-bit. The application supports plugins which are DLLs. Unfortunately, one of the mandatory functions each plugin needs to have is called FreeLibrary which of course conflicts with the kernel32 API of the same name. The reason why my plugin API uses the FreeLibrary name is that the application originated on a different platform where FreeLibrary doesn't clash with any OS APIs.
However, even on 32-bit Windows using FreeLibrary is not a problem because 32-bit DLLs use name mangling, i.e. the function is stored as _FreeLibrary and hence doesn't clash with the kernel32 API.
On 64-bit, though, I have a problem now because 64-bit doesn't seem to use name mangling. On 64-bit the compiler creates a symbol named FreeLibrary and this of course clashes with the kernel32 API of the same name and refuses to link, leading to the following error:
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
kernel32.lib(KERNEL32.dll) : error LNK2005: FreeLibrary already defined in test.o
Creating library test.lib and object test.exp
test.dll : fatal error LNK1169: one or more multiply defined symbols found
Thus, I'm wondering whether there is any way to force x64 DLLs to use name mangling as on 32-bit so that my DLL can export a symbol named FreeLibrary without any clashes with kernel32?
Or is there any other solution to work around this problem?
The only solution I see is to rename FreeLibrary to something that doesn't clash with OS APIs for the x64 versions of my application but of course I'd like to avoid this because it reduces the consistency of my application's plugin API. If possible, I'd like to keep the FreeLibrary name across all platforms and architectures.
Any ideas? I guess if it was possible on 32-bit to use reserved names like FreeLibrary in a DLL then there should be a way to do it on 64-bit as well, shouldn't there? But I don't see how...

I would not try to convince the compiler to mangle the names of the functions. That way lies madness.
To clarify, your only issue is the duplicate symbols when linking plugin DLLs. The application itself shouldn't care what the functions are named, because it's going to call the plugin entry points through function pointers received via GetProcAddress.
Assuming, the plugins don't ever need to call Windows APIs implemented in kernel32.dll, you could try omitting kernel32.dll from the linker command. (See the /NODEFAULTLIB option.) If kernel32.dll isn't part of the link, there should be no collision.
But that won't work because /MT in the command line implies you depend on the C run-time library, which, in turn, depends on some kernel32.dll APIs. (Also, are you sure you want to link the plugins against the static run-time library and not the DLL version?)
So the remaining option is to change the name of the function. This should be trivial, since you're porting anyway. You could even use the preprocessor to hack the name when compiling the plugins so that you don't need to change their source code:
cl /EHsc /c /DFreeLibrary=Plugin_FreeLibrary /Fotest.o test.c
And then change the GetProcAddress call in the application to look for Plugin_FreeLibrary instead of FreeLibrary, which I assume happens in just one place.

Related

What is the standard way to manage calling-convention compatibility between a program and its DLL plugins?

I'm building a C program which explicitly dynamically loads DLLs as part of a plugin system. I'm using GCC with MinGW on Windows 7.
What calling convention should the exported functions in the DLLs use, in order to be as robust as possible: run successfully on different Windows machines, survive different compiler versions, etc.
I know that the main executable and the DLLs need only use the same calling convention. How is this normally managed?
Currently I'm only aiming at supporting Windows (even though answers referring also to the same subject on Linux will be welcome as well).
EDIT:
Please let me clarify the question, as discussed in a comment section with #S. S. Anne.
I'm less concerned about the particular calling convention. I'm more concerned with what is the standard way to ensure compatibility between a binary built on machine X and a DLL (plugin thing) built by somebody else on machine Y, which might have a different OS etc.
One approach I can think of, is that in the header file distributed to plugin developers, we define a macro that specifies the expected calling convention of functions exposed by the plugin to the main program. These functions will be defined by the plugin developer using this macro.
For example, the api.h header, supplied to plugin developers, defines #define CALL __cdecl. And after doing #include "api.h", the exported functions in the plugin DLL are declared like so: void CALL func(void);.
Is this solution used in practice? Are there different approaches?
Edit following question edit
No, you will not have to "ensure compatibility between a binary built on machine X and a DLL (plugin thing) built by somebody else on machine Y, which might have a different OS etc" unless the OS that binary X was built for is completely different from the OS that binary Y was built on. For context, this is a list of operating systems that are not compatible with each other:
Windows
Linux
Mac
BSD
You do not need to manually specify any calling convention. You don't even need to think about any calling conventions.
Your solution is not used in practice. The different approach required is to do nothing.
Original answer
For x86_64 Windows, the default Microsoft x64 ABI calling convention is what's used across the board. This should be enabled by default.
For x86 Windows, the image is a bit muddier: Most Windows API calls use __stdcall, but __cdecl is the default convention for user-defined functions. The difference between the two is that in the former, the callee cleans the stack, while in the latter, the caller cleans the stack.
In this case, I would go with __cdecl, as this is the default for both MSVC++ and GCC targeting Windows.
See __cdecl or __stdcall on Windows? for more information on this.
On Linux, you should always go with the default calling convention for your architecture. This option is always the most portable.
In conclusion, using the default calling convention should be fine across the board. You shouldn't have any problems with it.

Resolve shared library path on Windows and *nix systems

When loading shared library given its name, systems searches for the actual file (eg .dll) in some directories, based on search order, or in cache.
How can I programmatically get the resolved path of DLL given its name, but without actually loading it? E.g. on Windows, for kernel32 or kernel32.dll it would probably return C:\windows\system32\kernel32.dll whereas given foo it could be C:\Program Files\my\app\foo.dll.
If that can't be done, is there another way to determinate whether certain library belongs to system? E.g. user32.dll or libc.so.6 are system libraries but avcodec-55.dll or myhelperslib.so are not.
I'm interested solutions that work on Windows, Linux and Mac OS.
On Windows, LoadLibraryEx has the LOAD_LIBRARY_AS_DATAFILE flag which opens the DLL without performing the operations you refer to as "actually loading it".
This can be combined with any of the search order flags (Yeah, there is more than just one search order).
Unfortunately, you cannot use GetModuleFilename. Use GetMappedFileName instead.
The LoadLibraryEx documentation also says specifically not to use the SearchPath function to locate DLLs and not to use the DONT_RESOLVE_DLL_REFERENCES flag mentioned in comments.
For Linux, there's an existing tool ldd for which source code is available. It does actually load the shared libraries, but with a special environment variable LD_TRACE_LOADED_OBJECTS set that by convention causes them to skip doing anything. Because this is just a convention, beware that malicious files can perform actions when loaded by ldd CVE-2009-5064.

What library has the __main function reference in gcc assembly output

When compiling an empty c program using MinGW the assembly output contains the line
call __main
what library is this from? I expected linking with msvcrt.dll to work (linking using ld), but as it did not, it must be define elsewhere.
There are many related/practically the same question elsewhere, but none of them (as far as I have seen, been searching for a while now) actually contain the answer to this question, so please double check before marking as duplicate.
__main should be provided by the libgcc library, which comes with the MinGW compiler.
If you use the compiler driver (that is, the gcc command-line tool) to link your program, rather than invoking ld directly, this library should be automatically added to the link. Using the compiler driver to link is recommended practice for this and several other reasons.
Depending on exactly which version of MinGW you have and which version of GCC it embeds, libgcc or part of it may be a DLL, which you must bundle if you are shipping MinGW-compiled executables.
On my Windows 10 machine, it is in \Program Files\mingw-w64\x86_64-8.1.0-win32-seh-rt_v6-rev0\mingw64\lib\gcc\x86_64-w64-mingw32\8.1.0\libgcc.a which is then linked directly with the executable, so you do not have to include any DLL with you software.

Why do I need a redistributable package on unmanaged code? (msvcp100.dll)

What is the purpose of the 'msvcrXXX.dll' and 'msvcpXXX.dll'? And what are the differences between msvcr and msvcp?
Why do I need to link them to my binary if it's just a very simple and unmanaged .dll? Is it because it's part of the linker? Why isn't it in the Windows system directory by default as a common library?
I'm just trying to understand why in Windows there are somethings so complicated....
msvcrXXXX.dll is the DLL for the C runtime library.
msvcpXXXX.dll is the DLL for the C++ runtime library.
One or both of these dependencies will be added to your binary if you are building using /MD or /MDd, which are the defaults specified by Visual Studio when you create a new C++ project. Using either of these flags indicates that you want your program to link with the DLL version of the C/C++ runtime. You can change the defaults under Project Properties->Configuration Properties->C/C++/Code Generation/Runtime Library.
If you change your project to use /MT or /MTd, then your application will not generate references to either of the DLLs listed above, because the C/C++ runtimes will be linked directly into your program. For most simple programs, this will not cause any problems. However, if your program is broken up into several DLLs that all are built using these flags, then each DLL will maintain a copy of the referenced CRT functions and static data, and you may run into memory allocation/freeing problems. To avoid these, you need to make sure that objects allocated within a given DLL are also freed in that same module.
In general, it is more efficient to use the /MD and /MDd flags for applications that have multiple modules (DLLs), because all of those modules will share a single copy of the C/C++ runtime libraries and their associated data structures within the application process.
For simple, single-module applications, though, feel free to build using /MT or /MTd.

Static link intel CRT

I am compiling a C code using the intel compiler. I integrated icc with visual studio 2010. I want to generate an optimized executable which will run on a windows machine. It is actually a virtual machine in the cloud. I don't have a chance to install any redistributable library to the target machine. I want to statically link all the required libraries. How can I do this?
I suppose you meant icl since you're mentioning VS2010/Windows (icc would be Linux/Mac version): just selecting 'Multi-threaded (/MT)' under Project settings->Configuration properties->C/C++->Code Generation should work. It'll cause both MSVC and Intel runtime to be statically linked into app.
But then it also depends which other libraries are you using, it might not work for all. In that case you can check the dependencies with depends.exe (http://www.dependencywalker.com/) and copy them side-by-side with your .exe to target machine.
Try adding -i-static -static-libcxa to the final linkage.
This should force static linking for intel libraries only.
(You can also try -static as littleadv suggested in the comment, but this will produce a huge static executable with no shared libraries at all)
One more note: A simple workaround would be to copy the executable with the required shared libraries (those that do not exist at the host) to the same directory. Then set LD_LIBRARY_PATH=. before running your dynamically linked executable. This will force searching for libraries in the current directory as well as system directories.
EDIT: I just noticed you said "windows machine". The above is relevant to UNIX machines so probably not useful to you. I'll leave it here in case someone needs the information.

Resources