Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dlopen from memory?

I'm looking for a way to load generated object code directly from memory.

I understand that if I write it to a file, I can call dlopen to dynamically load its symbols and link them. However, this seems a bit of a roundabout way, considering that it starts off in memory, is written to disk, and then is reloaded in memory by dlopen. I'm wondering if there is some way to dynamically link object code that exists in memory. From what I can tell there might be a few different ways to do this:

  1. Trick dlopen into thinking that your memory location is a file, even though it never leaves memory.

  2. Find some other system call which does what I'm looking for (I don't think this exists).

  3. Find some dynamic linking library which can link code directly in memory. Obviously, this one is a bit hard to google for, as "dynamic linking library" turns up information on how to dynamically link libraries, not on libraries which perform the task of dynamically linking.

  4. Abstract some API from a linker and create a new library out its codebase. (obviously this is the least desirable option for me).

So which ones of these are possible? feasible? Could you point me to any of the things I hypothesized existed? Is there another way I haven't even thought of?

like image 828
Jeremy Salwen Avatar asked Feb 19 '11 21:02

Jeremy Salwen


People also ask

Is Dlopen a system call?

dlopen isn't a system call, it's a library function in the libdl library. Only system calls show up in strace . On Linux and on many other platforms (especially those that use the ELF format for executables), dlopen is implemented by opening the target library with open() and mapping it into memory with mmap() .

What is Dlopen?

dlopen() The function dlopen() loads the dynamic shared object (shared library) file named by the null-terminated string filename and returns an opaque "handle" for the loaded object.


2 Answers

I don't see why you'd be considering dlopen, since that will require a lot more nonportable code to generate the right object format on disk (e.g. ELF) for loading. If you already know how to generate machine code for your architecture, just mmap memory with PROT_READ|PROT_WRITE|PROT_EXEC and put your code there, then assign the address to a function pointer and call it. Very simple.

like image 33
R.. GitHub STOP HELPING ICE Avatar answered Oct 05 '22 15:10

R.. GitHub STOP HELPING ICE


I needed a solution to this because I have a scriptable system that has no filesystem (using blobs from a database) and needs to load binary plugins to support some scripts. This is the solution I came up with which works on FreeBSD but may not be portable.

void *dlblob(const void *blob, size_t len) {     /* Create shared-memory file descriptor */     int fd = shm_open(SHM_ANON, O_RDWR, 0);     ftruncate(fd, len);     /* MemMap file descriptor, and load data */     void *mem = mmap(NULL, len, PROT_WRITE, MAP_SHARED, fd, 0);     memcpy(mem, blob, len);     munmap(mem, len);     /* Open Dynamic Library from SHM file descriptor */     void *so = fdlopen(fd,RTLD_LAZY);     close(fd);     return so; } 

Obviously the code lacks any kind of error checking etc, but this is the core functionality.

ETA: My initial assumption that fdlopen is POSIX was wrong, this appears to be a FreeBSD-ism.

like image 122
Parakleta Avatar answered Oct 05 '22 15:10

Parakleta