Skip to content

Instantly share code, notes, and snippets.

@heatd

heatd/nopies.cpp Secret

Created November 5, 2022 20:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heatd/9326eab8a7887453b25ef7dd42e786a9 to your computer and use it in GitHub Desktop.
Save heatd/9326eab8a7887453b25ef7dd42e786a9 to your computer and use it in GitHub Desktop.
/* 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