package main import ( "github.com/edsrzf/mmap-go" "reflect" "unsafe" ) // Addr returns the address in memory of a byte slice, as a uintptr func Addr(b []byte) uintptr { hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b)) return hdr.Data } // BuildTo converts a byte-slice into an arbitrary-signatured // function. The out argument should be a pointer to a variable of // `func' type. // // Arguments to the resulting function will be passed to code using a // hybrid of the GCC and 6c ABIs: The compiled code will receive, via // the GCC ABI, a single argument, a void* pointing at the beginning // of the 6c argument frame. For concreteness, on amd64, a // func([]byte) int would result in %rdi pointing at the 6c stack // frame, like so: // // 24(%rdi) [ return value ] // 16(%rdi) [ cap(slice) ] // 8(%rdi) [ len(slice) ] // 0(%rdi) [ uint8* data ] func BuildTo(b []byte, out interface{}) { buildToInternal(b, out, Build) } func buildToInternal(b []byte, out interface{}, build func([]byte) func()) { v := reflect.ValueOf(out) if v.Type().Kind() != reflect.Ptr { panic("BuildTo: must pass a pointer") } if v.Elem().Type().Kind() != reflect.Func { panic("BuildTo: must pass a pointer to func") } f := build(b) ival := *(*struct { typ uintptr val uintptr })(unsafe.Pointer(&out)) // Since we know that out has concrete type of *func(..) ..., // we know it fits into a word, and thus `val' is just the // pointer itself (http://research.swtch.com/interfaces) *(*func())(unsafe.Pointer(ival.val)) = f } func Build(b []byte) func() { dummy := jitcall fn := &struct { trampoline uintptr jitcode uintptr }{**(**uintptr)(unsafe.Pointer(&dummy)), Addr(b)} return *(*func())(unsafe.Pointer(&fn)) } func ToExecutableMemory(data []byte) []byte { b, _ := mmap.MapRegion(nil, len(data), mmap.EXEC|mmap.RDWR, mmap.ANON, int64(0)) copy(b, data) return b } func jitcall() {}