8000 Modify CodeBlock to use executable memory (#181) · kddnewton/ruby@3e66538 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3e66538

Browse files
maximecbkddnewton
andauthored
Modify CodeBlock to use executable memory (ruby#181)
* vec to *mut u8 * Revert changes to cruby_bindings.inc.rs * Revert Cargo.toml, build.rs * Revert asm tests * Revert bindings * Remove yjit/src/external.c * Introduce a way to have dummy (non-executable) code blocks Co-authored-by: Kevin Newton <kddnewton@gmail.com>
1 parent 63ee2fa commit 3e66538

File tree

4 files changed

+397
-253
lines changed

4 files changed

+397
-253
lines changed

yjit.c

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,118 @@ static codeblock_t *ocb = NULL;
6363
//
6464
// The "_yjit_" part is for trying to be informative. We might want different
6565
// suffixes for symbols meant for Rust and symbols meant for broader CRuby.
66+
67+
/*
68+
void rb_yjit_mark_all_writable(uint8_t *mem_block, uint32_t mem_size) {
69+
if (mprotect(mem_block, mem_size, PROT_READ | PROT_WRITE)) {
70+
fprintf(stderr, "Couldn't make JIT page (%p) writeable, errno: %s", (void *)mem_block, strerror(errno));
71+
abort();
72+
}
73+
}
74+
75+
void rb_yjit_mark_all_executable(uint8_t *mem_block, uint32_t mem_size) {
76+
if (mprotect(mem_block, mem_size, PROT_READ | PROT_EXEC)) {
77+
fprintf(stderr, "Couldn't make JIT page (%p) executable, errno: %s", (void *)mem_block, strerror(errno));
78+
abort();
79+
}
80+
}
81+
82+
#if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE)
83+
// Align the current write position to a multiple of bytes
84+
static uint8_t *align_ptr(uint8_t *ptr, uint32_t multiple)
85+
{
86+
// Compute the pointer modulo the given alignment boundary
87+
uint32_t rem = ((uint32_t)(uintptr_t)ptr) % multiple;
88+
89+
// If the pointer is already aligned, stop
90+
if (rem == 0)
91+
return ptr;
92+
93+
// Pad the pointer by the necessary amount to align it
94+
uint32_t pad = multiple - rem;
95+
96+
return ptr + pad;
97+
}
98+
#endif
99+
100+
// Allocate a block of executable memory
101+
uint8_t *rb_yjit_alloc_exec_mem(uint32_t mem_size) {
102+
#ifndef _WIN32
103+
uint8_t *mem_block;
104+
105+
// On Linux
106+
#if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE)
107+
// Align the requested address to page size
108+
uint32_t page_size = (uint32_t)sysconf(_SC_PAGESIZE);
109+
uint8_t *req_addr = align_ptr((uint8_t*)&rb_yjit_alloc_exec_mem, page_size);
110+
111+
do {
112+
// Try to map a chunk of memory as executable
113+
mem_block = (uint8_t*)mmap(
114+
(void*)req_addr,
115+
mem_size,
116+
PROT_READ | PROT_EXEC,
117+
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE,
118+
-1,
119+
0
120+
);
121+
122+
// If we succeeded, stop
123+
if (mem_block != MAP_FAILED) {
124+
break;
125+
}
126+
127+
// +4MB
128+
req_addr += 4 * 1024 * 1024;
129+
} while (req_addr < (uint8_t*)&rb_yjit_alloc_exec_mem + INT32_MAX);
130+
131+
// On MacOS and other platforms
132+
#else
133+
// Try to map a chunk of memory as executable
134+
mem_block = (uint8_t*)mmap(
135+
(void*)yjit_alloc_exec_mem,
136+
mem_size,
137+
PROT_READ | PROT_EXEC,
138+
MAP_PRIVATE | MAP_ANONYMOUS,
139+
-1,
140+
0
141+
);
142+
#endif
143+
144+
// Fallback
145+
if (mem_block == MAP_FAILED) {
146+
// Try again without the address hint (e.g., valgrind)
147+
mem_block = (uint8_t*)mmap(
148+
NULL,
149+
mem_size,
150+
PROT_READ | PROT_EXEC,
151+
MAP_PRIVATE | MAP_ANONYMOUS,
152+
-1,
153+
0
154+
);
155+
}
156+
157+
// Check that the memory mapping was successful
158+
if (mem_block == MAP_FAILED) {
159+
perror("mmap call failed");
160+
exit(-1);
161+
}
162+
163+
// Fill the executable memory with PUSH DS (0x1E) so that
164+
// executing uninitialized memory will fault with #UD in
165+
// 64-bit mode.
166+
yjit_mark_all_writable(mem_block, mem_size);
167+
memset(mem_block, 0x1E, mem_size);
168+
yjit_mark_all_executable(mem_block, mem_size);
169+
170+
return mem_block;
171+
#else
172+
// Windows not supported for now
173+
return NULL;
174+
#endif
175+
}
176+
*/
177+
66178
uint8_t *
67179
rb_yjit_alloc_exec_mem(uint32_t mem_size)
68180
{

0 commit comments

Comments
 (0)
0