Load function written in amd64 assembly into memory and call it

44 views Asked by At

I am trying to write a small jit compiler. For that, I need to somehow load new code into memory and then execute it.

Given the output of the compiler for a function that simply adds the 2nd and 3rd argument

push %rbp
mov %rsp, %rbp
sub $44, %rsp
movl %esi, -4(%rbp)
movl %edx, -8(%rbp)
#     return a+b
movl -4(%rbp), %esi
movl -8(%rbp), %r11d
addl %r11d, %esi
movl %esi, %eax
leave
ret

I save my compiler output to a file, called subfunction.S and translate it via as -o subfunction.o subfunction.S.

I then try to load it into memory and execute it as follows:

#include <stdio.h>
#include <sys/mman.h>

typedef int (*fun_pointer)(int, int, int);

int main(){
    FILE *f = fopen("subfunction.o", "r");

  if (f)
  {
    fseek(f, 0, SEEK_END);
    int length = ftell(f);
    fseek(f, 0, SEEK_SET);
    char *memory = mmap(NULL,   // address
                        length+10, // size
                        PROT_READ | PROT_WRITE | PROT_EXEC,
                        MAP_PRIVATE | MAP_ANONYMOUS,
                        -1, // fd (not used here)
                        0); // offset (not used here)
    if (memory)
    {
      fread(memory, 1, length, f);
      fclose(f);
      fun_pointer function = memory;
      int res = function(0,1,2);
      printf("RESULT: %d", res);
      fflush(stdout);
    }
  }
}

Note that my assembly code contains no external references (with regard to linking).

This unfortunately does not work (=> Segfault)(*). My guess is, that my compilation step using as is not appropriate to create binary data that can be executed from memory. I also tried using ld (with tmp.o as input) and load the output of it into memory. Again with no success.

(*) Actually changing sub $44, %rsp to sub 44, %rsp, which makes no sense, as 44 is interpreted as memory location causes no segfault (but also no return value). This leads me to think that it might be some kind of alignment issue?

0

There are 0 answers