如何获取 elf 二进制文件的堆起始地址
how to get heap start address of a elf binary
我用 C 编写了一个示例程序,它使用 libelf 来转储不同的部分。
但是我想转储堆和堆栈段的起始地址,该地址仅在进程“活动”时可用(运行ning)。
这就是我对从磁盘读取的二进制文件所做的。
elf_fd = open(elf_fname, O_RDWR);
if(elf_fd < 0) {
fprintf(stderr, "Failed to open \"%s\" reason=%s\n", elf_fname, strerror(errno));
return -1;;
}
followed by
if(elf_version(EV_CURRENT) == EV_NONE) {
fprintf(stderr, "Failed to initialize libelf\n");
res = -1;
goto done;
}
elf->e = elf_begin(elf->fd, ELF_C_READ, NULL);
if(!elf->e) {
int err = elf_errno();
if (err != 0) {
fprintf(stderr, "Failed to open ELF file code=%d reason=%s\n", err,
elf_errmsg(err));
}
res = -1;
goto done;
}
当我读取磁盘上的二进制图像时,这工作正常
运行 时间我尝试的是而不是这样做
那就是使用 open
返回的 elf_fd
elf_fd = open(elf_fname, O_RDWR);
if(elf_fd < 0) {
fprintf(stderr, "Failed to open \"%s\" reason=%s\n", elf_fname, strerror(errno));
return -1;;
}
I instead do this
That is i get a handle from the pid of the current process
elf_fd = pidfd_open(getpid(), 0);
if (elf_fd == -1) {
perror("pidfd_open");
fprintf(stderr, "failed to open self %d\n", elf_fd);
exit(EXIT_FAILURE);
}
它 returns 我是一个有效的描述符,但是当我将此描述符与
一起使用时
elf->e = elf_begin(elf->fd, ELF_C_READ, NULL);
if(!elf->e) {
int err = elf_errno();
if (err != 0) {
fprintf(stderr, "Failed to open ELF file code=%d reason=%s\n", err,
elf_errmsg(err));
}
}
它说“无效的描述符”。
问题是如何从其中获取实时进程的堆和堆栈基址
是的,我也在主调用的一开始就尝试过
sbrk(0) & 它似乎打印了堆起始地址,但这可能并不总是可靠的,因为在没有 malloc 调用之前可能没有堆
现在它似乎确实打印出来了。
Question is how can i get heap & stack base address of a live process from within it
请注意,堆和堆栈都与 ELF 格式没有任何关系,或者 libelf
。
没有“堆基址”这样的东西——大多数现代堆分配器将执行多重mmap
调用从 OS 获取内存,然后将其“分发”给各种 malloc
请求。
i did also try at the very start in main call sbrk(0)
“Legacy”malloc
用于使用 sbrk()
获取内存,但很少有现代的这样做。如果您使用的 malloc 确实使用 sbrk
,那么在 main
开始附近调用 sbrk(0)
是一个可用的近似值。
对于主线程堆栈,您可能希望这样做。一个很好的初步近似是采用 &argc
,并将其四舍五入到页面边界。
如果你想获得更好的近似值,你可以使用这样一个事实,即在 Linux(可能还有其他 ELF 平台)上,内核在调用入口点之前将 specific values 放在堆栈上。遍历 __environ
值寻找最高地址将给出更好的近似值。
我用 C 编写了一个示例程序,它使用 libelf 来转储不同的部分。 但是我想转储堆和堆栈段的起始地址,该地址仅在进程“活动”时可用(运行ning)。
这就是我对从磁盘读取的二进制文件所做的。
elf_fd = open(elf_fname, O_RDWR);
if(elf_fd < 0) {
fprintf(stderr, "Failed to open \"%s\" reason=%s\n", elf_fname, strerror(errno));
return -1;;
}
followed by
if(elf_version(EV_CURRENT) == EV_NONE) {
fprintf(stderr, "Failed to initialize libelf\n");
res = -1;
goto done;
}
elf->e = elf_begin(elf->fd, ELF_C_READ, NULL);
if(!elf->e) {
int err = elf_errno();
if (err != 0) {
fprintf(stderr, "Failed to open ELF file code=%d reason=%s\n", err,
elf_errmsg(err));
}
res = -1;
goto done;
}
当我读取磁盘上的二进制图像时,这工作正常
运行 时间我尝试的是而不是这样做 那就是使用 open
返回的 elf_fdelf_fd = open(elf_fname, O_RDWR);
if(elf_fd < 0) {
fprintf(stderr, "Failed to open \"%s\" reason=%s\n", elf_fname, strerror(errno));
return -1;;
}
I instead do this
That is i get a handle from the pid of the current process
elf_fd = pidfd_open(getpid(), 0);
if (elf_fd == -1) {
perror("pidfd_open");
fprintf(stderr, "failed to open self %d\n", elf_fd);
exit(EXIT_FAILURE);
}
它 returns 我是一个有效的描述符,但是当我将此描述符与
一起使用时elf->e = elf_begin(elf->fd, ELF_C_READ, NULL);
if(!elf->e) {
int err = elf_errno();
if (err != 0) {
fprintf(stderr, "Failed to open ELF file code=%d reason=%s\n", err,
elf_errmsg(err));
}
}
它说“无效的描述符”。
问题是如何从其中获取实时进程的堆和堆栈基址
是的,我也在主调用的一开始就尝试过 sbrk(0) & 它似乎打印了堆起始地址,但这可能并不总是可靠的,因为在没有 malloc 调用之前可能没有堆 现在它似乎确实打印出来了。
Question is how can i get heap & stack base address of a live process from within it
请注意,堆和堆栈都与 ELF 格式没有任何关系,或者 libelf
。
没有“堆基址”这样的东西——大多数现代堆分配器将执行多重mmap
调用从 OS 获取内存,然后将其“分发”给各种 malloc
请求。
i did also try at the very start in main call
sbrk(0)
“Legacy”malloc
用于使用 sbrk()
获取内存,但很少有现代的这样做。如果您使用的 malloc 确实使用 sbrk
,那么在 main
开始附近调用 sbrk(0)
是一个可用的近似值。
对于主线程堆栈,您可能希望这样做。一个很好的初步近似是采用 &argc
,并将其四舍五入到页面边界。
如果你想获得更好的近似值,你可以使用这样一个事实,即在 Linux(可能还有其他 ELF 平台)上,内核在调用入口点之前将 specific values 放在堆栈上。遍历 __environ
值寻找最高地址将给出更好的近似值。