OLD | NEW |
(Empty) | |
| 1 //=== X86MCNaCl.cpp - Expansion of NaCl pseudo-instructions --*- C++ -*-=// |
| 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 // |
| 10 //===----------------------------------------------------------------------===// |
| 11 #define DEBUG_TYPE "x86-sandboxing" |
| 12 |
| 13 #include "MCTargetDesc/X86MCTargetDesc.h" |
| 14 #include "MCTargetDesc/X86BaseInfo.h" |
| 15 #include "MCTargetDesc/X86MCNaCl.h" |
| 16 #include "X86NaClDecls.h" |
| 17 #include "llvm/MC/MCAsmInfo.h" |
| 18 #include "llvm/MC/MCContext.h" |
| 19 #include "llvm/MC/MCExpr.h" |
| 20 #include "llvm/MC/MCInstrInfo.h" |
| 21 #include "llvm/MC/MCRegisterInfo.h" |
| 22 #include "llvm/MC/MCInst.h" |
| 23 #include "llvm/MC/MCObjectFileInfo.h" |
| 24 #include "llvm/MC/MCStreamer.h" |
| 25 #include "llvm/CodeGen/ValueTypes.h" |
| 26 #include "llvm/Support/CommandLine.h" |
| 27 #include "llvm/Support/Debug.h" |
| 28 |
| 29 using namespace llvm; |
| 30 |
| 31 cl::opt<bool> FlagUseZeroBasedSandbox("sfi-zero-based-sandbox", |
| 32 cl::desc("Use a zero-based sandbox model" |
| 33 " for the NaCl SFI."), |
| 34 cl::init(false)); |
| 35 // This flag can be set to false to test the performance impact of |
| 36 // hiding the sandbox base. |
| 37 cl::opt<bool> FlagHideSandboxBase("sfi-hide-sandbox-base", |
| 38 cl::desc("Prevent 64-bit NaCl sandbox" |
| 39 " pointers from being written to" |
| 40 " the stack. [default=true]"), |
| 41 cl::init(true)); |
| 42 |
| 43 const int kNaClX86InstructionBundleSize = 32; |
| 44 |
| 45 // See the notes below where these functions are defined. |
| 46 namespace { |
| 47 unsigned getX86SubSuperRegister_(unsigned Reg, EVT VT, bool High=false); |
| 48 unsigned DemoteRegTo32_(unsigned RegIn); |
| 49 } // namespace |
| 50 |
| 51 static MCSymbol *CreateTempLabel(MCContext &Context, const char *Prefix) { |
| 52 SmallString<128> NameSV; |
| 53 raw_svector_ostream(NameSV) |
| 54 << Context.getAsmInfo()->getPrivateGlobalPrefix() // get internal label |
| 55 << Prefix << Context.getUniqueSymbolID(); |
| 56 return Context.GetOrCreateSymbol(NameSV); |
| 57 } |
| 58 |
| 59 static void PushReturnAddress(const llvm::MCSubtargetInfo &STI, |
| 60 MCContext &Context, MCStreamer &Out, |
| 61 MCSymbol *RetTarget) { |
| 62 const MCExpr *RetTargetExpr = MCSymbolRefExpr::Create(RetTarget, Context); |
| 63 if (Context.getObjectFileInfo()->getRelocM() == Reloc::PIC_) { |
| 64 // Calculate return_addr |
| 65 // The return address should not be calculated into R11 because if the push |
| 66 // instruction ends up at the start of a bundle, an attacker could arrange |
| 67 // an indirect jump to it, which would push the full jump target |
| 68 // (which itself was calculated into r11) onto the stack. |
| 69 MCInst LEAInst; |
| 70 LEAInst.setOpcode(X86::LEA64_32r); |
| 71 LEAInst.addOperand(MCOperand::CreateReg(X86::R10D)); // DestReg |
| 72 LEAInst.addOperand(MCOperand::CreateReg(X86::RIP)); // BaseReg |
| 73 LEAInst.addOperand(MCOperand::CreateImm(1)); // Scale |
| 74 LEAInst.addOperand(MCOperand::CreateReg(0)); // IndexReg |
| 75 LEAInst.addOperand(MCOperand::CreateExpr(RetTargetExpr)); // Offset |
| 76 LEAInst.addOperand(MCOperand::CreateReg(0)); // SegmentReg |
| 77 Out.EmitInstruction(LEAInst, STI); |
| 78 // push return_addr |
| 79 MCInst PUSHInst; |
| 80 PUSHInst.setOpcode(X86::PUSH64r); |
| 81 PUSHInst.addOperand(MCOperand::CreateReg(X86::R10)); |
| 82 Out.EmitInstruction(PUSHInst, STI); |
| 83 } else { |
| 84 // push return_addr |
| 85 MCInst PUSHInst; |
| 86 PUSHInst.setOpcode(X86::PUSH64i32); |
| 87 PUSHInst.addOperand(MCOperand::CreateExpr(RetTargetExpr)); |
| 88 Out.EmitInstruction(PUSHInst, STI); |
| 89 } |
| 90 } |
| 91 |
| 92 static void EmitDirectCall(const llvm::MCSubtargetInfo &STI, |
| 93 const MCOperand &Op, bool Is64Bit, MCStreamer &Out) { |
| 94 const bool HideSandboxBase = |
| 95 (FlagHideSandboxBase && Is64Bit && !FlagUseZeroBasedSandbox); |
| 96 if (HideSandboxBase) { |
| 97 // For NaCl64, the sequence |
| 98 // call target |
| 99 // return_addr: |
| 100 // is changed to |
| 101 // push return_addr |
| 102 // jmp target |
| 103 // .align 32 |
| 104 // return_addr: |
| 105 // This avoids exposing the sandbox base address via the return |
| 106 // address on the stack. |
| 107 |
| 108 // When generating PIC code, calculate the return address manually: |
| 109 // leal return_addr(%rip), %r10d |
| 110 // push %r10 |
| 111 // jmp target |
| 112 // .align 32 |
| 113 // return_addr: |
| 114 |
| 115 MCContext &Context = Out.getContext(); |
| 116 |
| 117 // Generate a label for the return address. |
| 118 MCSymbol *RetTarget = CreateTempLabel(Context, "DirectCallRetAddr"); |
| 119 |
| 120 PushReturnAddress(STI, Context, Out, RetTarget); |
| 121 |
| 122 // jmp target |
| 123 MCInst JMPInst; |
| 124 JMPInst.setOpcode(X86::JMP_4); |
| 125 JMPInst.addOperand(Op); |
| 126 Out.EmitInstruction(JMPInst, STI); |
| 127 |
| 128 Out.EmitCodeAlignment(kNaClX86InstructionBundleSize); |
| 129 Out.EmitLabel(RetTarget); |
| 130 } else { |
| 131 Out.EmitBundleLock(true); |
| 132 |
| 133 MCInst CALLInst; |
| 134 CALLInst.setOpcode(Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32); |
| 135 CALLInst.addOperand(Op); |
| 136 Out.EmitInstruction(CALLInst, STI); |
| 137 Out.EmitBundleUnlock(); |
| 138 } |
| 139 } |
| 140 |
| 141 static void EmitIndirectBranch(const llvm::MCSubtargetInfo &STI, |
| 142 const MCOperand &Op, bool Is64Bit, bool IsCall, |
| 143 MCStreamer &Out) { |
| 144 const bool HideSandboxBase = |
| 145 (FlagHideSandboxBase && Is64Bit && !FlagUseZeroBasedSandbox); |
| 146 const int JmpMask = -kNaClX86InstructionBundleSize; |
| 147 unsigned Reg32 = Op.getReg(); |
| 148 |
| 149 // For NaCl64, the sequence |
| 150 // jmp *%rXX |
| 151 // is changed to |
| 152 // mov %rXX,%r11d |
| 153 // and $0xffffffe0,%r11d |
| 154 // add %r15,%r11 |
| 155 // jmpq *%r11 |
| 156 // |
| 157 // And the sequence |
| 158 // call *%rXX |
| 159 // return_addr: |
| 160 // is changed to |
| 161 // mov %rXX,%r11d |
| 162 // push return_addr |
| 163 // and $0xffffffe0,%r11d |
| 164 // add %r15,%r11 |
| 165 // jmpq *%r11 |
| 166 // .align 32 |
| 167 // return_addr: |
| 168 // |
| 169 // This avoids exposing the sandbox base address via the return |
| 170 // address on the stack. |
| 171 |
| 172 // When generating PIC code for calls, calculate the return address manually: |
| 173 // mov %rXX,%r11d |
| 174 // leal return_addr(%rip), %r10d |
| 175 // pushq %r10 |
| 176 // and $0xffffffe0,%r11d |
| 177 // add %r15,%r11 |
| 178 // jmpq *%r11 |
| 179 // .align 32 |
| 180 // return_addr: |
| 181 |
| 182 MCSymbol *RetTarget = NULL; |
| 183 |
| 184 // For NaCl64, force an assignment of the branch target into r11, |
| 185 // and subsequently use r11 as the ultimate branch target, so that |
| 186 // only r11 (which will never be written to memory) exposes the |
| 187 // sandbox base address. But avoid a redundant assignment if the |
| 188 // original branch target is already r11 or r11d. |
| 189 const unsigned SafeReg32 = X86::R11D; |
| 190 const unsigned SafeReg64 = X86::R11; |
| 191 if (HideSandboxBase) { |
| 192 // In some cases, EmitIndirectBranch() is called with a 32-bit |
| 193 // register Op (e.g. r11d), and in other cases a 64-bit register |
| 194 // (e.g. r11), so we need to test both variants to avoid a |
| 195 // redundant assignment. TODO(stichnot): Make callers consistent |
| 196 // on 32 vs 64 bit register. |
| 197 if ((Reg32 != SafeReg32) && (Reg32 != SafeReg64)) { |
| 198 MCInst MOVInst; |
| 199 MOVInst.setOpcode(X86::MOV32rr); |
| 200 MOVInst.addOperand(MCOperand::CreateReg(SafeReg32)); |
| 201 MOVInst.addOperand(MCOperand::CreateReg(Reg32)); |
| 202 Out.EmitInstruction(MOVInst, STI); |
| 203 Reg32 = SafeReg32; |
| 204 } |
| 205 if (IsCall) { |
| 206 MCContext &Context = Out.getContext(); |
| 207 // Generate a label for the return address. |
| 208 RetTarget = CreateTempLabel(Context, "IndirectCallRetAddr"); |
| 209 // Explicitly push the (32-bit) return address for a NaCl64 call |
| 210 // instruction. |
| 211 PushReturnAddress(STI, Context, Out, RetTarget); |
| 212 } |
| 213 } |
| 214 const unsigned Reg64 = getX86SubSuperRegister_(Reg32, MVT::i64); |
| 215 |
| 216 const bool WillEmitCallInst = IsCall && !HideSandboxBase; |
| 217 Out.EmitBundleLock(WillEmitCallInst); |
| 218 |
| 219 MCInst ANDInst; |
| 220 ANDInst.setOpcode(X86::AND32ri8); |
| 221 ANDInst.addOperand(MCOperand::CreateReg(Reg32)); |
| 222 ANDInst.addOperand(MCOperand::CreateReg(Reg32)); |
| 223 ANDInst.addOperand(MCOperand::CreateImm(JmpMask)); |
| 224 Out.EmitInstruction(ANDInst, STI); |
| 225 |
| 226 if (Is64Bit && !FlagUseZeroBasedSandbox) { |
| 227 MCInst InstADD; |
| 228 InstADD.setOpcode(X86::ADD64rr); |
| 229 InstADD.addOperand(MCOperand::CreateReg(Reg64)); |
| 230 InstADD.addOperand(MCOperand::CreateReg(Reg64)); |
| 231 InstADD.addOperand(MCOperand::CreateReg(X86::R15)); |
| 232 Out.EmitInstruction(InstADD, STI); |
| 233 } |
| 234 |
| 235 if (WillEmitCallInst) { |
| 236 // callq *%rXX |
| 237 MCInst CALLInst; |
| 238 CALLInst.setOpcode(Is64Bit ? X86::CALL64r : X86::CALL32r); |
| 239 CALLInst.addOperand(MCOperand::CreateReg(Is64Bit ? Reg64 : Reg32)); |
| 240 Out.EmitInstruction(CALLInst, STI); |
| 241 } else { |
| 242 // jmpq *%rXX -or- jmpq *%r11 |
| 243 MCInst JMPInst; |
| 244 JMPInst.setOpcode(Is64Bit ? X86::JMP64r : X86::JMP32r); |
| 245 JMPInst.addOperand(MCOperand::CreateReg(Is64Bit ? Reg64 : Reg32)); |
| 246 Out.EmitInstruction(JMPInst, STI); |
| 247 } |
| 248 Out.EmitBundleUnlock(); |
| 249 if (RetTarget) { |
| 250 Out.EmitCodeAlignment(kNaClX86InstructionBundleSize); |
| 251 Out.EmitLabel(RetTarget); |
| 252 } |
| 253 } |
| 254 |
| 255 static void EmitRet(const llvm::MCSubtargetInfo &STI, const MCOperand *AmtOp, |
| 256 bool Is64Bit, MCStreamer &Out) { |
| 257 // For NaCl64 returns, follow the convention of using r11 to hold |
| 258 // the target of an indirect jump to avoid potentially leaking the |
| 259 // sandbox base address. |
| 260 const bool HideSandboxBase = (FlagHideSandboxBase && |
| 261 Is64Bit && !FlagUseZeroBasedSandbox); |
| 262 // For NaCl64 sandbox hiding, use r11 to hold the branch target. |
| 263 // Otherwise, use rcx/ecx for fewer instruction bytes (no REX |
| 264 // prefix). |
| 265 const unsigned RegTarget = HideSandboxBase ? X86::R11 : |
| 266 (Is64Bit ? X86::RCX : X86::ECX); |
| 267 MCInst POPInst; |
| 268 POPInst.setOpcode(Is64Bit ? X86::POP64r : X86::POP32r); |
| 269 POPInst.addOperand(MCOperand::CreateReg(RegTarget)); |
| 270 Out.EmitInstruction(POPInst, STI); |
| 271 |
| 272 if (AmtOp) { |
| 273 assert(!Is64Bit); |
| 274 MCInst ADDInst; |
| 275 unsigned ADDReg = X86::ESP; |
| 276 ADDInst.setOpcode(X86::ADD32ri); |
| 277 ADDInst.addOperand(MCOperand::CreateReg(ADDReg)); |
| 278 ADDInst.addOperand(MCOperand::CreateReg(ADDReg)); |
| 279 ADDInst.addOperand(*AmtOp); |
| 280 Out.EmitInstruction(ADDInst, STI); |
| 281 } |
| 282 |
| 283 EmitIndirectBranch(STI, MCOperand::CreateReg(RegTarget), Is64Bit, false, Out); |
| 284 } |
| 285 |
| 286 // Fix a register after being truncated to 32-bits. |
| 287 static void EmitRegFix(const llvm::MCSubtargetInfo &STI, unsigned Reg64, |
| 288 MCStreamer &Out) { |
| 289 // lea (%rsp, %r15, 1), %rsp |
| 290 // We do not need to add the R15 base for the zero-based sandbox model |
| 291 if (!FlagUseZeroBasedSandbox) { |
| 292 MCInst Tmp; |
| 293 Tmp.setOpcode(X86::LEA64r); |
| 294 Tmp.addOperand(MCOperand::CreateReg(Reg64)); // DestReg |
| 295 Tmp.addOperand(MCOperand::CreateReg(Reg64)); // BaseReg |
| 296 Tmp.addOperand(MCOperand::CreateImm(1)); // Scale |
| 297 Tmp.addOperand(MCOperand::CreateReg(X86::R15)); // IndexReg |
| 298 Tmp.addOperand(MCOperand::CreateImm(0)); // Offset |
| 299 Tmp.addOperand(MCOperand::CreateReg(0)); // SegmentReg |
| 300 Out.EmitInstruction(Tmp, STI); |
| 301 } |
| 302 } |
| 303 |
| 304 static void EmitSPArith(const llvm::MCSubtargetInfo &STI, unsigned Opc, |
| 305 const MCOperand &ImmOp, MCStreamer &Out) { |
| 306 Out.EmitBundleLock(false); |
| 307 |
| 308 MCInst Tmp; |
| 309 Tmp.setOpcode(Opc); |
| 310 Tmp.addOperand(MCOperand::CreateReg(X86::ESP)); |
| 311 Tmp.addOperand(MCOperand::CreateReg(X86::ESP)); |
| 312 Tmp.addOperand(ImmOp); |
| 313 Out.EmitInstruction(Tmp, STI); |
| 314 |
| 315 EmitRegFix(STI, X86::RSP, Out); |
| 316 Out.EmitBundleUnlock(); |
| 317 } |
| 318 |
| 319 static void EmitSPAdj(const llvm::MCSubtargetInfo &STI, const MCOperand &ImmOp, |
| 320 MCStreamer &Out) { |
| 321 Out.EmitBundleLock(false); |
| 322 |
| 323 MCInst Tmp; |
| 324 Tmp.setOpcode(X86::LEA64_32r); |
| 325 Tmp.addOperand(MCOperand::CreateReg(X86::RSP)); // DestReg |
| 326 Tmp.addOperand(MCOperand::CreateReg(X86::RBP)); // BaseReg |
| 327 Tmp.addOperand(MCOperand::CreateImm(1)); // Scale |
| 328 Tmp.addOperand(MCOperand::CreateReg(0)); // IndexReg |
| 329 Tmp.addOperand(ImmOp); // Offset |
| 330 Tmp.addOperand(MCOperand::CreateReg(0)); // SegmentReg |
| 331 Out.EmitInstruction(Tmp, STI); |
| 332 |
| 333 EmitRegFix(STI, X86::RSP, Out); |
| 334 Out.EmitBundleUnlock(); |
| 335 } |
| 336 |
| 337 static void EmitPrefix(const llvm::MCSubtargetInfo &STI, unsigned Opc, |
| 338 MCStreamer &Out, X86MCNaClSFIState &State) { |
| 339 assert(State.PrefixSaved == 0); |
| 340 assert(State.PrefixPass == false); |
| 341 |
| 342 MCInst PrefixInst; |
| 343 PrefixInst.setOpcode(Opc); |
| 344 State.PrefixPass = true; |
| 345 Out.EmitInstruction(PrefixInst, STI); |
| 346 |
| 347 assert(State.PrefixSaved == 0); |
| 348 assert(State.PrefixPass == false); |
| 349 } |
| 350 |
| 351 static void EmitMoveRegReg(const llvm::MCSubtargetInfo &STI, bool Is64Bit, |
| 352 unsigned ToReg, unsigned FromReg, MCStreamer &Out) { |
| 353 MCInst Move; |
| 354 Move.setOpcode(Is64Bit ? X86::MOV64rr : X86::MOV32rr); |
| 355 Move.addOperand(MCOperand::CreateReg(ToReg)); |
| 356 Move.addOperand(MCOperand::CreateReg(FromReg)); |
| 357 Out.EmitInstruction(Move, STI); |
| 358 } |
| 359 |
| 360 static void EmitRegTruncate(const llvm::MCSubtargetInfo &STI, unsigned Reg64, |
| 361 MCStreamer &Out) { |
| 362 unsigned Reg32 = getX86SubSuperRegister_(Reg64, MVT::i32); |
| 363 EmitMoveRegReg(STI, false, Reg32, Reg32, Out); |
| 364 } |
| 365 |
| 366 static void HandleMemoryRefTruncation(const llvm::MCSubtargetInfo &STI, |
| 367 MCInst *Inst, unsigned IndexOpPosition, |
| 368 MCStreamer &Out) { |
| 369 unsigned IndexReg = Inst->getOperand(IndexOpPosition).getReg(); |
| 370 if (FlagUseZeroBasedSandbox) { |
| 371 // With the zero-based sandbox, we use a 32-bit register on the index |
| 372 Inst->getOperand(IndexOpPosition).setReg(DemoteRegTo32_(IndexReg)); |
| 373 } else { |
| 374 EmitRegTruncate(STI, IndexReg, Out); |
| 375 } |
| 376 } |
| 377 |
| 378 static void ShortenMemoryRef(MCInst *Inst, unsigned IndexOpPosition) { |
| 379 unsigned ImmOpPosition = IndexOpPosition - 1; |
| 380 unsigned BaseOpPosition = IndexOpPosition - 2; |
| 381 unsigned IndexReg = Inst->getOperand(IndexOpPosition).getReg(); |
| 382 // For the SIB byte, if the scale is 1 and the base is 0, then |
| 383 // an equivalent setup moves index to base, and index to 0. The |
| 384 // equivalent setup is optimized to remove the SIB byte in |
| 385 // X86MCCodeEmitter.cpp. |
| 386 if (Inst->getOperand(ImmOpPosition).getImm() == 1 && |
| 387 Inst->getOperand(BaseOpPosition).getReg() == 0) { |
| 388 Inst->getOperand(BaseOpPosition).setReg(IndexReg); |
| 389 Inst->getOperand(IndexOpPosition).setReg(0); |
| 390 } |
| 391 } |
| 392 |
| 393 static void EmitLoad(const llvm::MCSubtargetInfo &STI, bool Is64Bit, |
| 394 unsigned DestReg, unsigned BaseReg, unsigned Scale, |
| 395 unsigned IndexReg, unsigned Offset, unsigned SegmentReg, |
| 396 MCStreamer &Out) { |
| 397 // Load DestReg from address BaseReg + Scale * IndexReg + Offset |
| 398 MCInst Load; |
| 399 Load.setOpcode(Is64Bit ? X86::MOV64rm : X86::MOV32rm); |
| 400 Load.addOperand(MCOperand::CreateReg(DestReg)); |
| 401 Load.addOperand(MCOperand::CreateReg(BaseReg)); |
| 402 Load.addOperand(MCOperand::CreateImm(Scale)); |
| 403 Load.addOperand(MCOperand::CreateReg(IndexReg)); |
| 404 Load.addOperand(MCOperand::CreateImm(Offset)); |
| 405 Load.addOperand(MCOperand::CreateReg(SegmentReg)); |
| 406 Out.EmitInstruction(Load, STI); |
| 407 } |
| 408 |
| 409 static bool SandboxMemoryRef(MCInst *Inst, |
| 410 unsigned *IndexOpPosition) { |
| 411 for (unsigned i = 0, last = Inst->getNumOperands(); i < last; i++) { |
| 412 if (!Inst->getOperand(i).isReg() || |
| 413 Inst->getOperand(i).getReg() != X86::PSEUDO_NACL_SEG) { |
| 414 continue; |
| 415 } |
| 416 // Return the index register that will need to be truncated. |
| 417 // The order of operands on a memory reference is always: |
| 418 // (BaseReg, ScaleImm, IndexReg, DisplacementImm, SegmentReg), |
| 419 // So if we found a match for a segment register value, we know that |
| 420 // the index register is exactly two operands prior. |
| 421 *IndexOpPosition = i - 2; |
| 422 |
| 423 // Remove the PSEUDO_NACL_SEG annotation. |
| 424 Inst->getOperand(i).setReg(0); |
| 425 return true; |
| 426 } |
| 427 return false; |
| 428 } |
| 429 |
| 430 static void EmitREST(const llvm::MCSubtargetInfo &STI, const MCInst &Inst, |
| 431 unsigned Reg32, bool IsMem, MCStreamer &Out) { |
| 432 unsigned Reg64 = getX86SubSuperRegister_(Reg32, MVT::i64); |
| 433 Out.EmitBundleLock(false); |
| 434 if (!IsMem) { |
| 435 EmitMoveRegReg(STI, false, Reg32, Inst.getOperand(0).getReg(), Out); |
| 436 } else { |
| 437 unsigned IndexOpPosition; |
| 438 MCInst SandboxedInst = Inst; |
| 439 if (SandboxMemoryRef(&SandboxedInst, &IndexOpPosition)) { |
| 440 HandleMemoryRefTruncation(STI, &SandboxedInst, IndexOpPosition, Out); |
| 441 ShortenMemoryRef(&SandboxedInst, IndexOpPosition); |
| 442 } |
| 443 EmitLoad(STI, false, Reg32, |
| 444 SandboxedInst.getOperand(0).getReg(), // BaseReg |
| 445 SandboxedInst.getOperand(1).getImm(), // Scale |
| 446 SandboxedInst.getOperand(2).getReg(), // IndexReg |
| 447 SandboxedInst.getOperand(3).getImm(), // Offset |
| 448 SandboxedInst.getOperand(4).getReg(), // SegmentReg |
| 449 Out); |
| 450 } |
| 451 |
| 452 EmitRegFix(STI, Reg64, Out); |
| 453 Out.EmitBundleUnlock(); |
| 454 } |
| 455 |
| 456 |
| 457 namespace { |
| 458 // RAII holder for the recursion guard. |
| 459 class EmitRawState { |
| 460 public: |
| 461 EmitRawState(X86MCNaClSFIState &S) : State(S) { |
| 462 State.EmitRaw = true; |
| 463 } |
| 464 ~EmitRawState() { |
| 465 State.EmitRaw = false; |
| 466 } |
| 467 private: |
| 468 X86MCNaClSFIState &State; |
| 469 }; |
| 470 } |
| 471 |
| 472 namespace llvm { |
| 473 // CustomExpandInstNaClX86 - |
| 474 // If Inst is a NaCl pseudo instruction, emits the substitute |
| 475 // expansion to the MCStreamer and returns true. |
| 476 // Otherwise, returns false. |
| 477 // |
| 478 // NOTE: Each time this function calls Out.EmitInstruction(), it will be |
| 479 // called again recursively to rewrite the new instruction being emitted. |
| 480 // Care must be taken to ensure that this does not result in an infinite |
| 481 // loop. Also, global state must be managed carefully so that it is |
| 482 // consistent during recursive calls. |
| 483 // |
| 484 // We need global state to keep track of the explicit prefix (PREFIX_*) |
| 485 // instructions. Unfortunately, the assembly parser prefers to generate |
| 486 // these instead of combined instructions. At this time, having only |
| 487 // one explicit prefix is supported. |
| 488 bool CustomExpandInstNaClX86(const llvm::MCSubtargetInfo &STI, |
| 489 const MCInst &Inst, MCStreamer &Out, |
| 490 X86MCNaClSFIState &State) { |
| 491 // If we are emitting to .s, only sandbox pseudos not supported by gas. |
| 492 if (Out.hasRawTextSupport()) { |
| 493 if (!(Inst.getOpcode() == X86::NACL_ANDSPi8 || |
| 494 Inst.getOpcode() == X86::NACL_ANDSPi32)) |
| 495 return false; |
| 496 } |
| 497 // If we make a call to EmitInstruction, we will be called recursively. In |
| 498 // this case we just want the raw instruction to be emitted instead of |
| 499 // handling the insruction here. |
| 500 if (State.EmitRaw == true && !State.PrefixPass) { |
| 501 return false; |
| 502 } |
| 503 EmitRawState E(State); |
| 504 unsigned Opc = Inst.getOpcode(); |
| 505 DEBUG(dbgs() << "CustomExpandInstNaClX86("; Inst.dump(); dbgs() << ")\n"); |
| 506 switch (Opc) { |
| 507 case X86::LOCK_PREFIX: |
| 508 case X86::REP_PREFIX: |
| 509 case X86::REPNE_PREFIX: |
| 510 case X86::REX64_PREFIX: |
| 511 // Ugly hack because LLVM AsmParser is not smart enough to combine |
| 512 // prefixes back into the instruction they modify. |
| 513 if (State.PrefixPass) { |
| 514 State.PrefixPass = false; |
| 515 State.PrefixSaved = 0; |
| 516 return false; |
| 517 } |
| 518 assert(State.PrefixSaved == 0); |
| 519 State.PrefixSaved = Opc; |
| 520 return true; |
| 521 case X86::CALLpcrel32: |
| 522 assert(State.PrefixSaved == 0); |
| 523 EmitDirectCall(STI, Inst.getOperand(0), false, Out); |
| 524 return true; |
| 525 case X86::CALL64pcrel32: |
| 526 case X86::NACL_CALL64d: |
| 527 assert(State.PrefixSaved == 0); |
| 528 EmitDirectCall(STI, Inst.getOperand(0), true, Out); |
| 529 return true; |
| 530 case X86::NACL_CALL32r: |
| 531 assert(State.PrefixSaved == 0); |
| 532 EmitIndirectBranch(STI, Inst.getOperand(0), false, true, Out); |
| 533 return true; |
| 534 case X86::NACL_CALL64r: |
| 535 assert(State.PrefixSaved == 0); |
| 536 EmitIndirectBranch(STI, Inst.getOperand(0), true, true, Out); |
| 537 return true; |
| 538 case X86::NACL_JMP32r: |
| 539 assert(State.PrefixSaved == 0); |
| 540 EmitIndirectBranch(STI, Inst.getOperand(0), false, false, Out); |
| 541 return true; |
| 542 case X86::NACL_JMP64r: |
| 543 case X86::NACL_JMP64z: |
| 544 assert(State.PrefixSaved == 0); |
| 545 EmitIndirectBranch(STI, Inst.getOperand(0), true, false, Out); |
| 546 return true; |
| 547 case X86::NACL_RET32: |
| 548 assert(State.PrefixSaved == 0); |
| 549 EmitRet(STI, NULL, false, Out); |
| 550 return true; |
| 551 case X86::NACL_RET64: |
| 552 assert(State.PrefixSaved == 0); |
| 553 EmitRet(STI, NULL, true, Out); |
| 554 return true; |
| 555 case X86::NACL_RETI32: |
| 556 assert(State.PrefixSaved == 0); |
| 557 EmitRet(STI, &Inst.getOperand(0), false, Out); |
| 558 return true; |
| 559 case X86::NACL_ASPi8: |
| 560 assert(State.PrefixSaved == 0); |
| 561 EmitSPArith(STI, X86::ADD32ri8, Inst.getOperand(0), Out); |
| 562 return true; |
| 563 case X86::NACL_ASPi32: |
| 564 assert(State.PrefixSaved == 0); |
| 565 EmitSPArith(STI, X86::ADD32ri, Inst.getOperand(0), Out); |
| 566 return true; |
| 567 case X86::NACL_SSPi8: |
| 568 assert(State.PrefixSaved == 0); |
| 569 EmitSPArith(STI, X86::SUB32ri8, Inst.getOperand(0), Out); |
| 570 return true; |
| 571 case X86::NACL_SSPi32: |
| 572 assert(State.PrefixSaved == 0); |
| 573 EmitSPArith(STI, X86::SUB32ri, Inst.getOperand(0), Out); |
| 574 return true; |
| 575 case X86::NACL_ANDSPi8: |
| 576 assert(State.PrefixSaved == 0); |
| 577 EmitSPArith(STI, X86::AND32ri8, Inst.getOperand(0), Out); |
| 578 return true; |
| 579 case X86::NACL_ANDSPi32: |
| 580 assert(State.PrefixSaved == 0); |
| 581 EmitSPArith(STI, X86::AND32ri, Inst.getOperand(0), Out); |
| 582 return true; |
| 583 case X86::NACL_SPADJi32: |
| 584 assert(State.PrefixSaved == 0); |
| 585 EmitSPAdj(STI, Inst.getOperand(0), Out); |
| 586 return true; |
| 587 case X86::NACL_RESTBPm: |
| 588 assert(State.PrefixSaved == 0); |
| 589 EmitREST(STI, Inst, X86::EBP, true, Out); |
| 590 return true; |
| 591 case X86::NACL_RESTBPr: |
| 592 case X86::NACL_RESTBPrz: |
| 593 assert(State.PrefixSaved == 0); |
| 594 EmitREST(STI, Inst, X86::EBP, false, Out); |
| 595 return true; |
| 596 case X86::NACL_RESTSPm: |
| 597 assert(State.PrefixSaved == 0); |
| 598 EmitREST(STI, Inst, X86::ESP, true, Out); |
| 599 return true; |
| 600 case X86::NACL_RESTSPr: |
| 601 case X86::NACL_RESTSPrz: |
| 602 assert(State.PrefixSaved == 0); |
| 603 EmitREST(STI, Inst, X86::ESP, false, Out); |
| 604 return true; |
| 605 } |
| 606 |
| 607 unsigned IndexOpPosition; |
| 608 MCInst SandboxedInst = Inst; |
| 609 // If we need to sandbox a memory reference and we have a saved prefix, |
| 610 // use a single bundle-lock/unlock for the whole sequence of |
| 611 // added_truncating_inst + prefix + mem_ref_inst. |
| 612 if (SandboxMemoryRef(&SandboxedInst, &IndexOpPosition)) { |
| 613 unsigned PrefixLocal = State.PrefixSaved; |
| 614 State.PrefixSaved = 0; |
| 615 |
| 616 if (PrefixLocal || !FlagUseZeroBasedSandbox) |
| 617 Out.EmitBundleLock(false); |
| 618 |
| 619 HandleMemoryRefTruncation(STI, &SandboxedInst, IndexOpPosition, Out); |
| 620 ShortenMemoryRef(&SandboxedInst, IndexOpPosition); |
| 621 |
| 622 if (PrefixLocal) |
| 623 EmitPrefix(STI, PrefixLocal, Out, State); |
| 624 Out.EmitInstruction(SandboxedInst, STI); |
| 625 |
| 626 if (PrefixLocal || !FlagUseZeroBasedSandbox) |
| 627 Out.EmitBundleUnlock(); |
| 628 return true; |
| 629 } |
| 630 |
| 631 // If the special case above doesn't apply, but there is still a saved prefix, |
| 632 // then the saved prefix should be bundled-locked with Inst, so that it cannot |
| 633 // be separated by bundle padding. |
| 634 if (State.PrefixSaved) { |
| 635 unsigned PrefixLocal = State.PrefixSaved; |
| 636 State.PrefixSaved = 0; |
| 637 Out.EmitBundleLock(false); |
| 638 EmitPrefix(STI, PrefixLocal, Out, State); |
| 639 Out.EmitInstruction(Inst, STI); |
| 640 Out.EmitBundleUnlock(); |
| 641 return true; |
| 642 } |
| 643 return false; |
| 644 } |
| 645 |
| 646 } // namespace llvm |
| 647 |
| 648 |
| 649 |
| 650 |
| 651 // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 652 // |
| 653 // This is an exact copy of getX86SubSuperRegister from X86RegisterInfo.h |
| 654 // We cannot use the original because it is part of libLLVMX86CodeGen, |
| 655 // which cannot be a dependency of this module (libLLVMX86Desc). |
| 656 // |
| 657 // However, in all likelyhood, the real getX86SubSuperRegister will |
| 658 // eventually be moved to MCTargetDesc, and then this copy can be |
| 659 // removed. |
| 660 |
| 661 namespace { |
| 662 unsigned getX86SubSuperRegister_(unsigned Reg, EVT VT, bool High) { |
| 663 switch (VT.getSimpleVT().SimpleTy) { |
| 664 default: return Reg; |
| 665 case MVT::i8: |
| 666 if (High) { |
| 667 switch (Reg) { |
| 668 default: return 0; |
| 669 case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX: |
| 670 return X86::AH; |
| 671 case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX: |
| 672 return X86::DH; |
| 673 case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX: |
| 674 return X86::CH; |
| 675 case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX: |
| 676 return X86::BH; |
| 677 } |
| 678 } else { |
| 679 switch (Reg) { |
| 680 default: return 0; |
| 681 case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX: |
| 682 return X86::AL; |
| 683 case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX: |
| 684 return X86::DL; |
| 685 case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX: |
| 686 return X86::CL; |
| 687 case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX: |
| 688 return X86::BL; |
| 689 case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI: |
| 690 return X86::SIL; |
| 691 case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI: |
| 692 return X86::DIL; |
| 693 case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP: |
| 694 return X86::BPL; |
| 695 case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP: |
| 696 return X86::SPL; |
| 697 case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8: |
| 698 return X86::R8B; |
| 699 case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9: |
| 700 return X86::R9B; |
| 701 case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10: |
| 702 return X86::R10B; |
| 703 case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11: |
| 704 return X86::R11B; |
| 705 case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12: |
| 706 return X86::R12B; |
| 707 case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13: |
| 708 return X86::R13B; |
| 709 case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14: |
| 710 return X86::R14B; |
| 711 case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15: |
| 712 return X86::R15B; |
| 713 } |
| 714 } |
| 715 case MVT::i16: |
| 716 switch (Reg) { |
| 717 default: return Reg; |
| 718 case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX: |
| 719 return X86::AX; |
| 720 case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX: |
| 721 return X86::DX; |
| 722 case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX: |
| 723 return X86::CX; |
| 724 case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX: |
| 725 return X86::BX; |
| 726 case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI: |
| 727 return X86::SI; |
| 728 case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI: |
| 729 return X86::DI; |
| 730 case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP: |
| 731 return X86::BP; |
| 732 case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP: |
| 733 return X86::SP; |
| 734 case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8: |
| 735 return X86::R8W; |
| 736 case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9: |
| 737 return X86::R9W; |
| 738 case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10: |
| 739 return X86::R10W; |
| 740 case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11: |
| 741 return X86::R11W; |
| 742 case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12: |
| 743 return X86::R12W; |
| 744 case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13: |
| 745 return X86::R13W; |
| 746 case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14: |
| 747 return X86::R14W; |
| 748 case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15: |
| 749 return X86::R15W; |
| 750 } |
| 751 case MVT::i32: |
| 752 switch (Reg) { |
| 753 default: return Reg; |
| 754 case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX: |
| 755 return X86::EAX; |
| 756 case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX: |
| 757 return X86::EDX; |
| 758 case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX: |
| 759 return X86::ECX; |
| 760 case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX: |
| 761 return X86::EBX; |
| 762 case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI: |
| 763 return X86::ESI; |
| 764 case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI: |
| 765 return X86::EDI; |
| 766 case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP: |
| 767 return X86::EBP; |
| 768 case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP: |
| 769 return X86::ESP; |
| 770 case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8: |
| 771 return X86::R8D; |
| 772 case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9: |
| 773 return X86::R9D; |
| 774 case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10: |
| 775 return X86::R10D; |
| 776 case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11: |
| 777 return X86::R11D; |
| 778 case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12: |
| 779 return X86::R12D; |
| 780 case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13: |
| 781 return X86::R13D; |
| 782 case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14: |
| 783 return X86::R14D; |
| 784 case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15: |
| 785 return X86::R15D; |
| 786 } |
| 787 case MVT::i64: |
| 788 switch (Reg) { |
| 789 default: return Reg; |
| 790 case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX: |
| 791 return X86::RAX; |
| 792 case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX: |
| 793 return X86::RDX; |
| 794 case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX: |
| 795 return X86::RCX; |
| 796 case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX: |
| 797 return X86::RBX; |
| 798 case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI: |
| 799 return X86::RSI; |
| 800 case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI: |
| 801 return X86::RDI; |
| 802 case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP: |
| 803 return X86::RBP; |
| 804 case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP: |
| 805 return X86::RSP; |
| 806 case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8: |
| 807 return X86::R8; |
| 808 case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9: |
| 809 return X86::R9; |
| 810 case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10: |
| 811 return X86::R10; |
| 812 case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11: |
| 813 return X86::R11; |
| 814 case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12: |
| 815 return X86::R12; |
| 816 case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13: |
| 817 return X86::R13; |
| 818 case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14: |
| 819 return X86::R14; |
| 820 case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15: |
| 821 return X86::R15; |
| 822 } |
| 823 } |
| 824 |
| 825 return Reg; |
| 826 } |
| 827 |
| 828 // This is a copy of DemoteRegTo32 from X86NaClRewritePass.cpp. |
| 829 // We cannot use the original because it uses part of libLLVMX86CodeGen, |
| 830 // which cannot be a dependency of this module (libLLVMX86Desc). |
| 831 // Note that this function calls getX86SubSuperRegister_, which is |
| 832 // also a copied function for the same reason. |
| 833 |
| 834 unsigned DemoteRegTo32_(unsigned RegIn) { |
| 835 if (RegIn == 0) |
| 836 return 0; |
| 837 unsigned RegOut = getX86SubSuperRegister_(RegIn, MVT::i32, false); |
| 838 assert(RegOut != 0); |
| 839 return RegOut; |
| 840 } |
| 841 } //namespace |
| 842 // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
OLD | NEW |