I haven't worked with production-quality VMs, but here are my five cents.
.text
sections in Unix executables belong to the file which stores executable code; at run-time this file section is mapped to a memory area allocated by the system linker during program initialization, that's all (on Linux, you can see the sections layout in memory in /proc/$PID/maps
).
As for JIT-compilation on Unix-like systems, I can only think of memory areas which have been allocated by mmap
system call with PROT_EXEC
flag enabled. This call is specified by POSIX standards and used by the Linux's system linker, ld.so
, to load any native executable file into memory. This call can be equally used for allocating new executable memory areas at run-time.
The usual heap is often protected by OS/MMU from being executed, as any /proc/$PID/maps
file suggests:
00dd4000-01292000 rw-p 00000000 00:00 0 [heap]
here rw-p
means that no data in [heap]
can be executed (though, e.g., it is not the case with 32-bit x86 CPUs without PAE, they don't have hardware capability to prevent running some memory data as code), but can be read/written.
So a VM needs a dedicated memory area with code execution permission. Indeed, let's look for rwx
memory areas in some java process memory layout:
# cat /proc/12929/maps | grep rwx # I run a Java VM with PID 12929
f3700000-f3940000 rwxp 00000000 00:00 0 # - an unnamed executable & writable region
Then execution of native code is a matter of assembling JIT-compiled native code either position-independently (like shared objects code is compiled, with gcc
option -fPIC
) or using the address returned by mmap()
.