我找到了一个解决方案,很高兴了解发生了什么。希望你会喜欢。
当你测试它时,你可以看到如果你分配一个“大”的内存块,1MB
然后mprotect
管理添加执行权限。使用二分搜索,您可以发现最佳位置在128KB
. Glibc 的 malloc 以一种有趣的方式工作,您应该阅读一下,但很快,它会提前分配内存并在您需要时给您一些内存。如果它用完了内存,它会分配更多等等。但是在某些大小下,它不会从它自己的池中为您提供内存。你要求一个足够大的缓冲区,让他专门为你分配一个。此阈值为 128KB,并DEFAULT_MMAP_THRESHOLD
在源代码中定义。
默认内存由 glibc.o 分配,它位于不同的内存段中,并在运行时加载。因此,您的库无权更改该内存保护并添加PERM_EXEC
. 但是当您要求大内存并 malloc 为您分配新内存时,您的图书馆拥有此内存,因此您可以根据需要更改它的权限。
更多详细信息以及如何解决小内存量的问题:
那么 GCC 是如何为你分配内存的呢?使用mmap
- http://man7.org/linux/man-pages/man2/mmap.2.html
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(void *addr, size_t length);
mmap
在新的内存段中分配内存。If addr is NULL, then the kernel chooses the (page-aligned) address at which to create the mapping
. 因此,我们可以使用此函数分配内存。length
必须是页面大小 ( 4096
) 的乘积,这对于少量内存来说是非常浪费的。如果fd
是-1
,则内存被零填充。
使用这种方法,我们可以根据需要分配具有保护的内存,在这种情况下,具有执行权限。