* Patch in a jmpq instruction. */
| 324 | * Patch in a jmpq instruction. |
| 325 | */ |
| 326 | static void patchJump(Patch *P, unsigned offset) |
| 327 | { |
| 328 | assert(offset <= PATCH_MAX - JMP_SIZE); |
| 329 | assert(offset < P->I->size); |
| 330 | assert(P->A != nullptr); |
| 331 | |
| 332 | intptr_t diff = (P->A->lb + P->A->entry) - |
| 333 | (P->I->addr + offset + JMP_SIZE); |
| 334 | assert(diff >= INT32_MIN && diff <= INT32_MAX); |
| 335 | int32_t rel32 = (int32_t)diff; |
| 336 | |
| 337 | uint8_t *bytes = P->I->PATCH + offset, |
| 338 | *state = P->I->STATE + offset; |
| 339 | assert(*state == STATE_INSTRUCTION || *state == STATE_FREE); |
| 340 | *bytes++ = /*jmpq opcode=*/0xE9; |
| 341 | *state++ = STATE_PATCHED; |
| 342 | offset++; |
| 343 | |
| 344 | const uint8_t *rel32p8 = (uint8_t *)&rel32; |
| 345 | unsigned i = 0; |
| 346 | for (; i < sizeof(rel32) && offset + i < P->I->size; i++) |
| 347 | { |
| 348 | assert(state[i] == STATE_INSTRUCTION || state[i] == STATE_FREE || |
| 349 | (state[i] == STATE_PATCHED && bytes[i] == rel32p8[i])); |
| 350 | bytes[i] = rel32p8[i]; |
| 351 | state[i] = STATE_PATCHED; |
| 352 | } |
| 353 | for (; i < sizeof(rel32); i++) |
| 354 | { |
| 355 | assert(state[i] != STATE_QUEUED); |
| 356 | if (state[i] == STATE_FREE) |
| 357 | { |
| 358 | bytes[i] = rel32p8[i]; |
| 359 | state[i] = STATE_PATCHED; |
| 360 | } |
| 361 | else |
| 362 | state[i] |= STATE_LOCKED; |
| 363 | } |
| 364 | } |
| 365 | |
| 366 | /* |
| 367 | * Patch in a short jmp instruction. |
no outgoing calls
no test coverage detected