题
我想尝试我的手在一些JIT compilataion(只是为了学习的缘故),这将是不错的,它的工作跨平台的,因为我运行所有了三个主要在家(在Windows,OS X和Linux) 。 考虑到这一点,我想知道是否有什么办法让出使用虚拟内存窗口函数与执行权限分配内存。将是很好只是使用malloc或新,并在这样的块指向的处理器。
任何提示?
解决方案
一种可能性是使其成为运行程序的Windows安装分为配置DEP的AlwaysOff(坏主意)或DEP选择禁用(更好的主意)。
的要求这可以通过改变Boot.ini文件具有设置进行配置(下WinXp的SP2 +和WIN2K3 SP1 +至少):
/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
不过,说实话,如果你只是希望尽量减少依赖于平台的代码,这很容易通过代码隔离成一个单一的功能只是做,是这样的:
void *MallocWithoutDep(size_t sz) {
#if defined _IS_WINDOWS
return VirtualMalloc(sz, OPT_DEP_OFF); // or whatever
#elif defined IS_LINUX
// Do linuxy thing
#elif defined IS_MACOS
// Do something almost certainly inexplicable
#endif
}
如果你把自己的文件中的所有平台相关的功能,你的代码的其余部分是自动平台无关。
其他提示
DEP是刚刚从存储器的每个非代码页关闭执行权限。应用程序的代码被加载到存储器,其具有执行许可;而且有很多这在Windows / Linux的/ MacOSX的工作,甚至当DEP是激活即时编译器的。这是因为,有一种方法以动态地分配与所需的权限组存储器。
通常,普通的malloc不应该被使用,因为权限是每页面。 malloc内存的对准网页仍然可以在一些开销的价格。如果你不使用malloc,一些自定义的内存管理(仅适用于可执行代码)。自定义管理是做JIT的一种常见的方式。
有从Chromium项目,它使用JIT的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的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):标志为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或铬/铬,或任何现代JIT,DEP应该是有效的,并且将JIT在细粒度的方式管理存储的权限。