14
14
+----------------------------------------------------------------------+
15
15
| Authors: Dmitry Stogov <[email protected] > |
16
16
| Xinchen Hui <[email protected] > |
17
+
17
18
+----------------------------------------------------------------------+
18
19
*/
19
20
20
- #define HAVE_DISASM 1
21
- #define DISASM_INTEL_SYNTAX 0
22
21
23
- #include "jit/libudis86/itab.c"
24
- #include "jit/libudis86/decode.c"
25
- #include "jit/libudis86/syn.c"
26
- #if DISASM_INTEL_SYNTAX
27
- # include "jit/libudis86/syn-intel.c"
22
+ #ifdef HAVE_CAPSTONE
23
+ # define HAVE_DISASM 1
24
+ # include <capstone/capstone.h>
25
+ # define HAVE_CAPSTONE_ITER 1
28
26
#else
29
- # include "jit/libudis86/syn-att.c"
30
- #endif
31
- #include "jit/libudis86/udis86.c"
27
+ # define HAVE_DISASM 1
28
+ # define DISASM_INTEL_SYNTAX 0
29
+
30
+ # include "jit/libudis86/itab.c"
31
+ # include "jit/libudis86/decode.c"
32
+ # include "jit/libudis86/syn.c"
33
+ # if DISASM_INTEL_SYNTAX
34
+ # include "jit/libudis86/syn-intel.c"
35
+ # else
36
+ # include "jit/libudis86/syn-att.c"
37
+ # endif
38
+ # include "jit/libudis86/udis86.c"
39
+ #endif /* HAVE_CAPSTONE */
32
40
33
41
static void zend_jit_disasm_add_symbol (const char * name ,
34
42
uint64_t addr ,
@@ -48,8 +56,6 @@ static void zend_jit_disasm_add_symbol(const char *name,
48
56
#include <dlfcn.h>
49
57
#endif
50
58
51
- static struct ud ud ;
52
-
53
59
struct _sym_node {
54
60
uint64_t addr ;
55
61
uint64_t end ;
@@ -214,12 +220,34 @@ static const char* zend_jit_disasm_find_symbol(uint64_t addr,
214
220
return NULL ;
215
221
}
216
222
217
- static const char * zend_jit_disasm_resolver (struct ud * ud ,
223
+ #ifdef HAVE_CAPSTONE
224
+ static uint64_t zend_jit_disasm_branch_target (csh cs , const cs_insn * insn )
225
+ {
226
+ unsigned int i ;
227
+
228
+ if (cs_insn_group (cs , insn , X86_GRP_JUMP )) {
229
+ for (i = 0 ; i < insn -> detail -> x86 .op_count ; i ++ ) {
230
+ if (insn -> detail -> x86 .operands [i ].type == X86_OP_IMM ) {
231
+ return insn -> detail -> x86 .operands [i ].imm ;
232
+ }
233
+ }
234
+ }
235
+
236
+ return 0 ;
237
+ }
238
+ #endif
239
+
240
+ static const char * zend_jit_disasm_resolver (
241
+ #ifndef HAVE_CAPSTONE
242
+ struct ud * ud ,
243
+ #endif
218
244
uint64_t addr ,
219
245
int64_t * offset )
220
246
{
221
247
#ifndef _WIN32
248
+ # ifndef HAVE_CAPSTONE
222
249
((void )ud );
250
+ # endif
223
251
const char * name ;
224
252
void * a = (void * )(zend_uintptr_t )(addr );
225
253
Dl_info info ;
@@ -261,16 +289,69 @@ static int zend_jit_disasm(const char *name,
261
289
zval zv , * z ;
262
290
zend_long n , m ;
263
291
HashTable labels ;
264
- const struct ud_operand * op ;
265
292
uint64_t addr ;
266
293
int b ;
294
+ #ifdef HAVE_CAPSTONE
295
+ csh cs ;
296
+ cs_insn * insn ;
297
+ # ifdef HAVE_CAPSTONE_ITER
298
+ const uint8_t * cs_code ;
299
+ size_t cs_size ;
300
+ uint64_t cs_addr ;
301
+ # else
302
+ size_t count , i ;
303
+ # endif
304
+ const char * sym ;
305
+ int64_t offset = 0 ;
306
+ char * p , * q , * r ;
307
+ #else
308
+ struct ud ud ;
309
+ const struct ud_operand * op ;
310
+ #endif
311
+
312
+ #ifdef HAVE_CAPSTONE
313
+ # if defined(__x86_64__ ) || defined(_WIN64 )
314
+ if (cs_open (CS_ARCH_X86 , CS_MODE_64 , & cs ) != CS_ERR_OK )
315
+ return 0 ;
316
+ cs_option (cs , CS_OPT_DETAIL , CS_OPT_ON );
317
+ # if DISASM_INTEL_SYNTAX
318
+ cs_option (cs , CS_OPT_SYNTAX , CS_OPT_SYNTAX_INTEL );
319
+ # else
320
+ cs_option (cs , CS_OPT_SYNTAX , CS_OPT_SYNTAX_ATT );
321
+ # endif
322
+ # else
323
+ if (cs_open (CS_ARCH_X86 , CS_MODE_32 , & cs ) != CS_ERR_OK )
324
+ return 0 ;
325
+ cs_option (cs , CS_OPT_DETAIL , CS_OPT_ON );
326
+ # if DISASM_INTEL_SYNTAX
327
+ cs_option (cs , CS_OPT_SYNTAX , CS_OPT_SYNTAX_INTEL );
328
+ # else
329
+ cs_option (cs , CS_OPT_SYNTAX , CS_OPT_SYNTAX_ATT );
330
+ # endif
331
+ # endif
332
+ #else
333
+ ud_init (& ud );
334
+ # if defined(__x86_64__ ) || defined(_WIN64 )
335
+ ud_set_mode (& ud , 64 );
336
+ # else
337
+ ud_set_mode (& ud , 32 );
338
+ # endif
339
+ # if DISASM_INTEL_SYNTAX
340
+ ud_set_syntax (& ud , UD_SYN_INTEL );
341
+ # else
342
+ ud_set_syntax (& ud , UD_SYN_ATT );
343
+ # endif
344
+ ud_set_sym_resolver (& ud , zend_jit_disasm_resolver );
345
+ #endif /* HAVE_CAPSTONE */
267
346
268
347
if (name ) {
269
348
fprintf (stderr , "%s: ; (%s)\n" , name , filename ? filename : "unknown" );
270
349
}
271
350
351
+ #ifndef HAVE_CAPSTONE
272
352
ud_set_input_buffer (& ud , (uint8_t * )start , (uint8_t * )end - (uint8_t * )start );
273
353
ud_set_pc (& ud , (uint64_t )(uintptr_t )start );
354
+ #endif
274
355
275
356
zend_hash_init (& labels , 8 , NULL , NULL , 0 );
276
357
if (op_array && cfg ) {
@@ -284,6 +365,26 @@ static int zend_jit_disasm(const char *name,
284
365
}
285
366
}
286
367
}
368
+ #ifdef HAVE_CAPSTONE
369
+ ZVAL_TRUE (& zv );
370
+ # ifdef HAVE_CAPSTONE_ITER
371
+ cs_code = start ;
372
+ cs_size = (uint8_t * )end - (uint8_t * )start ;
373
+ cs_addr = (uint64_t )(uintptr_t )cs_code ;
374
+ insn = cs_malloc (cs );
375
+ while (cs_disasm_iter (cs , & cs_code , & cs_size , & cs_addr , insn )) {
376
+ if ((addr = zend_jit_disasm_branch_target (cs , insn ))) {
377
+ # else
378
+ count = cs_disasm (cs , start , (uint8_t * )end - (uint8_t * )start , (uintptr_t )start , 0 , & insn );
379
+ for (i = 0 ; i < count ; i ++ ) {
380
+ if ((addr = zend_jit_disasm_branch_target (cs , & (insn [i ])))) {
381
+ # endif
382
+ if (addr >= (uint64_t )(uintptr_t )start && addr < (uint64_t )(uintptr_t )end ) {
383
+ zend_hash_index_add (& labels , addr , & zv );
384
+ }
385
+ }
386
+ }
387
+ #else
287
388
ZVAL_TRUE (& zv );
288
389
while (ud_disassemble (& ud )) {
289
390
op = ud_insn_opr (& ud , 0 );
@@ -294,6 +395,7 @@ static int zend_jit_disasm(const char *name,
294
395
}
295
396
}
296
397
}
398
+ #endif
297
399
298
400
zend_hash_sort (& labels , zend_jit_cmp_labels , 0 );
299
401
@@ -309,6 +411,88 @@ static int zend_jit_disasm(const char *name,
309
411
}
310
412
} ZEND_HASH_FOREACH_END ();
311
413
414
+ #ifdef HAVE_CAPSTONE
415
+ # ifdef HAVE_CAPSTONE_ITER
416
+ cs_code = start ;
417
+ cs_size = (uint8_t * )end - (uint8_t * )start ;
418
+ cs_addr = (uint64_t )(uintptr_t )cs_code ;
419
+ while (cs_disasm_iter (cs , & cs_code , & cs_size , & cs_addr , insn )) {
420
+ z = zend_hash_index_find (& labels , insn -> address );
421
+ # else
422
+ for (i = 0 ; i < count ; i ++ ) {
423
+ z = zend_hash_index_find (& labels , insn [i ].address );
424
+ # endif
425
+ if (z ) {
426
+ if (Z_LVAL_P (z ) < 0 ) {
427
+ fprintf (stderr , ".ENTRY" ZEND_LONG_FMT ":\n" , - Z_LVAL_P (z ));
428
+ } else {
429
+ fprintf (stderr , ".L" ZEND_LONG_FMT ":\n" , Z_LVAL_P (z ));
430
+ }
431
+ }
432
+
433
+ # ifdef HAVE_CAPSTONE_ITER
434
+ fprintf (stderr , "\t%s " , insn -> mnemonic );
435
+ p = insn -> op_str ;
436
+ # else
437
+ fprintf (stderr , "\t%s " , insn [i ].mnemonic );
438
+ p = insn [i ].op_str ;
439
+ # endif
440
+ /* Try to replace the target addresses with a symbols */
441
+ while ((q = strchr (p , 'x' )) != NULL ) {
442
+ if (p != q && * (q - 1 ) == '0' ) {
443
+ r = q + 1 ;
444
+ addr = 0 ;
445
+ while (1 ) {
446
+ if (* r >= '0' && * r <= '9' ) {
447
+ addr = addr * 16 + (* r - '0' );
448
+ } else if (* r >= 'A' && * r <= 'F' ) {
449
+ addr = addr * 16 + (* r - 'A' + 10 );
450
+ } else if (* r >= 'a' && * r <= 'f' ) {
451
+ addr = addr * 16 + (* r - 'a' + 10 );
452
+ } else {
453
+ break ;
454
+ }
455
+ r ++ ;
456
+ }
457
+ if (addr >= (uint64_t )(uintptr_t )start && addr < (uint64_t )(uintptr_t )end ) {
458
+ if ((z = zend_hash_index_find (& labels , addr ))) {
459
+ if (Z_LVAL_P (z ) < 0 ) {
460
+ fwrite (p , 1 , q - p - 1 , stderr );
461
+ fprintf (stderr , ".ENTRY" ZEND_LONG_FMT , - Z_LVAL_P (z ));
462
+ } else {
463
+ fwrite (p , 1 , q - p - 1 , stderr );
464
+ fprintf (stderr , ".L" ZEND_LONG_FMT , Z_LVAL_P (z ));
465
+ }
466
+ } else {
467
+ fwrite (p , 1 , r - p , stderr );
468
+ }
469
+ } else if ((sym = zend_jit_disasm_resolver (addr , & offset ))) {
470
+ fwrite (p , 1 , q - p - 1 , stderr );
471
+ fputs (sym , stderr );
472
+ if (offset != 0 ) {
473
+ if (offset > 0 ) {
474
+ fprintf (stderr , "+%" PRIx64 , offset );
475
+ } else {
476
+ fprintf (stderr , "-%" PRIx64 , offset );
477
+ }
478
+ }
479
+ } else {
480
+ fwrite (p , 1 , r - p , stderr );
481
+ }
482
+ p = r ;
483
+ } else {
484
+ fwrite (p , 1 , q - p + 1 , stderr );
485
+ p = q + 1 ;
486
+ }
487
+ }
488
+ fprintf (stderr , "%s\n" , p );
489
+ }
490
+ # ifdef HAVE_CAPSTONE_ITER
491
+ cs_free (insn , 1 );
492
+ # else
493
+ cs_free (insn , count );
494
+ # endif
495
+ #else
312
496
ud_set_input_buffer (& ud , (uint8_t * )start , (uint8_t * )end - (uint8_t * )start );
313
497
ud_set_pc (& ud , (uint64_t )(uintptr_t )start );
314
498
@@ -351,28 +535,20 @@ static int zend_jit_disasm(const char *name,
351
535
}
352
536
fprintf (stderr , "\t%s\n" , ud_insn_asm (& ud ));
353
537
}
538
+ #endif
354
539
fprintf (stderr , "\n" );
355
540
356
541
zend_hash_destroy (& labels );
357
542
543
+ #ifdef HAVE_CAPSTONE
544
+ cs_close (& cs );
545
+ #endif
546
+
358
547
return 1 ;
359
548
}
360
549
361
550
static int zend_jit_disasm_init (void )
362
551
{
363
- ud_init (& ud );
364
- #if defined(__x86_64__ ) || defined(_WIN64 )
365
- ud_set_mode (& ud , 64 );
366
- #else
367
- ud_set_mode (& ud , 32 );
368
- #endif
369
- #if DISASM_INTEL_SYNTAX
370
- ud_set_syntax (& ud , UD_SYN_INTEL );
371
- #else
372
- ud_set_syntax (& ud , UD_SYN_ATT );
373
- #endif
374
- ud_set_sym_resolver (& ud , zend_jit_disasm_resolver );
375
-
376
552
#ifndef ZTS
377
553
#define REGISTER_EG (n ) \
378
554
zend_jit_disasm_add_symbol("EG("#n")", \
0 commit comments