-
-
Save heatd/9326eab8a7887453b25ef7dd42e786a9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* nopslide/10 2.39 ns 2.37 ns 307780820 | |
nopslide/64 4.28 ns 4.26 ns 182545569 | |
nopslide/512 12.8 ns 12.7 ns 53419222 | |
nopslide/4096 99.3 ns 99.0 ns 5201753 | |
nopslide/32768 970 ns 966 ns 774362 | |
nopslide/65536 2048 ns 2040 ns 352776 | |
jmpnoslide/10 2.95 ns 2.93 ns 230307847 | |
jmpnoslide/64 3.42 ns 3.41 ns 228452609 | |
jmpnoslide/512 2.65 ns 2.63 ns 197591155 | |
jmpnoslide/4096 3.30 ns 3.28 ns 224464465 | |
jmpnoslide/32768 2.81 ns 2.78 ns 226038725 | |
jmpnoslide/65536 3.24 ns 3.21 ns 255799730 | |
*/ | |
#include <sys/mman.h> | |
#include <cstring> | |
#include <benchmark/benchmark.h> | |
const uint8_t nop_5byte[] = {0x0f, 0x1f, 0x44, 0x00, 0x00}; | |
const uint8_t nop_4byte[] = {0x0f, 0x1f, 0x40, 0x00}; | |
const uint8_t nop_3byte[] = {0x0f, 0x1f, 0x00}; | |
const uint8_t nop_2byte[] = {0x66, 0x90}; | |
const uint8_t nop_1byte[] = {0x90}; | |
void __replace_instructions(void *ip, const void *instructions, size_t size) | |
{ | |
std::memcpy(ip, instructions, size); | |
} | |
#define REPLACE_INSTR_N(N) \ | |
while (size >= N) \ | |
{ \ | |
__replace_instructions((void *) instr, __PASTE(__PASTE(nop_, N), byte), N); \ | |
size -= N; \ | |
instr += N; \ | |
} | |
#define ___PASTE(a, b) a##b | |
#define __PASTE(a, b) ___PASTE(a, b) | |
void nop_out(void *ip, size_t size) | |
{ | |
char *instr = (char *) ip; | |
REPLACE_INSTR_N(5); | |
REPLACE_INSTR_N(4); | |
REPLACE_INSTR_N(3); | |
REPLACE_INSTR_N(2); | |
REPLACE_INSTR_N(1); | |
} | |
typedef void (*test_func)(void); | |
test_func setup_test(std::size_t len, bool add_jmp) | |
{ | |
void *mem = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); | |
if (mem == MAP_FAILED) | |
std::abort(); | |
nop_out(mem, len - 1); | |
((uint8_t *)mem)[len - 1] = 0xc3; | |
if (add_jmp) | |
{ | |
auto dst = (uint8_t *) mem + len - 1; | |
uint8_t *p = (uint8_t *) mem; | |
p[0] = 0xe9; | |
auto ninstr = p + 5; | |
uint32_t displacement = static_cast<uint32_t>(dst - ninstr); | |
std::memcpy(&p[1], &displacement, sizeof(uint32_t)); | |
} | |
mprotect(mem, len, PROT_READ | PROT_EXEC); | |
return (test_func) mem; | |
} | |
void nopslide(benchmark::State &state) | |
{ | |
auto len = state.range(); | |
auto func = setup_test(len, false); | |
for (auto _ : state) | |
{ | |
func(); | |
} | |
munmap((void *) func, len); | |
} | |
BENCHMARK(nopslide)->Range(10, 0x10000); | |
void jmpnoslide(benchmark::State &state) | |
{ | |
auto len = state.range(); | |
auto func = setup_test(len, true); | |
for (auto _ : state) | |
{ | |
func(); | |
} | |
munmap((void *) func, len); | |
} | |
BENCHMARK(jmpnoslide)->Range(10, 0x10000); | |
BENCHMARK_MAIN(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment