How to deal with undefined symbols when loading Mono libraries in Linux - mono

I'm porting my Windows Mono application to Linux, one step at a time, first to WSL Linux under Windows 10, then hopefully to Real Ubuntu. Everything described here behaves identically under both WSL and Ubuntu 20.04.
My application loads the /usr/lib/libmono-2.0.so shared library, but in doing so the loader throws an exception: undefined symbol: _ZTIPi. Some research showed that this symbol was defined in libstdc++.so, so I "pre-loaded" that as well. That had no effect.
Meanwhile, I found this code fragment perusing the mono code base. It would be in mono\mini\mini-llvm.c: (https://github.com/mono/mono/blob/main/mono/mini/mini-llvm.c)
/* Add a reference to the c++ exception we throw/catch */
{
LLVMTypeRef exc = LLVMPointerType (LLVMInt8Type (), 0);
module->sentinel_exception = LLVMAddGlobal (module->lmodule, exc, "_ZTIPi");
LLVMSetLinkage (module->sentinel_exception, LLVMExternalLinkage);
mono_llvm_set_is_constant (module->sentinel_exception);
}
What exactly is happening here? What do I need to know and understand to successfully load this library?

Solution so far was to build and install Mono outside of the default release.
See https://www.mono-project.com/docs/compiling-mono/linux/
then One Stop Shop Build Script (Debian)
If you follow the instructions, your alternate Mono installation would be in /usr/local
This would suggest that the Mono release was somehow incorrectly compiled.

So, having found this after having the same issue, thank you for the information in the question and answer, it helped me figure out how to solve it. However, your solution doesn't answer your "What exactly is happening here?", which I shall try to explain.
Let's start with the _ZTIPi symbol, which when run through c++filt comes out as: typeinfo for int*
Which is indeed a part of the C++ standard library. It is listed as undefined in the default install of libmono, but not listed at all in the one I compiled from source.
You can check this with something like:
$ readelf --all /usr/lib/libmono-2.0.so | grep _ZTIPi
However, libstdc++.so isn't listed as needed library in either case.
You can check this with something like:
$ readelf --all /usr/lib/libmono-2.0.so | grep NEEDED
This all means that when you try to load in libmono the dynamic linker will try to resolve the _ZTIPi symbol by looking in the libraries listed by libmono (where it can't find it), and in the global symbol table for the process, which may or may not have it.
If you link against libmono at compile-time the solution would be to also link against libstdc++ at that time. This way, your executable will list libstdc++ as needed library, causing the dynamic linker to load its symbols into the global symbol table. When loading libmono the dynamic linker can then find the symbol fine.
If you load libmono dynamically at runtime, you'll have to load in libstdc++ first, using something like this:
void * cxxlib = dlopen("libstdc++.so.6", RTLD_LAZY | RTLD_GLOBAL);
Key thing here is the RTLD_GLOBAL flag, which will add all symbols to the global table, so they can be found when you're trying to load libmono.
And alternative is of course to build mono yourself, which should end you up with a libmono that isn't subtly broken. In that case, make sure to throw in a call to mono_set_dirs, like this:
mono_set_dirs("/opt/mono/lib", "/opt/mono/etc");

Related

GNU Radio missing Osmocom. Cant even build it to install

I am trying to follow along with some Youtube tutorials by the maker of HackRF and when using GNU Radio it seems they no longer have Osmocom, or WX blocks. So I go to the repo found here https://github.com/osmocom/gr-osmosdr/tree/master , also note they dont have an "issues" tab to ask questions in. Anyways I follow the instructions and get this failure:
CMake Error at /usr/lib/cmake/pybind11/pybind11Tools.cmake:165 (add_library):
Target "osmosdr_python" links to target "sndfile::sndfile" but the target
was not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
Call Stack (most recent call first):
/usr/lib/x86_64-linux-gnu/cmake/gnuradio/GrPybind.cmake:261 (pybind11_add_module)
python/bindings/CMakeLists.txt:28 (GR_PYBIND_MAKE_OOT)
CMake Error at lib/CMakeLists.txt:51 (add_library):
Target "gnuradio-osmosdr" links to target "sndfile::sndfile" but the target
was not found. Perhaps a find_package() call is missing for an IMPORTED
target, or an ALIAS target is missing?
So I am not sure where to go from here. Is there a replacement to Osmocom? I noticed a "soapy" source called HackRF but it is so basic compared to the Osmocom one. I dont really understand how GNURadio works but nerfing a feature that is documented all over the internet in GNU Radio tutorials seems odd.
Any ideas?
Yes, gr-soapy is the what I'd recommend you use. It's not a "replacement", it's an alternative. But unlike gr-osmosdr (which was never part of GNU Radio), it's part of modern GNU Radio.
Your youtube tutorials must be really outdated if they still use WXGui (we've started telling people WXGUI was no longer maintained and will be removed about 10 years ago). That's a bad start. Instead, try to go through the official GNU Radio Academy at https://tutorials.gnuradio.org
but it is so basic compared to the Osmocom one
What feature that the HackRF actually has and that is useful to you are you missing?

Registering a DirectshowFilter links InprocServer32 registry entry to regsvr32.exe instead of host DLL, where did I go wrong?

I have a DirectShow filter (MonogramAAC encoder) successfully compiling. It also registers successfully, however, when I try to instantiate the filter in GrapheditPlus, it shows a CO_E_ERRORINDLL. After inspecting the filter properties under GraphEditPlus, the filter was actually linked to RegSvr32.exe instead of the actual host DLL!
Here's the evidence:
I'm sure the .def file in the linker is correct, I also tested that it IS being considered by the compiler and it is correctly pointing to the filter DLL.
A little bakground info:
I couldn't get the original project to compile under Visual Studio 2017 after automated conversion. (I couldn't resolve strange MFC and runtime library linker errors between the Monogram filter and the libaac.lib library, that I'm also able to compile successfully).
Finally I decided to recreate a brand-new VS2017 Project mimicking the original one and got it to compile and register (with the only warning being the mismatch between the Project name and the output library), but obviously I missed something important while recreating the project.
Any pointers?
Ok, I managed to find the reason for this unexpected behavior in this old post.
RegSvr32 just calls the DllRegisterServer entry point in your code.
What gets written to the registry is entirely up to your filter. If
you are using the standard baseclass call to AMovieDllRegisterServer2
as your DllRegisterServer, I would suspect that something went wrong
in setting up g_hInst, which should have been done by the call
DllEntryPoint in your DllMain.
…
The DllMain is not being called, so g_hInst stays 0 and
GetModuleFileNameA(...) returns the name of the currently executing
program instead of my filter.
The filter is using MFC (dynamically linked), and its DllMain() version is not calling the DllEntryPoint() function. I had to override the MFC DllMain() by adding extern "C" { int _afxForceUSRDLL; } as described in an answer to this question and call DllEntryPoint() myself to fix the registration problem. (I also found a missing #define was the reason for the property page not showing up).

Static library with ARC support linked to non-ARC project causing linker errors

I have a non-ARC project that uses an ARC-enabled static library. This is a supported scenario, so that everything works fine. That is, until I run the code on a 4.x device, including the Simulator. In that case the code blows up with the following linker error:
dyld: lazy symbol binding failed: Symbol not found: _objc_storeStrong
Referenced from: /Users/zoul/Library/Application Support/iPhone Simulator/4.3.2/Applications/…/Demo.app/Demo
Expected in: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/Foundation.framework/Foundation
This happens as soon as some of the ARC-enabled code attempts to call _objc_storeStrong function, like in an init method (self = [super init]). Converting the main project to ARC solves the problem, but I’d like to know if there are other solutions.
I assumed that the toolchain may have added the necessary libraries to link to, in order for ARC to work properly. So the linker transcript may contain this piece of information. If the project of the app itself is not ARC-enabled, you may not get these by default, but you could still link to them by defining them explicitly.
Looking at the build transcript you can indeed find the appropriate linker flag there: it’s called -fobjc-arc (just as the related compiler flag). When you add this setting to Other Linker Flags, the linker will include the ARC library with the main build product and the code should run fine.
I'm adding a new answer to this as the previous accepted solution no longer appears to work with Xcode 4.3.2. I can only assume that the -fobjc-arc linker flag was never supposed to be exposed and has now been removed.
This appears to be a known issue although the only thread I can find on this with somebody from Apple commenting on the devforums dates back to mid-2011. From that thread, it is suggested that manually linking the following file solves the issue:
${DEVROOT}/Platforms/iPhoneOS.platform/Developer/usr/lib/arc/libarclite_iphoneos.a
This requires you to be compiling using the latest compiler/SDK though. I'm submitting this answer without testing, please upvote if it works, downvote if it doesn't!

Getting: "Compilation exited with code 134" when attempting to use "LLVM Optimizing Compiler" switch

I'm getting a "Compilation exited with code 134" when attempting to use the "LLVM Optimizing Compiler" switch for release iPhone builds, using MonoTouch 4.0.1.
I don't get much information from build output window at all - just:
"Compilation exited with code 134, command:"
MONO_PATH=(snip)/bin/iPhone/Release/LSiOS.app /Developer/MonoTouch/usr/bin/arm-darwin-mono --llvm --aot=mtriple=armv7-darwin,nimt-trampolines=2048,full,static,asmonly,nodebug,llvm-path=/Developer/MonoTouch/LLVM/bin/,outfile=/var/folders/03/033pAAGuHgGkIy4CorbVV++++TI/-Tmp-/tmp38107451.tmp/Newtonsoft.Json.MonoTouch.dll.7.s "(snip)/bin/iPhone/Release/LSiOS.app/Newtonsoft.Json.MonoTouch.dll"
Mono Ahead of Time compiler - compiling assembly (snip)/mscorlib.dll
What is odd is that in earlier command lines, there is a correlation between the DLL mentioned in the arm-darwin-mono command line and what is the compiling, but in this case it says "mscorlib.dll".
Any thoughts?
I have found a few cases (googling and from bugzilla.xamarin.com) where the error code 134 is related to Mono.Linker being too aggressive (removing something that's needed).
This is easy to confirm by turning off the linker, i.e. "Don't link" in Linker Options. If the build works then you can try isolating the assembly where the linker makes a mistake.
E.g. add a "--linkskip=mscorlib" to the mtouch extra parameters and re-enable linking. This will link everything (Link All) or all SDK (Link SDK assemblies) except the assembly you selected (mscorlib in the example). That's only a workaround and a bug report should be filled so the issue can be fixed properly (and get you all the linker advantages).
However be warned that there are other issues sharing the same error code, like:
http://ios.xamarin.com/Documentation/Troubleshoot#Error_134.3a_mtouch_failed_with_the_following_message.3a
YMMV
mtouch does its native builds in parallel so the logs can be confusing, e.g. you can see a bit of assembly X output followed by some assembly Y output.
Reading the full log might help you (or us) to pinpoint the issue.
I was having the exact same problem Scolestock. My app would build fine until I enabled llvm, then it was "Compilation exited with code 134, command" when trying to build the 7s for the app itself.
I'm elated to say that after 2 days of painstakingly whittling my app down to the core problem, I was able to isolate the issue to the usage of embedded dictionaries such as:
Dictionary<enum, Dictionary<enum, value>>
I was able to fix this by defining a class for the embedded dictionary and using that instead:
public class MyDefinition : Dictionary<enum, value>
{
}
...
public Dictionary<enum, MyDefinition>
Not sure if this will help you, but hopefully it'll help some poor soul who decides to use embedded dictionaries and runs into my same problem.

std::thread in MacPorts gcc4.5

I'm trying to compile some software I've been writing in Linux that uses some fancy new C++0x features on my Mac. I used MacPorts to install the gcc45 package, which gave me /opt/local/bin/g++-mp-4.5, however this compiler doesn't want to compile anything in <thread>. Eg I try to compile:
//test.cpp
#include <thread>
int main()
{
std::thread x;
return 0;
}
and get:
bash-3.2$ /opt/local/bin/g++-mp-4.5 -std=c++0x test.cpp
test.cpp: In function 'int main()':
test.cpp:5:2: error: 'thread' is not a member of 'std'
test.cpp:5:14: error: expected ';' before 'x'
A quick look in /opt/local/include/gcc45/c++/thread shows that the std::thread class is defined, but is guarded by the following:
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
Again, this works perfectly on my Ubuntu machine, so what's the proper way to enable the c++0x <thread> library under the MacPorts version of g++ 4.5 (g++-mp-4.5)? Failing that, is there anything I need to know (configure flags, etc.) before I go about compiling gcc 4.5 myself?
Update:
It doesn't look like the SO community knows much about this, so maybe it's time to go a little closer to the developers. Does anyone know of an official mailing list I could forward this question to? Are there any etiquette tips to help me get an answer?
Update 2:
I asked SO for another temporary solution here, and so I'm now just substituting the boost::thread libraries for the std ones. Unfortunately, there is no boost::future so this isn't quite a full solution yet. Any help would still be greatly appreciated.
Actually <thread> library doesn't work under Mac OS X because pthreads here don't have some functions with timeouts (e.g. pthread_mutex_timedlock()). Availability of this functions have to be checked using _POSIX_TIMEOUTS macro but it's defined to -1 in Mac OS X 10.4, 10.5 and 10.6 (I don't know what's about 10.7) and this functions are really absent in pthread.h.
The _POSIX_TIMEOUTS macro is checked during the configuration of libstdc++. If the check ends successfully _GLIBCXX_HAS_GTHREADS macro becomes defined. And <thread> contents become available with -std=c++0x.
libstdc++ really needs _POSIX_TIMEOUTS e.g. in std::timed_mutex class implementation (see <mutex> header).
To summarize, I think that <thread> would become available on Mac OS X when GCC's gthreads or libstdc++ will implement pthread_mutex_timedlock() (and others) emulation or when this functions will be implemented in Mac OS X.
Or maybe there would be a way in the future C++ standard to query for language features (e.g. this timed functions and classes) and it will be possible to build libstdc++ with this features disabled. However I'm not very familiar with the future standard and have doubts about that feature.
Update - gcc4.7 now allows compilation of on OS X: See here