How to resolve weak symbol __gnu_Unwind_Find_exidx? - linker

I am trying to build a c++ app on TizenRT platform. After linking, I find that the
_gnu_Unwind_Find_exidx symbol is coming as a weak symbol in the final binary. It seems that this symbol is used by unwind-arm.c. I could not find the implementation of this API in the arm gcc toolchain. I realised that we need to implement this API according to our platform and hence I implemented it in my C library.
However, even after linking the C++ app with the C library (Which has the new implementation of this API), the symbol still appears as a weak symbol in the final binary.
My link command is somewhat as follows:
arm-none-eabi-ld my-app.o --start-group libxxx.a libc.a libgcc.a --end-group
I have used libgcc.a at the end because I suppose that libc.a and other libraries might have a dependency on it. However, I have put all the libraries in the group. So, I was hoping that the linker would search all the libraries recursively to resolve all undefined symbols.
Does the linker treat weak symbols differently from undefined symbols?
How do I tell the linker to pick the implementation of the API in my C library?
Regards!

Related

Why does (host) GCC need to be built against the target's standard library?

I've been looking into building cross-toolchains and have a general question about the compilation and workings of gcc.
The question is about this excerpt from the official gcc documentation:
In order to build GCC, the C standard library and headers must be present for all target variants for which target libraries will be built (and not only the variant of the host C++ compiler).
Why is the target's standard library required to build the (cross) compiler itself? Shouldn't the (cross) compiler running on the host only require the host's standard library to be built and then be able to compile the target's standard library?
I also found this on crosstool-NG's how a toolchain is constructed:
the final compiler needs the C library, to know how to use it, but: building the C library requires a compiler
This is consistent with what's stated above but I don't get why the final compiler needs to be built against a prebuilt target C library just to know how to use it later on. What is there to know for the host compiler about the target C library? Isn't it the linker's job to link target programs against the target's standard library at compile time?
Because that's the only way to ensure a working compiler for the target platform is created. There's no point in creating a non-working compiler, distributing it to the target platform, and finding out then that it's useless.
In general, a non-shared-object executable file is only successfully created if there are no unresolved symbols.
Per the GCC 11.2 "Overall Options" documentation
Compilation can involve up to four stages: preprocessing, compilation proper, assembly and linking, always in that order. GCC is capable of preprocessing and compiling several files either into several assembler input files, or into one assembler input file; then each assembler input file produces an object file, and linking combines all the object files (those newly compiled, and those specified as input) into an executable file.
So the final step is linking. The GNU linker 'ld' man page states:
Normally the linker will generate an error message for each
reported unresolved symbol but the option
--warn-unresolved-symbols can change this to a warning.
and
--error-unresolved-symbols
This restores the linker's default behaviour of generating
errors when it is reporting unresolved symbols.
So, by default linking fails when there are unresolved symbols.
Why?
Because if there are unresolved symbols, the resulting executable file won't work when it's run.
And the only way to ensure there are no unresolved symbols is to have all the necessary libraries from the target platform available when cross-compiling so all symbols can be resolved when the new compiler executables are being linked.

choose exported symbols when linking an elf application and shared library

when linking an elf application or share library, I want to choose which symbols to export. By default, when linking an application no function symbol is exported and when linking a shared library all function symbols are exported. Is there any way to control which symbols to export? When linking an application, I can use -rdynamic or -Wl,--export-dynamic to get all symbols, and I can use -Wl,--dynamic-list <symfile> to get only some symbols. However when linking a library, are those options ignored?
Found out after testing a little:
for ELF applications, you can use -rdynamic or -Wl,--export-dynamic to export all symbols, or you can use -Wl,--dynamic-list <sym-file> to export only some symbols when linking your application through gcc.
for ELF libraries, you can't use -rdynamic, -Wl,--export-dynamic or -Wl,--dynamic-list <symfile>, you must use -Wl,--version-script=<verfile> when linking your library through gcc.
The version-script and the sym-file are almost the same, except that for sym-file you do not code a version and a scope. Documentation: gnu ld
Is there any way to control which symbols to export?
The usual way to control symbol visibility in shared library is either
Use linker script, as described here, or
Use __attribute__((visibility("default"))) on symbols you explicitly want to export and build with -fvisibility=hidden (which will hide everything else).

What does this linking error mean?

