Skip to content

Commit 3c6ac42

Browse files
committed
Add relocations for tb and tbnz instructions.
1 parent 166a2d8 commit 3c6ac42

File tree

5 files changed

+113
-6
lines changed

5 files changed

+113
-6
lines changed

cTools/libs/arch/aarch64/aarch64.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,3 +675,23 @@ uint8_t aarch64_put_cb( uint32_t *dst
675675
return 4;
676676
}
677677

678+
uint8_t aarch64_put_tb( uint32_t *dst
679+
, uint64_t pc
680+
, uint64_t target_addr
681+
, uint8_t reg_num
682+
, bool non_zero
683+
, bool x64
684+
, uint8_t bit_pos
685+
)
686+
{
687+
int64_t imm14 = SIGN_EXTEND((int64_t)(target_addr - pc) >> 2, 13);
688+
689+
*dst = (x64 ? 0x10000000 : 0x0)
690+
| (uint32_t)0x36000000
691+
| (non_zero ? 0x01000000 : 0x0)
692+
| (uint32_t)(bit_pos & 0x1f) << 19
693+
| (uint32_t)(imm14 & 0x3FFF) << 5
694+
| (uint32_t)(reg_num & 0x1F);
695+
696+
return 4;
697+
}

cTools/libs/arch/aarch64/aarch64.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,5 +282,15 @@ uint8_t aarch64_put_cb( uint32_t *dst
282282
, bool x64
283283
);
284284

285+
EXPORT_FUNC
286+
uint8_t aarch64_put_tb( uint32_t *dst
287+
, uint64_t pc
288+
, uint64_t target_addr
289+
, uint8_t reg_num
290+
, bool non_zero
291+
, bool x64
292+
, uint8_t bit_pos
293+
);
294+
285295
#endif /* __AARCH64_H */
286296

cTools/libs/arch/aarch64/aarch64_code_move.c

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
418462
CODE_MOVE_ERROR
419463
aarch64_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
}

cTools/libs/arch/code_move.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ typedef enum {
6464
RELOC_AARCH64_B_COND,
6565
RELOC_AARCH64_B_COND_ABS,
6666
RELOC_AARCH64_CB,
67+
RELOC_AARCH64_TB
6768
} RELOC_TYPE;
6869

6970
static_assert(sizeof(RELOC_TYPE) == 4, "RELOC_TYPE must be 32 bit");

cmake/toolchain/cflags/coverage.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" ST
3232
if (NOT WIN32)
3333
append_cflags(COVERAGE_CFLAGS "-fprofile-instr-generate -fcoverage-mapping")
3434
endif ()
35+
if ("${CMAKE_XCODE_BUILD_SYSTEM}" STREQUAL "12")
36+
# Problem detected with xcode 12, maybe some other versions also contain
37+
# Xcode doesn't link coverage library without this parameter
38+
string(APPEND _LINKER_FLAGS " --coverage")
39+
endif ()
3540
endif ()
3641

3742
append_cflags(COVERAGE_CFLAGS -fno-omit-frame-pointer)

0 commit comments

Comments
 (0)