55#include <stdlib.h>
66#include <string.h>
77#include <stdarg.h>
8+ #include <stdint.h>
89#include <assert.h>
910
11+ // For mmapp(), sysconf()
1012#ifndef _WIN32
11- // For mmapp()
13+ #include <unistd.h>
1214#include <sys/mman.h>
1315#endif
1416
1820uint32_t sig_imm_size (int64_t imm )
1921{
2022 // Compute the smallest size this immediate fits in
21- if (imm >= -128 && imm <= 127 )
23+ if (imm >= INT8_MIN && imm <= INT8_MAX )
2224 return 8 ;
23- if (imm >= -32768 && imm <= 32767 )
25+ if (imm >= INT16_MIN && imm <= INT16_MAX )
2426 return 16 ;
25- if (imm >= -2147483648 && imm <= 2147483647 )
27+ if (imm >= INT32_MIN && imm <= INT32_MAX )
2628 return 32 ;
2729
2830 return 64 ;
@@ -32,11 +34,11 @@ uint32_t sig_imm_size(int64_t imm)
3234uint32_t unsig_imm_size (uint64_t imm )
3335{
3436 // Compute the smallest size this immediate fits in
35- if (imm <= 255 )
37+ if (imm <= UINT8_MAX )
3638 return 8 ;
37- else if (imm <= 65535 )
39+ else if (imm <= UINT16_MAX )
3840 return 16 ;
39- else if (imm <= 4294967295 )
41+ else if (imm <= UINT32_MAX )
4042 return 32 ;
4143
4244 return 64 ;
@@ -124,23 +126,73 @@ x86opnd_t const_ptr_opnd(const void *ptr)
124126 return opnd ;
125127}
126128
129+ // Align the current write position to a multiple of bytes
130+ static uint8_t * align_ptr (uint8_t * ptr , uint32_t multiple )
131+ {
132+ // Compute the pointer modulo the given alignment boundary
133+ uint32_t rem = ((uint32_t )(uintptr_t )ptr ) % multiple ;
134+
135+ // If the pointer is already aligned, stop
136+ if (rem == 0 )
137+ return ptr ;
138+
139+ // Pad the pointer by the necessary amount to align it
140+ uint32_t pad = multiple - rem ;
141+
142+ return ptr + pad ;
143+ }
144+
127145// Allocate a block of executable memory
128146uint8_t * alloc_exec_mem (uint32_t mem_size )
129147{
130148#ifndef _WIN32
131- // Map the memory as executable
132- uint8_t * mem_block = (uint8_t * )mmap (
133- (void * )& alloc_exec_mem ,
134- mem_size ,
135- PROT_READ | PROT_WRITE | PROT_EXEC ,
136- MAP_PRIVATE | MAP_ANONYMOUS ,
137- -1 ,
138- 0
139- );
149+ uint8_t * mem_block ;
150+
151+ // On Linux
152+ #if defined(MAP_FIXED_NOREPLACE ) && defined(_SC_PAGESIZE )
153+ // Align the requested address to page size
154+ uint32_t page_size = (uint32_t )sysconf (_SC_PAGESIZE );
155+ uint8_t * req_addr = align_ptr ((uint8_t * )& alloc_exec_mem , page_size );
156+
157+ while (req_addr < (uint8_t * )& alloc_exec_mem + INT32_MAX )
158+ {
159+ // Try to map a chunk of memory as executable
160+ mem_block = (uint8_t * )mmap (
161+ (void * )req_addr ,
162+ mem_size ,
163+ PROT_READ | PROT_WRITE | PROT_EXEC ,
164+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE ,
165+ -1 ,
166+ 0
167+ );
140168
169+ // If we succeeded, stop
170+ if (mem_block != MAP_FAILED ) {
171+ break ;
172+ }
173+
174+ // +4MB
175+ req_addr += 4 * 1024 * 1024 ;
176+ }
177+
178+ // On MacOS and other platforms
179+ #else
180+ // Try to map a chunk of memory as executable
181+ mem_block = (uint8_t * )mmap (
182+ (void * )alloc_exec_mem ,
183+ mem_size ,
184+ PROT_READ | PROT_WRITE | PROT_EXEC ,
185+ MAP_PRIVATE | MAP_ANONYMOUS ,
186+ -1 ,
187+ 0
188+ );
189+ #endif
190+
191+ // Fallback
141192 if (mem_block == MAP_FAILED ) {
193+ // Try again without the address hint (e.g., valgrind)
142194 mem_block = (uint8_t * )mmap (
143- NULL , // try again without the address hint (e.g., valgrind)
195+ NULL ,
144196 mem_size ,
145197 PROT_READ | PROT_WRITE | PROT_EXEC ,
146198 MAP_PRIVATE | MAP_ANONYMOUS ,
@@ -161,6 +213,7 @@ uint8_t* alloc_exec_mem(uint32_t mem_size)
161213
162214 return mem_block ;
163215#else
216+ // Windows not supported for now
164217 return NULL ;
165218#endif
166219}
@@ -180,15 +233,11 @@ void cb_align_pos(codeblock_t* cb, uint32_t multiple)
180233{
181234 // Compute the pointer modulo the given alignment boundary
182235 uint8_t * ptr = & cb -> mem_block [cb -> write_pos ];
183- uint32_t rem = ((uint32_t )(uintptr_t )ptr ) % multiple ;
184-
185- // If the pointer is already aligned, stop
186- if (rem == 0 )
187- return ;
236+ uint8_t * aligned_ptr = align_ptr (ptr , multiple );
188237
189238 // Pad the pointer by the necessary amount to align it
190- uint32_t pad = multiple - rem ;
191- cb -> write_pos += pad ;
239+ ptrdiff_t pad = aligned_ptr - ptr ;
240+ cb -> write_pos += ( int32_t ) pad ;
192241}
193242
194243// Set the current write position
@@ -818,7 +867,7 @@ void cb_write_jcc_ptr(codeblock_t* cb, const char* mnem, uint8_t op0, uint8_t op
818867
819868 // Compute the jump offset
820869 int64_t rel64 = (int64_t )(dst_ptr - end_ptr );
821- assert (rel64 >= -2147483648 && rel64 <= 2147483647 );
870+ assert (rel64 >= INT32_MIN && rel64 <= INT32_MAX );
822871
823872 // Write the relative 32-bit jump offset
824873 cb_write_int (cb , (int32_t )rel64 , 32 );
@@ -901,7 +950,7 @@ void call_ptr(codeblock_t* cb, x86opnd_t scratch_reg, uint8_t* dst_ptr)
901950 int64_t rel64 = (int64_t )(dst_ptr - end_ptr );
902951
903952 // If the offset fits in 32-bit
904- if (rel64 >= -2147483648 && rel64 <= 2147483647 )
953+ if (rel64 >= INT32_MIN && rel64 <= INT32_MAX )
905954 {
906955 call_rel32 (cb , (int32_t )rel64 );
907956 return ;
0 commit comments