2014-10-31 45 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