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*)&param, (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