5
5
#include <stdlib.h>
6
6
#include <string.h>
7
7
#include <stdarg.h>
8
+ #include <stdint.h>
8
9
#include <assert.h>
9
10
11
+ // For mmapp(), sysconf()
10
12
#ifndef _WIN32
11
- // For mmapp()
13
+ #include <unistd.h>
12
14
#include <sys/mman.h>
13
15
#endif
14
16
18
20
uint32_t sig_imm_size (int64_t imm )
19
21
{
20
22
// Compute the smallest size this immediate fits in
21
- if (imm >= -128 && imm <= 127 )
23
+ if (imm >= INT8_MIN && imm <= INT8_MAX )
22
24
return 8 ;
23
- if (imm >= -32768 && imm <= 32767 )
25
+ if (imm >= INT16_MIN && imm <= INT16_MAX )
24
26
return 16 ;
25
- if (imm >= -2147483648 && imm <= 2147483647 )
27
+ if (imm >= INT32_MIN && imm <= INT32_MAX )
26
28
return 32 ;
27
29
28
30
return 64 ;
@@ -32,11 +34,11 @@ uint32_t sig_imm_size(int64_t imm)
32
34
uint32_t unsig_imm_size (uint64_t imm )
33
35
{
34
36
// Compute the smallest size this immediate fits in
35
- if (imm <= 255 )
37
+ if (imm <= UINT8_MAX )
36
38
return 8 ;
37
- else if (imm <= 65535 )
39
+ else if (imm <= UINT16_MAX )
38
40
return 16 ;
39
- else if (imm <= 4294967295 )
41
+ else if (imm <= UINT32_MAX )
40
42
return 32 ;
41
43
42
44
return 64 ;
@@ -124,23 +126,73 @@ x86opnd_t const_ptr_opnd(const void *ptr)
124
126
return opnd ;
125
127
}
126
128
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
+
127
145
// Allocate a block of executable memory
128
146
uint8_t * alloc_exec_mem (uint32_t mem_size )
129
147
{
130
148
#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
+ );
140
168
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
141
192
if (mem_block == MAP_FAILED ) {
193
+ // Try again without the address hint (e.g., valgrind)
142
194
mem_block = (uint8_t * )mmap (
143
- NULL , // try again without the address hint (e.g., valgrind)
195
+ NULL ,
144
196
mem_size ,
145
197
PROT_READ | PROT_WRITE | PROT_EXEC ,
146
198
MAP_PRIVATE | MAP_ANONYMOUS ,
@@ -161,6 +213,7 @@ uint8_t* alloc_exec_mem(uint32_t mem_size)
161
213
162
214
return mem_block ;
163
215
#else
216
+ // Windows not supported for now
164
217
return NULL ;
165
218
#endif
166
219
}
@@ -180,15 +233,11 @@ void cb_align_pos(codeblock_t* cb, uint32_t multiple)
180
233
{
181
234
// Compute the pointer modulo the given alignment boundary
182
235
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 );
188
237
189
238
// 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 ;
192
241
}
193
242
194
243
// 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
818
867
819
868
// Compute the jump offset
820
869
int64_t rel64 = (int64_t )(dst_ptr - end_ptr );
821
- assert (rel64 >= -2147483648 && rel64 <= 2147483647 );
870
+ assert (rel64 >= INT32_MIN && rel64 <= INT32_MAX );
822
871
823
872
// Write the relative 32-bit jump offset
824
873
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)
901
950
int64_t rel64 = (int64_t )(dst_ptr - end_ptr );
902
951
903
952
// If the offset fits in 32-bit
904
- if (rel64 >= -2147483648 && rel64 <= 2147483647 )
953
+ if (rel64 >= INT32_MIN && rel64 <= INT32_MAX )
905
954
{
906
955
call_rel32 (cb , (int32_t )rel64 );
907
956
return ;
0 commit comments