2

I have a .so library and while building it I didn't get any undefined reference errors. But now I am building an executable using the .so file and I can see the undefined reference errors during the linking stage as shown below:

xy.so: undefined reference to `MICRO_TO_NANO_ULL'

I referred to this and this but couldn't really understand the dynamic linking.

Also reading from here lead to more confusion:

Dynamic linking is accomplished by placing the name of a sharable library in the executable image. Actual linking with the library routines does not occur until the image is run, when both the executable and the library are placed in memory. An advantage of dynamic linking is that multiple programs can share a single copy of the library.

My questions are:

  • Doesn't dynamic linking means that when I start the executable using ./executable_name then if the linker not able to locate the .so file on which executable depends it should crash?

  • What actually is dynamic linking if all external entity references are resolved while building? Is it some sort of pre-check performed by dynamic linker? Else dynamic linker can make use of LD_LIBRARY_PATH to get additional libraries to resolve the undefined symbols.

Yug Singh
  • 3,112
  • 5
  • 27
  • 52
  • People voting for the question to be closed - Please post a link where I can read about it and I will delete the question myself. – Yug Singh Jan 24 '20 at 12:23
  • You should indeed post the linker errors you observe. – Ctx Jan 24 '20 at 12:24
  • @YugSingh "Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question." -- close reason for "Needs focus" – S.S. Anne Jan 24 '20 at 12:24
  • @S.S.Anne I felt like the questions were related and occurred to me while trying to understand the dynamic linking. That's why I posted them as part of same question. Thanks for the suggestion. – Yug Singh Jan 24 '20 at 12:25
  • @Ctx I have added the linker error. Thanks for the suggestion. – Yug Singh Jan 24 '20 at 12:27
  • Assuming `MICRO_TO_NANO_ULL` is a macro, don't you get `implicit declaration of function` warning? – KamilCuk Jan 24 '20 at 12:32
  • @KamilCuk I searched for the `implicit function declaration` warning in the logs but it returned nothing. – Yug Singh Jan 24 '20 at 12:34
  • @KamilCuk Thanks. I can see the warning `-Wimplicit-function-declaration`. Need to read about it. Also, I can see the same warning with `printf` also but that doesn't seem to cause any issues. – Yug Singh Jan 24 '20 at 12:38
  • @YugSingh That means you need to `#include` your header file and `stdio.h` inside your library's source code. Implicit declaractions of variadic functions cause undefined behavior. – S.S. Anne Jan 24 '20 at 12:47
  • Implicit declarations are even invalid since long ago, but today compilers usually still tolerate it. – Ctx Jan 24 '20 at 12:54

4 Answers4

2

Doesn't dynamic linking means that when I start the executable using ./executable_name then if the linker not able to locate the .so file on which executable depends it should crash?

No, linker will exit with "No such file or directory" message.

Imagine it like this:

  • Your executable stores somewhere a list of shared libraries it needs.
  • Linker, think of it as a normal program.
  • Linker opens your executable.
  • Linker reads this list. For each file.
    • It tries to find this file in linker paths.
    • If it finds the file, it "loads" it.
    • If it can't find the file, it get's errno with No Such file or directory from open() call. And then prints a message that it can't find the library and terminates your executable.
  • When running the executable, linker dynamically searches for a symbol in shared libraries.
    • When it can't find a symbol, it prints some message and the executable teerminates.

You can for example set LD_DEBUG=all to inspect what linker is doing. You can also inspect your executable under strace to see all the open calls.

What actually is dynamic linking if all external entity references are resolved while building?

Dynamic linking is when you run the executable then the linker loads each shared library.

When building, your compiler is kind enough to check for you, that all symbols that you use in your program exist in shared libraries. This is just for safety. You can for example disable this check with ex. --unresolved-symbols=ignore-in-shared-libs.

Is it some sort of pre-check performed by dynamic linker?

Yes.

Else dynamic linker can make use of LD_LIBRARY_PATH to get additional libraries to resolve the undefined symbols.

LD_LIBRARY_PATH is just a comma separated list of paths to search for the shared library. Paths in LD_LIBRARY_PATH are just processed before standard paths. That's all. It doesn't get "additional libraries", it gets additional paths to search for the libraries - libraries stay the same.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • 1
    What you describe at the top is the situation, when the _dynamic linker itself_ is not found. The error message is different, if just a shared library or a single symbol is not found. – Ctx Jan 24 '20 at 12:56
  • Shouldn't the answer to `Is it some sort of pre-check performed by dynamic linker? ` be **no** as in the previous paragraph you mentioned `When building, your compiler is kind enough to check for you, that all symbols that you use in your program exist in shared libraries.`? In this question I was still referring to undefined reference error we get while building the executable. – Yug Singh Jan 27 '20 at 13:04
