@@ -331,6 +331,66 @@ static target_ulong reverse_bits(target_ulong num)
331
331
reverse_num <<= count ;
332
332
return reverse_num ;
333
333
}
334
+ /*
335
+ * Isolate the portion of code gen which can setjmp/longjmp.
336
+ * Return the size of the generated code, or negative on error.
337
+ */
338
+ static int libafl_setjmp_gen_code (CPUArchState * env , TranslationBlock * tb ,
339
+ vaddr pc , void * host_pc ,
340
+ int * max_insns , int64_t * ti )
341
+ {
342
+ int ret = sigsetjmp (tcg_ctx -> jmp_trans , 0 );
343
+ if (unlikely (ret != 0 )) {
344
+ return ret ;
345
+ }
346
+
347
+ tcg_func_start (tcg_ctx );
348
+
349
+ tcg_ctx -> cpu = env_cpu (env );
350
+
351
+ // -- start gen_intermediate_code
352
+ const int num_insns = 1 ; // do "as-if" we were translating a single target instruction
353
+
354
+ #ifndef TARGET_INSN_START_EXTRA_WORDS
355
+ tcg_gen_insn_start (pc );
356
+ #elif TARGET_INSN_START_EXTRA_WORDS == 1
357
+ tcg_gen_insn_start (pc , 0 );
358
+ #elif TARGET_INSN_START_EXTRA_WORDS == 2
359
+ tcg_gen_insn_start (pc , 0 , 0 );
360
+ #else
361
+ #error Unhandled TARGET_INSN_START_EXTRA_WORDS value
362
+ #endif
363
+
364
+ struct libafl_edge_hook * hook = libafl_edge_hooks ;
365
+ while (hook ) {
366
+ if (hook -> cur_id != (uint64_t )-1 && hook -> helper_info .func ) {
367
+ TCGv_i64 tmp0 = tcg_constant_i64 (hook -> data );
368
+ TCGv_i64 tmp1 = tcg_constant_i64 (hook -> cur_id );
369
+ TCGTemp * tmp2 [2 ] = { tcgv_i64_temp (tmp0 ), tcgv_i64_temp (tmp1 ) };
370
+ tcg_gen_callN (& hook -> helper_info , NULL , tmp2 );
371
+ tcg_temp_free_i64 (tmp0 );
372
+ tcg_temp_free_i64 (tmp1 );
373
+ }
374
+ if (hook -> cur_id != (uint64_t )-1 && hook -> jit ) {
375
+ hook -> jit (hook -> data , hook -> cur_id );
376
+ }
377
+ hook = hook -> next ;
378
+ }
379
+ tcg_gen_goto_tb (0 );
380
+ tcg_gen_exit_tb (tb , 0 );
381
+
382
+ // This is obviously wrong, but it is required that the number / size of target instruction translated
383
+ // is at least 1. For now, we make it so that no problem occurs later on.
384
+ tb -> icount = num_insns ; // number of target instructions translated in the TB.
385
+ tb -> size = num_insns ; // size (in target bytes) of target instructions translated in the TB.
386
+ // -- end gen_intermediate_code
387
+
388
+ assert (tb -> size != 0 );
389
+ tcg_ctx -> cpu = NULL ;
390
+ * max_insns = tb -> icount ;
391
+
392
+ return tcg_gen_code (tcg_ctx , tb , pc );
393
+ }
334
394
335
395
/* Called with mmap_lock held for user mode emulation. */
336
396
TranslationBlock * libafl_gen_edge (CPUState * cpu , target_ulong src_block ,
@@ -339,25 +399,37 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
339
399
int cflags )
340
400
{
341
401
CPUArchState * env = cpu_env (cpu );
342
- TranslationBlock * tb , * existing_tb ;
343
- tb_page_addr_t phys_pc , phys_page2 ;
344
- target_ulong virt_page2 ;
402
+ TranslationBlock * tb ;
403
+ tb_page_addr_t phys_pc ;
345
404
tcg_insn_unit * gen_code_buf ;
346
405
int gen_code_size , search_size , max_insns ;
347
- #ifdef CONFIG_PROFILER
348
- TCGProfile * prof = & tcg_ctx -> prof ;
349
406
int64_t ti ;
350
- #endif
407
+ void * host_pc ;
351
408
352
409
target_ulong pc = src_block ^ reverse_bits ((target_ulong )exit_n );
353
410
354
- (void )virt_page2 ;
355
- (void )phys_page2 ;
356
- (void )phys_pc ;
357
- (void )existing_tb ;
358
-
359
411
assert_memory_lock ();
412
+ qemu_thread_jit_write ();
360
413
414
+ phys_pc = get_page_addr_code_hostp (env , src_block , & host_pc );
415
+ phys_pc ^= reverse_bits ((tb_page_addr_t )exit_n );
416
+
417
+ // if (phys_pc == -1) {
418
+ // /* Generate a one-shot TB with 1 insn in it */
419
+ // cflags = (cflags & ~CF_COUNT_MASK) | 1;
420
+ // }
421
+
422
+ /* Generate a one-shot TB with max 16 insn in it */
423
+ cflags = (cflags & ~CF_COUNT_MASK ) | LIBAFL_MAX_INSNS ;
424
+ QEMU_BUILD_BUG_ON (LIBAFL_MAX_INSNS > TCG_MAX_INSNS );
425
+
426
+ max_insns = cflags & CF_COUNT_MASK ;
427
+ if (max_insns == 0 ) {
428
+ max_insns = TCG_MAX_INSNS ;
429
+ }
430
+ QEMU_BUILD_BUG_ON (CF_COUNT_MASK + 1 != TCG_MAX_INSNS );
431
+
432
+ // edge hooks generation callbacks
361
433
struct libafl_edge_hook * hook = libafl_edge_hooks ;
362
434
int no_exec_hook = 1 ;
363
435
while (hook ) {
@@ -371,21 +443,8 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
371
443
if (no_exec_hook )
372
444
return NULL ;
373
445
374
- qemu_thread_jit_write ();
375
-
376
- phys_pc = get_page_addr_code (env , src_block );
377
- phys_pc ^= reverse_bits ((tb_page_addr_t )exit_n );
378
-
379
- /* Generate a one-shot TB with max 8 insn in it */
380
- cflags = (cflags & ~CF_COUNT_MASK ) | 8 ;
381
-
382
- max_insns = cflags & CF_COUNT_MASK ;
383
- if (max_insns == 0 ) {
384
- max_insns = TCG_MAX_INSNS ;
385
- }
386
- QEMU_BUILD_BUG_ON (CF_COUNT_MASK + 1 != TCG_MAX_INSNS );
387
-
388
- buffer_overflow1 :
446
+ buffer_overflow :
447
+ assert_no_pages_locked ();
389
448
tb = tcg_tb_alloc (tcg_ctx );
390
449
if (unlikely (!tb )) {
391
450
/* flush must be done */
@@ -398,79 +457,116 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
398
457
399
458
gen_code_buf = tcg_ctx -> code_gen_ptr ;
400
459
tb -> tc .ptr = tcg_splitwx_to_rx (gen_code_buf );
460
+
401
461
if (!(cflags & CF_PCREL )) {
402
462
tb -> pc = pc ;
403
463
}
464
+
404
465
tb -> cs_base = cs_base ;
405
466
tb -> flags = flags ;
406
467
tb -> cflags = cflags | CF_IS_EDGE ;
407
- //tb_set_page_addr0(tb, phys_pc);
408
- //tb_set_page_addr1(tb, -1);
409
- tcg_ctx -> gen_tb = tb ;
468
+ tb_set_page_addr0 (tb , phys_pc );
469
+ tb_set_page_addr1 (tb , -1 );
470
+ // if (phys_pc != -1) {
471
+ // tb_lock_page0(phys_pc);
472
+ // }
410
473
411
- #ifdef CONFIG_PROFILER
412
- /* includes aborted translations because of exceptions */
413
- qatomic_set (& prof -> tb_count1 , prof -> tb_count1 + 1 );
414
- ti = profile_getclock ();
474
+ tcg_ctx -> gen_tb = tb ;
475
+ tcg_ctx -> addr_type = TARGET_LONG_BITS == 32 ? TCG_TYPE_I32 : TCG_TYPE_I64 ;
476
+ #ifdef CONFIG_SOFTMMU
477
+ tcg_ctx -> page_bits = TARGET_PAGE_BITS ;
478
+ tcg_ctx -> page_mask = TARGET_PAGE_MASK ;
479
+ tcg_ctx -> tlb_dyn_max_bits = CPU_TLB_DYN_MAX_BITS ;
480
+ #endif
481
+ tcg_ctx -> insn_start_words = TARGET_INSN_START_WORDS ;
482
+ #ifdef TCG_GUEST_DEFAULT_MO
483
+ tcg_ctx -> guest_mo = TCG_GUEST_DEFAULT_MO ;
484
+ #else
485
+ tcg_ctx -> guest_mo = TCG_MO_ALL ;
415
486
#endif
416
487
417
- tcg_func_start (tcg_ctx );
418
-
419
- tcg_ctx -> cpu = env_cpu (env );
420
-
421
- hook = libafl_edge_hooks ;
422
- size_t hcount = 0 , hins = 0 ;
423
- while (hook ) {
424
- if (hook -> cur_id != (uint64_t )-1 && hook -> helper_info .func ) {
425
- hcount ++ ;
426
- hins ++ ;
427
- TCGv_i64 tmp0 = tcg_constant_i64 (hook -> data );
428
- TCGv_i64 tmp1 = tcg_constant_i64 (hook -> cur_id );
429
- TCGTemp * tmp2 [2 ] = { tcgv_i64_temp (tmp0 ), tcgv_i64_temp (tmp1 ) };
430
- tcg_gen_callN (& hook -> helper_info , NULL , tmp2 );
431
- tcg_temp_free_i64 (tmp0 );
432
- tcg_temp_free_i64 (tmp1 );
433
- }
434
- if (hook -> cur_id != (uint64_t )-1 && hook -> jit ) {
435
- hcount ++ ;
436
- hins += hook -> jit (hook -> data , hook -> cur_id );
437
- }
438
- hook = hook -> next ;
439
- }
440
- tcg_gen_goto_tb (0 );
441
- tcg_gen_exit_tb (tb , 0 );
442
- tb -> size = hcount ;
443
- tb -> icount = hins ;
444
-
445
- assert (tb -> size != 0 );
446
- tcg_ctx -> cpu = NULL ;
447
- max_insns = tb -> icount ;
448
-
488
+ restart_translate :
449
489
trace_translate_block (tb , pc , tb -> tc .ptr );
450
490
451
- #ifdef CONFIG_PROFILER
452
- qatomic_set (& prof -> tb_count , prof -> tb_count + 1 );
453
- qatomic_set (& prof -> interm_time ,
454
- prof -> interm_time + profile_getclock () - ti );
455
- ti = profile_getclock ();
456
- #endif
457
-
458
- gen_code_size = tcg_gen_code (tcg_ctx , tb , pc );
491
+ gen_code_size = libafl_setjmp_gen_code (env , tb , pc , host_pc , & max_insns , & ti );
459
492
if (unlikely (gen_code_size < 0 )) {
460
- goto buffer_overflow1 ;
493
+ switch (gen_code_size ) {
494
+ case -1 :
495
+ /*
496
+ * Overflow of code_gen_buffer, or the current slice of it.
497
+ *
498
+ * TODO: We don't need to re-do gen_intermediate_code, nor
499
+ * should we re-do the tcg optimization currently hidden
500
+ * inside tcg_gen_code. All that should be required is to
501
+ * flush the TBs, allocate a new TB, re-initialize it per
502
+ * above, and re-do the actual code generation.
503
+ */
504
+ qemu_log_mask (CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT ,
505
+ "Restarting code generation for "
506
+ "code_gen_buffer overflow\n" );
507
+ tb_unlock_pages (tb );
508
+ tcg_ctx -> gen_tb = NULL ;
509
+ goto buffer_overflow ;
510
+
511
+ case -2 :
512
+ assert (false && "This should never happen for edge code. There must be a bug." );
513
+ /*
514
+ * The code generated for the TranslationBlock is too large.
515
+ * The maximum size allowed by the unwind info is 64k.
516
+ * There may be stricter constraints from relocations
517
+ * in the tcg backend.
518
+ *
519
+ * Try again with half as many insns as we attempted this time.
520
+ * If a single insn overflows, there's a bug somewhere...
521
+ */
522
+ assert (max_insns > 1 );
523
+ max_insns /= 2 ;
524
+ qemu_log_mask (CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT ,
525
+ "Restarting code generation with "
526
+ "smaller translation block (max %d insns)\n" ,
527
+ max_insns );
528
+
529
+ /*
530
+ * The half-sized TB may not cross pages.
531
+ * TODO: Fix all targets that cross pages except with
532
+ * the first insn, at which point this can't be reached.
533
+ */
534
+ // phys_p2 = tb_page_addr1(tb);
535
+ // if (unlikely(phys_p2 != -1)) {
536
+ // tb_unlock_page1(phys_pc, phys_p2);
537
+ // tb_set_page_addr1(tb, -1);
538
+ // }
539
+ goto restart_translate ;
540
+
541
+ case -3 :
542
+ /*
543
+ * We had a page lock ordering problem. In order to avoid
544
+ * deadlock we had to drop the lock on page0, which means
545
+ * that everything we translated so far is compromised.
546
+ * Restart with locks held on both pages.
547
+ */
548
+ qemu_log_mask (CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT ,
549
+ "Restarting code generation with re-locked pages" );
550
+ goto restart_translate ;
551
+
552
+ default :
553
+ g_assert_not_reached ();
554
+ }
461
555
}
556
+ tcg_ctx -> gen_tb = NULL ;
557
+
462
558
search_size = encode_search (tb , (void * )gen_code_buf + gen_code_size );
463
559
if (unlikely (search_size < 0 )) {
464
- goto buffer_overflow1 ;
560
+ tb_unlock_pages (tb );
561
+ goto buffer_overflow ;
465
562
}
466
563
tb -> tc .size = gen_code_size ;
467
564
468
- #ifdef CONFIG_PROFILER
469
- qatomic_set (& prof -> code_time , prof -> code_time + profile_getclock () - ti );
470
- qatomic_set (& prof -> code_in_len , prof -> code_in_len + tb -> size );
471
- qatomic_set (& prof -> code_out_len , prof -> code_out_len + gen_code_size );
472
- qatomic_set (& prof -> search_out_len , prof -> search_out_len + search_size );
473
- #endif
565
+ /*
566
+ * For CF_PCREL, attribute all executions of the generated code
567
+ * to its first mapping.
568
+ */
569
+ perf_report_code (pc , tb , tcg_splitwx_to_rx (gen_code_buf ));
474
570
475
571
qatomic_set (& tcg_ctx -> code_gen_ptr , (void * )
476
572
ROUND_UP ((uintptr_t )gen_code_buf + gen_code_size + search_size ,
@@ -492,6 +588,8 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
492
588
tb_reset_jump (tb , 1 );
493
589
}
494
590
591
+ assert_no_pages_locked ();
592
+
495
593
#ifndef CONFIG_USER_ONLY
496
594
tb -> page_addr [0 ] = tb -> page_addr [1 ] = -1 ;
497
595
#endif
@@ -543,12 +641,14 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
543
641
544
642
gen_code_buf = tcg_ctx -> code_gen_ptr ;
545
643
tb -> tc .ptr = tcg_splitwx_to_rx (gen_code_buf );
644
+
546
645
//// --- Begin LibAFL code ---
547
646
// Always include pc for edge hooks
548
647
//if (!(cflags & CF_PCREL)) {
549
648
tb -> pc = pc ;
550
649
//}
551
650
//// --- End LibAFL code ---
651
+
552
652
tb -> cs_base = cs_base ;
553
653
tb -> flags = flags ;
554
654
tb -> cflags = cflags ;
0 commit comments