I wonder if it's possible for a linux process to call code located in the memory of another process?
Let's say we have a function f() in process A and we want process B to call it. What I thought about is using mmap with MAP_SHARED and PROT_EXEC flags to map the memory containing the function code and pass the pointer to B, assuming, that f() will not call any other function from A binary. Will it ever work? If yes, then how do I determine the size of f() in memory?
=== EDIT ===
I know, that shared libraries will do exactly that, but I wonder if it's possible to dynamically share code between processes.
Yes, you can do that, but the first process must have first created the shared memory via mmap
and either a memory-mapped file, or a shared area created with shm_open
.
If you are sharing compiled code then that's what shared libraries were created for. You can link against them in the ordinary way and the sharing will happen automatically, or you can load them manually using dlopen
(e.g. for a plugin).
Update:
As the code has been generated by a compiler then you will have relocations to worry about. The compiler does not produce code that will Just Work anywhere. It expects that the .data
section is in a certain place, and that the .bss
section has been zeroed. The GOT will need to be populated. Any static constructors will have to be called.
In short, what you want is probably dlopen
. This system allows you to open a shared library like it was a file, and then extract function pointers by name. Each program that dlopen
s the library will share the code sections, thus saving memory, but each will have its own copy of the data section, so they do not interfere with each other.
Beware that you need to compile your library code with -fPIC
or else you won't get any code sharing either (actually, the linkers and dynamic loaders for many architectures probably don't support libraries that aren't PIC anyway).
The standard approach is to put the code of f()
in a shared library libfoo.so
. Then you could either link to that library (e.g. by building program A with gcc -Wall a.c -lfoo -o a.bin
), or load it dynamically (e.g. in program B) using dlopen(3) then retrieving the address of f
using dlsym
.
When you compile a shared library you want to :
foo1.c
with gcc -Wall -fPIC -c foo1.c -o foo1.pic.o
into position independent code, and likewise for foo2.c
into foo2.pic.o
libfoo.so
with gcc -Wall -shared foo*.pic.o -o libfoo.so
; notice that you can link additional shared libraries into lbfoo.so
(e.g. by appending -lm
to the linking command)See also the Program Library Howto.
You could play insane tricks by mmap
-ing some other /proc/1234/mem
but that is not reasonable at all. Use shared libraries.
PS. you can dlopen
a big lot (hundreds of thousands) of shared objects lib*.so
files; you may want to dlclose
them (but practically you don't have to).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With