A technique to mock "static interfaces" (e.g. isInputRange)

Jacob Carlborg via Digitalmars-d digitalmars-d at puremagic.com
Fri May 27 11:49:12 PDT 2016


On 2016-05-27 15:12, Atila Neves wrote:

> I get an SSL warning for that link.

Hmm, here's the code inline:

module red;

import std.stdio;

import core.sys.posix.sys.mman : mprotect, PROT_NONE, PROT_READ, 
PROT_WRITE, PROT_EXEC;
import core.stdc.errno : errno;
import core.stdc.string : memmove, memcpy;

extern (C) int getpagesize();

void procWrite(void* pos, const ref ubyte[6] data)
{
     void* addr = pos;
     size_t page = getpagesize();
     addr -= (cast(size_t)addr) % page;

     if(0 != mprotect(addr, page, PROT_READ | PROT_WRITE | PROT_EXEC)){
         return; // error
     }
     memmove(pos, data.ptr, data.length);
     mprotect(pos, page, PROT_READ | PROT_EXEC);
}

ubyte[6] redirect(void* from, void* to)
{

     // compute ASM
     ubyte[6] cmd;

     // // sanity checks
     if(((from <= to) && (to <= from+5))
         || ((to <= from) && (from <= to+5)))
     {
         return cmd;
         //throw new Exception("illegal source-destination combination");
     }

     cmd[0] = 0xE9; // jmp
     cmd[5] = 0xC3; // retn

     size_t new_dest = cast(size_t) to;
     new_dest = new_dest - (cast(size_t)from + 5);
     int offset = cast(int)cast(ptrdiff_t)new_dest;

     cmd[1 .. 1 + offset.sizeof] = (cast(ubyte*)&offset)[0 .. 
offset.sizeof];

     // // save original
     ubyte[6] original = (cast(ubyte*)from)[0 .. cmd.length];

     // write asm
     procWrite(from, cmd);
     return original;
     // return null;
}

void restoreRedirection(void* addr, const ref ubyte[6] data)
{
     procWrite(addr, data);
}

void a()
{
     writeln("a");
}

void b()
{
     writeln("b");
}

void bar(Foo foo)
{
     writeln("bar");
}

class Foo
{
     void foo()
     {
         writeln("foo");
     }
}

void replaceMethod()
{
     auto f = new Foo;
     auto f2 = new Foo;
     auto vtbl = (cast(void**)f.__vptr)[0 .. 6].dup;
     vtbl[5] = &bar;
     f.__vptr = cast(immutable(void*)*) vtbl.ptr;
     f.foo();
     f2.foo();
}

void replaceFunction()
{
     a();
     auto r = redirect(&a, &b);
     a();
     restoreRedirection(&a, r);
     a();
}

void main()
{
     replaceMethod();
     replaceFunction();
}

-- 
/Jacob Carlborg


More information about the Digitalmars-d mailing list