Jer*_*wen 28 c dynamic-linking ld dlopen
我正在寻找一种直接从内存加载生成的目标代码的方法.
我知道如果我将它写入文件,我可以调用dlopen动态加载其符号并链接它们.然而,考虑到它从内存开始,写入磁盘,然后由dlopen重新加载到内存中,这似乎有点迂回.我想知道是否有某种方法来动态链接存在于内存中的目标代码.据我所知,可能有几种不同的方法来做到这一点:
尽管它永远不会留下记忆,但我还是认为你的记忆位置是一个文件.
找一些其他的系统调用来完成我正在寻找的东西(我认为这不存在).
找到一些动态链接库,它可以直接在内存中链接代码.显然,这个有点难以谷歌,因为"动态链接库"会显示有关如何动态链接库的信息,而不是关于执行动态链接任务的库的信息.
从链接器中提取一些API并在其代码库中创建一个新库.(显然这对我来说是最不可取的选择).
那么这些可能是哪些?可行?你能指出我假设存在的任何事情吗?还有另一种我甚至没想过的方法吗?
Par*_*eta 11
我需要一个解决方案,因为我有一个没有文件系统的脚本系统(使用数据库中的blob),需要加载二进制插件来支持一些脚本.这是我提出的解决方案,它可以在FreeBSD上运行,但可能无法移植.
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;
}
Run Code Online (Sandbox Code Playgroud)
显然,代码缺少任何类型的错误检查等,但这是核心功能.
ETA:我最初的假设fdlopen
是POSIX错了,这似乎是一个FreeBSD主义.
R..*_*R.. 10
我不明白你为什么要考虑dlopen
,因为这需要更多的非便携代码才能在磁盘(例如ELF)上生成正确的对象格式以进行加载.如果您已经知道如何为您的体系结构生成机器代码,只需将mmap
内存PROT_READ|PROT_WRITE|PROT_EXEC
和代码放在那里,然后将地址分配给函数指针并调用它.非常简单.
我们在 Google 实现了一种方法来做到这一点。不幸的是上游 glibc 未能理解这一需求,因此它从未被接受。带有补丁的功能请求已停止。它被称为dlopen_from_offset
.
dlopen_with_offset glibc 代码可在 glibc google/grte* 分支中找到。但没有人应该喜欢修改自己的 glibc。
除了写出文件然后再次加载文件之外,没有标准的方法可以做到这一点dlopen()
.
您可以在当前的特定平台上找到一些替代方法.由您决定是否比使用"标准和(相对)便携式"方法更好.
由于首先生成目标代码是特定于平台的,因此对其他特定于平台的技术可能并不重要.但这是一个判断调用 - 无论如何取决于存在一种相对不太可能的非标准技术.