Thunking problems with arch issues
Hiemlick Hiemlicker via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri Jul 1 18:40:40 PDT 2016
The following code works on dmd x64. Fails on dmd x32 and ldc
x64. The problem is the passed variable.
import std.stdio;
version (Windows)
{
import core.sys.windows.windows;
void makeExecutable(ubyte[] code)
{
DWORD old;
VirtualProtect(code.ptr, code.length,
PAGE_EXECUTE_READWRITE, &old);
}
}
else
version (linux)
{
import core.sys.posix.sys.mman;
import core.sys.posix.unistd;
static if (!is(typeof(&mprotect)))
extern(C) int mprotect(void*, size_t, int);
void makeExecutable(ubyte[] code)
{
auto pageSize = sysconf(_SC_PAGE_SIZE);
auto address = ((cast(size_t)code.ptr) & ~(pageSize-1));
int pageCount =
(address/pageSize == (address+code.length)/pageSize)
? 1 : 2;
mprotect(cast(void*)address, pageSize * pageCount,
PROT_READ | PROT_WRITE | PROT_EXEC);
}
}
else
static assert(0, "TODO");
R function(A) delegate2function(R, A...)(R delegate(A) d)
{
enum size_t TEMPLATE1 = cast(size_t)0x01234567_01234567;
enum size_t TEMPLATE2 = cast(size_t)0x89ABCDEF_89ABCDEF;
static R functionTemplate(A args)
{
R delegate(A) d;
d.ptr = cast(typeof(d.ptr ))TEMPLATE1;
d.funcptr = cast(typeof(d.funcptr))TEMPLATE2;
return d(args);
}
static void functionTemplateEnd() {}
static void replaceWord(ubyte[] a, size_t from, size_t to)
{
foreach (i; 0..a.length - size_t.sizeof + 1)
{
auto p = cast(size_t*)(a.ptr + i);
if (*p == from)
{
*p = to;
return;
}
}
assert(0);
}
auto templateStart = cast(ubyte*)&functionTemplate;
auto templateEnd = cast(ubyte*)&functionTemplateEnd;
auto templateBytes = templateStart[0 .. templateEnd -
templateStart];
// must allocate type with pointers, otherwise GC won't scan
it
auto functionWords = new void*[(templateBytes.length /
(void*).sizeof) + 3];
// store context in word-aligned boundary, so the GC can find
it
functionWords[0] = d.ptr;
functionWords[1] = d.funcptr;
functionWords = functionWords[2..$];
auto functionBytes =
(cast(ubyte[])functionWords)[0..templateBytes.length];
functionBytes[] = templateBytes[];
replaceWord(functionBytes, TEMPLATE1, cast(size_t)d.ptr );
replaceWord(functionBytes, TEMPLATE2, cast(size_t)d.funcptr);
makeExecutable(functionBytes);
return cast(typeof(return)) functionBytes.ptr;
}
public struct sExtThread(T)
{
uint Id = 0;
HANDLE Handle;
alias callbackType = extern (Windows) uint function(void*);
public void Create(uint delegate(T) c, T param, bool suspended =
false, uint stackSize = 16000)
{
Handle = CreateThread(cast(SECURITY_ATTRIBUTES*)null,
stackSize, cast(callbackType)delegate2function(c),
cast(void*)¶m, (suspended) ? CREATE_SUSPENDED : 0, &Id);
}
}
void main()
{
import std.stdio;
string q = "WTFSDFA";
sExtThread!string t;
t.Create((p)
{
writeln(q);
writeln(p);
return 1;
}, "ASDFASDF");
getchar();
}
p is invalid.
Obviously isn't not necessary to pass p but still, somethings
wrong. I stole the delegate2function from Vladimir "The
Propeller" Panteleev! Thanks Vlad!
It doesn't seem to be a problem with x86 since LDC x64 has the
same problem(or writes junk I guess). Could be an issue with
delegate2function but it's a bit over my head.
More information about the Digitalmars-d-learn
mailing list