@@ -589,6 +589,118 @@ static void test_virtual_write(void)
589589 OK (uc_close (uc ));
590590}
591591
592+ static void test_virtual_write_tb_invalidation_callback (uc_engine * uc , uint64_t rip , uint32_t size , void * userdata )
593+ {
594+ /*
595+ * mov rax,QWORD PTR ds:0x2000
596+ * test rax,rax
597+ * je rip+0x10000000
598+ * mov rbx,QWORD PTR ds:0x2008
599+ * test rax,rax
600+ * jz rip+0x10000000 <_main+0x22>
601+ * hlt
602+ */
603+ char code1 [] = { 0x48 , 0x8B , 0x04 , 0x25 , 0x00 , 0x20 , 0x00 , 0x00 , 0x48 , 0x85 , 0xC0 , 0x74 , 0x10 , 0x48 , 0x8B , 0x1C , 0x25 , 0x08 , 0x20 , 0x00 , 0x00 , 0x48 , 0x85 , 0xC0 , 0x74 , 0x03 , 0xF4 , 0x90 , 0x90 };
604+ /*
605+ * mov rax,QWORD PTR ds:0x2000
606+ * test rax,rax
607+ * je rip+0x10000000
608+ * mov rbx,QWORD PTR ds:0x2008
609+ * test rax,rax
610+ * jz rip+0x10000000
611+ * hlt
612+ */
613+ char code2 [] = { 0x48 , 0x8B , 0x04 , 0x25 , 0x00 , 0x28 , 0x00 , 0x00 , 0x48 , 0x85 , 0xC0 , 0x74 , 0x10 , 0x48 , 0x8B , 0x1C , 0x25 , 0x08 , 0x28 , 0x00 , 0x00 , 0x48 , 0x85 , 0xC0 , 0x74 , 0x03 , 0xF4 , 0x90 , 0x90 };
614+
615+ int state = * (int * )userdata ;
616+
617+ if (state == 0 ) {
618+ return ;
619+ }
620+ if (state == 1 && (rip & 0xff00 ) == 0x1000 && (rip & 0xff ) == 0x0d ) {
621+ * (int * )userdata = 0 ; //hook is called twice because the loop break
622+ //so set state to 0 again to indicate we are done at this point
623+ OK (uc_vmem_write (uc , 0x1800 , UC_PROT_EXEC , code2 , sizeof (code2 )));
624+ return ;
625+ }
626+ if (state == 2 && (rip & 0xff00 ) == 0x1800 && (rip & 0xff ) == 0x0d ) {
627+ * (int * )userdata = 0 ; //hook is called twice because the loop break
628+ //so set state to 0 again to indicate we are done at this point
629+ OK (uc_vmem_write (uc , 0x1800 , UC_PROT_EXEC , code1 , sizeof (code1 )));
630+ return ;
631+ }
632+ }
633+
634+ static void test_virtual_write_tb_invalidation (void )
635+ {
636+ uc_engine * uc ;
637+ uc_hook hook1 , hook2 ;
638+ int state = 0 ;
639+ uint64_t rax1 = 0x01 ;
640+ uint64_t rbx1 = 0x02 ;
641+ uint64_t rax2 = 0x11 ;
642+ uint64_t rbx2 = 0x12 ;
643+ uint64_t res = 0 ;
644+ /*
645+ * mov rax,QWORD PTR ds:0x2000
646+ * test rax,rax
647+ * je 1d <bla>
648+ * mov rbx,QWORD PTR ds:0x2008
649+ * test rax,rax
650+ * je 1d <bla>
651+ * hlt
652+ * nop
653+ * nop
654+ * bla:
655+ */
656+ char code1 [] = { 0x48 , 0x8B , 0x04 , 0x25 , 0x00 , 0x20 , 0x00 , 0x00 , 0x48 , 0x85 , 0xC0 , 0x74 , 0x10 , 0x48 , 0x8B , 0x1C , 0x25 , 0x08 , 0x20 , 0x00 , 0x00 , 0x48 , 0x85 , 0xC0 , 0x74 , 0x03 , 0xF4 , 0x90 , 0x90 };
657+
658+ OK (uc_open (UC_ARCH_X86 , UC_MODE_64 , & uc ));
659+ OK (uc_ctl_tlb_mode (uc , UC_TLB_VIRTUAL ));
660+ OK (uc_hook_add (uc , & hook1 , UC_HOOK_TLB_FILL , test_virtual_write_tlb_fill , NULL , 1 , 0 ));
661+ OK (uc_hook_add (uc , & hook2 , UC_HOOK_BLOCK , & test_virtual_write_tb_invalidation_callback , & state , 1 , 0 ));
662+ OK (uc_mem_map (uc , 0x0 , 0x2000 , UC_PROT_ALL ));
663+
664+ OK (uc_vmem_write (uc , 0x1000 , UC_PROT_EXEC , code1 , sizeof (code1 )));
665+ OK (uc_vmem_write (uc , 0x1800 , UC_PROT_EXEC , code1 , sizeof (code1 )));
666+ OK (uc_vmem_write (uc , 0x2000 , UC_PROT_READ , & rax1 , sizeof (rax1 )));
667+ OK (uc_vmem_write (uc , 0x2008 , UC_PROT_READ , & rbx1 , sizeof (rbx1 )));
668+ OK (uc_vmem_write (uc , 0x2800 , UC_PROT_READ , & rax2 , sizeof (rax2 )));
669+ OK (uc_vmem_write (uc , 0x2808 , UC_PROT_READ , & rbx2 , sizeof (rbx2 )));
670+
671+ /*
672+ * run all code once to ensure that the tb are created
673+ */
674+ OK (uc_emu_start (uc , 0x1000 , 0 , 0 , 0 ));
675+ OK (uc_emu_start (uc , 0x1800 , 0 , 0 , 0 ));
676+
677+ /*
678+ * state one:
679+ * run code1 at 0x1000
680+ * write code2 to 0x1800
681+ * run code2 at 0x1800
682+ */
683+ state = 1 ;
684+ OK (uc_emu_start (uc , 0x1000 , 0 , 0 , 0 ));
685+ OK (uc_emu_start (uc , 0x1800 , 0 , 0 , 0 ));
686+
687+ OK (uc_reg_read (uc , UC_X86_REG_RAX , & res ));
688+ TEST_CHECK (rax2 == res );
689+ OK (uc_reg_read (uc , UC_X86_REG_RBX , & res ));
690+ TEST_CHECK (rbx2 == res );
691+
692+ state = 2 ;
693+ OK (uc_emu_start (uc , 0x1000 , 0 , 0 , 0 ));
694+ OK (uc_emu_start (uc , 0x1800 , 0 , 0 , 0 ));
695+
696+ OK (uc_reg_read (uc , UC_X86_REG_RAX , & res ));
697+ TEST_CHECK (rax2 == res );
698+ OK (uc_reg_read (uc , UC_X86_REG_RBX , & res ));
699+ TEST_CHECK (rbx1 == res );
700+
701+ OK (uc_close (uc ));
702+ }
703+
592704TEST_LIST = {{"test_map_correct" , test_map_correct },
593705 {"test_map_wrapping" , test_map_wrapping },
594706 {"test_mem_protect" , test_mem_protect },
@@ -608,4 +720,5 @@ TEST_LIST = {{"test_map_correct", test_map_correct},
608720 test_mem_read_and_write_large_memory_block },
609721 {"test_virtual_to_physical" , test_virtual_to_physical },
610722 {"test_virtual_write" , test_virtual_write },
723+ {"test_virtual_write_tb_invalidation" , test_virtual_write_tb_invalidation },
611724 {NULL , NULL }};
0 commit comments