[asan-assembly-instrumentation] Added CFI directives to the generated instrumentation...
authorYuri Gorshenin <ygorshenin@google.com>
Wed, 10 Sep 2014 09:45:49 +0000 (09:45 +0000)
committerYuri Gorshenin <ygorshenin@google.com>
Wed, 10 Sep 2014 09:45:49 +0000 (09:45 +0000)
Summary: [asan-assembly-instrumentation] Added CFI directives to the generated instrumentation code.

Reviewers: eugenis

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D5189

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217482 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCTargetAsmParser.h
lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp
lib/Target/X86/AsmParser/X86AsmInstrumentation.h
lib/Target/X86/AsmParser/X86AsmParser.cpp
test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll [new file with mode: 0644]

index 4197389..b13de67 100644 (file)
@@ -123,6 +123,9 @@ public:
   virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
                              SMLoc &EndLoc) = 0;
 
+  /// Sets frame register corresponding to the current MachineFunction.
+  virtual void SetFrameRegister(unsigned RegNo) {}
+
   /// ParseInstruction - Parse one assembly instruction.
   ///
   /// The parser is positioned following the instruction name. The target
index 71dca74..cca5f22 100644 (file)
@@ -33,6 +33,7 @@
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
 #include "llvm/Target/TargetSubtargetInfo.h"
 using namespace llvm;
 
@@ -146,6 +147,10 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode,
                        " we don't have an asm parser for this target\n");
   Parser->setAssemblerDialect(Dialect);
   Parser->setTargetParser(*TAP.get());
+  if (MF) {
+    const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
+    TAP->SetFrameRegister(TRI->getFrameRegister(*MF));
+  }
 
   // Don't implicitly switch to the text section before the asm.
   int Res = Parser->Run(/*NoInitialTextSection*/ true,
index 3d0f72f..68c1b2d 100644 (file)
@@ -294,6 +294,7 @@ public:
 
   X86AddressSanitizer32(const MCSubtargetInfo &STI)
       : X86AddressSanitizer(STI) {}
+
   virtual ~X86AddressSanitizer32() {}
 
   virtual void StoreFlags(MCStreamer &Out) override {
@@ -307,6 +308,22 @@ public:
   virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
                                             MCContext &Ctx,
                                             MCStreamer &Out) override {
+    const MCRegisterInfo* MRI = Ctx.getRegisterInfo();
+    if (MRI && FrameReg != X86::NoRegister) {
+      EmitInstruction(
+          Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EBP));
+      if (FrameReg == X86::ESP) {
+        Out.EmitCFIAdjustCfaOffset(4 /* byte size of the FrameReg */);
+        Out.EmitCFIRelOffset(
+            MRI->getDwarfRegNum(X86::EBP, true /* IsEH */), 0);
+      }
+      EmitInstruction(
+          Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EBP).addReg(FrameReg));
+      Out.EmitCFIRememberState();
+      Out.EmitCFIDefCfaRegister(
+          MRI->getDwarfRegNum(X86::EBP, true /* IsEH */));
+    }
+
     EmitInstruction(
         Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.addressReg(MVT::i32)));
     EmitInstruction(
@@ -330,6 +347,14 @@ public:
         Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.shadowReg(MVT::i32)));
     EmitInstruction(
         Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.addressReg(MVT::i32)));
+
+    if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
+      EmitInstruction(
+          Out, MCInstBuilder(X86::POP32r).addReg(X86::EBP));
+      Out.EmitCFIRestoreState();
+      if (FrameReg == X86::ESP)
+        Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the FrameReg */);
+    }
   }
 
   virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
@@ -526,6 +551,7 @@ public:
 
   X86AddressSanitizer64(const MCSubtargetInfo &STI)
       : X86AddressSanitizer(STI) {}
+
   virtual ~X86AddressSanitizer64() {}
 
   virtual void StoreFlags(MCStreamer &Out) override {
@@ -539,6 +565,21 @@ public:
   virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
                                             MCContext &Ctx,
                                             MCStreamer &Out) override {
+    const MCRegisterInfo *RegisterInfo = Ctx.getRegisterInfo();
+    if (RegisterInfo && FrameReg != X86::NoRegister) {
+      EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RBP));
+      if (FrameReg == X86::RSP) {
+        Out.EmitCFIAdjustCfaOffset(8 /* byte size of the FrameReg */);
+        Out.EmitCFIRelOffset(
+            RegisterInfo->getDwarfRegNum(X86::RBP, true /* IsEH */), 0);
+      }
+      EmitInstruction(
+          Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RBP).addReg(FrameReg));
+      Out.EmitCFIRememberState();
+      Out.EmitCFIDefCfaRegister(
+          RegisterInfo->getDwarfRegNum(X86::RBP, true /* IsEH */));
+    }
+
     EmitAdjustRSP(Ctx, Out, -128);
     EmitInstruction(
         Out, MCInstBuilder(X86::PUSH64r).addReg(RegCtx.shadowReg(MVT::i64)));
