- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想在不使用 dlfcn.h
中的函数的情况下动态加载一个库,我有一个充满 .so 文件的文件夹:
gcc -Wall -shared -fPIC -o filename.so filename.c
并且它们都有一个入口函数,名为:
void __start(int size, char** cmd);
(我知道,可能不是最好的名字)
然后我尝试通过 so 调用 open
,然后读取 elf header 作为 Elf64_Ehdr
使用 mmap
将其加载到内存中(我知道我应该使用 mprotect
但我想让它先工作,然后添加安全性),最后将 elf header 条目添加到 mmap 返回的指针(加上偏移量 0x100)。
测试代码如下:
#include <elf.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
typedef void (*ptr_t) (int, char**);
void* alloc_ex_memory(int fd) {
struct stat s;
fstat(fd, &s);
void * ptr = mmap(0, s.st_size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
if (ptr == (void *)-1) {
perror("mmap");
return NULL;
}
return ptr;
}
void* load_ex_file(const char* elfFile) {
Elf64_Ehdr header;
void * ptr;
FILE* file = fopen(elfFile, "rb");
if(file) {
fread(&header, 1, sizeof(header), file);
if (memcmp(header.e_ident, ELFMAG, SELFMAG) == 0) {
ptr = alloc_ex_memory(fileno(file));
printf("PTR AT -> %p\n", ptr);
printf("Entry at -> %lx\n", header.e_entry+256);
ptr = (header.e_entry + 256);
} else {
ptr = NULL;
}
fclose(file);
return ptr;
}
return NULL;
}
int main(int argc, char** argv) {
ptr_t func = load_ex_file(argv[1]);
printf("POINTER AT: %p\n", func);
getchar();
func(argc, argv);
return 0;
}
让我再解释一下:当我运行 objdump -d filename.so
时,我发现 _start
位于 0x6c0
。 elf header 入口点返回 0x5c0
(我补偿它在 dec 中添加 256)。
此外,pmap
显示了一个可执行区域正在创建,比方说 0x7fdf94d0c000
所以我得到并调用的函数指针方向位于 0x7fdf94d0c6c0
这应该是入口点并且可以通过函数指针调用。但我得到的是,你猜对了:段错误。
最后,我想指出的是,我有相同的示例运行 (dlopen
, dlsym
, dlclose
) 但是它要求我使用 mmap 技巧。我已经看到我的教授成功实现了它,但我不知道如何实现。 (也许我缺少一种更简单的方法)。
我的代码基于 this jit example
提前致谢!
编辑:这是我编译成 .so 的 .c 代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void __start(int size, char** cmd) {
if (size==2) {
if (!strcmp(cmd[1], "-l")) {
printf("******.********.*****@udc.es\n");
return;
} else if (!strcmp(cmd[1], "-n")) {
printf("****** ******** *****\n");
return;
}
} else if (size==1) {
printf("****** ******** ***** (******.********.*****@udc.es)\n");
return;
}
printf("Wrong command syntax: autores [-l | -n]\n");
}
最佳答案
its required that i use the mmap trick. I have seen my professor implement it successfully but i cannot figure out how.
为此,您的 __start
必须完全独立,并且不调用任何其他库(您通过调用 strcmp
和 printf
违反了该要求)。
当您调用未解析的符号时,您要求动态加载器解析该符号,加载器为此需要各种信息。该信息通常在 dlopen
期间设置称呼。因为你绕过了 dlopen
,您的程序崩溃一点也不令人惊讶。
您的第一步应该是更改您的代码,使 __start
根本不做任何事情(为空),然后确认您可以调用 __start
.这将确认您正在正确计算其地址。
其次,为该代码添加一个崩溃:
void __start(...)
{
int *p = NULL;
*p = 42; // should crash here
}
并确认您现在正在观察崩溃。这将确认您的代码已被调用。
第三,删除崩溃代码并使用仅直接系统调用(例如write(1, "Hello\n", 6)
(但不要调用write
——你必须直接在你的库中实现它))来实现无论你需要什么。
关于c - mmap 加载共享对象并获取函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53297596/
我想了解 mmap 的工作原理。mmap 的用户级调用如下所示。 void *mmap(void *addr, size_t len, int prot, int flags, int
我正在做一个Bottle驱动程序,我使用 yield 关键字和 mmap.mmap 对象在输出流中发送多个映射文件,如以下代码所示: for mapping in mappings: yield
我来自 C++/RAII 世界。 所以我对何时以及如何调用 mmap.close() 感到困惑[不是 file.close()]。 或者,根本不调用它?会不会漏气? 至于来自 document 的示例
我正在我的大学上操作系统类(class),我们的任务之一是使用 mmap 实现简单的 malloc。现在我开始工作了,我尝试使用 valgrind 来检测遗留的任何错误。不管是否释放内存,valgri
有谁知道 mmap(2) 和 mmap(3) 的区别是什么?手册第 3 节被描述为“本章描述了除第 2 章中描述的实现系统调用的库函数之外的所有库函数。” mmap(3) 不执行系统调用吗? 阅读这两
我不知道我在理解mmap时错过了哪些知识。我就是想不通。但让我这样问我的问题: 我有很多(例如 3 个)文件 block ,其大小分别为 s1、s2、s3。 s1、s2 和 s3 均小于 Mmap (
在 Linux 下: #free -m total used free shared buffers cachedMem:
我正在尝试将 C 库(beaglebone PRU 驱动程序 prussdrv.c)与 Python 连接。我想要访问的特定函数返回一个 mmap 指针,如下所示: int __prussdrv_me
当我调用mmap时: ptr = mmap(NULL, ...); 并要求系统提供一个缓冲区并将文件映射到其中,然后使用 再次调用 mmap ptr2 = mmap(ptr, ...); 尝试
在 Android 上用 Java 内存映射一个大文件效果很好。但是当映射总数超过 ~1.5GB 时,即使有多个映射调用,它也会失败: mmap failed: ENOMEM (Out of memo
我在具有 64G 内存和大量磁盘空间的 debian-64 上运行一个专门的数据库守护进程。它使用磁盘上的哈希表(mmaped)并通过定期 write() 调用将实际数据写入文件。当进行大量更新时,m
C++代码: #include #include #include #include #include using namespace std; #define FILE_MODE (S_I
我想处理一个由 4Kb block 组成的文件。 随着事情的发生,我将编写更多数据并映射新部分,取消映射我不再需要的部分。 当要映射的文件数据总量约为 4Gb 时,仅 4Kb 的 map() 是否太小
大家好,我正在尝试将下面的代码转换为 python(访问树莓派 1Mhz 计时器),我不知道什么时候要映射对象,我们需要 + TIMER_OFFSET (timer = (long long int
我所做的是一个垃圾收集器,使用mmap(2)为用户空间分配空间,这就要求最初分配时可以从任何地方开始,但是后面的分配地址应该是与之前的分配连续,如下所示: page_size = getpagesiz
众所周知,最重要的 mmap() 功能是在许多进程之间共享文件映射。但众所周知,每个进程都有自己的地址空间。 问题是内存映射文件(更具体地说,它的数据)真正保存在哪里,以及进程如何访问这些内存? 我的
什么限制了内存映射文件的大小?我知道它不能大于未分配地址空间的最大连续块,并且应该有足够的可用磁盘空间。但是还有其他限制吗? 最佳答案 您太保守了:内存映射文件可能大于地址空间。 查看 内存映射文件的
如果我使用 mmap 来编写 uint32_t,我会遇到大端/小端约定的问题吗?特别是,如果我在 big-endian 机器上写入一些数据 mmap,当我尝试在 little-endian 机器上读取
所以,对于我最后一年的项目,我使用 Video4Linux2 从相机中提取 YUV420 图像,将它们解析为 x264(本地使用这些图像),然后通过 Live555 将编码流发送到 RTP/RTCP通
是 mmap在它们的效果中调用原子? 也就是说,是否由 mmap 进行了映射更改以原子方式出现在访问受影响区域的其他线程中? 作为试金石,请考虑您执行 mmap 的情况。在一个全为零的文件中(来自线程
我是一名优秀的程序员,十分优秀!