| 523 | //------------------------------------------------------------------------- |
| 524 | |
| 525 | A64_JNIEXPORT void *A64HookFunctionV(void *const symbol, void *const replace, |
| 526 | void *const rwx, const uintptr_t rwx_size) { |
| 527 | constexpr uint_fast64_t mask = 0x03ffffffu; // 0b00000011111111111111111111111111 |
| 528 | |
| 529 | uint32_t *trampoline = static_cast<uint32_t *>(rwx), *original = static_cast<uint32_t *>(symbol); |
| 530 | |
| 531 | static_assert(A64_MAX_INSTRUCTIONS >= 5, "please fix A64_MAX_INSTRUCTIONS!"); |
| 532 | auto pc_offset = static_cast<int64_t>(__intval(replace) - __intval(symbol)) >> 2; |
| 533 | if (llabs(pc_offset) > mask) { |
| 534 | int32_t count = (reinterpret_cast<uint64_t>(original + 2) & 7u) != 0u ? 5 : 4; |
| 535 | if (trampoline) { |
| 536 | if (rwx_size < count * 10u) { |
| 537 | return NULL; |
| 538 | } //if |
| 539 | __fix_instructions(original, count, trampoline); |
| 540 | } //if |
| 541 | |
| 542 | if (__make_rwx(original, 5 * sizeof(uint32_t)) == 0) { |
| 543 | if (count == 5) { |
| 544 | original[0] = A64_NOP; |
| 545 | ++original; |
| 546 | } //if |
| 547 | original[0] = 0x58000051u; // LDR X17, #0x8 |
| 548 | original[1] = 0xd61f0220u; // BR X17 |
| 549 | *reinterpret_cast<int64_t *>(original + 2) = __intval(replace); |
| 550 | __flush_cache(symbol, 5 * sizeof(uint32_t)); |
| 551 | |
| 552 | A64_LOGI("inline hook %p->%p successfully! %zu bytes overwritten", |
| 553 | symbol, replace, 5 * sizeof(uint32_t)); |
| 554 | } else { |
| 555 | |
| 556 | trampoline = NULL; |
| 557 | } //if |
| 558 | } else { |
| 559 | if (trampoline) { |
| 560 | if (rwx_size < 1u * 10u) { |
| 561 | return NULL; |
| 562 | } //if |
| 563 | __fix_instructions(original, 1, trampoline); |
| 564 | } //if |
| 565 | |
| 566 | if (__make_rwx(original, 1 * sizeof(uint32_t)) == 0) { |
| 567 | __sync_cmpswap(original, *original, |
| 568 | 0x14000000u | (pc_offset & mask)); // "B" ADDR_PCREL26 |
| 569 | __flush_cache(symbol, 1 * sizeof(uint32_t)); |
| 570 | |
| 571 | A64_LOGI("inline hook %p->%p successfully! %zu bytes overwritten", |
| 572 | symbol, replace, 1 * sizeof(uint32_t)); |
| 573 | } else { |
| 574 | |
| 575 | trampoline = NULL; |
| 576 | } //if |
| 577 | } //if |
| 578 | |
| 579 | return trampoline; |
| 580 | } |
| 581 | |
| 582 | //------------------------------------------------------------------------- |
no test coverage detected