What does this linking error mean? - linker

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.

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.

Finding location of linker functions

I have a situation where I recently added a bunch of pcap functionality to a shared library that I've written to do some packet sniffing/injecting stuff.
I installed the pcap stuff, i.e.
sudo apt-get install libpcap-dev
wrote all the code, then tried to build it with my makefile
All compiled and linked no problem
But when I looked more closely I noticed I hadn't specified -lpcap as a library dependency
But the linker hasn't complained about any undefined references..
So the question is how is the linker finding those pcap functions that I've called in my library code?
I was aware that if you use socket.h functions they're contained within the standard C runtime lib so you don't need to explicitly specify a library dependency. Is it the same for pcap?
Is there a way of querying where the linker has found its functions, i.e. where it found the pcap functions in this instance? I'd like to understand whats going on, rather than just being glad it worked..
To clarify, can you find the specific library file (.so or .a) that the linker has used when linking to a function that my code references?
possibly a verbose option to see exactly what the linker is doing?

Make AIX load all shared symbols at run time?

I'm on AIX 5.3, working with C.
I have an application (foo) that links in a shared library (lib1.so) at run time, then dynamically loads another library (lib2.so) via dlopen(). lib2.so uses some functions in lib1.so that foo does not use. When I execute the application, I get an error similar to:
rtld: 0712-001 Symbol someLibFunc was referenced from module
/libdir/lib2.so(), but a runtime definition of the symbol was not found.
I don't believe that changing the dlopen() flags would have any effect, since my issue seems to have something to do with what symbols are imported when run-time linking occurs. Is there some type of ld option I can use when building foo to force it to import all shared library symbols? This same build works great in my Linux environment.
I found the culprit.
I ran 'dump -Tv' on lib1.so and found that the function I expected to be exported was not there (although it did show up in nm, oddly enough). The library was linked with -bexpall so all symbols should be there. I dug deeper into the ld man page and saw that expall did not export symbols prefixed with an underscore (_). The function I was trying to use began with an underscore. I found the 'expfull' ld option, which exports symbols prefixed with an underscore, rebuilt lib1.so with that option, and everything is good now.

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.

linker error in c

how can i resolve a linker error in c?
this is the error message:
undefined reference to HPDF_Page_SetRGBStroke
If you are using an external library, you have to tell the linker that it should be included. It has no means of automagically finding out what you're using there.
Using gcc you can do this by compiling the program with -llibrary.
Apparently, you're trying to use a routine from the libharu PDF library, and it seems you're not linking against this library.
How exactly you would resolve this depends on the toolchain you're using -- under gcc, you would have to add a -lharu option or similar to the linker options.

Resources