1

Doesn't dynamic linking means that when I start the executable using ./executable_name then if the linker not able to locate the .so file on which executable depends it should crash?

Yes. If the .so file is not present at run-time.

What actually is dynamic linking if all external entity references are resolved while building? Is it some sort of pre-check performed by dynamic linker? Else dynamic linker can make use of LD_LIBRARY_PATH to get additional libraries to resolve the undefined symbols.

It allows for libraries to be upgraded and have applications still be able to use the library, and it reduces memory usage by loading one copy of the library instead of one in every application that uses it.

The linker just creates references to these symbols so that the underlying variables or functions can be used later. It does not link the variables and functions directly into the executable.

The dynamic linker does not pull in any libraries unless those libraries are specified in the executable (or by extension any library the executable depends on). If you provide an LD_LIBRARY_PATH directory with a .so file of an entirely different version than what the executable requires the executable can crash.


In your case, it seems as if a required macro definition has not been found and the compiler is using implicit declaration rules. You can easily fix this by compiling your code with -pedantic -pedantic-errors (assuming you're using GCC).

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
  • `If the linker wouldn't require the symbols to link then the dynamic linker would just fail at run-time and there's no point in that, as then software would build correctly and not run correctly.` If it is required for linker to **link the symbol** at **build-time** then it's not dynamic linking. Pls correct me If I am wrong. – Yug Singh Jan 24 '20 at 12:33
  • Is this mandatory for the linker to create the references to symbols used in the application or can it be bypassed? The reason for asking it is because at run-time dynamic linker can make use of `LD_LIBRARY_PATH` for searching the symbol. and as you mentioned in the answer the references can be changed. – Yug Singh Jan 24 '20 at 12:47
  • 1
    @YugSingh Mandatory. It would be silly for a program to build correctly and then fail at run-time. `LD_LIBRARY_PATH` *only* searches for `.so` files. The references *cannot* be changed, only the underlying functions or variables. – S.S. Anne Jan 24 '20 at 12:48
1

It looks like there is a #define missing when you compile your shared library. This error

xy.so: undefined reference to `MICRO_TO_NANO_ULL'

means, that something like

#define MICRO_TO_NANO_ULL(sec) ((unsigned long long)sec * 1000)

should be present, but is not.

The compiler assumes then, that it is an external function and creates an (undefined) symbol for it, while it should be resolved at compile time by a preprocessor macro.

If you include the correct file (grep for the macro name) or put an appropriate definition at the top of your source file, then the linker error should vanish.

Ctx
  • 18,090
  • 24
  • 36
  • 51
1

Doesn't dynamic linking means that when I start the executable using ./executable_name then if the linker not able to locate the .so file on which executable depends it should crash?

It will crash. The time of crash does depend on the way you call a certain exported function from the .so file. You might retrieve all exported functions via functions pointers by yourself by using dlopen dlysm and co. In this case the program will crash at first call in case it does not find the exported method.

In case of the executable just calling an exported method from a shared object (part of it's header) the dynamic linker uses the information of the method to be called in it's executable (see second answer) and crashes in case of not finding the lib or a mismatch in symbols.

What actually is dynamic linking if all external entity references are resolved while building? Is it some sort of pre-check performed by dynamic linker? Else dynamic linker can make use of LD_LIBRARY_PATH to get additional libraries to resolve the undefined symbols.

You need to differentiate between the actual linking and the dynamic linking. Starting off with the actual linking: In case of linking a static library, the actual linking will copy all code from the method to be called inside the executable/library using it. When linking a dynamic library you will not copy code but symbols. The symbols contain offsets or other information pointing to the acual code in the dynamic library. If the executable does invoke a method which is not exported by the dynamic library though, it will already fail at the actual linking part.

Now when starting your executable, the OS will at some point try to load the shared object into memory where the code actually resides in. If it does not find it or also if it is imcotable (i.e.: the executable was linked to a library using different exports), it might still fail at runtime.

Chris
  • 1,226
  • 1
  • 12
  • 26