2014-10-31 67 views
0

要验证程序,我需要生成一个确定性地址跟踪。所以我使用mmap在虚拟内存中的固定位置分配数组。在固定位置的内存映射数组

这是我有:

#define PG_SIZE 4096 
#define PG_START(_v) ((_v) & ~(unsigned long)(PG_SIZE-1)) 

// has to be aligned to page. otherwise it will be done for you. 
#define ARRAY_ONE_BASE PG_START(0xffeffd000) 
#define ARRAY_ONE_SIZE (4096 * 2 * sizeof(int)) 


unsigned long * allocateArray(unsigned long addr, size_t size) { 

    int stack_prot = PROT_READ | PROT_WRITE; 
    int flags = MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS; 
    unsigned long *m_map; 

    m_map = mmap((caddr_t)PG_START(addr), size, stack_prot, flags, -1, 0); 

    // fail if mmap faield 
    if (m_map == MAP_FAILED) { 
     perror("mmap failed"); 
     abort(); 
    } 

    printf("Base address of allocated variable: %li\n", m_map); 
    assert((void *)m_map == (void *)addr); 

    return m_map; 
} 


int main(int argc, char *argv[]) {  
    unsigned long *addrOne = allocateArray(ARRAY_ONE_BASE, ARRAY_ONE_SIZE); 
} 

如果我编译和运行上面的代码,它工作正常。但是,当我尝试运行valgrind工具lackey时,它会出现分段错误。

命令:

gcc program.c 
valgrind --read-var-info=yes --tool=lackey a.out 

输出:

==28528== Lackey, an example Valgrind tool 
==28528== Copyright (C) 2002-2013, and GNU GPL'd, by Nicholas Nethercote. 
==28528== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info 
==28528== Command: a.out 
==28528== 
==28528== 
==28528== Process terminating with default action of signal 11 (SIGSEGV) 
==28528== Bad permissions for mapped region at address 0x0 
==28528== at 0x0: ??? 
==28528== 
==28528== Counted 1 call to main() 
==28528== 
==28528== Jccs: 
==28528== total:   22,338 
==28528== taken:   9,947 (44%) 
==28528== 
==28528== Executed: 
==28528== SBs entered: 21,937 
==28528== SBs completed: 14,439 
==28528== guest instrs: 120,810 
==28528== IRStmts:  723,993 
==28528== 
==28528== Ratios: 
==28528== guest instrs : SB entered = 55 : 10 
==28528==  IRStmts : SB entered = 330 : 10 
==28528==  IRStmts : guest instr = 59 : 10 
==28528== 
==28528== Exit code:  0 
Segmentation fault (core dumped) 

我已经试过在的mmap保护标志的不同组合,但有没有运气。我会很感激任何帮助。

回答

2

无法保证具有MAP_FIXED的mmap()将始终有效。

http://pubs.opengroup.org/onlinepubs/007908799/xsh/mmap.html有:

MAP_FIXED时在flags参数设置,实施被告知PA的值必须是地址,准确。如果设置了MAP_FIXED,则mmap()可能会返回MAP_FAILED并将errno设置为[EINVAL]。

和Linux帮助页:

MAP_FIXED

不要解释地址作为一个提示:在精确该地址处的映射。 addr必须是页面大小的倍数。如果由addr和len指定的内存区域与任何现有映射的页面重叠,则现有映射的重叠部分将被丢弃。如果指定的地址不能使用,mmap()将失败。由于要求固定地址进行映射的可移植性较低,因此不鼓励使用此选项。

例如,我有类似的结果在Ubuntu 14.04 运行程序,但它没有在我的Ubuntu 14.04 箱(这是很自然的考虑地址本身):

$ ./a.out 
mmap failed: Cannot allocate memory 
Aborted 

此外,Valgrind的放more restrictions上MAP_FIXED:

(线路076)

  • 尝试将客户端的固定和暗示映射放在请求的地址。除Valgrind保留的区域外,固定映射允许在任何地方使用;如果需要的话,客户端可以垃圾自己的映射。

我再改ARRAY_ONE_BASE在你的程序0xffeffd000到0x10ffeffd000,和它的工作:

$ valgrind --read-var-info=yes --tool=lackey ./a.out 
==6319== Lackey, an example Valgrind tool 
==6319== Copyright (C) 2002-2013, and GNU GPL'd, by Nicholas Nethercote. 
==6319== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info 
==6319== Command: ./a.out 
==6319== 
Base address of allocated variable: 0x10ffeffd000 
==6319== 
==6319== Counted 1 call to main() 
==6319== 
==6319== Jccs: 
==6319== total:   20,945 
==6319== taken:   9,423 (44%) 
==6319== 
==6319== Executed: 
==6319== SBs entered: 19,675 
==6319== SBs completed: 12,655 
==6319== guest instrs: 105,453 
==6319== IRStmts:  614,550 
==6319== 
==6319== Ratios: 
==6319== guest instrs : SB entered = 53 : 10 
==6319==  IRStmts : SB entered = 312 : 10 
==6319==  IRStmts : guest instr = 58 : 10 
==6319== 
==6319== Exit code:  0 

我不是专家到Valgrind的或Linux地址布局,但它看起来像你精心挑选的地址碰巧碰到一些Valgrind保留区域时发生0xffeffd000。

+0

更改内存地址的工作。我并不知道valgrind中的保留区域。谢谢! – goyalankit 2014-10-31 16:59:14