3

Mac OS X provides a useful library for dynamic loading, called dyld. Among the many interesting functions for dynamic loading handling are functions to allow one to install callbacks which will be called by dyld whenever an image is loaded or unloaded, by dlopen and dlclose, respectively. Those functions are void _dyld_register_func_for_add_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)) and void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)), respectively.

I know it's not possible to have an exact port for Linux, because dyld functions deal with mach-o files and Linux uses ELF files.

So, is there an equivalent of the dyld library for Linux. Or, at least, is there an equivalent of those two functions, _dyld_register_func_for_add_image and _dyld_register_func_for_remove_image, in any Linux library? Or will I have to implement my own versions of these two by myself, which is not so hard, but I would have to find a way to make dlopen and dlclose call callback functions whenever they get called.

EDIT

To must things clearer, I need to make a library that has a callback function that must be called whenever an external library is dynamically loaded by dlopen. My callback function must perform some operations on any dynamic loaded library.

LuisABOL
  • 2,951
  • 4
  • 25
  • 57
  • Why exactly are you asking? What do you want to do with your hooks? What kind of application what sort of plugins? – Basile Starynkevitch Mar 29 '13 at 13:11
  • 1
    I believe that `LD_PRELOAD` for `dlopen` would do what you want... – Basile Starynkevitch Mar 29 '13 at 13:20
  • But why are you asking? What do you want to achieve? – Basile Starynkevitch Mar 29 '13 at 13:21
  • @BasileStarynkevitch When you told me about `LD_PRELOAD`, I thought something: is it possible to create my own version of `dlopen`, which overrides the standard `dlopen` but uses it internally, so that my `dlopen` is the only one who can see the standard `dlopen` and the rest of the program sees my version? (Sorry, for so many "dlopen"s ;) – LuisABOL Mar 29 '13 at 13:28
  • What should your callback function do? – Basile Starynkevitch Mar 29 '13 at 13:28
  • Yes, `LD_PRELOAD` can override the system `dlopen` with your own. But please, explain & edit your question to tell why you need such things, what does your `_dyld_register_func_for_add_image` callback is really doing, and is it affecting shared libraries which are not `dlopen`-ed but simply dynamically linked... – Basile Starynkevitch Mar 29 '13 at 13:29
  • @BasileStarynkevitch Well, my project is a Objective-C runtime library. It is almost ready. It needs to register classes and call some load methods for all object files that were loaded. So, whenever a new library is dynamically loaded, my library needs to check the content of the file looking for any class symbol to register it and add it to some loaded functions list. – LuisABOL Mar 29 '13 at 13:31
  • Then, look at what GCC objective-C runtime is doing. And the details obviously depend of the details of the objective-C compiler you are using on Linux.... – Basile Starynkevitch Mar 29 '13 at 13:32
  • @BasileStarynkevitch Yes, but the point is my library is compatible to NeXT/Apple's one, not to GNUStep. And Apple's version uses `_dyld_register_func_for_add_image` to register the function that must be called whenever `dlopen` is called to look inside any loaded library to find ObjC symbols. – LuisABOL Mar 29 '13 at 13:35
  • @BasileStarynkevitch Maybe I should really create my own version of `dlopen`... – LuisABOL Mar 29 '13 at 13:36

1 Answers1

2

Yes, it is called dlopen(3) using the -ldl standard library

More precisely:

  • compile your plugin's source code using the -fPIC flag to get position independent code object files *.pic.o
  • make a shared library plugin by linking with gcc -shared your *.pic.o files (and you can also link another shared library).
  • use GCC function attributes, notably constructor and destructor functions (or static C++ data with explicit constructors & destructors, hence the name). The functions with __attribute__((constructor)) are called during dlopen time of your plugin, those with __attribute__((destructor)) in your plugin are called during dlclose time
  • linking the main program with the -rdynamic attribute is useful & needed, as soon as the plugin call some functions in the main program.
  • don't forget to declare extern "C" your C++ plugin functions (needed for the program)
  • use dlsym inside your main program to fetch function or data addresses inside your plugin.

There is indeed no hooks for dlopen like _dyld_register_func_for_add_image does. You may want to use constructor functions and/or dl_iterate_phdr(3) to mimic that.

If you can change the plugin (the shared object which you dlopen) you could play constructor tricks inside to mimic such hooks. Otherwise, use some own convention (e.g. that a plugin having a module_start function gets that module_start function called just after dlopen etc...).

Some libraries are wrapping dlopen into something of higher level. For example Qt has QPluginLoader & QLibrary etc...

There is also the LD_PRELOAD trick (perhaps you might redefine your own dlopen & dlclose thru such a trick, and have your modified functions do the hooks). The ifunc function attribute might also be relevant.

And since Gnu Libc is free software providing the dlopen - there is also MUSL Libc, you could patch it to suit your needs. dladdr(3) could be useful too!

addenda

If you are making your own runtime for some Objective-C, you should know well the conventions of the Objective-C compiler using that runtime, and you probably could have your own module loader, instead of overloading dlopen...

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Yes, I knew it already, of course, but the standard library doesn't provide any functions to set callbacks to be called whenever an image is loaded or unloaded... – LuisABOL Mar 29 '13 at 12:58
  • Ok, Mr. Starynkevitch, thank you for the attention. But, maybe I should have explained my problem more precisely. I'm not trying to make a plugin that is going to be treated by a callback function when it is dlopen. Actually, I need to make a library that has a special function that must be called whenever any other library is dynamically loaded by `dlopen`. – LuisABOL Mar 29 '13 at 13:10