October 04, 2013
On Friday, 4 October 2013 at 22:00:36 UTC, Adam D. Ruppe wrote:
> I'm just playing at this point and I'm pretty sure these hacks won't quite work or might even be kinda useless... but one way to avoid the hassle of making the machine code yourself is to get the compiler to do it.
>
> So we'll write our function (just 32 bit here, the 64 bit didn't work and I'm not sure why, could be because of this http://stackoverflow.com/a/6313264/1457000 ) in D then copy it into the magic memory:
>
> void sayHello() {
> 	asm {
> 		naked;
> 	}
> 	static immutable hello = "hello!\n";
> 	auto sptr = hello.ptr;
> 	auto slen = hello.length;
> 	version(D_InlineAsm_X86)
> 	asm { // 32 bit
> 		mov ECX, sptr;
> 		mov EDX, slen;
> 		mov EBX, 1; // stdout
> 		mov EAX, 4; // sys_write
> 		int 0x80;
> 	}
>
> 	asm {
> 		ret;
> 	}
> }
> void sayHelloEnd(){} // I'm using this with the assumption that the two functions will be right next to each other in memory, thus sayHello's code goes from &sayHello .. &sayHelloEnd. idk if that is really true but it seems to work for me
>
> import core.sys.posix.sys.mman;
>
> void main()
> {
>        // NOTE: you did uint* before, now i'm doing ubyte* since we're really working in bytes, not ints
>         ubyte[] opcodes = (cast(ubyte*) mmap(null, 4096, PROT_EXEC | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0))[0 .. 4096];
> 	assert(opcodes !is null);
> 	scope(exit)
> 		munmap(opcodes.ptr, 4096);
>
>        // copy the code from our sayHello function that dmd compiled for us into the executable memory area
> 	auto f = cast(ubyte*) &sayHello;
> 	auto fe = cast(ubyte*) &sayHelloEnd;
> 	auto len = fe - f;
> 	import std.stdio;
> 	writeln("length: ", len); // shouldn't be very large
>         opcodes[0 .. len] = f[0 .. len]; // copy it over
>         void* function() func = cast(void* function()) opcodes;
>         func(); // and run it
>
> 	writeln("ending function normally!");
>
>       // then write over it to prove we still can...
> 	opcodes[0] = 0xcc;
> 	func(); // this should trap
> }
>
>
>
>
> Perhaps you could string together a bunch of little functions written in D and inline asm to build your executable code most easily using tricks like this. Assuming it continues to work in more complex situations!

Hmm interesting... I'll have to work with it some! I get a segmentation fault with this code though :| It outputs:
length: 24
Segmentation fault (core dumped)

Thanks for the help though!
October 04, 2013
On Friday, 4 October 2013 at 22:00:36 UTC, Adam D. Ruppe wrote:
> I'm just playing at this point and I'm pretty sure these hacks won't quite work or might even be kinda useless... but one way to avoid the hassle of making the machine code yourself is to get the compiler to do it.
>
> So we'll write our function (just 32 bit here, the 64 bit didn't work and I'm not sure why, could be because of this http://stackoverflow.com/a/6313264/1457000 ) in D then copy it into the magic memory:
>
> void sayHello() {
> 	asm {
> 		naked;
> 	}
> 	static immutable hello = "hello!\n";
> 	auto sptr = hello.ptr;
> 	auto slen = hello.length;
> 	version(D_InlineAsm_X86)
> 	asm { // 32 bit
> 		mov ECX, sptr;
> 		mov EDX, slen;
> 		mov EBX, 1; // stdout
> 		mov EAX, 4; // sys_write
> 		int 0x80;
> 	}
>
> 	asm {
> 		ret;
> 	}
> }
> void sayHelloEnd(){} // I'm using this with the assumption that the two functions will be right next to each other in memory, thus sayHello's code goes from &sayHello .. &sayHelloEnd. idk if that is really true but it seems to work for me
>
> import core.sys.posix.sys.mman;
>
> void main()
> {
>        // NOTE: you did uint* before, now i'm doing ubyte* since we're really working in bytes, not ints
>         ubyte[] opcodes = (cast(ubyte*) mmap(null, 4096, PROT_EXEC | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0))[0 .. 4096];
> 	assert(opcodes !is null);
> 	scope(exit)
> 		munmap(opcodes.ptr, 4096);
>
>        // copy the code from our sayHello function that dmd compiled for us into the executable memory area
> 	auto f = cast(ubyte*) &sayHello;
> 	auto fe = cast(ubyte*) &sayHelloEnd;
> 	auto len = fe - f;
> 	import std.stdio;
> 	writeln("length: ", len); // shouldn't be very large
>         opcodes[0 .. len] = f[0 .. len]; // copy it over
>         void* function() func = cast(void* function()) opcodes;
>         func(); // and run it
>
> 	writeln("ending function normally!");
>
>       // then write over it to prove we still can...
> 	opcodes[0] = 0xcc;
> 	func(); // this should trap
> }
>
>
>
>
> Perhaps you could string together a bunch of little functions written in D and inline asm to build your executable code most easily using tricks like this. Assuming it continues to work in more complex situations!

Hmm interesting... I'll have to work with it some! I get a segmentation fault with this code though :| It outputs:
length: 24
Segmentation fault (core dumped)

Thanks for the help though!
1 2
Next ›   Last »