From 59573e6e7a6e0e5a45fd1e5fc46187766b292b35 Mon Sep 17 00:00:00 2001 From: MITSUNARI Shigeo Date: Tue, 24 Jul 2018 18:07:35 +0900 Subject: [PATCH] add PROTECT_RE mode for protect() --- readme.md | 3 ++- readme.txt | 3 ++- sample/static_buf.cpp | 6 +++++- sample/test0.cpp | 4 ++-- test/jmp.cpp | 3 ++- test/test_address.bat | 2 +- test/test_avx.bat | 2 +- test/test_avx512.bat | 2 +- test/test_nm.bat | 2 +- xbyak/xbyak.h | 40 +++++++++++++++++++++++++++++++--------- xbyak/xbyak_mnemonic.h | 2 +- 11 files changed, 49 insertions(+), 20 deletions(-) diff --git a/readme.md b/readme.md index 04bbc94..9b8ab74 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ -Xbyak 5.65 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++ +Xbyak 5.66 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++ ============= Abstract @@ -333,6 +333,7 @@ The header files under xbyak/ are independent of cybozulib. History ------------- +* 2018/Jul/24 ver 5.66 add CodeArray::PROTECT_RE to mode of protect() * 2018/Jun/26 ver 5.65 fix push(qword [mem]) * 2018/Mar/07 ver 5.64 fix zero division in Cpu() on some cpu * 2018/Feb/14 ver 5.63 fix Cpu::setCacheHierarchy() and fix EvexModifierZero for clang<3.9(thanks to mgouicem) diff --git a/readme.txt b/readme.txt index b1c15a2..4f17d00 100644 --- a/readme.txt +++ b/readme.txt @@ -1,5 +1,5 @@ - C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.65 + C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.66 ----------------------------------------------------------------------------- ◎概要 @@ -343,6 +343,7 @@ cybozulibは単体テストでのみ利用されていて、xbyak/ディレク ----------------------------------------------------------------------------- ◎履歴 +2018/07/24 ver 5.66 protect()のmodeにCodeArray::PROTECT_REを追加 2018/06/26 ver 5.65 fix push(qword [mem]) 2018/03/07 ver 5.64 Cpu()の中でzero divisionが出ることがあるのを修正 2018/02/14 ver 5.63 Cpu::setCacheHierarchy()の修正とclang<3.9のためのEvexModifierZero修正(thanks to mgouicem) diff --git a/sample/static_buf.cpp b/sample/static_buf.cpp index a2ef0e2..7cf8038 100644 --- a/sample/static_buf.cpp +++ b/sample/static_buf.cpp @@ -13,7 +13,6 @@ struct Code : Xbyak::CodeGenerator { { puts("generate"); printf("ptr=%p, %p\n", getCode(), buf); - Xbyak::CodeArray::protect(buf, sizeof(buf), true); #ifdef XBYAK32 mov(eax, ptr [esp + 4]); add(eax, ptr [esp + 8]); @@ -23,6 +22,11 @@ struct Code : Xbyak::CodeGenerator { lea(rax, ptr [rdi + rsi]); #endif ret(); + Xbyak::CodeArray::protect(buf, sizeof(buf), Xbyak::CodeArray::PROTECT_RE); + } + ~Code() + { + Xbyak::CodeArray::protect(buf, sizeof(buf), Xbyak::CodeArray::PROTECT_RW); } } s_code; diff --git a/sample/test0.cpp b/sample/test0.cpp index e437092..eabd745 100644 --- a/sample/test0.cpp +++ b/sample/test0.cpp @@ -165,15 +165,15 @@ int main() const size_t codeSize = 1024; uint8 buf[codeSize + 16]; uint8 *p = CodeArray::getAlignedAddress(buf); - CodeArray::protect(p, codeSize, true); Sample s(p, codeSize); + CodeArray::protect(p, codeSize, CodeArray::PROTECT_RE); int (*func)(int) = s.getCode(); if (Xbyak::CastTo(func) != p) { fprintf(stderr, "internal error %p %p\n", p, Xbyak::CastTo(func)); return 1; } printf("0 + ... + %d = %d\n", 100, func(100)); - CodeArray::protect(p, codeSize, false); + CodeArray::protect(p, codeSize, CodeArray::PROTECT_RW); } puts("OK"); testReset(); diff --git a/test/jmp.cpp b/test/jmp.cpp index 79d5490..2578adb 100644 --- a/test/jmp.cpp +++ b/test/jmp.cpp @@ -1143,10 +1143,11 @@ CYBOZU_TEST_AUTO(rip_addr_with_fixed_buf) ret(); } } code; - Xbyak::CodeArray::protect(p, 4096, true); + Xbyak::CodeArray::protect(p, 4096, Xbyak::CodeArray::PROTECT_RE); code.getCode()(); CYBOZU_TEST_EQUAL(*x0, 123); CYBOZU_TEST_EQUAL(*x1, 456); CYBOZU_TEST_EQUAL(buf[8], 99); + Xbyak::CodeArray::protect(p, 4096, Xbyak::CodeArray::PROTECT_RW); } #endif diff --git a/test/test_address.bat b/test/test_address.bat index f96542f..f82c125 100644 --- a/test/test_address.bat +++ b/test/test_address.bat @@ -31,7 +31,7 @@ address %1% jit > nm.cpp echo cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2% cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2% nm_frame > x.lst -diff x.lst ok.lst +diff -w x.lst ok.lst wc x.lst :end diff --git a/test/test_avx.bat b/test/test_avx.bat index 5e51aa2..e40de15 100644 --- a/test/test_avx.bat +++ b/test/test_avx.bat @@ -38,5 +38,5 @@ make_nm jit > nm.cpp echo cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2% cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2% nm_frame |%FILTER% > x.lst -diff x.lst ok.lst +diff -w x.lst ok.lst wc x.lst diff --git a/test/test_avx512.bat b/test/test_avx512.bat index a49d562..5234146 100644 --- a/test/test_avx512.bat +++ b/test/test_avx512.bat @@ -27,5 +27,5 @@ awk "{if (index($3, ""-"")) { conti=substr($3, 0, length($3) - 1) } else { conti make_512 jit > nm.cpp cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2% /DXBYAK_AVX512 nm_frame |%FILTER% > x.lst -diff x.lst ok.lst +diff -w x.lst ok.lst wc x.lst diff --git a/test/test_nm.bat b/test/test_nm.bat index 32abfac..0d63b65 100644 --- a/test/test_nm.bat +++ b/test/test_nm.bat @@ -39,5 +39,5 @@ if /i "%Y%"=="1" ( make_nm jit > nm.cpp cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2% nm_frame |%FILTER% > x.lst -diff x.lst ok.lst +diff -w x.lst ok.lst wc x.lst diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h index d703522..c33f085 100644 --- a/xbyak/xbyak.h +++ b/xbyak/xbyak.h @@ -105,7 +105,7 @@ namespace Xbyak { enum { DEFAULT_MAX_CODE_SIZE = 4096, - VERSION = 0x5650 /* 0xABCD = A.BC(D) */ + VERSION = 0x5660 /* 0xABCD = A.BC(D) */ }; #ifndef MIE_INTEGER_TYPE_DEFINED @@ -848,10 +848,15 @@ protected: uint64 disp = i->getVal(top_); rewrite(i->codeOffset, disp, i->jmpSize); } - if (alloc_->useProtect() && !protect(top_, size_, true)) throw Error(ERR_CANT_PROTECT); + if (alloc_->useProtect() && !protect(top_, size_, PROTECT_RWE)) throw Error(ERR_CANT_PROTECT); isCalledCalcJmpAddress_ = true; } public: + enum ProtectMode { + PROTECT_RW = 0, // read/write + PROTECT_RWE = 1, // read/write/exec + PROTECT_RE = 2 // read/exec + }; explicit CodeArray(size_t maxSize, void *userPtr = 0, Allocator *allocator = 0) : type_(userPtr == AutoGrow ? AUTO_GROW : userPtr ? USER_BUF : ALLOC_BUF) , alloc_(allocator ? allocator : (Allocator*)&defaultAllocator_) @@ -861,7 +866,7 @@ public: , isCalledCalcJmpAddress_(false) { if (maxSize_ > 0 && top_ == 0) throw Error(ERR_CANT_ALLOC); - if ((type_ == ALLOC_BUF && alloc_->useProtect()) && !protect(top_, maxSize, true)) { + if ((type_ == ALLOC_BUF && alloc_->useProtect()) && !protect(top_, maxSize, PROTECT_RWE)) { alloc_->free(top_); throw Error(ERR_CANT_PROTECT); } @@ -869,7 +874,7 @@ public: virtual ~CodeArray() { if (isAllocType()) { - if (alloc_->useProtect()) protect(top_, maxSize_, false); + if (alloc_->useProtect()) protect(top_, maxSize_, PROTECT_RW); alloc_->free(top_); } } @@ -960,19 +965,36 @@ public: change exec permission of memory @param addr [in] buffer address @param size [in] buffer size - @param canExec [in] true(enable to exec), false(disable to exec) + @param protectMode [in] mode(RW/RWE/RE) @return true(success), false(failure) */ - static inline bool protect(const void *addr, size_t size, bool canExec) + static inline bool protect(const void *addr, size_t size, int protectMode) { -#if defined(_WIN32) +#if defined(_MSC_VER) + const DWORD c_rw = PAGE_READWRITE; + const DWORD c_rwe = PAGE_EXECUTE_READWRITE; + const DWORD c_re = PAGE_EXECUTE_READ; + DWORD mode; +#else + const int c_rw = PROT_READ | PROT_WRITE; + const int c_rwe = PROT_READ | PROT_WRITE | PROT_EXEC; + const int c_re = PROT_READ | PROT_EXEC; + int mode; +#endif + switch (protectMode) { + case PROTECT_RW: mode = c_rw; break; + case PROTECT_RWE: mode = c_rwe; break; + case PROTECT_RE: mode = c_re; break; + default: + return false; + } +#if defined(_MSC_VER) DWORD oldProtect; - return VirtualProtect(const_cast(addr), size, canExec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldProtect) != 0; + return VirtualProtect(const_cast(addr), size, mode, &oldProtect) != 0; #elif defined(__GNUC__) size_t pageSize = sysconf(_SC_PAGESIZE); size_t iaddr = reinterpret_cast(addr); size_t roundAddr = iaddr & ~(pageSize - static_cast(1)); - int mode = PROT_READ | PROT_WRITE | (canExec ? PROT_EXEC : 0); return mprotect(reinterpret_cast(roundAddr), size + (iaddr - roundAddr), mode) == 0; #else return true; diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h index fea242a..07dd8f3 100644 --- a/xbyak/xbyak_mnemonic.h +++ b/xbyak/xbyak_mnemonic.h @@ -1,4 +1,4 @@ -const char *getVersionString() const { return "5.65"; } +const char *getVersionString() const { return "5.66"; } void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); } void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); } void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }