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

Function optimizeJump

src/e9patch/e9optimize.cpp:217–274  ·  view source on GitHub ↗

* Optimize a jump (or call) instruction. */

Source from the content-addressed store, hash-verified

215 * Optimize a jump (or call) instruction.
216 */
217static void optimizeJump(const Binary *B, intptr_t addr, uint8_t *bytes,
218 size_t size)
219{
220 if (!option_Opeephole || size == 0)
221 return;
222
223 bool jcc = false, jmp = false;
224 switch (bytes[0])
225 {
226 case 0xE9:
227 jmp = true;
228 // Fallthrough:
229 case 0xE8:
230 if (size != /*sizeof(jmpq/call rel32)=*/5)
231 return;
232 break;
233 case 0x0F:
234 if (size != /*sizeof(jcc rel32)=*/6)
235 return;
236 jcc = true;
237 switch (bytes[1])
238 {
239 case 0x80: case 0x81: case 0x82: case 0x83: case 0x84:
240 case 0x85: case 0x86: case 0x87: case 0x88: case 0x89:
241 case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E:
242 case 0x8F:
243 break;
244 default:
245 return;
246 }
247 break;
248 default:
249 return;
250 }
251
252 int32_t rel32 = *(int32_t *)(bytes + (jcc? 2: 1));
253 intptr_t target = addr + (intptr_t)size + (intptr_t)rel32;
254 const Instr *J = findInstr(B, target);
255 if (J == nullptr)
256 return;
257 target = getTrampolineEntry(B->Es, J);
258 if (target == INTPTR_MIN)
259 target = getCFTTarget(J->addr, J->PATCH, J->size, CFT_JMP);
260 if (target == INTPTR_MIN)
261 return;
262
263 intptr_t diff = target - (addr + (intptr_t)size);
264 if (jmp && diff == 0)
265 {
266 // As a special case, we can replace this JMP with a 5-byte NOP.
267 bytes[0] = 0x0F; bytes[1] = 0x1F; bytes[2] = 0x44;
268 bytes[3] = 0x00; bytes[4] = 0x00;
269 return;
270 }
271 if (diff < INT32_MIN || diff > INT32_MAX)
272 return;
273 *(int32_t *)(bytes + (jcc? 2: 1)) = (int32_t)diff;
274}

Callers 1

optimizeAllJumpsFunction · 0.85

Calls 3

findInstrFunction · 0.85
getTrampolineEntryFunction · 0.85
getCFTTargetFunction · 0.85

Tested by

no test coverage detected