2009-02-20 57 views
1

我正在考慮嘗試我的手在一些JIT compilataion(只是爲了學習),它會很高興讓它跨平臺工作,因爲我在家裏運行所有主要的三個(Windows,操作系統x,linux)。有鑑於此,我想知道是否有任何方法擺脫使用虛擬內存窗口函數來分配具有執行權限的內存。只要使用malloc或new並將處理器指向這樣的塊就會很好。JIT編譯和DEP

任何提示?

+0

VirtualProtectEx有什麼問題? 「我想要做什麼VirtualProtectEx,但我不想使用VirtualProtectEx?」咦? – 2009-02-20 18:25:37

+0

如果您仔細閱讀我的問題,您會看到我想讓代碼跨平臺。這意味着我不想使用Windows API中的任何東西,只要我能幫到它。唯一的平臺依賴的東西應該最好是x86指令集。 – mac 2009-02-20 19:34:53

+1

這只是不會發生。編譯器(而不是解釋器)是特定於平臺的。即使在x86中,你也必須在Linux中處理像位置無關的代碼。更不用提執行權限,這是硬件輔助的,但是居住在操作系統中。 – 2009-02-20 19:43:43

回答

0

其中一種可能性是要求運行程序的Windows安裝要麼配置爲DEP AlwaysOff(壞主意)或DEP OptOut(更好的主意)。

這可以(在WinXp下SP2 +和WIN2K3 SP1 +至少),通過改變boot.ini文件有設置進行配置:

/noexecute=OptOut 

,然後配置您的個性化方案,通過選擇退出(下XP):

Start button 
    Control Panel 
     System 
      Advanced tab 
       Performance Settings button 
        Data Execution Prevention tab 

這應該允許您從對動態創建的malloc()塊你的程序中執行代碼。

請記住,這會讓您的程序更容易受到DEP旨在防止的攻擊的影響。

它看起來像這樣,也可以在Windows 2008上使用命令:

bcdedit.exe /set {current} nx OptOut 
5

DEP是剛剛從內存每個非代碼頁關閉執行權限。應用程序代碼被加載到具有執行權限的內存中;並且在Windows/Linux/MacOSX中有很多JIT,即使在DEP處於活動狀態時也是如此。這是因爲有一種方法可以根據需要設置權限來動態分配內存。

通常,不應使用普通的malloc,因爲權限是每頁。在某些開銷的情況下,仍然可以將malloced內存與頁面對齊。如果你不會使用malloc,一些自定義內存管理(僅限於可執行代碼)。定製管理是進行JIT的常用方式。

有一個來自Chromium項目的解決方案,它使用JIT for javascript V8 VM,並且它是跨平臺的。爲了實現跨平臺,所需的功能在多個文件中實現,並在編譯時選擇。 Linux(鉻src/v8/src/platform-linux.cc)標誌是mmap()的PROT_EXEC。

void* OS::Allocate(const size_t requested, 
        size_t* allocated, 
        bool is_executable) { 
    const size_t msize = RoundUp(requested, AllocateAlignment()); 
    int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 
    void* addr = OS::GetRandomMmapAddr(); 
    void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
    if (mbase == MAP_FAILED) { 
    /** handle error */ 
    return NULL; 
    } 
    *allocated = msize; 
    UpdateAllocatedSpaceLimits(mbase, msize); 
    return mbase; 
} 

的Win32(SRC/V8/SRC/platform-win32.cc):標誌的VirtualAlloc

void* OS::Allocate(const size_t requested, 
        size_t* allocated, 
        bool is_executable) { 
    // The address range used to randomize RWX allocations in OS::Allocate 
    // Try not to map pages into the default range that windows loads DLLs 
    // Use a multiple of 64k to prevent committing unused memory. 
    // Note: This does not guarantee RWX regions will be within the 
    // range kAllocationRandomAddressMin to kAllocationRandomAddressMax 
#ifdef V8_HOST_ARCH_64_BIT 
    static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000; 
    static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000; 
#else 
    static const intptr_t kAllocationRandomAddressMin = 0x04000000; 
    static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000; 
#endif 

    // VirtualAlloc rounds allocated size to page size automatically. 
    size_t msize = RoundUp(requested, static_cast<int>(GetPageSize())); 
    intptr_t address = 0; 

    // Windows XP SP2 allows Data Excution Prevention (DEP). 
    int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 

    // For exectutable pages try and randomize the allocation address 
    if (prot == PAGE_EXECUTE_READWRITE && 
     msize >= static_cast<size_t>(Page::kPageSize)) { 
    address = (V8::RandomPrivate(Isolate::Current()) << kPageSizeBits) 
     | kAllocationRandomAddressMin; 
    address &= kAllocationRandomAddressMax; 
    } 

    LPVOID mbase = VirtualAlloc(reinterpret_cast<void *>(address), 
           msize, 
           MEM_COMMIT | MEM_RESERVE, 
           prot); 
    if (mbase == NULL && address != 0) 
    mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot); 

    if (mbase == NULL) { 
    LOG(ISOLATE, StringEvent("OS::Allocate", "VirtualAlloc failed")); 
    return NULL; 
    } 

    ASSERT(IsAligned(reinterpret_cast<size_t>(mbase), OS::AllocateAlignment())); 

    *allocated = msize; 
    UpdateAllocatedSpaceLimits(mbase, static_cast<int>(msize)); 
    return mbase; 
} 

的MacOS(SRC/V8/SRC/platform-macos.cc)的PAGE_EXECUTE_READWRITE:旗是mmap的PROT_EXEC,就像Linux或其他posix一樣。

void* OS::Allocate(const size_t requested, 
        size_t* allocated, 
        bool is_executable) { 
    const size_t msize = RoundUp(requested, getpagesize()); 
    int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 
    void* mbase = mmap(OS::GetRandomMmapAddr(), 
        msize, 
        prot, 
        MAP_PRIVATE | MAP_ANON, 
        kMmapFd, 
        kMmapFdOffset); 
    if (mbase == MAP_FAILED) { 
    LOG(Isolate::Current(), StringEvent("OS::Allocate", "mmap failed")); 
    return NULL; 
    } 
    *allocated = msize; 
    UpdateAllocatedSpaceLimits(mbase, msize); 
    return mbase; 
} 

我還要注意,bcdedit.exe樣的方式應僅適用於很老的方案,在內存中創建新的可執行代碼,但不設置此頁面上的exec屬性中。對於較新的程序,如firefox或Chrome/Chromium或任何現代JIT,DEP應該是主動的,JIT將以細粒度的方式管理內存許可。