Hello tech@, The attached diff changes the order in which clang will allocate registers on X86, specifically so EBX / RBX are selected last. The reason is because some instructions using RBX as the destination operand and either RAX or RCX as the source result in machine code that includes a C3 or CB byte, which is useful as a return in ROP gadgets. By choosing EBX/RBX last, there are less of these instructions, and therefore less of these gadgets.
diff --git lib/Target/X86/X86RegisterInfo.td lib/Target/X86/X86RegisterInfo.td index 3a61a7247c7..f5106c40445 100644 --- lib/Target/X86/X86RegisterInfo.td +++ lib/Target/X86/X86RegisterInfo.td @@ -339,8 +339,8 @@ def GR16 : RegisterClass<"X86", [i16], 16, R8W, R9W, R10W, R11W, R14W, R15W, R12W, R13W)>; def GR32 : RegisterClass<"X86", [i32], 32, - (add EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP, - R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D)>; + (add EAX, ECX, EDX, ESI, EDI, EBP, ESP, + R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D, EBX)>; // GR64 - 64-bit GPRs. This oddly includes RIP, which isn't accurate, since // RIP isn't really a register and it can't be used anywhere except in an @@ -349,7 +349,7 @@ def GR32 : RegisterClass<"X86", [i32], 32, // tests because of the inclusion of RIP in this register class. def GR64 : RegisterClass<"X86", [i64], 64, (add RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, - RBX, R14, R15, R12, R13, RBP, RSP, RIP)>; + R14, R15, R12, R13, RBP, RSP, RIP, RBX)>; // Segment registers for use by MOV instructions (and others) that have a // segment register as one operand. Always contain a 16-bit segment