@@ -354,7 +354,7 @@ aarch64_move_b_cond( uint32_t instr
354354 uint64_t new_target_addr = new_pc + ((uint64_t )new_imm19 << 2 );
355355 if (target_addr == new_target_addr ) {
356356 STDERROR_LOG ("BC\n" );
357- // We can fit offset into 26 bits.
357+ // We can fit offset into 19 bits.
358358 r -> type = RELOC_AARCH64_B_COND ;
359359 r -> new_size = aarch64_put_b_cond ( (uint32_t * )dst
360360 , new_pc
@@ -399,7 +399,7 @@ aarch64_move_cb( uint32_t instr
399399 uint64_t new_target_addr = new_pc + ((uint64_t )new_imm19 << 2 );
400400 if (target_addr == new_target_addr ) {
401401 STDERROR_LOG ("CB\n" );
402- // We can fit offset into 26 bits.
402+ // We can fit offset into 19 bits.
403403 r -> type = RELOC_AARCH64_CB ;
404404 r -> new_size = aarch64_put_cb ( (uint32_t * )dst
405405 , new_pc
@@ -415,6 +415,50 @@ aarch64_move_cb( uint32_t instr
415415 return r -> new_size ;
416416}
417417
418+ static uint8_t
419+ aarch64_move_tb ( uint32_t instr
420+ , uint8_t * dst
421+ , uint64_t old_pc
422+ , uint64_t new_pc
423+ , vt_sorted_vector_t * rel
424+ )
425+ {
426+ bt_reloc * r = GET_PRE_INIT_BT_RELOC (rel );
427+ bool x64 = !!(instr & 0x80000000 );
428+ bool non_zero = !!(instr & 0x01000000 );
429+ uint8_t reg_num = instr & 0x1F ;
430+ int64_t imm14 = SIGN_EXTEND ((instr >> 5 ) & 0x3FFF , 13 );
431+ uint8_t bit_pos = (x64 ? 0x20 : 0 )
432+ | ((instr & 0x00f80000 ) >> 19 );
433+
434+ uint64_t target_addr = old_pc + ((uint64_t )imm14 << 2 );
435+ r -> old_target = target_addr ;
436+ target_addr = get_instr_new_addr (target_addr , rel );
437+ r -> new_target = target_addr ;
438+
439+ int64_t new_imm14 = ((target_addr - new_pc ) >> 2 ) & 0x3FFF ;
440+ new_imm14 = SIGN_EXTEND (new_imm14 , 13 );
441+
442+ uint64_t new_target_addr = new_pc + ((uint64_t )new_imm14 << 2 );
443+ if (target_addr == new_target_addr ) {
444+ // We can fit offset into 14 bits.
445+ r -> type = RELOC_AARCH64_TB ;
446+ r -> new_size = aarch64_put_tb ( (uint32_t * )dst
447+ , new_pc
448+ , target_addr
449+ , reg_num
450+ , non_zero
451+ , x64
452+ , bit_pos
453+ );
454+ } else {
455+ STDERROR_LOG ("TB: cannot fit in the 11 bits\n" );
456+ }
457+
458+ return r -> new_size ;
459+
460+ }
461+
418462CODE_MOVE_ERROR
419463aarch64_instr_move ( const uint8_t * src
420464 , uint8_t * dst
@@ -501,6 +545,15 @@ aarch64_instr_move( const uint8_t *src
501545 STDERROR_LOG ("CB: new instr: %" PRIx32 "\n" , * (uint32_t * )dst );
502546 break ;
503547 }
548+ case AARCH64_INSTR_OP_TBZ32 :
549+ case AARCH64_INSTR_OP_TBNZ32 :
550+ case AARCH64_INSTR_OP_TBZ64 :
551+ FALLTHROUGH ;
552+ case AARCH64_INSTR_OP_TBNZ64 :
553+ {
554+ r -> new_size = aarch64_move_tb (instr , dst , old_pc , new_pc , rel );
555+ break ;
556+ }
504557 case AARCH64_INSTR_OP_BCEQ :
505558 case AARCH64_INSTR_OP_BCNE :
506559 case AARCH64_INSTR_OP_BCCS :
@@ -517,10 +570,6 @@ aarch64_instr_move( const uint8_t *src
517570 case AARCH64_INSTR_OP_BCLE :
518571 case AARCH64_INSTR_OP_RETAASPPC :
519572 case AARCH64_INSTR_OP_RETABSPPC :
520- case AARCH64_INSTR_OP_TBZ32 :
521- case AARCH64_INSTR_OP_TBNZ32 :
522- case AARCH64_INSTR_OP_TBZ64 :
523- case AARCH64_INSTR_OP_TBNZ64 :
524573 case AARCH64_INSTR_OP_LDRF32 :
525574 case AARCH64_INSTR_OP_LDRF64 :
526575 case AARCH64_INSTR_OP_LDRF128 :
@@ -767,6 +816,28 @@ resolve_relocations( vt_sorted_vector_t *rel
767816 STDERROR_LOG ("\tFinal CB: %" PRIx32 "\n" , * (uint32_t * )instr_p );
768817 break ;
769818 }
819+ case RELOC_AARCH64_TB :
820+ {
821+ STDERROR_LOG ("Reloc CB:\n" );
822+ STDERROR_LOG ("\told_target: 0x%" PRIx64 ", new_pc_old_target: 0x%" PRIx64 "\n" , r [i ].old_target
823+ , old_target -> new_pc );
824+ bool x64 = !!((* ((uint32_t * )instr_p )) & 0x80000000 );
825+ bool non_zero = !!((* ((uint32_t * )instr_p )) & 0x01000000 );
826+ uint8_t bit_pos = (x64 ? 0x20 : 0 )
827+ | (((* ((uint32_t * )instr_p )) & 0x00f80000 ) >> 19 );
828+
829+ STDERROR_LOG ("\tPre Final CB: %" PRIx32 "\n" , * (uint32_t * )instr_p );
830+ aarch64_put_tb ( (uint32_t * )instr_p
831+ , r [i ].new_pc
832+ , r [i ].new_target
833+ , reg_num
834+ , non_zero
835+ , x64
836+ , bit_pos
837+ );
838+ STDERROR_LOG ("\tFinal CB: %" PRIx32 "\n" , * (uint32_t * )instr_p );
839+ break ;
840+ }
770841 default :
771842 break ;
772843 }
0 commit comments