Fill into pTramp the function pointer of the built trampoline function. * This function contains the first instructions of original function, * where some instructions needs a modification, and a jump * to the remaining instructions of original function. */
| 490 | * to the remaining instructions of original function. |
| 491 | */ |
| 492 | static bool write_tramp_function(const void *orig_fun, void **pTramp) |
| 493 | { |
| 494 | static unsigned char* currentTrampAddr = nullptr; |
| 495 | |
| 496 | currentTrampAddr = static_cast<unsigned char*>(allocate_nearby_segment(currentTrampAddr, orig_fun)); |
| 497 | |
| 498 | if (!currentTrampAddr) { |
| 499 | *pTramp = nullptr; |
| 500 | return false; |
| 501 | } |
| 502 | |
| 503 | *pTramp = currentTrampAddr; |
| 504 | |
| 505 | const unsigned char* pOrig = static_cast<const unsigned char*>(orig_fun); |
| 506 | |
| 507 | /* Overwrite the trampoline function */ |
| 508 | LOG(LL_DEBUG, LCF_HOOK, " Building our trampoline function in %p", currentTrampAddr); |
| 509 | |
| 510 | /* Write each instruction of the original function that we will overwrite, |
| 511 | * and update instructions with relative addresses. Our trampoline function |
| 512 | * is written in an address that is at most 32-bit away from the original |
| 513 | * function, so that for instructions with 32-bit relative address can be |
| 514 | * updated in place. |
| 515 | * Our trampoline will look like that: |
| 516 | * orig_instr1 |
| 517 | * ... |
| 518 | * orig_instrN |
| 519 | * ff 25 00 00 00 00 jmp *(%rip) |
| 520 | * ad dr re ss to or ig fn address to orig function offset by N bytes |
| 521 | * |
| 522 | * For the short jump instructions, we change the offset |
| 523 | * to jump to another jump instruction |
| 524 | * orig_instr1 |
| 525 | * 7e of jne 0xof |
| 526 | * orig_instrN |
| 527 | * ff 25 00 00 00 00 jmp *(%rip) |
| 528 | * ad dr re ss to or ig fn address to orig function offset by N bytes |
| 529 | * ad dr re ss to ju mp 01 address to orig called function 01 |
| 530 | */ |
| 531 | |
| 532 | int cur_offset = 0; |
| 533 | std::list<jmp_info> jmp_list; |
| 534 | instr_info instr; |
| 535 | |
| 536 | while (cur_offset < JMP_INSTR_LEN) { |
| 537 | /* Transcribe each instruction, and update the occasionnal relative address */ |
| 538 | int instr_len = instruction_length(pOrig + cur_offset, &instr); |
| 539 | |
| 540 | /* Print instruction */ |
| 541 | std::ostringstream oss_orig; |
| 542 | for (int off = cur_offset; off < cur_offset + instr_len; off++) { |
| 543 | oss_orig << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(*(pOrig + off)) << " "; |
| 544 | } |
| 545 | LOG(LL_DEBUG, LCF_HOOK, " Found instruction %s", oss_orig.str().c_str()); |
| 546 | |
| 547 | // Case where modRM with offset relative to the current instruction |
| 548 | // pointer value. We need to change the offset in place |
| 549 | bool relative_rip = instr.has_modRM && |
no test coverage detected