Changing the load order of the library at runtime (for example, LD_PRELOAD, but at runtime)

How do I change the library from which a function is loaded at runtime?

For example, let's say I want to replace the standard printf function with something new, I can write my own version and compile it into a shared library, and then put "LD_PRELOAD = / my / library.so" in the environment before running my executable file.

But let's say that instead I want to change this connection from the program itself. Of course, this should be possible ... right?

EDIT
And no, the following does not work (but if you can tell me how to do this, then that will be enough).

 void* mylib = dlopen("/path/to/library.so",RTLD_NOW); printf = dlsym(mylib,"printf"); 
+6
c linux shared-libraries
source share
6 answers

AFAIK, this is not possible. The general rule is that if the same character appears in two libraries, ld.so will support the library that was loaded first. LD_PRELOAD works by verifying that the specified libraries are loaded before any implicitly loaded libraries.

So, once the execution has begun, all implicitly loaded libraries will be loaded, and therefore it is too late to load them in front of them.

+4
source share

There is no clean solution, but it is possible. I see two options:

  • Overwrite the printf prolog with the replace function.

    This is a fairly popular solution for connecting functions in MS Windows. You can find examples of hooking functions by rewriting code on Google.

  • Rewrite ELF relocation / binding tables.

    See this article on codeproject , which does almost what you ask, but only in the dlopen () 'ed module area. In your case, you also want to edit your main (usually non-PIC) module. I have not tried, but maybe it is as simple as calling the provided code:

     void* handle = dlopen(NULL, RTLD_LAZY); void* original; original = elf_hook(argv[0], LIBRARY_ADDRESS_BY_HANDLE(handle), printf, my_printf); 

    If this fails, you will need to read the source of your dynamic linker to find out what needs to be adapted.

+2
source share

It should be said that trying to replace functions from libc in your application has undefined behavior in accordance with ISO C / POSIX, regardless of whether you do it statically or dynamically. It may work (and will mainly work on GNU / Linux), but it is unreasonable to rely on its work. If you just want to use the name "printf", but if you have something non-standard in your program, the best way to do this is #undef printf and #define printf my_printf AFTER, including any system headers. That way, you donโ€™t interfere with any internal use of the function by the libraries you use ... and your implementation of my_printf may even call the printf system if / when it needs to.

On the other hand, if your goal is to interfere with libraries, somewhere down, you are likely to run into compatibility issues. A more suitable approach is likely to determine why the library will not do what you want, without overriding the functions that it uses, fixing and sending patches upstream, if appropriate.

+1
source share

there is an environment variable LD_LIBRARY_PATH where the linker is looking for libraries of destruction, adds your path to LD_LIBRARY_PATH, hope this works

0
source share

You cannot change this. In the general case, the NIX binding symbol (or rather, the lack of a concept) is selected from the first object where it is found. (Except for the odd AIX, which by default runs as OS / 2.)

Programmatically, you can always try dlsym(RTLD_DEFAULT) and dlsym(RTLD_NEXT) . man dlsym for more. Although he quickly gets out of hand. Why rarely used.

0
source share

Save the dlsym () result in a lookup table (array, hash table, etc.). Then #undef print and #define print use your version of the lookup table.

-2
source share

All Articles