| 426 | //------------------------------------------------------------------------- |
| 427 | |
| 428 | static void __fix_instructions(uint32_t *__restrict inp, int32_t count, uint32_t *__restrict outp) { |
| 429 | context ctx; |
| 430 | ctx.basep = reinterpret_cast<int64_t>(inp); |
| 431 | ctx.endp = reinterpret_cast<int64_t>(inp + count); |
| 432 | memset(ctx.dat, 0, sizeof(ctx.dat)); |
| 433 | static_assert(sizeof(ctx.dat) / sizeof(ctx.dat[0]) == A64_MAX_INSTRUCTIONS, |
| 434 | "please use A64_MAX_INSTRUCTIONS!"); |
| 435 | #ifndef NDEBUG |
| 436 | if (count > A64_MAX_INSTRUCTIONS) { |
| 437 | A64_LOGE("too many fixing instructions!"); |
| 438 | } //if |
| 439 | #endif // NDEBUG |
| 440 | |
| 441 | while (--count >= 0) { |
| 442 | if (__fix_branch_imm(&inp, &outp, &ctx)) continue; |
| 443 | if (__fix_cond_comp_test_branch(&inp, &outp, &ctx)) continue; |
| 444 | if (__fix_loadlit(&inp, &outp, &ctx)) continue; |
| 445 | if (__fix_pcreladdr(&inp, &outp, &ctx)) continue; |
| 446 | |
| 447 | // without PC-relative offset |
| 448 | ctx.process_fix_map(ctx.get_and_set_current_index(inp, outp)); |
| 449 | *(outp++) = *(inp++); |
| 450 | } |
| 451 | |
| 452 | constexpr uint_fast64_t mask = 0x03ffffffu; // 0b00000011111111111111111111111111 |
| 453 | auto callback = reinterpret_cast<int64_t>(inp); |
| 454 | auto pc_offset = static_cast<int64_t>(callback - reinterpret_cast<int64_t>(outp)) >> 2; |
| 455 | if (llabs(pc_offset) > mask) { |
| 456 | if ((reinterpret_cast<uint64_t>(outp + 2) & 7u) != 0u) { |
| 457 | outp[0] = A64_NOP; |
| 458 | ++outp; |
| 459 | } //if |
| 460 | outp[0] = 0x58000051u; // LDR X17, #0x8 |
| 461 | outp[1] = 0xd61f0220u; // BR X17 |
| 462 | *reinterpret_cast<int64_t *>(outp + 2) = callback; |
| 463 | // outp += 4; |
| 464 | } else { |
| 465 | outp[0] = 0x14000000u | (pc_offset & mask); // "B" ADDR_PCREL26 |
| 466 | // ++outp; |
| 467 | } //if |
| 468 | } |
| 469 | |
| 470 | //------------------------------------------------------------------------- |
| 471 |
no test coverage detected