MCPcopy Create free account
hub / github.com/GJDuck/e9patch / tactic_T0

Function tactic_T0

src/e9patch/e9tactics.cpp:802–877  ·  view source on GitHub ↗

* Tactic T0: Batch instructions that are not jump targets. * Assumes (overapproximate) control-flow-recovery */

Source from the content-addressed store, hash-verified

800 * Assumes (overapproximate) control-flow-recovery
801 */
802static Patch *tactic_T0(Binary &B, Instr *I, const Trampoline *T,
803 Tactic tactic = TACTIC_T0)
804{
805 if (!option_tactic_T0 || !option_OCFR || !canPatch(I) || I->T != T)
806 return nullptr;
807
808 // Step (1): build batch backwards, up to limit or target reached.
809 Instr *J = I;
810 size_t size = 0;
811 for (unsigned limit = T0_LIMIT; !J->target && limit > 0; limit--)
812 {
813 size += J->size;
814 Instr *K = J->pred();
815 if (K == nullptr ||
816 (K->STATE[0] != STATE_INSTRUCTION &&
817 K->STATE[0] != STATE_QUEUED))
818 break;
819 J = K;
820 }
821
822 // Step (2): Build batch fowards until sizeof(jmpq), or a CFT.
823 Instr *L = I;
824 bool cft = false; // isUnconditionalCFT(I);
825 while (!cft && size < /*sizeof(jmpq)=*/5)
826 {
827 Instr *K = L->succ();
828 if (K == nullptr || K->target || !canPatch(K) ||
829 (K->is_patched && !K->is_evicted))
830 break;
831 L = K;
832 size += L->size;
833 cft = isCFT(L->ORIG, L->size, CFT_CALL | CFT_RET | CFT_JMP);
834 }
835 if (J == L)
836 return nullptr; // Batch is a single instruction == T0 failed
837
838 // Step (3): "Free" all batched instructions.
839 Patch *P = nullptr;
840 for (Instr *K = L; K != nullptr && K->addr >= J->addr; K = K->pred())
841 {
842 Patch *Q = new Patch(K, TACTIC_T0, nullptr);
843 patchUnused(Q, /*offset=*/0);
844 Q->next = P;
845 P = Q;
846 }
847
848 // Step (4): Build batch trampoline.
849 Trampoline *U = nullptr;
850 {
851 size_t num_entries = 1;
852 uint8_t *ptr =
853 new uint8_t[sizeof(Trampoline) + num_entries * sizeof(Entry)];
854 U = (Trampoline *)ptr;
855 U->prot = PROT_READ | PROT_EXEC;
856 U->num_entries = num_entries;
857 U->preload = false;
858 U->entries[0].kind = ENTRY_BATCH;
859 U->entries[0].length = 0;

Callers 1

patchFunction · 0.85

Calls 9

canPatchFunction · 0.85
isCFTFunction · 0.85
patchUnusedFunction · 0.85
tactic_B1Function · 0.85
tactic_B2Function · 0.85
tactic_T1Function · 0.85
undoFunction · 0.85
predMethod · 0.80
succMethod · 0.80

Tested by

no test coverage detected