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