Complicated dynamic and static linking with duplicates (Firefox Add-on, WebRTC and VP8) - firefox-addon

I've tried to formulate the problem in an abstract way, but anyway I give details about the actual libraries in the end.
Dynamic library Addon is statically linked against other library WebRTC which has some code in assembly and this code is linked into WebRTC as object files together with WebRTC's own object files. Lets call this assembly code VP8. Functions of VP8 are marked extern inside WebRTC. Some function Encode() from Addon calls functions of WebRTC which eventually calls functions from VP8.
Now, the application Firefox which is going to load library Addon is quite complex and has its own version (means statically linked) of library WebRTC(let's call it WebRTC2), but an older one.
So, here is a problem: if a call of Encode() is made from the application Firefox, WebRTC functions get called (not WebRTC2, which is correct) BUT when WebRTC tries to call VP8 functions, they get called from the WebRTC2 version (means application's version of WebRTC), but not from WebRTC.
Is there are way to force WebRTC make calls only from local copy of VP8?
Application Firefox is a Firefox browser, WebRTC is a WebRTC library, VP8 is a VP8 codec library (inside WebRTC) and Addon is my Firefox C++ add-on.
UPDATE - DETAILED DESCRIPTION
Here is "unabstract" description of the problem:
So there is a C++ XPCOM add-on which is statically linked against latest version of WebRTC library.
At some point inside add-on a call for encoding a frame is made (method Encode of VP8Encoder class) and it crashes in Firefox all the time, while continue to work well on test programs using gtest framework.
The problem is that at some point inside WebRTC there is VP8 assembly code which is get called for encoding and functions of this assembly code are declared as extern in implementation files. Actually, it crashes on vp8_intra_pred_y_ve_sse2 function.
I've compared three assembly codes of this function: one is from my version of WebRTC (used in add-on), second - where debugger crashed and the third one - from source code of Mozilla's WebRTC.
It turned out that for some weird reason, Mozilla's code get called instead of add-on's WebRTC (they both have same names of course) and as Mozilla's WebRTC code is outdated, it crashes with EXC_BAD_ACCESS.

This probably won't be much help to you, but since no one else has responded, here I go ...
You didn't mention if you're running on Linux, Windows, or something else. My answer is for Linux. I believe Windows loads dynamic libraries differently.
I think what's happening is that you've statically linked against the WebRTC library stub interfaces and those stub interfaces are dynamically linking to the actual implementation, and then getting the first instance of the WebRTC library loaded into firefox instead of the second. Be sure that you're really linking against a statically compiled version of the WebRTC library.
The linux dlopen(3) man page has an interesting flag listed that seems like it would help if your library was the one loading the WebRTC library:
void *dlopen(const char *filename, int flag);
dlopen()
The function dlopen() loads the dynamic library file named by the null-
terminated string filename and returns an opaque "handle" for the
dynamic library. [...]
RTLD_DEEPBIND (since glibc 2.3.4)
Place the lookup scope of the symbols in this library ahead of
the global scope. This means that a self-contained library will
use its own symbols in preference to global symbols with the
same name contained in libraries that have already been loaded.
This flag is not specified in POSIX.1-2001.
Unfortunately, firefox is the one loading your library.
If your library was dynamically linked against WebRTC (which it seems to be) and you explicitly loaded the WebRTC library you want using dl_open() with the RTLD_DEEPBIND flag, than that would solve your problem.
This won't help you much since its not your code that's binding to vp8_intra_pred_y_ve_sse2, but its worth pointing out that gcc also has the dlsym() function which can take a couple of special flags:
void *dlsym(void *handle, const char *symbol);
dlsym()
The function dlsym() takes a "handle" of a dynamic library returned by
dlopen() and the null-terminated symbol name, returning the address
where that symbol is loaded into memory. [...]
There are two special pseudo-handles, RTLD_DEFAULT and RTLD_NEXT. The
former will find the first occurrence of the desired symbol using the
default library search order. The latter will find the next occurrence
of a function in the search order after the current library. This
allows one to provide a wrapper around a function in another shared
library.
You could use that in your code to at least debug what's going on by having it print out the values it gets for a lookup of vp8_intra_pred_y_ve_sse2.
Finally, the same man page notes that linux has a dlvsm() that takes a version string argument as well, allowing the XPCOM code to specify which version of the function it wants:
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <dlfcn.h>
void *dlvsym(void *handle, char *symbol, char *version);
If it were me, and I was forced to dynamically link the stuff, I'd go with the brute force approach. Go into the libraries and change the function names (in both libraries). Its not elegant, and it will be a headache whenever a new version of either library comes out, but its simple and direct.

Related

How to use PathCchCanonicalizeEx with C++Builder 10.2?

I have a legacy Windows project using the legacy 32 Bit C++ compiler. For various reasons I need to use the Windows 8+ function PathCchCanonicalizeEx. C++Builder seems to provide the header and some module definition file for that, but I can't find any library to link against:
[ilink32 Error] Error: Unresolved external 'PathCchCanonicalizeEx' referenced from C:\[...]\WIN32\DEBUG\TMP\FILE.OBJ
How am I supposed to fix this? Do I need to add a Windows 8.1 SDK? Is the necessary lib simply named differently and I can't find it? Something completely different?
According my tests, one has two options:
IMPLIB/MKEXP
I'm developing/testing a some Windows 10 21H2, which provides an implementation for PathCchCanonicalizeEx in some DLL already. So if that source DLL is known, one can use IMPLIB or MKEXP to create an import library manually. I did that and after adding the created library from IMPLIB to my project, the linker errors were instantly gone.
Though, it's not that easy to know where PathCchCanonicalizeEx is placed in. One pretty easily finds the api-ms-win-core-path-l1-1-0.dll, but that thing is NOT an actual file on the disk and therefore can't be used by IMPLIB or MKEXP. That name is only a virtual concept for the library loader to address the same named API set of modern Windows, the extension .dll doesn't mean it's a file at all.
You can use an API set name in the context of a loader operation such as LoadLibrary or P/Invoke instead of a DLL module name to ensure a correct route to the implementation no matter where the API is actually implemented on the current device. However, when you do this you must append the string .dll at the end of the contract name. This is a requirement of the loader to function properly, and is not considered actually a part of the contract name. Although contract names appear similar to DLL names in this context, they are fundamentally different from DLL module names and do not directly refer to a file on disk.
https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-apisets#api-set-contract-names
What you really need to work with is KernelBase.dll, which is even documented by MS.
implib "KernelBase x86.lib" C:\Windows\SysWOW64\KernelBase.dll
implib "KernelBase x86-64.lib" C:\Windows\System32\KernelBase.dll
Module Definition File
The downside of manually creating LIB files is that one needs to maintain those with the project. Things depend on if the target is 32 or 64 Bit, DEBUG or RELEASE, so paths might become a bit complex, one might need to create relative paths for libraries in the project settings using placeholders for the target and stuff like that.
It seems that all of this can be avoided with Module Definition Files, which's purpose is to provide IMPORT and EXPORT statements to either consume exported functions by other DLLs or make that possible for others with own functions. I've successfully resolved my linker problems by simply creating a file named like my app using the extension .def alongside my other project files. That file needs to be added to the project, though.
dbxml.cbproj
dbxml.cbproj.local
dbxml.cpp
dbxml.def
dbxml.res
[...]
The following content made the app use the correct function from the correct DLL. Though, what didn't work was using the API set name, which resulted in an error message by the linker.
IMPORTS
KernelBase.PathCchCanonicalizeEx
IMPORTS
api-ms-win-core-path-l1-1-0.PathCchCanonicalizeEx
[ilink32 Error] Invalid command line switch for "ilink32". Parameter "ItemSpec" cannot be null.
[ilink32 Error] Fatal: Error processing .DEF file
The latter is after restarting C++Builder, so I guess the format of the file is simply wrong because of the API set name.

IOS dylib entry points

We are experimenting with Dart ffi (foreign function interface) and are looking to directly call into the IOS AVFoundation dylib from dart.
To use ffi we need to dynamically load the AVFoundation dylib.
These leads to several questions.
how do we find the path of the AVFoundation dylib?
how do we get/find a list of entry points into the dylib?
do we load the dylib directly or do we need to load it via a framework?
we are likely to need to load other dylibs (for core features) so ideally we need a generic method of identifying the path to the dylib and its set of entry points.
Will we have any trouble shipping an app that uses dynamically loaded dylibs? I come across something (which I've now lost) that seems to be suggesting that the app store may not allow an app to be uploaded that uses dynamic loading.
We are considering an alternate path which is to create a small objective-c library that effectively proxies through the calls from av foundation, however we are trying to avoid any objective-c/swift code.

Cannot static link to glewInit() with Mingw

I am currently building a program using GLEW, compiled with MinGW ( in Eclipse ). I built the GLEW libs from the source provided by the GLEW website.
I have been able to use the GLEW declared functions without a problem if I link with the .DLL. However, if I try to link with the static library ( libglew32.a ) with the "GLEW_STATIC" flag defined, I get an error for the function "glewInit()":
undefined reference to `imp_glewInit#0'
If I open up libglew32.a in a hex editor, I can see that there is an entry, but it is named _glewInit#0. So it seems like the disconnect is that my program's compile is trying to append this "imp" string to the front of the function name in the library.
It seems like there must be mis-match of the calling convention here, but I don't know what would cause it yet. There are certainly lots of different ways that GLEW declares the api functions in the header depending on what compiler definitions are set, but I haven't narrowed it down yet.
Any ideas out there?
It looks like that imp prefix gets added for function stubs that are intended to be loaded at runtime from a .DLL. In other words, I wasn't actually staticly linking against GLEW. It turned out that I didn't quite have my eclipse C++ symbols set up correctly, so GLEW_STATIC was not being defined. After making sure that it was set up in the g++ call, it links just fine.

Rewriting symbols in static iOS libraries

I am working on an iOS app which links several static libraries. The challenge is, those linked libraries define same method names with different implementations. Oddly, I don't get any duplicate symbol definition errors; but, to no surprise, I end up with access to only one implementation of the method.
To be more clear, say I have libA and libB and they both define a global C method called func1()
When I link both libA and libB, and make a call to func1(), it resolves to either libA's or libB's implementation without any compilation warning. I, however, need to be able to access both libA's func1() and libB's func1() separately.
There's a similar SO post that explains how it can be done in C (via symbol renaming) but unfortunately, as I found out, objcopy tool doesn't work for ARM architecture (hence iPhone).
(I will submit it to the App Store, hence, dynamic linking is not an option)
It appears that you are in luck - you can still rename symbols with the ARM binary format, it's just a bit more hacky than the objcopy method...
NOTE: This has only been tested minimally, and I would strongly advise you to make a backup of all libraries in question before trying this!
Also note that this only works for files not compiled with the C++ compiler! This will fail if the C++ compiler was used on these files.
First, you will need a decent hex editor, for this example, I will be using Hex Fiend.
Next, you will open up a copy of your of of your libraries, let's call it lib1-renamed.a, and do the following with it:
Find the name of the symbol you wish to re-name. It can be found using the nm tool, or, if you know the header name, you should be set.
Next, you will use hex fiend, and to a textual replace of the old name (in this case foo), and give it a new name (in this case, bar). These names must have the same length, or it will corrupt the binary's offsets!
Note: if there is more than one function that contain's foo's name in it, you may have problems.
Now, you must edit the headers of the library you changed, to use the new function name (bar) instead of the old one.
If you have done the three simple† steps above properly, you should now be able to compile & link the two files successfully, and call both implementations.
If you are trying to do this with a universal binary (e.g. one the works on the simulator as well), you'd be best off using lipo to separate the two binaries, using objcopy on the i386/x64 binary, and then using my method on the ARM binary, and lipo it back together.
†: Simplicity is not guaranteed, nor is it covered by the Richard J. Ross III super warranty. For more information about the super warranty, call 1-800-FREE-WARRANTY now. That's 1-800-FREE-WARRANTY now!

AIX dynamic linking

I'm working on porting a library onto AIX. It works on Solaris, Windows and Linux but AIX is giving me headaches. I'm at a point where it builds and runs but I have an issue with some of the libraries it's linking in. Ideally I want to be able to ship a library that just requires the c runtime to be available with no other dependencies. At the moment I'm having a problem with libpthread which I can see is a symlink to an AIX specific threading library.
My issue is this:
If I don't link pthread (I don't seem to need to on Solaris for the same code base) then I get undefined symbols. That's fine I am using pthreads. If I link it in then it works fine, except that any calling application also has to link to pthreads. I don't really understand is why does my calling app, which has no dependency on pthread, need to link against it just because it's calling a library which links to the shared object?
I'm on AIX 6.1 using gcc 4.2.4.
I'd be OK with shipping a library that requires pthreads to be present on the library path (ideally we'd get a static version) but I'm a bit unhappy about shipping a library that places linker rqeuirements on the client.
Any ideas on what I might be doing wrong?
I defeinitely seem to be going in circles. I removed the -shared flag on the linker to resolve an earlier problem and that, of course, makes the library static. So the behaviour is just normal behaviour in that if you depend on a dynamic library from a static one you have to link both into your app. So I've put the shared flag back and now half of my functions are no longer accessible. It does explain the problem I was seeing though.

Resources