gpt4 book ai didi

JIT 编译和 DEP

转载 作者:行者123 更新时间:2023-12-01 08:42:41 29 4
gpt4 key购买 nike

我正在考虑尝试一些 jit 编译(只是为了学习),因为我在家里运行所有主要的三个(windows、os x、linux),所以让它跨平台工作会很好。
考虑到这一点,我想知道是否有任何方法可以摆脱使用虚拟内存窗口函数来分配具有执行权限的内存。只使用 malloc 或 new 并将处理器指向这样的块会很好。

有小费吗?

最佳答案

DEP 只是关闭了内存中每个非代码页的执行权限。应用程序的代码加载到具有执行权限的内存中;并且有很多 JIT 可以在 Windows/Linux/MacOSX 中运行,即使 DEP 处于事件状态。这是因为有一种方法可以使用所需的权限集动态分配内存。

通常,不应使用普通的 malloc,因为权限是每页的。以一定的开销为代价,仍然可以将 malloced 内存与页面对齐。如果你不会使用malloc,一些自定义的内存管理(只针对可执行代码)。自定义管理是一种常见的 JIT 方式。

Chromium 项目有一个解决方案,它使用 JIT 用于 javascript V8 VM 并且是跨平台的。为了跨平台,需要的功能在几个文件中实现,并在编译时选择。

Linux: (chromium 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 的 PAGE_EXECUTE_READWRITE
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): flag 是 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 -like 方式应该只用于非常旧的程序,它在内存中创建新的可执行代码,但不在此页面上设置 Exec 属性。对于较新的程序,如 firefox 或 Chrome/Chromium,或任何现代 JIT,DEP 应该处于事件状态,并且 JIT 将以细粒度的方式管理内存权限。

关于JIT 编译和 DEP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/570257/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com