1 //===-- X86FixupGadgets.cpp - Fixup Instructions that make ROP Gadgets ----===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file defines a function pass that checks instructions for sequences
11 /// that will lower to a potentially useful ROP gadget, and attempts to
12 /// replace those sequences with alternatives that are not useful for ROP.
13 ///
14 //===----------------------------------------------------------------------===//
15
16 #include "X86.h"
17 #include "X86InstrBuilder.h"
18 #include "X86InstrInfo.h"
19 #include "X86MachineFunctionInfo.h"
20 #include "X86Subtarget.h"
21 #include "X86TargetMachine.h"
22 #include "llvm/CodeGen/MachineFunction.h"
23 #include "llvm/CodeGen/MachineFunctionPass.h"
24 #include "llvm/CodeGen/MachineInstrBuilder.h"
25 #include "llvm/CodeGen/MachineRegisterInfo.h"
26 #include "llvm/CodeGen/Passes.h"
27 #include "llvm/MC/MCAsmInfo.h"
28 #include "llvm/MC/MCSymbol.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/raw_ostream.h"
31 using namespace llvm;
32
33 #define FIXUPGADGETS_DESC "X86 ROP Gadget Fixup"
34 #define FIXUPGADGETS_NAME "x86-fixup-gadgets"
35
36 #define DEBUG_TYPE FIXUPGADGETS_NAME
37
38 // Toggle with cc1 option: -mllvm -x86-fixup-gadgets=<true|false>
39 static cl::opt<bool> FixupGadgets(
40 "x86-fixup-gadgets", cl::Hidden,
41 cl::desc("Replace ROP friendly instructions with safe alternatives"),
42 cl::init(true));
43
44 namespace {
45 class FixupGadgetsPass : public MachineFunctionPass {
46
47 public:
48 static char ID;
49
getPassName() const50 StringRef getPassName() const override { return FIXUPGADGETS_DESC; }
51
FixupGadgetsPass()52 FixupGadgetsPass()
53 : MachineFunctionPass(ID), STI(nullptr), TII(nullptr), TRI(nullptr) {}
54
55 /// Loop over all the instructions and replace ROP friendly
56 /// seuqences with less ROP friendly alternatives
57 bool runOnMachineFunction(MachineFunction &MF) override;
58
getRequiredProperties() const59 MachineFunctionProperties getRequiredProperties() const override {
60 return MachineFunctionProperties().set(
61 MachineFunctionProperties::Property::NoVRegs);
62 }
63
64 private:
65 const X86Subtarget *STI;
66 const X86InstrInfo *TII;
67 const X86RegisterInfo *TRI;
68 bool Is64Bit;
69
70 struct FixupInfo {
71 unsigned op1;
72 unsigned op2;
73 bool fixup;
74 bool align;
75 };
76
77 uint8_t getRegNum(const MachineOperand &MO) const;
78 uint8_t getRegNum(unsigned reg) const;
79 struct FixupInfo isROPFriendly(MachineInstr &MI) const;
80 bool isROPFriendlyImm(const MachineOperand &MO) const;
81 bool isROPFriendlyRegPair(const MachineOperand &Dst,
82 const MachineOperand &Src) const;
83 bool isROPFriendlyReg(const MachineOperand &Dst, uint8_t RegOpcode) const;
84 bool badModRM(uint8_t Mod, uint8_t RegOpcode, uint8_t RM) const;
85 void checkSIB(const MachineInstr &MI, unsigned CurOp,
86 struct FixupInfo &info) const;
87 bool needsFixup(struct FixupInfo &fi) const;
88 bool needsAlign(struct FixupInfo &fi) const;
89 unsigned getWidestRegForReg(unsigned reg) const;
90 unsigned getEquivalentRegForReg(unsigned oreg, unsigned nreg) const;
91 bool hasImplicitUseOrDef(const MachineInstr &MI, unsigned Reg1,
92 unsigned Reg2) const;
93 bool fixupWithoutExchange(MachineInstr &MI);
94
95 bool fixupInstruction(MachineFunction &MF, MachineBasicBlock &MBB,
96 MachineInstr &MI, struct FixupInfo Info);
97 };
98 char FixupGadgetsPass::ID = 0;
99 } // namespace
100
createX86FixupGadgetsPass()101 FunctionPass *llvm::createX86FixupGadgetsPass() {
102 return new FixupGadgetsPass();
103 }
104
getRegNum(const MachineOperand & MO) const105 uint8_t FixupGadgetsPass::getRegNum(const MachineOperand &MO) const {
106 return TRI->getEncodingValue(MO.getReg()) & 0x7;
107 }
108
getRegNum(unsigned reg) const109 uint8_t FixupGadgetsPass::getRegNum(unsigned reg) const {
110 return TRI->getEncodingValue(reg) & 0x7;
111 }
112
isROPFriendlyImm(const MachineOperand & MO) const113 bool FixupGadgetsPass::isROPFriendlyImm(const MachineOperand &MO) const {
114 int64_t imm = MO.getImm();
115 for (int i = 0; i < 8; ++i) {
116 uint8_t byte = (imm & 0xff);
117 if (byte == 0xc2 || byte == 0xc3 || byte == 0xca || byte == 0xcb) {
118 return true;
119 }
120 imm = imm >> 8;
121 }
122 return false;
123 }
124
isROPFriendlyRegPair(const MachineOperand & Dst,const MachineOperand & Src) const125 bool FixupGadgetsPass::isROPFriendlyRegPair(const MachineOperand &Dst,
126 const MachineOperand &Src) const {
127
128 if (!Dst.isReg() || !Src.isReg())
129 llvm_unreachable("Testing non registers for bad reg pair!");
130
131 uint8_t Mod = 3;
132 uint8_t RegOpcode = getRegNum(Src);
133 uint8_t RM = getRegNum(Dst);
134 return badModRM(Mod, RegOpcode, RM);
135 }
136
isROPFriendlyReg(const MachineOperand & Dst,uint8_t RegOpcode) const137 bool FixupGadgetsPass::isROPFriendlyReg(const MachineOperand &Dst, uint8_t RegOpcode) const {
138
139 if (!Dst.isReg())
140 llvm_unreachable("Testing non register for bad reg!");
141
142 uint8_t Mod = 3;
143 uint8_t RM = getRegNum(Dst);
144 return badModRM(Mod, RegOpcode, RM);
145 }
146
badModRM(uint8_t Mod,uint8_t RegOpcode,uint8_t RM) const147 bool FixupGadgetsPass::badModRM(uint8_t Mod, uint8_t RegOpcode,
148 uint8_t RM) const {
149 uint8_t ModRM = ((Mod << 6) | (RegOpcode << 3) | RM);
150 if (ModRM == 0xc2 || ModRM == 0xc3 || ModRM == 0xca || ModRM == 0xcb)
151 return true;
152 return false;
153 }
154
checkSIB(const MachineInstr & MI,unsigned CurOp,struct FixupInfo & info) const155 void FixupGadgetsPass::checkSIB(const MachineInstr &MI, unsigned CurOp,
156 struct FixupInfo &info) const {
157
158 const MachineOperand &Base = MI.getOperand(CurOp + X86::AddrBaseReg);
159 const MachineOperand &Scale = MI.getOperand(CurOp + X86::AddrScaleAmt);
160 const MachineOperand &Index = MI.getOperand(CurOp + X86::AddrIndexReg);
161
162 if (!Scale.isImm() || !Base.isReg() || !Index.isReg())
163 llvm_unreachable("Wrong type operands");
164
165 if (Scale.getImm() != 8 || Base.getReg() == 0 || Index.getReg() == 0)
166 return;
167
168 if (badModRM(3, getRegNum(Index), getRegNum(Base))) {
169 info.op1 = CurOp + X86::AddrBaseReg;
170 info.op2 = CurOp + X86::AddrIndexReg;
171 info.fixup = true;
172 }
173 }
174
175 struct FixupGadgetsPass::FixupInfo
isROPFriendly(MachineInstr & MI) const176 FixupGadgetsPass::isROPFriendly(MachineInstr &MI) const {
177
178 const MCInstrDesc &Desc = MI.getDesc();
179 unsigned CurOp = X86II::getOperandBias(Desc);
180 uint64_t TSFlags = Desc.TSFlags;
181 uint64_t Form = TSFlags & X86II::FormMask;
182 bool HasVEX_4V = TSFlags & X86II::VEX_4V;
183 bool HasEVEX_K = TSFlags & X86II::EVEX_K;
184
185 struct FixupInfo info = {0, 0, false, false};
186
187 // Look for constants with c3 in them
188 for (const auto &MO : MI.operands()) {
189 if (MO.isImm() && isROPFriendlyImm(MO)) {
190 info.align = true;
191 break;
192 }
193 }
194
195 switch (Form) {
196 case X86II::Pseudo: {
197 // Pesudos that are replaced with real instructions later
198 switch (MI.getOpcode()) {
199 case X86::ADD64rr_DB:
200 case X86::ADD32rr_DB:
201 case X86::ADD16rr_DB:
202 goto Handle_MRMDestReg;
203 case X86::ADD16ri_DB:
204 case X86::ADD32ri_DB:
205 case X86::ADD64ri32_DB:
206 case X86::ADD16ri8_DB:
207 case X86::ADD32ri8_DB:
208 case X86::ADD64ri8_DB:
209 goto Handle_MRMXr;
210 default:
211 break;
212 }
213 break;
214 }
215 case X86II::AddRegFrm: {
216 uint8_t BaseOpcode = X86II::getBaseOpcodeFor(TSFlags);
217 uint8_t Opcode = BaseOpcode + getRegNum(MI.getOperand(CurOp));
218 if (Opcode == 0xc2 || Opcode == 0xc3 || Opcode == 0xca || Opcode == 0xcb) {
219 info.op1 = CurOp;
220 info.fixup = true;
221 }
222 break;
223 }
224 case X86II::MRMDestMem: {
225 checkSIB(MI, CurOp, info);
226 unsigned opcode = MI.getOpcode();
227 if (opcode == X86::MOVNTImr || opcode == X86::MOVNTI_64mr)
228 info.align = true;
229 break;
230 }
231 case X86II::MRMSrcMem: {
232 CurOp += 1;
233 if (HasVEX_4V)
234 CurOp += 1;
235 if (HasEVEX_K)
236 CurOp += 1;
237 checkSIB(MI, CurOp, info);
238 break;
239 }
240 case X86II::MRMSrcMem4VOp3: {
241 CurOp += 1;
242 checkSIB(MI, CurOp, info);
243 break;
244 }
245 case X86II::MRMSrcMemOp4: {
246 CurOp += 3;
247 checkSIB(MI, CurOp, info);
248 break;
249 }
250 case X86II::MRMXm:
251 case X86II::MRM0m:
252 case X86II::MRM1m:
253 case X86II::MRM2m:
254 case X86II::MRM3m:
255 case X86II::MRM4m:
256 case X86II::MRM5m:
257 case X86II::MRM6m:
258 case X86II::MRM7m: {
259 if (HasVEX_4V)
260 CurOp += 1;
261 if (HasEVEX_K)
262 CurOp += 1;
263 checkSIB(MI, CurOp, info);
264 break;
265 }
266 case X86II::MRMDestReg: {
267 Handle_MRMDestReg:
268 const MachineOperand &DstReg = MI.getOperand(CurOp);
269 info.op1 = CurOp;
270 CurOp += 1;
271 if (HasVEX_4V)
272 CurOp += 1;
273 if (HasEVEX_K)
274 CurOp += 1;
275 const MachineOperand &SrcReg = MI.getOperand(CurOp);
276 info.op2 = CurOp;
277 if (isROPFriendlyRegPair(DstReg, SrcReg))
278 info.fixup = true;
279 break;
280 }
281 case X86II::MRMSrcReg: {
282 const MachineOperand &DstReg = MI.getOperand(CurOp);
283 info.op1 = CurOp;
284 CurOp += 1;
285 if (HasVEX_4V)
286 CurOp += 1;
287 if (HasEVEX_K)
288 CurOp += 1;
289 const MachineOperand &SrcReg = MI.getOperand(CurOp);
290 info.op2 = CurOp;
291 if (isROPFriendlyRegPair(SrcReg, DstReg))
292 info.fixup = true;
293 break;
294 }
295 case X86II::MRMSrcReg4VOp3: {
296 const MachineOperand &DstReg = MI.getOperand(CurOp);
297 info.op1 = CurOp;
298 CurOp += 1;
299 const MachineOperand &SrcReg = MI.getOperand(CurOp);
300 info.op2 = CurOp;
301 if (isROPFriendlyRegPair(SrcReg, DstReg))
302 info.fixup = true;
303 break;
304 }
305 case X86II::MRMSrcRegOp4: {
306 const MachineOperand &DstReg = MI.getOperand(CurOp);
307 info.op1 = CurOp;
308 CurOp += 3;
309 const MachineOperand &SrcReg = MI.getOperand(CurOp);
310 info.op2 = CurOp;
311 if (isROPFriendlyRegPair(SrcReg, DstReg))
312 info.fixup = true;
313 break;
314 }
315 case X86II::MRMXr:
316 case X86II::MRM0r:
317 case X86II::MRM1r: {
318 Handle_MRMXr:
319 if (HasVEX_4V)
320 CurOp += 1;
321 if (HasEVEX_K)
322 CurOp += 1;
323 const MachineOperand &DstReg = MI.getOperand(CurOp);
324 info.op1 = CurOp;
325 if (isROPFriendlyReg(DstReg, Form == X86II::MRM1r ? 1 : 0))
326 info.fixup = true;
327 break;
328 }
329 case X86II::MRM_C2:
330 case X86II::MRM_C3:
331 case X86II::MRM_CA:
332 case X86II::MRM_CB: {
333 info.align = true;
334 break;
335 }
336 default:
337 break;
338 }
339 return info;
340 }
341
needsFixup(struct FixupInfo & fi) const342 bool FixupGadgetsPass::needsFixup(struct FixupInfo &fi) const {
343 return (fi.fixup == true);
344 }
345
needsAlign(struct FixupInfo & fi) const346 bool FixupGadgetsPass::needsAlign(struct FixupInfo &fi) const {
347 return (fi.align == true);
348 }
349
getWidestRegForReg(unsigned reg) const350 unsigned FixupGadgetsPass::getWidestRegForReg(unsigned reg) const {
351
352 switch (reg) {
353 case X86::AL:
354 case X86::AH:
355 case X86::AX:
356 case X86::EAX:
357 case X86::RAX:
358 return Is64Bit ? X86::RAX : X86::EAX;
359 case X86::BL:
360 case X86::BH:
361 case X86::BX:
362 case X86::EBX:
363 case X86::RBX:
364 return Is64Bit ? X86::RBX : X86::EBX;
365 case X86::CL:
366 case X86::CH:
367 case X86::CX:
368 case X86::ECX:
369 case X86::RCX:
370 return Is64Bit ? X86::RCX : X86::ECX;
371 case X86::DL:
372 case X86::DH:
373 case X86::DX:
374 case X86::EDX:
375 case X86::RDX:
376 return Is64Bit ? X86::RDX : X86::EDX;
377 case X86::R8B:
378 case X86::R8W:
379 case X86::R8D:
380 case X86::R8:
381 return X86::R8;
382 case X86::R9B:
383 case X86::R9W:
384 case X86::R9D:
385 case X86::R9:
386 return X86::R9;
387 case X86::R10B:
388 case X86::R10W:
389 case X86::R10D:
390 case X86::R10:
391 return X86::R10;
392 case X86::R11B:
393 case X86::R11W:
394 case X86::R11D:
395 case X86::R11:
396 return X86::R11;
397 default:
398 return X86::NoRegister; // Non-GP Reg
399 }
400 return 0;
401 }
402
403 // For given register oreg return the equivalent size register
404 // from the nreg register set. Eg. For oreg ebx and nreg ax, return eax.
getEquivalentRegForReg(unsigned oreg,unsigned nreg) const405 unsigned FixupGadgetsPass::getEquivalentRegForReg(unsigned oreg,
406 unsigned nreg) const {
407 unsigned compreg = getWidestRegForReg(nreg);
408
409 switch (oreg) {
410 case X86::AL:
411 case X86::BL:
412 case X86::CL:
413 case X86::DL:
414 case X86::R8B:
415 case X86::R9B:
416 case X86::R10B:
417 case X86::R11B:
418 switch (compreg) {
419 case X86::EAX:
420 case X86::RAX:
421 return X86::AL;
422 case X86::EBX:
423 case X86::RBX:
424 return X86::BL;
425 case X86::ECX:
426 case X86::RCX:
427 return X86::CL;
428 case X86::EDX:
429 case X86::RDX:
430 return X86::DL;
431 case X86::R8:
432 return X86::R8B;
433 case X86::R9:
434 return X86::R9B;
435 case X86::R10:
436 return X86::R10B;
437 case X86::R11:
438 return X86::R11B;
439 default:
440 llvm_unreachable("Unknown 8 bit register");
441 }
442 break;
443 case X86::AH:
444 case X86::BH:
445 case X86::CH:
446 case X86::DH:
447 switch (compreg) {
448 case X86::EAX:
449 return X86::AH;
450 case X86::EBX:
451 return X86::BH;
452 case X86::ECX:
453 return X86::CH;
454 case X86::EDX:
455 return X86::DH;
456 default:
457 llvm_unreachable("Using H registers in REX mode");
458 }
459 break;
460 case X86::AX:
461 case X86::BX:
462 case X86::CX:
463 case X86::DX:
464 case X86::R8W:
465 case X86::R9W:
466 case X86::R10W:
467 case X86::R11W:
468 switch (compreg) {
469 case X86::EAX:
470 case X86::RAX:
471 return X86::AX;
472 case X86::EBX:
473 case X86::RBX:
474 return X86::BX;
475 case X86::ECX:
476 case X86::RCX:
477 return X86::CX;
478 case X86::EDX:
479 case X86::RDX:
480 return X86::DX;
481 case X86::R8:
482 return X86::R8W;
483 case X86::R9:
484 return X86::R9W;
485 case X86::R10:
486 return X86::R10W;
487 case X86::R11:
488 return X86::R11W;
489 default:
490 llvm_unreachable("Unknown 16 bit register");
491 }
492 break;
493 case X86::EAX:
494 case X86::EBX:
495 case X86::ECX:
496 case X86::EDX:
497 case X86::R8D:
498 case X86::R9D:
499 case X86::R10D:
500 case X86::R11D:
501 switch (compreg) {
502 case X86::EAX:
503 case X86::RAX:
504 return X86::EAX;
505 case X86::EBX:
506 case X86::RBX:
507 return X86::EBX;
508 case X86::ECX:
509 case X86::RCX:
510 return X86::ECX;
511 case X86::EDX:
512 case X86::RDX:
513 return X86::EDX;
514 case X86::R8:
515 return X86::R8D;
516 case X86::R9:
517 return X86::R9D;
518 case X86::R10:
519 return X86::R10D;
520 case X86::R11:
521 return X86::R11D;
522 default:
523 llvm_unreachable("Unknown 32 bit register");
524 }
525 break;
526 case X86::RAX:
527 case X86::RBX:
528 case X86::RCX:
529 case X86::RDX:
530 case X86::R8:
531 case X86::R9:
532 case X86::R10:
533 case X86::R11:
534 return compreg;
535 default:
536 llvm_unreachable("Unknown input register!");
537 }
538 }
539
hasImplicitUseOrDef(const MachineInstr & MI,unsigned Reg1,unsigned Reg2) const540 bool FixupGadgetsPass::hasImplicitUseOrDef(const MachineInstr &MI,
541 unsigned Reg1, unsigned Reg2) const {
542
543 const MCInstrDesc &Desc = MI.getDesc();
544
545 const ArrayRef<MCPhysReg> ImpDefs = Desc.implicit_defs();
546 for (MCPhysReg ImpDef : ImpDefs) {
547 unsigned w = getWidestRegForReg(ImpDef);
548 if (w == Reg1 || w == Reg2) {
549 return true;
550 }
551 }
552
553 const ArrayRef<MCPhysReg> ImpUses = Desc.implicit_uses();
554 for (MCPhysReg ImpUse : ImpUses) {
555 unsigned w = getWidestRegForReg(ImpUse);
556 if (w == Reg1 || w == Reg2) {
557 return true;
558 }
559 }
560 return false;
561 }
562
fixupWithoutExchange(MachineInstr & MI)563 bool FixupGadgetsPass::fixupWithoutExchange(MachineInstr &MI) {
564 switch (MI.getOpcode()) {
565 case X86::MOV8rr_REV:
566 MI.setDesc(TII->get(X86::MOV8rr));
567 break;
568 case X86::MOV16rr_REV:
569 MI.setDesc(TII->get(X86::MOV16rr));
570 break;
571 case X86::MOV32rr_REV:
572 MI.setDesc(TII->get(X86::MOV32rr));
573 break;
574 case X86::MOV64rr_REV:
575 MI.setDesc(TII->get(X86::MOV64rr));
576 break;
577 case X86::MOV8rr:
578 MI.setDesc(TII->get(X86::MOV8rr_REV));
579 break;
580 case X86::MOV16rr:
581 MI.setDesc(TII->get(X86::MOV16rr_REV));
582 break;
583 case X86::MOV32rr:
584 MI.setDesc(TII->get(X86::MOV32rr_REV));
585 break;
586 case X86::MOV64rr:
587 MI.setDesc(TII->get(X86::MOV64rr_REV));
588 break;
589 default:
590 return false;
591 }
592 return true;
593 }
594
fixupInstruction(MachineFunction & MF,MachineBasicBlock & MBB,MachineInstr & MI,FixupInfo Info)595 bool FixupGadgetsPass::fixupInstruction(MachineFunction &MF,
596 MachineBasicBlock &MBB,
597 MachineInstr &MI, FixupInfo Info) {
598
599 if (!needsAlign(Info) && !needsFixup(Info))
600 return false;
601
602 DebugLoc DL = MI.getDebugLoc();
603
604 // Check for only needs alignment
605 if (needsAlign(Info) && !needsFixup(Info)) {
606 BuildMI(MBB, MI, DL, TII->get(X86::JMP_TRAP));
607 return true;
608 }
609
610 unsigned XCHG = Is64Bit ? X86::XCHG64rr : X86::XCHG32rr;
611
612 unsigned OrigReg1 = MI.getOperand(Info.op1).getReg();
613 // Swap with RAX/EAX unless we have a second register to swap with
614 unsigned OrigReg2 = Is64Bit ? X86::RAX : X86::EAX;
615 if (Info.op2)
616 OrigReg2 = MI.getOperand(Info.op2).getReg();
617
618 unsigned SwapReg1 = getWidestRegForReg(OrigReg1);
619 unsigned SwapReg2 = getWidestRegForReg(OrigReg2);
620 unsigned CompReg1 = SwapReg1;
621 unsigned CompReg2 = SwapReg2;
622
623 // Just align if:
624 // - we have a non-GP reg to swap with
625 // - the instruction implicitly uses one of the registers we are swapping
626 // - if we are fixing an instruction that skips the xchg back
627 if (SwapReg1 == X86::NoRegister || SwapReg2 == X86::NoRegister ||
628 hasImplicitUseOrDef(MI, CompReg1, CompReg2) || MI.isCall() ||
629 MI.isReturn() || MI.isBranch() || MI.isIndirectBranch() ||
630 MI.isBarrier()) {
631 BuildMI(MBB, MI, DL, TII->get(X86::JMP_TRAP));
632 return true;
633 }
634
635 // Make sure our XCHG doesn't make a gadget
636 if (badModRM(3, getRegNum(SwapReg1), getRegNum(SwapReg2))) {
637 unsigned treg = SwapReg1;
638 SwapReg1 = SwapReg2;
639 SwapReg2 = treg;
640 }
641
642 // Check for specific instructions we can fix without the xchg dance
643 if (fixupWithoutExchange(MI)) {
644 return true;
645 }
646
647 // Swap the two registers to start
648 BuildMI(MBB, MI, DL, TII->get(XCHG))
649 .addReg(SwapReg1, RegState::Define)
650 .addReg(SwapReg2, RegState::Define)
651 .addReg(SwapReg1).addReg(SwapReg2);
652
653 // Check for needs alignment
654 if (needsAlign(Info))
655 BuildMI(MBB, MI, DL, TII->get(X86::JMP_TRAP));
656
657 // Swap the registers inside the instruction
658 for (MachineOperand &MO : MI.operands()) {
659 if (!MO.isReg())
660 continue;
661
662 unsigned reg = MO.getReg();
663 unsigned match = getWidestRegForReg(reg);
664 if (match == CompReg1)
665 MO.setReg(getEquivalentRegForReg(reg, OrigReg2));
666 else if (match == CompReg2)
667 MO.setReg(getEquivalentRegForReg(reg, OrigReg1));
668 }
669
670 // And swap the two registers back
671 BuildMI(MBB, ++MachineBasicBlock::instr_iterator(MI), DL, TII->get(XCHG))
672 .addReg(SwapReg1, RegState::Define)
673 .addReg(SwapReg2, RegState::Define)
674 .addReg(SwapReg1).addReg(SwapReg2);
675
676 return true;
677 }
678
runOnMachineFunction(MachineFunction & MF)679 bool FixupGadgetsPass::runOnMachineFunction(MachineFunction &MF) {
680 if (!FixupGadgets)
681 return false;
682
683 STI = &MF.getSubtarget<X86Subtarget>();
684 TII = STI->getInstrInfo();
685 TRI = STI->getRegisterInfo();
686 Is64Bit = STI->is64Bit();
687 std::vector<std::pair<MachineInstr *, FixupInfo>> fixups;
688 FixupInfo info;
689
690 bool modified = false;
691
692 for (auto &MBB : MF) {
693 fixups.clear();
694 for (auto &MI : MBB) {
695 info = isROPFriendly(MI);
696 if (needsAlign(info) || needsFixup(info))
697 fixups.push_back(std::make_pair(&MI, info));
698 }
699 for (auto &fixup : fixups)
700 modified |= fixupInstruction(MF, MBB, *fixup.first, fixup.second);
701 }
702
703 return modified;
704 }
705