Does Clang/GCC really support a delay loading feat

2019-01-18 15:59发布

问题:

Would you mind to leave your comment on this if you have really experienced which relates to the title above? I have tried to make a shared object to be delay loaded with both Clang and GCC on Ubuntu (I actually don't mind which compiler is used), but they do not look really support any delay loading feature (I expected the delay loading feature put a stub in a parent object, which was trying to load another object on demand, at a moment when the functionality is required, but it actually did not). The following commands show that I tried to make libbar.so to be delay loaded against to libfoo.so:

clang bar.c -fPIC -shared -o libbar.so
clang foo.c -Wl,-zlazy,lL'/path/to/where/lib/is',-lbar -o foo

You'll see the libfoo.so raise an exception before entering to the entry if libbar.so does not exist. Anyway, I don't mind if there were any typo in the commands above, but want to know Clang/GCC really supports a delay loading feature or not.

Personally, however, I can't believe if Linux program developers have been required to invoke dlopen() or dlsym() to make a shared object to be delay loaded if Clang/GCC did not support any delay loading feature. It could be okay if the object was written in C, but if it were written in C++, the situation must be completely complicated :(

I believe a solution which is realized with a help from compiler or linker is the best because I have successfully done it with Windows and Mac OS. So I feel it would be a natural reaction where citizen wants to dream to have a delay loading feature even on Clang/GCC. I'd also be appreciate if you have any comment on my feeling.

PS. I know Solaris supports a delay loading feature but that's not a way to go for me because I will don't develop anything on it.

Anyway, thank you very much in advance.

回答1:

This is more a question of functionality provided by the run time linker, ld-linux.so.

This linker does support lazy binding of symbols, but not lazy loading of libraries. What this means is that each of the shared objects which an executable requires are loaded when the program starts, but the symbols within the program are not resolved to the loaded libraries until they are first referenced.

The reason for this is performance. A library may contain many thousands of symbols for functions that never get called in a single execution of a program. Resolving them all would be a waste of time.

For this reason, if a library does not contain the expected symbols, you can get 'undefined symbol' errors well after the program has started running, but if a library is missing altogether, you will get an error before the program starts.

The -zlazy option which you are quoting controls lazy symbol binding only. In fact it is enabled by default (at least for GCC, I did not check for clang).

The only way to have a library loaded after program startup, for example in response to some command line option, configuration or other dynamic condition, is to call dlopen.

You might want to look around for a good plugin framework - for references see:

  • Cross-Platform C++ Dynamic Library Plugin Loader
  • What's safe for a C++ plug-in system?
  • Good patterns for a C/C++ plugin-based system?


回答2:

Linux does not support delay loading of libraries out of the box but it can easily be implemented using the same mechanism that is used on Windows i.e. by linking against small stub static library which dlopens main shared library on first call to any of it's functions.

You can implement such stub library by hand, via custom script tailored for your project or use Implib.so to generate it automatically:

$ clang bar.c -fPIC -shared -o libbar.so
$ implib-gen.py libbar.so
$ clang foo.c libbar.tramp.S libbar.init.c -o foo