@@ -564,6 +605,14 @@ public:
     EmitInstruction(
         Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.shadowReg(MVT::i64)));
     EmitAdjustRSP(Ctx, Out, 128);
+
+    if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
+      EmitInstruction(
+          Out, MCInstBuilder(X86::POP64r).addReg(X86::RBP));
+      Out.EmitCFIRestoreState();
+      if (FrameReg == X86::RSP)
+        Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the FrameReg */);
+    }
   }
 
   virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
@@ -771,7 +820,7 @@ void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize,
 } // End anonymous namespace
 
 X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo &STI)
-    : STI(STI) {}
+    : STI(STI), FrameReg(X86::NoRegister) {}
 
 X86AsmInstrumentation::~X86AsmInstrumentation() {}
 
index 4b23b4b..aa2ed03 100644 (file)
@@ -34,6 +34,10 @@ class X86AsmInstrumentation {
 public:
   virtual ~X86AsmInstrumentation();
 
+  void SetFrameRegister(unsigned RegNo) {
+    FrameReg = RegNo;
+  }
+
   // Tries to instrument and emit instruction.
   virtual void InstrumentAndEmitInstruction(
       const MCInst &Inst,
@@ -50,6 +54,8 @@ protected:
   void EmitInstruction(MCStreamer &Out, const MCInst &Inst);
 
   const MCSubtargetInfo &STI;
+
+  unsigned FrameReg;
 };
 
 } // End llvm namespace
index 48ba7b0..8014c31 100644 (file)
@@ -788,6 +788,8 @@ public:
 
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
 
+  void SetFrameRegister(unsigned RegNo) override;
+
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
 
@@ -970,6 +972,10 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo,
   return false;
 }
 
+void X86AsmParser::SetFrameRegister(unsigned RegNo) {
+  Instrumentation->SetFrameRegister(RegNo);
+}
+
 std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
   unsigned basereg =
     is64BitMode() ? X86::RSI : (is32BitMode() ? X86::ESI : X86::SI);
diff --git a/test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll b/test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll
new file mode 100644 (file)
index 0000000..dfa418f
--- /dev/null
@@ -0,0 +1,45 @@
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=+sse2 -asm-instrumentation=address -asan-instrument-assembly | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK-LABEL: mov8b_rbp
+; CHECK: pushq %rbp
+; CHECK-NOT: .cfi_adjust_cfa_offset 8
+; CHECK: movq %rbp, %rbp
+; CHECK: .cfi_remember_state
+; CHECK: .cfi_def_cfa_register %rbp
+; CHECK: leaq -128(%rsp)
+; CHECK: callq __asan_report_load8@PLT
+; CHECK: leaq 128(%rsp)
+; CHECK: popq %rbp
+; CHECK: .cfi_restore_state
+; CHECK-NOT: .cfi_adjust_cfa_offset -8
+; CHECK: retq
+define void @mov8b_rbp(i64* %dst, i64* %src) #0 {
+entry:
+  tail call void asm sideeffect "movq ($0), %rax \0A\09movq %rax, ($1) \0A\09", "r,r,~{rax},~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %src, i64* %dst)
+  ret void
+}
+
+; CHECK-LABEL: mov8b_rsp
+; CHECK: pushq %rbp
+; CHECK: .cfi_adjust_cfa_offset 8
+; CHECK: movq %rsp, %rbp
+; CHECK: .cfi_remember_state
+; CHECK: .cfi_def_cfa_register %rbp
+; CHECK: leaq -128(%rsp)
+; CHECK: callq __asan_report_load8@PLT
+; CHECK: leaq 128(%rsp)
+; CHECK: popq %rbp
+; CHECK: .cfi_restore_state
+; CHECK: .cfi_adjust_cfa_offset -8
+; CHECK: retq
+define void @mov8b_rsp(i64* %dst, i64* %src) #1 {
+entry:
+  tail call void asm sideeffect "movq ($0), %rax \0A\09movq %rax, ($1) \0A\09", "r,r,~{rax},~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %src, i64* %dst)
+  ret void
+}
+
+attributes #0 = { nounwind sanitize_address uwtable "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" }
+attributes #1 = { nounwind sanitize_address uwtable "no-frame-pointer-elim"="false" }