When I was compiling a new software, I encountered a bunch of errors emitted by ld.
/usr/lib/libstreamanalyzer.so.0: undefined reference to `xmlSAXUserParseMemory#LIBXML2_2.4.30'
/usr/lib/libstreamanalyzer.so.0: undefined reference to `xmlCtxtResetPush#LIBXML2_2.6.1'
/usr/lib/libstreamanalyzer.so.0: undefined reference to `xmlCreatePushParserCtxt#LIBXML2_2.4.30'
This seems to be confusing. Linker is supposed to be looking for symbols in objects, not library names, but it seems in this case those before the # is the function name/symbol, and LIBXML2_2.6.1 is a library name. And for dynamic library, the soname x.y.z version should only matter in dynamic linking stage, that is when the executable actually runs.
So what does this error really means, and what part of the above assumptions are wrong?
Edit:
The problem appears after installing libxml2 2.7.8. It is gone after libxml2 is upgraded to 2.9.1.
When I was compiling a new software, I encountered a bunch of errors
No, you didn't. You encountered errors when linking, which is different from compiling.
Linker is supposed to be looking for symbols in objects
UNIX linkers also look for symbols in libraries (both archive and shared).
LIBXML2_2.6.1 is a library name
No, it's not. It's a symbol version, which happens to reflect the library in which that symbol was defined.
So what does this error really means
This error means: when libstreamanalyzer.so.0 was linked, it was linked against a library (most likely libxml2.so) that provided versioned symbols xmlSAXUserParseMemory#LIBXML2_2.4.30, etc.
You are now linking your binary against some other version of libxml2, one which does not provide these symbols, and your binary will not work.

linking library built with g 2.95.2 to object files built with gcc 4.6

I'm trying to reuse an old static library built with Linux GCC 2.95.2. I'm using a recent compiler (GCC 4.6) from a 32bit Ubuntu distro. The library is written in C++. I have problems linking against the functions which are encapsulated in classes.
I guess that the naming of the symbols has changed.
http://www.qnx.com/developers/docs/6.3.2/momentics/compatibility/about.html#C++_code:
GCC 2.95.3 (from 6.2.1 or 6.3) and GCC 3.3.5 use different C++ ABIs and have different name mangling. As a result, you can't link C++ binaries (objects, executables, libraries) built with GCC 2.95.3 with binaries built with GCC 3.3.5.
The error output of ld is:
undefined reference to `foo1::Bar()'
(class foo1; Member Bar)
With the tool mn the symbols could be read out. The matching symbol is named in a different way:
Bar__4Foo1
Question: Is there a way the rename the symbols in the library file? Or can I force ld to accept the old naming format?
I guess that the naming of the symbols has changed.
Correct.
What you are missing is that the naming has changed for a reason, namely code produced by g++ 2.95 and g++ 3.3 is ABI incompatible. If you were allowed to link two objects compiled with these compilers together, all you'd get is unexplainable crashes.
By changing the name mangling, GCC developers have saved you the trouble of debugging such crashes.
Is there a way the rename the symbols in the library file?
There is, but if you succeed with that, you'll end up with said crashes, so don't shoot your foot off.

Listing the dependencies of a shared library in Solaris

I am converting a set of static libraries to shared libraries and was able to create the shared libraries successfully. The problem is with the exe's because linking with static library can have unresolved symbols in the library but that is not the case with shared libraries. All the symbols in the shared library should get resolved.
Example:
PROG1 calls LIB1.a calls LIB2.a
Now the make file of PROG1 need not have LIB2.a as PROG1 calls to LIB1.a do not result in calling LIB2.a .So some LIB2.a symbols in LIB1.a can remain unresolved.
After conversion
Both LIB1.so and LIB2.so have to be included in the makefile of PROG1. Including LIB2.so resolves few linkage issues of LIB1.so but new issues appear due to inclusion of LIB2.so(as it may be depend on LIB3.so)
SO is there any way to find out the all the dependent libraries of a shared library?
I tried using ldd but it prints nothing.
Please let me know if my analysis is wrong.
This is a slightly personal opinion, but I think you should link your shared libraries so that you get an error for unresolved symbols (with -z defs). That means you sort out each library independently and don't get any nasty surprises at link time.
Of course, this only works if your libraries are clean and don't contain recursive dependencies (which are probably a bad thing anyway) and you aren't trying to do dynamic loading where you can load any of impl_1.so, impl_2.so or impl3_.so to provide code for a client client.so at runtime. But it works well if all you have are link time dependencies.
Indeed, if you don't do this, and are using ld rather than cc to do the linking,, you'll get pretty much what you're seeing - no dependencies, and errors at linktime

Resources