12

I want to make a simple just-in-time compiler with c on Linux.

How can I allocate memory such that I can write out raw x86 code to it and execute it as any other function?

pklall
  • 245
  • 4
  • 9

2 Answers2

17

See mprotect(). Once you have filled a (n-)page-sized memory region (allocated with mmap()) with code, change its permissions to disallow writes and allow execution.

ninjalj
  • 42,493
  • 9
  • 106
  • 148
  • @Ignacio: link is down, archive link: http://web.archive.org/web/20090203055327/http://people.redhat.com/drepper/selinux-mem.html – ninjalj Jun 03 '11 at 20:59
  • The new home for the article seems to be https://www.akkadia.org/drepper/selinux-mem.html – Per Mildner Sep 23 '18 at 12:27
8

In addition to using mprotect correctly to provide first write and then execute permission, on some OS/hardware operations you may need to flush the I-cache. At this moment (mid-2010), all recent x86 processors have separate level 1 caches for instructions and data, and somebody has to make sure that if you write new instructions into memory (which will update the D-cache), you don't then try to execute stale bits from the I-cache. Exactly how to flush the I-cache from userspace will depend on both your hardware and the OS. My advice would be to read Intel's documentation on "self-modifying code" for their IA-32 multiprocessors. This should be enough to get you through.

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
  • 2
    x86 doesn't need this; x86 ISA rules require I-cache to be coherent with data caches, and at most a `jmp` is required before newly-written bytes are "seen". But good point because other architectures don't have coherent I-cache. – Peter Cordes Nov 27 '17 at 12:03
  • But fun fact, you do still need gcc's `__builtin___clear_cache` on x86 if storing into a buffer and then casting it to a function pointer, otherwise gcc optimizes away the stores as being dead stores. See [The repetitive byte counter](https://codegolf.stackexchange.com/a/160236) for an example. – Peter Cordes Oct 09 '18 at 14:16