在linux x64(3.16.0-29-generic)上,使用下面的代码我尝试使用mmap分配一些特定的内存地址。 我使用-m32和-m64进行了编译。 所以我发现内存地址(所有地址都是十六进制 - 3个最后的零是用于页面allignement)下面是不可分配的: 0,000,1,000,2,000到F,000,有时10,000(有时候我可以使用它),之后我到达400,000,600,000,600,001。
据我所知,我的代码加载到400.000而其他东西加载在600.000和601.000。 我如何控制程序和数据部分的加载位置,以防我希望这些地址是空闲的,并记录哪些内存地址应该可用。 为什么我不能将初始地址用作0.000到10.000? (应该是什么?)。
有点脏的代码如下:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
int mprotect(void *addr, size_t len, int prot);
constexpr int64_t cc=0x5858585858585858;
#define Return asm volatile("movq $0x5858585858585858,%rax;");return;
int64_t funcEnd=0x0;
constexpr int maxCode=0x800;
int8_t code[maxCode];
constexpr int pageSz=8192;
char s[0x8];
void testCode(void){
int a=8,b=7;
a+=b*a;
for(size_t i=0;i<sizeof(s);i++)s[i]=i;
//Return;
}
typedef void (*action)(void);
int main(int argc, char **argv)
{
action a=&testCode;
//testCode();
int8_t *p0=(int8_t*)a,*p=p0,*p1=p0+maxCode;
while(p!=p1)
if ( (*(int64_t*)p++)==cc) break;
if(p!=p1){
printf("found\n");
void* myAddr=(void*)(1 * 0x1000);
void* ma;int cnt=0;
for(unsigned int i=0x0;i<0x100000;i++){
void* p=(void*)(i*0x1000);
ma=mmap(p,0x1000,PROT_EXEC|PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,0,0);
if(ma!=p)
printf("mapping of %p failed\n",p);
}
p+=sizeof(int64_t)+2;
if(ma==myAddr){
memcpy(ma,(void*)a,p-(int8_t*)a);
(*(action)ma)();
}
}else
printf("not found");
return 0;
}